/* ═════════════════════════════════════════════════════════════════
   fleet-shell.css — SquareKeeper Fleet office PAGE primitives.
   ═════════════════════════════════════════════════════════════════

   ⚠ NO CHROME RULES HERE. The sidebar, top bar, shell layout, brand block,
   welcome line, nav rows, active pill, footer buttons and version block are
   ALL owned by the suite's shared /assets/css/module-chrome.css (Platform-
   owned, loaded by every fleet page before this file) — the same sheet Works
   and every Property module render from. Restating a chrome rule in a
   product-local sheet is the drift vector that sheet exists to kill
   (Platform/MODULE_NAV_TEMPLATE_SPEC.md §1). This file carries only what
   sits INSIDE #pageContent, the pre-auth boot screen, the sidebar language
   toggle (a Works-pattern addition the shared sheet has no rule for), the
   access-denied fallback and print.

   Fleet-owned: Modules/SquareKeeper_Fleet/Web/fleet-assets/. Served from
   /fleet-assets/ on fleet.squarekeeper.com — a path Fleet owns, never the
   shared /assets/ bundle (feedback_shared_asset_sync_delivers_vendored_copy).
   ═════════════════════════════════════════════════════════════════ */

/* ── Page container + view head ─────────────────────────────────
   #pageContent (shared) already pads 24px / 14px on phones and scrolls. The
   content spans the FULL viewport width like Works and every Property module
   (Matt, 2026-09-02 QA: the first cut capped it at 960px — no measure cap
   here). Works-style view head: h1 + a muted sub line (org name, date); the
   top bar repeats the title in caps. */
.fx-page { min-width: 0; }
.fx-viewhead {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: 16px; flex-wrap: wrap; margin: 0 0 18px;
}
.fx-viewhead h1 { font-size: 22px; font-weight: 700; color: var(--text-primary); margin: 0; line-height: 1.2; }
.fx-viewhead .fx-sub { font-size: 13px; color: var(--text-muted); margin-top: 4px; }
.fx-viewhead .fx-actions { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }

/* ── Cards / rows / messages (the fleet page vocabulary) ──────── */
.fx-card {
  background: var(--bg-panel); border: 1px solid var(--border-default);
  border-radius: 14px; padding: 20px; margin-bottom: 18px;
}
.fx-card h2 { font-size: 15px; margin: 0 0 4px; color: var(--text-primary); }
.fx-hint { font-size: 13px; color: var(--text-muted); line-height: 1.6; margin: 0 0 14px; }
.fx-empty { font-size: 13px; color: var(--text-muted); }
.fx-msg { font-size: 13px; border-radius: 9px; padding: 10px 12px; margin-top: 12px; }
.fx-msg.err { color: var(--st-danger-fg); background: var(--st-danger-bg); border: 1px solid var(--st-danger-br); }
.fx-row {
  display: flex; align-items: center; gap: 12px; padding: 12px 0;
  border-top: 1px solid var(--border-default); flex-wrap: wrap;
}
.fx-row:first-of-type { border-top: none; }
.fx-rowmain { flex: 1 1 220px; min-width: 0; }
.fx-rowname { font-size: 14px; font-weight: 600; color: var(--text-primary); }
.fx-rowsub { font-size: 12px; color: var(--text-muted); }
.fx-link { color: var(--accent-primary); font-weight: 600; text-decoration: none; }
.fx-link:hover { text-decoration: underline; }

/* ── Dashboard stat tiles ────────────────────────────────────────
   Typography (label / value / hint) is the CANONICAL .stat-box set from
   module-chrome.css — identical to OM/MM/PM tiles. Only the grid and the
   "tile is a link" affordance are ours. Value colour: neutral by default;
   .warn / .success modifiers come from the shared sheet (theme-aware). */
.fx-stats {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 14px; margin-bottom: 18px;
}
a.stat-box { display: block; text-decoration: none; color: inherit; }
a.stat-box:hover { text-decoration: none; }
.stat-box .value { color: var(--text-primary); }
.stat-box .value.pending { color: var(--text-faint); }
/* Today-at-a-glance state chips — brand FILL + white ink for proven (SK Green
   v2 fill pair, theme-invariant), the needs-review AMBER for anything a human
   should look at (never red: an unproven stop is a prompt, not a failure). */
.fx-chip {
  display: inline-block; font-size: 12px; font-weight: 700; padding: 3px 10px;
  border-radius: 50px; white-space: nowrap;
}
.fx-chip.done { background: var(--accent-fill); color: var(--accent-onfill); }
.fx-chip.todo { background: var(--st-warn-bg); color: var(--st-warn-fg); border: 1px solid var(--st-warn-br); }
.fx-chip.short { background: #B45309; color: #fff; }
.fx-chip.none { background: var(--bg-app); color: var(--text-muted); border: 1px solid var(--border-default); }

/* ── Boot screen (pre-auth) ──────────────────────────────────────
   .loading-screen / .loading-icon / .loading-spinner / .loading-text are the
   shared sheet's. The tile icon has transparent rounded corners, so it is
   clipped full-bleed like the Works boot + every login logo. */
.loading-screen .loading-icon { clip-path: inset(7.6% round 16%); border-radius: 0; }

/* ── Sidebar language toggle (Works pattern: EN | ES above Sign out) ──
   The buttons carry the page's `fl-langbtn` class because every page's
   applyLangStatic() rewrites [data-setlang] className to exactly that; styled
   here at (0,2,0) so a page-local .fl-langbtn rule (0,1,0) can never win.
   The rail is DARK in both themes (--bg-chrome #06060C), so the inks are the
   rail's literals (#CBD5E1 = 7.88:1), never a page token that flips light.
   Selected = the FILL pair (#0A8A06 + white, 4.515:1, theme-invariant) — NOT
   --accent-primary, which is the TEXT accent and would paint white on #1ACD15
   in dark theme (BRAND_STYLE_GUIDE §3.3). */
.sidebar-lang { display: flex; gap: 4px; margin: 10px 14px 2px; }
.sidebar-lang .fl-langbtn {
  flex: 1; font-family: var(--font-ui); font-size: 11px; font-weight: 700;
  letter-spacing: .5px; padding: 5px 0; border-radius: 6px;
  border: 1px solid #334155; background: transparent; color: #CBD5E1; cursor: pointer;
}
.sidebar-lang .fl-langbtn.on { background: var(--accent-fill); color: var(--accent-onfill); border-color: var(--accent-fill); }
.sidebar-lang .fl-langbtn:not(.on):hover { color: #E2E8F0; border-color: #475569; }

/* ── Access denied ───────────────────────────────────────────────
   requireAuth's showAccessDenied() REPLACES document.body with .access-denied
   markup styled in the suite's style.css — which fleet pages do not load, so
   it rendered raw top-left for a customer who had merely signed in at the
   wrong product's door (verified live 2026-08-27). Scoped here once, for every
   page, instead of a copy per page. */
.access-denied {
  text-align: center; padding: 80px 24px; color: var(--text-muted);
  max-width: 520px; margin: 0 auto; font-family: inherit;
}
.access-denied h1 { color: var(--text-primary); margin-bottom: 8px; font-size: 22px; }
.access-denied a { color: var(--accent-primary); }
.access-denied .mt-16 { margin-top: 16px; }

/* ── Print (the /route cab sheet) ────────────────────────────────
   The shell is a fixed 100dvh flex frame with an inner scroll pane, which
   prints as ONE clipped page. Flatten it: chrome off, document flow back.
   !important because the shared sheet pins #appLayout/#sidebar heights with
   !important of its own; this file loads later, so equal-weight rules win. */
@media print {
  body { overflow: visible !important; background: #fff; }
  #appLayout { display: block !important; height: auto !important; overflow: visible !important; }
  #mainArea { display: block !important; }
  #sidebar, #topBar, #chromeHamburger, #chromeBackdrop { display: none !important; }
  #pageContent { overflow: visible !important; padding: 0 !important; background: #fff !important; }
}
