/* ============================================================
   OWNER: Blake Brose (address in the private repo, not in this public file). Canonical home:
   Smart-Foundation-Repair/sfr-app-chrome. This is Blake's App Chrome
   Standard — SEPARATE from Steve's "Design System v1" governance work in
   sfr-brand-guide. Do not overwrite from that project without Blake's OK.
   ============================================================
   SFR App Core — the shared chrome standard for every SFR web app
   ------------------------------------------------------------
   The canonical chrome is the brand guide itself (brand.fixitforever.com):
   navy header with the stacked white WORDMARK logo, uppercase VV Ruby nav
   links (honey on hover), pale-yellow ground, white content sheet, navy
   footer. Drop this ONE file into any SFR app and use the .app-* classes.

   Approved standard (2026-07-02, refined from the brand guide):
     - Header  = navy bar; LEFT stacked WORDMARK logo + small app label;
                 RIGHT uppercase VV Ruby nav (honey hover) + user avatar
     - Fonts   = VV Ruby Sans (display, uppercase) + Figtree (body)
     - Ground  = Pale #F1ECBE; content on a white sheet (docs) or white
                 panels full-width (dashboards)
     - Footer  = navy, centered wordmark + line
     - Purpose-fit: field app keeps its sidebar; public forms stay simple;
       all consume these SAME tokens + logo + favicon.

   LICENSING: VV Ruby Sans is licensed to SFR — do NOT ship the woff2 in
   public repos. Public/customer surfaces fall back to Montserrat Bold
   (all-caps), already in --sfr-font-display below.
   ============================================================ */

:root {
  /* Brand palette — locked, exact-match to the brand guide */
  --sfr-navy:  #1E2A3B;
  --sfr-honey: #EAB33F;
  --sfr-pale:  #F1ECBE;
  --sfr-white: #FFFFFF;
  --sfr-black: #000000;
  --sfr-ink:   #1E2A3B;

  /* Structural navy tints */
  --sfr-navy-600: #34465f;
  --sfr-navy-line: rgba(30, 42, 59, 0.16);
  --sfr-pale-edge: #d8d2a0;
  --sfr-line: rgba(30, 42, 59, 0.14);
  --sfr-gray-ground: #F5F6F8;

  /* Semantic status — SEPARATE from the honey accent, never reused as accent */
  --sfr-good: #1B7F3B;
  --sfr-warn: #B7791F;
  --sfr-bad:  #C2310E;

  /* Typography */
  --sfr-font-display: "VV Ruby Sans", "Montserrat", system-ui, -apple-system, "Segoe UI", sans-serif;
  --sfr-font-body:    "Figtree", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;

  /* Metrics — brand-guide faithful */
  --sfr-header-maxw: 1180px;   /* header inner width; dashboards may set to none */
  --sfr-content-maxw: 1180px;  /* white sheet width for document apps */
  --sfr-radius: 8px;           /* buttons + cards */
  --sfr-radius-pill: 999px;    /* pills + chips */
  --sfr-shadow: 0 10px 30px rgba(30, 42, 59, 0.10);
  --sfr-sheet-shadow: 0 0 60px rgba(30, 42, 59, 0.12);
}

/* ---- MINIMUM FONT SIZE — LOCKED (Blake, 2026-07-04) ----
   Nothing below 8pt anywhere. On the web that means:
     - 11px absolute floor for ALL text (0.6875rem)
     - 12px floor (0.75rem) for uppercase VV Ruby Sans — headers, table headers,
       letterspaced caps — because the condensed all-caps face reads smaller
       than its nominal size.
   No font-size in this file or any consuming app may go below these floors.
   Trigger case: the leverage-table header on opord.fixitforever.com. */

/* ---- Type discipline (uppercase baked into the display face) ----
   VV Ruby Sans is a CONDENSED face — it needs generous tracking or the letters
   "smash" together and read small. Default tracking is deliberately open. */
.sfr-display,
.app-label,
.app-nav a,
.app-footer__meta {
  font-family: var(--sfr-font-display);
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

/* ==========================================================================
   HEADER — navy bar, wordmark logo + app label, uppercase nav (brand guide)
   ========================================================================== */
.app-header {
  position: sticky;
  top: 0;
  z-index: 50;
  background: var(--sfr-navy);
  color: var(--sfr-white);
  box-shadow: 0 2px 14px rgba(0, 0, 0, 0.18);
}
.app-header__inner {
  max-width: var(--sfr-header-maxw);
  margin: 0 auto;
  padding: 12px 24px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 18px;
}
/* Dashboards that run full-width tables set this on the inner to align the
   header edges with the content. */
.app-header__inner--full { max-width: none; }

/* LEFT: stacked wordmark logo + small app label */
.app-header__brand {
  display: flex;
  align-items: center;
  gap: 14px;
  text-decoration: none;
  color: inherit;
  flex: none;
  min-width: 0;
}
.app-wordmark { height: 30px; width: auto; display: block; flex: none; }
/* App/sheet NAME — WHITE and slightly LARGER than the menu, so it reads as the
   title of the page, not a nav item. Honey stays reserved for nav hover/active. */
.app-label {
  font-size: 1.08rem;
  font-weight: 700;
  color: var(--sfr-white);
  letter-spacing: 0.05em;
  padding-left: 16px;
  border-left: 1px solid rgba(255, 255, 255, 0.28);
  white-space: nowrap;
}

/* RIGHT: nav links + user avatar */
.app-header__right {
  display: flex;
  align-items: center;
  gap: 22px;
  min-width: 0;
}
.app-nav { display: flex; align-items: center; gap: 28px; flex-wrap: wrap; }
.app-nav a {
  color: rgba(255, 255, 255, 0.80);
  font-size: 0.98rem;
  font-weight: 600;
  letter-spacing: 0.06em;   /* open the condensed face so the menu reads fast */
  text-decoration: none;
  transition: color 0.12s;
}
.app-nav a:hover { color: var(--sfr-honey); }
.app-nav a.is-active { color: var(--sfr-honey); }

/* Grouped / collapsible menu — when an app has many destinations, group them
   under a SUBJECT with a caret trigger + dropdown. Apps toggle .is-open (and it
   also opens on hover). Keeps the top bar clean and readable. */
.app-nav__group { position: relative; display: inline-flex; }
.app-nav__trigger {
  display: inline-flex; align-items: center; gap: 7px;
  font-family: var(--sfr-font-display); text-transform: uppercase;
  font-size: 0.98rem; font-weight: 600; letter-spacing: 0.06em;
  color: rgba(255, 255, 255, 0.80); background: none; border: 0;
  cursor: pointer; padding: 0;
}
.app-nav__trigger::after { content: "▾"; font-size: 0.72em; opacity: 0.8; }
.app-nav__group:hover .app-nav__trigger,
.app-nav__group.is-open .app-nav__trigger { color: var(--sfr-honey); }
.app-nav__menu {
  position: absolute; top: calc(100% + 10px); left: 0; min-width: 210px;
  display: none; flex-direction: column; gap: 2px;
  background: var(--sfr-navy); border: 1px solid rgba(255, 255, 255, 0.14);
  border-radius: 10px; padding: 8px; box-shadow: 0 14px 34px rgba(0, 0, 0, 0.34);
  z-index: 60;
}
.app-nav__group:hover .app-nav__menu,
.app-nav__group.is-open .app-nav__menu { display: flex; }
.app-nav__menu a {
  padding: 9px 12px; border-radius: 7px; font-size: 0.94rem; letter-spacing: 0.05em;
  color: rgba(255, 255, 255, 0.82);
}
.app-nav__menu a:hover { background: rgba(255, 255, 255, 0.07); color: var(--sfr-honey); }

.app-user {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: var(--sfr-navy-600);
  border: 1px solid rgba(255, 255, 255, 0.28);
  flex: none;
}

@media (max-width: 760px) {
  .app-header__inner { flex-wrap: wrap; padding: 10px 16px; gap: 10px; }
  .app-wordmark { height: 24px; }
  .app-header__right { width: 100%; gap: 14px; }
  .app-nav { gap: 14px; font-size: 0.78rem; overflow-x: auto; }
}

/* ==========================================================================
   PAGE GROUND + CONTENT
   ========================================================================== */
.app-ground-pale { background: var(--sfr-pale); }
.app-ground-gray { background: var(--sfr-gray-ground); }

/* Document / reference apps — centered white sheet on the pale ground */
.app-sheet {
  max-width: var(--sfr-content-maxw);
  margin: 0 auto;
  background: var(--sfr-white);
  box-shadow: var(--sfr-sheet-shadow);
}

/* Dashboards — full-width content region with white panels/cards */
.app-shell { width: 100%; margin: 0 auto; padding: 24px 24px 64px; }
.app-panel,
.app-card {
  background: var(--sfr-white);
  border: 1px solid var(--sfr-line);
  border-radius: 20px; /* softer, website-faithful rounding */
  box-shadow: var(--sfr-shadow);
}

/* Honey uppercase EYEBROW above a navy headline — the website's signature
   section-header pattern (honey eyebrow → big navy VV Ruby title). */
.app-eyebrow {
  font-family: var(--sfr-font-display);
  text-transform: uppercase;
  font-weight: 800;
  font-size: 0.75rem; /* 12px caps floor */
  letter-spacing: 0.16em;
  color: var(--sfr-honey);
  display: block;
}

/* ==========================================================================
   HEADINGS — generous VV Ruby scale. The condensed display face reads small,
   so headings run LARGER and tracking looser than a normal sans would.
   ========================================================================== */
.app-h1, .app-h2, .app-h3, .app-h4 {
  font-family: var(--sfr-font-display);
  text-transform: uppercase;
  color: var(--sfr-navy);
  letter-spacing: 0.05em;
  line-height: 1.1;
  font-weight: 700;
  margin: 0;
}
.app-h1 { font-size: clamp(1.9rem, 3.4vw, 2.7rem); }
.app-h2 { font-size: clamp(1.45rem, 2.6vw, 1.95rem); }
.app-h3 { font-size: 1.3rem; letter-spacing: 0.055em; }
.app-h4 { font-size: 1.05rem; letter-spacing: 0.07em; }

/* ==========================================================================
   BUTTONS + CONTROLS
   ========================================================================== */
.app-btn {
  font-family: var(--sfr-font-display);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  font-weight: 800;
  font-size: 13px;
  border-radius: var(--sfr-radius-pill); /* website uses full-radius PILLS */
  padding: 11px 22px;
  border: 2px solid transparent;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  line-height: 1;
  transition: filter 0.12s, background 0.12s, color 0.12s;
}
.app-btn--primary   { background: var(--sfr-honey); color: var(--sfr-navy); border-color: var(--sfr-honey); }
.app-btn--primary:hover { filter: brightness(0.95); }
/* Secondary = OUTLINE pill: honey border, navy text (matches the site). */
.app-btn--secondary { background: var(--sfr-white); color: var(--sfr-navy); border-color: var(--sfr-honey); }
.app-btn--secondary:hover { background: var(--sfr-pale); }
.app-btn--ghost     { background: transparent; color: var(--sfr-navy); border-color: var(--sfr-line); }
.app-btn--ghost:hover { border-color: var(--sfr-navy); }

.app-pill {
  font-family: var(--sfr-font-display);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  font-weight: 700;
  font-size: 12px; /* 12px caps floor */
  padding: 5px 12px;
  border-radius: var(--sfr-radius-pill);
  border: 1px solid var(--sfr-navy);
  color: var(--sfr-navy);
  background: transparent;
  cursor: pointer;
}
.app-pill.is-active { background: var(--sfr-honey); border-color: var(--sfr-honey); color: var(--sfr-navy); }

.app-header a:focus-visible,
.app-btn:focus-visible,
.app-pill:focus-visible { outline: 3px solid var(--sfr-honey); outline-offset: 2px; }

/* ==========================================================================
   FOOTER — navy, centered wordmark + line (brand guide)
   ========================================================================== */
.app-footer {
  background: var(--sfr-navy);
  color: rgba(255, 255, 255, 0.8);
  text-align: center;
  padding: 40px 24px;
}
.app-footer__mark { height: 26px; width: auto; margin: 0 auto 14px; display: block; }
.app-footer__meta {
  font-size: 0.75rem; /* 12px caps floor */
  font-weight: 700;
  letter-spacing: 0.08em;
  color: rgba(255, 255, 255, 0.55);
}

@media (prefers-reduced-motion: reduce) {
  .app-nav a, .app-btn { transition: none; }
}

/* ==========================================================================
   BRAND GRAPHICS — use the GraphicKit art the way the website does: in
   NON-DATA zones only (loading, empty states, auth, whisper-light watermark).
   Assets live in this repo's assets/ (sfr-mascot.svg, sfr-anvil.svg,
   sfr-pattern.svg, sfr-badge.svg) — copy into each app's /public.
   ========================================================================== */

/* Loading — the running-mascot loader (Blake's /sfr-loading.gif) on a theme-
   stable CREAM "stage" so the navy line-art mascot stays legible in BOTH light
   and dark mode. The GIF takes over automatically once dropped in /public; the
   static mascot SVG is the fallback. Used for EVERY loading scenario. */
.app-loading { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 18px; padding: 64px 0; }
/* Route-level loader — fixed, full-viewport, centered on the SCREEN regardless of
   top/side layout (Blake, 2026-07-03: the mascot must be screen-centered, not
   shifted right by the sidebar). Inline loaders keep the base .app-loading. */
.app-loading--full { position: fixed; inset: 0; z-index: 30; min-height: 0; padding: 0; }
.app-loading__stage, .app-empty__stage, .app-error__stage {
  display: inline-flex; align-items: center; justify-content: center;
  background: transparent; border: 0; box-shadow: none; padding: 0;
}
.app-loading__stage img { height: 132px; width: auto; display: block; }
.app-loading .app-loading__label { font-family: var(--sfr-font-display); text-transform: uppercase; font-weight: 800; font-size: 0.75rem; letter-spacing: 0.16em; color: var(--sfr-honey); }
@keyframes sfr-run { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-7px); } }
.sfr-run { animation: sfr-run 0.9s ease-in-out infinite; }

/* Empty state — a kit graphic on the same cream stage + message, not dead space. */
.app-empty { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 16px; padding: 56px 24px; text-align: center; }
.app-empty__stage img { height: 128px; width: auto; display: block; }
.app-empty__title { font-family: var(--sfr-font-display); text-transform: uppercase; font-weight: 800; letter-spacing: 0.04em; color: var(--sfr-navy); font-size: 1.15rem; }
.app-empty__body { color: var(--sfr-navy); opacity: 0.72; max-width: 42ch; }

/* Error / 404 — the same cream mascot stage, a calm headline, and a honey action
   button. NEVER a raw stack trace (UI-SPEC States / Copywriting Contract). */
.app-error { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 16px; padding: 64px 24px; text-align: center; min-height: 62vh; }
.app-error__stage img { height: 128px; width: auto; display: block; }
.app-error__title { font-family: var(--sfr-font-display); text-transform: uppercase; font-weight: 800; letter-spacing: 0.03em; color: var(--sfr-navy); font-size: 1.4rem; }
.app-error__body { color: var(--sfr-navy); opacity: 0.72; max-width: 46ch; }
.app-error__actions { display: flex; gap: 10px; flex-wrap: wrap; justify-content: center; margin-top: 4px; }

/* mascot stage transparent in both themes */
.dark .app-empty__title, .dark .app-error__title { color: #eef1f5; }
.dark .app-empty__body, .dark .app-error__body { color: #c3ccd6; }

/* Watermark — whisper-light brand pattern/mascot behind content (never over data). */
.app-watermark { position: relative; }
.app-watermark::after {
  content: ""; position: absolute; right: 18px; bottom: 14px; width: 180px; height: 180px;
  background: no-repeat center / contain; opacity: 0.05; pointer-events: none;
}
.app-watermark--mascot::after { background-image: url("assets/sfr-mascot.svg"); }
.app-watermark--pattern::after { width: 100%; height: 100%; right: 0; bottom: 0; opacity: 0.035; background-image: url("assets/sfr-pattern.svg"); background-size: 420px; }

@media (prefers-reduced-motion: reduce) { .sfr-run { animation: none; } }

/* ==========================================================================
   DARK-MODE LEGIBILITY OVERRIDES — the robust way (use INSTEAD of a fragile
   per-element dark: sweep). Static hubs get this via importing sfr-app-core.css;
   Tailwind/Next apps copy this block into their own globals.css. Flips hardcoded
   content utilities in dark: navy/black text -> light, white panels -> dark,
   dark borders -> light. EXCEPTION: navy text on SOLID honey (pills) stays navy.
   ========================================================================== */
.dark .text-brand-navy { color: #e8eaed; }
.dark .text-brand-navy\/90 { color: rgba(232, 234, 237, 0.90); }
.dark .text-brand-navy\/80 { color: rgba(232, 234, 237, 0.80); }
.dark .text-brand-navy\/70 { color: rgba(232, 234, 237, 0.72); }
.dark .text-brand-navy\/60 { color: rgba(232, 234, 237, 0.64); }
.dark .text-brand-navy\/50 { color: rgba(232, 234, 237, 0.56); }
.dark .text-brand-navy\/40 { color: rgba(232, 234, 237, 0.50); }
.dark .text-brand-navy\/30 { color: rgba(232, 234, 237, 0.42); }
.dark .text-brand-navy\/20 { color: rgba(232, 234, 237, 0.34); }
.dark .text-brand-black { color: #e8eaed; }
.dark .text-brand-black\/70 { color: rgba(232, 234, 237, 0.72); }
.dark .text-brand-black\/60 { color: rgba(232, 234, 237, 0.64); }
.dark .text-brand-black\/50 { color: rgba(232, 234, 237, 0.56); }
.dark .bg-white, .dark .bg-brand-white { background-color: #141c28; }
.dark .border-brand-navy\/5, .dark .border-brand-navy\/10, .dark .border-brand-navy\/15, .dark .border-brand-navy\/20,
.dark .border-brand-black\/5, .dark .border-brand-black\/10, .dark .border-brand-black\/15, .dark .border-brand-black\/20 { border-color: rgba(255, 255, 255, 0.12); }
.dark .bg-brand-honey.text-brand-navy { color: var(--color-brand-navy); }

/* Pale-yellow used as a CONTENT highlight fill -> dark tint in dark mode; the
   page <main> ground stays the dark ground (forced, beats this override). Add
   this alongside the dark-legibility overrides above. */
.dark .bg-brand-pale-yellow,
.dark .bg-brand-pale-yellow\/40,
.dark .bg-brand-pale-yellow\/30,
.dark .bg-brand-pale-yellow\/25,
.dark .bg-brand-pale-yellow\/20 { background-color: rgba(255, 255, 255, 0.05); }
.dark main { background-color: #0e141d !important; }

/* ==========================================================================
   UNIFIED CHROME v1 (2026-07-03) — the flex-bar header the shared <AppChrome>
   component renders, its honey uppercase TEXT-link nav, the right-side tools
   cluster (layout + theme toggles + user), and the top↔side layout morph. This
   is THE chrome every app consumes via @sfr/app-chrome. (The
   .app-header__inner/__brand/__right block far above is the LEGACY static-hub
   structure — migrate hubs onto this.) Fonts resolve through --sfr-font-display
   / --sfr-font-body (set them from your next/font vars for hashed faces; else
   they fall back to VV Ruby / Figtree from :root).
   ========================================================================== */
.app-header {
  display: flex; align-items: center; gap: 18px; flex-wrap: wrap;
  min-height: 56px; padding: 0 24px;
}
.app-brand { display: flex; align-items: center; gap: 14px; text-decoration: none; color: inherit; flex-shrink: 0; }
/* .app-wordmark (30px) + .app-label (white, divider) are defined above. */
.app-nav { display: flex; align-items: center; gap: 2px; margin-right: auto; flex-wrap: wrap; }
.app-nav__link {
  font-family: var(--sfr-font-display); text-transform: uppercase; letter-spacing: 0.06em;
  font-weight: 700; font-size: 0.82rem; color: rgba(255, 255, 255, 0.82);
  background: transparent; border: 0; cursor: pointer; padding: 8px 12px;
  border-radius: 8px; text-decoration: none; line-height: 1;
  display: inline-flex; align-items: center; gap: 4px; transition: color 0.15s, background 0.15s;
}
.app-nav__link:hover { color: var(--sfr-honey); background: rgba(255, 255, 255, 0.06); }
.app-nav__link.active { color: var(--sfr-honey); background: transparent; }
.app-aux { display: flex; align-items: center; gap: 12px; }
.app-tools { display: flex; align-items: center; gap: 6px; flex-shrink: 0; }
/* Mobile hamburger — hidden on desktop; the @media (max-width:767px) block below
   reveals it and turns .app-nav into a drawer. First child of .app-tools. */
.app-hamburger {
  display: none; align-items: center; justify-content: center;
  width: 36px; height: 36px; border: 0; background: transparent;
  color: var(--sfr-white); border-radius: 8px; cursor: pointer; flex-shrink: 0;
}
.app-hamburger:hover { background: rgba(255, 255, 255, 0.08); color: var(--sfr-honey); }
.themebtn, .layoutbtn {
  width: 32px; height: 32px; display: inline-flex; align-items: center; justify-content: center;
  border-radius: 7px; background: transparent; border: 0; color: rgba(255, 255, 255, 0.8); cursor: pointer;
}
.themebtn:hover, .layoutbtn:hover { background: rgba(255, 255, 255, 0.1); color: var(--sfr-honey); }
.layoutbtn { display: none; }             /* desktop-only */
@media (min-width: 768px) { .layoutbtn { display: inline-flex; } }

/* Top ↔ side morph (desktop): the whole header becomes a fixed left sidebar and
   the content shifts right. Put the app's content root under .app-body (or apply
   the padding on your own wrapper). Mobile always keeps the top bar. */
@media (min-width: 768px) {
  .layout-side .app-header {
    position: fixed; left: 0; top: 0; height: 100vh; width: 244px;
    flex-direction: column; align-items: stretch; flex-wrap: nowrap;
    justify-content: flex-start; gap: 18px; padding: 20px 16px; overflow-y: auto; z-index: 60;
  }
  .layout-side .app-brand { flex-direction: column; align-items: center; text-align: center; gap: 10px; }
  .layout-side .app-label { border-left: 0; padding-left: 0; }
  .layout-side .app-nav { flex-direction: column; align-items: stretch; width: 100%; margin-right: 0; gap: 4px; }
  .layout-side .app-nav__link { width: 100%; justify-content: flex-start; }
  .layout-side .app-aux { flex-direction: column; align-items: stretch; width: 100%; gap: 8px; }
  .layout-side .app-tools { margin-top: auto; width: 100%; }
  .layout-side .app-body { padding-left: 244px; }
}

/* Screen-reader-only (used by <LoadingMascot> for role=status). */
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}

/* ==========================================================================
   CHARTS IN DARK MODE — a MANDATORY rule (added 2026-07-03 after scorecard
   /trends rendered charts invisible in dark). SVG uses `fill`/`stroke`, NOT CSS
   `color`, so the HTML dark-legibility overrides can't reach chart ink. Recharts
   hardcodes navy axis text + navy data lines + faint black axes → all vanish on
   the dark ground. Any app that renders charts MUST ship these dark overrides
   (they're inert when there's no chart). Flip: light text, visible lines,
   softened axes/grid. Status-colored dots keep their own inline fills — leave
   dots alone. (Better still: theme chart colors via a CSS var; until then, this.)
   ========================================================================== */
.dark svg text,
.dark .recharts-text { fill: #c3ccd6; }
.dark .recharts-curve.recharts-line-curve { stroke: #cdd6e2; }
.dark .recharts-cartesian-axis-line,
.dark .recharts-cartesian-axis-tick line { stroke: rgba(255, 255, 255, 0.18); }
.dark .recharts-cartesian-grid line { stroke: rgba(255, 255, 255, 0.10); }
.dark .recharts-reference-line line { stroke: rgba(255, 255, 255, 0.24); }

/* Charts — let axis tick labels render into the card padding instead of being
   clipped by the SVG/container box (fixes cut-off week + y-axis labels, scorecard
   /trends 2026-07-03). Pair with adequate chart margins (bottom/left ≥ 4). */
.recharts-wrapper, .recharts-surface { overflow: visible; }

/* ==========================================================================
   COLLAPSE THE MENU (nav-collapsed) — reclaim screen space (Blake, 2026-07-03:
   a collapse option on every menu/page). Top bar → hide the nav links. Sidebar →
   slide the whole sidebar away + reclaim the width; a fixed reopen button (PORTAL
   it to <body> — the sidebar transform is a containing block for fixed children)
   brings it back. Desktop-only, like the layout selector.
   ========================================================================== */
.collapsebtn { width: 32px; height: 32px; display: none; align-items: center; justify-content: center; border-radius: 7px; background: transparent; border: 0; color: rgba(255, 255, 255, 0.8); cursor: pointer; }
.collapsebtn:hover { background: rgba(255, 255, 255, 0.1); color: var(--sfr-honey); }
@media (min-width: 768px) { .collapsebtn { display: inline-flex; } }
.app-header { transition: transform 0.2s ease; }
.menu-reopen{position:fixed;left:0;top:0;z-index:45;display:none;align-items:flex-start;justify-content:center;padding-top:14px;width:44px;height:100vh;background:var(--sfr-navy);color:#fff;border:0;cursor:pointer}
.menu-reopen:hover { background: #2a3a52; }
.nav-collapsed:not(.layout-side) .app-nav { display: none; }
@media (min-width: 768px) {
  .layout-side.nav-collapsed .app-header { transform: translateX(-102%); }
  .layout-side.nav-collapsed .app-body { padding-left: 44px; }
  .layout-side.nav-collapsed .menu-reopen { display: inline-flex; }
}

/* ==========================================================================
   MOBILE HAMBURGER DRAWER (2026-07-07) — below 768px the inline nav collapses
   behind a hamburger (first child of .app-tools). Tapping it toggles `nav-open`
   on the header, which drops the nav as a full-width drawer under the bar. This
   block sits LAST so it overrides the legacy @media (max-width:760px) overflow-x
   rule on .app-nav (and the .nav-collapsed .app-nav display:none). Desktop
   (≥768px) is untouched — the hamburger stays display:none and the nav stays
   inline. ADAPTED from the canonical sfr-app-chrome drawer: this hub's nav is
   FLAT (no .app-nav__group / .app-nav__menu dropdowns), so those drawer
   selectors are omitted — only .app-nav and .app-nav__link exist here.
   ========================================================================== */
@media (max-width: 767px) {
  .app-header { position: relative; }
  .app-hamburger { display: inline-flex; }
  /* Nav becomes a hidden drawer anchored under the header bar. */
  .app-nav {
    display: none; position: absolute; top: 100%; left: 0; right: 0;
    flex-direction: column; align-items: stretch; gap: 2px; margin: 0;
    background: var(--sfr-navy); padding: 10px 12px 14px;
    box-shadow: 0 10px 26px rgba(0, 0, 0, 0.32);
    border-top: 1px solid rgba(255, 255, 255, 0.12);
    max-height: 76vh; overflow-x: hidden; overflow-y: auto; z-index: 55;
  }
  .nav-open .app-nav, .app-header.nav-open .app-nav { display: flex; }
  /* Full-width tap targets. */
  .app-nav__link { width: 100%; justify-content: flex-start; padding: 12px; }
}

/* ==========================================================================
   ACCORDION + WORKFLOW STEPPER — the collapse standard (2026-07-10, Blake).
   Prefer this over card carousels for reference lists AND step-by-step work.
     .app-acc                      reference accordion: independent sections,
                                    all collapsed, click a head to open/close.
     .app-acc.app-acc--stepper     workflow: only the active step is open; the
                                    "mark complete" CTA checks + collapses it and
                                    auto-opens the next; later steps are locked;
                                    a progress bar + resume (localStorage) track it.
   Behavior auto-wires from sfr-chrome.js (also window.SFRAcc.init() after any
   dynamic render). Markup contract — see README "Accordion / Workflow Stepper":
     <div class="app-acc[ app-acc--stepper]" [data-app-workflow="unique-id"]>
       <div class="app-acc__done">…all-steps-complete banner (stepper only)…</div>
       <div class="app-acc__progress"><span class="app-acc__bar"><span></span></span>
            <span class="app-acc__count"></span></div>          (stepper only)
       <div class="app-acc__item">
         <button class="app-acc__head" type="button">
           <span class="app-acc__marker">1</span>
           <span class="app-acc__title">Step title</span>
           <span class="app-acc__status">Step 1</span>
           <span class="app-acc__chevron" aria-hidden="true"></span>
         </button>
         <div class="app-acc__panelwrap"><div class="app-acc__panel">
           <div class="app-acc__body"> …content…
             <div class="app-acc__cta">
               <button class="app-btn app-btn--primary" type="button" data-app-acc-complete>Mark step complete</button>
             </div>
           </div>
         </div></div>
       </div>
     </div>
   ========================================================================== */
.app-acc { display: flex; flex-direction: column; gap: 10px; }
.app-acc__item {
  border: 1px solid var(--sfr-navy-line);
  border-radius: var(--sfr-radius);
  background: var(--sfr-white);
  overflow: hidden;
}
.app-acc__item.is-open { border-color: var(--sfr-honey); }
.app-acc__head {
  display: flex; align-items: center; gap: 12px; width: 100%;
  text-align: left; cursor: pointer; background: none; border: 0;
  padding: 14px 16px; font-family: var(--sfr-font-body); color: var(--sfr-navy);
}
.app-acc__head:hover { background: var(--sfr-pale); }
.app-acc__head:disabled { cursor: not-allowed; opacity: 0.55; }
.app-acc__head:focus-visible { outline: 3px solid var(--sfr-honey); outline-offset: -2px; }
.app-acc__marker {
  flex: none; width: 24px; height: 24px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-family: var(--sfr-font-display); font-weight: 700; font-size: 0.75rem;
  background: var(--sfr-gray-ground); color: var(--sfr-navy-600);
  border: 1.5px solid var(--sfr-navy-line);
}
.app-acc__item.is-open .app-acc__marker,
.app-acc__item.is-done .app-acc__marker {
  background: var(--sfr-honey); color: var(--sfr-navy); border-color: var(--sfr-honey);
}
.app-acc__title {
  flex: 1; min-width: 0;
  font-family: var(--sfr-font-display); text-transform: uppercase; letter-spacing: 0.02em;
  font-size: 0.9375rem; font-weight: 600; line-height: 1.3; color: var(--sfr-navy);
}
.app-acc__status {
  flex: none; white-space: nowrap;
  font-family: var(--sfr-font-display); font-size: 0.6875rem; font-weight: 700;
  letter-spacing: 0.06em; text-transform: uppercase; color: var(--sfr-navy-600);
}
.app-acc__chevron {
  flex: none; width: 16px; height: 16px; transition: transform 0.22s ease;
  color: var(--sfr-navy-600);
  background: no-repeat center / 12px url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%2334465f' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
}
.app-acc__item.is-open .app-acc__chevron { transform: rotate(180deg); }
.app-acc__panelwrap { display: grid; grid-template-rows: 0fr; transition: grid-template-rows 0.24s ease; }
.app-acc__item.is-open .app-acc__panelwrap { grid-template-rows: 1fr; }
.app-acc__panel { overflow: hidden; }
.app-acc__body {
  padding: 2px 16px 16px 52px;
  font-family: var(--sfr-font-body); font-size: 0.84375rem; color: var(--sfr-navy); line-height: 1.6;
}
.app-acc__cta { margin-top: 14px; display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.app-acc__hint { font-family: var(--sfr-font-body); font-size: 0.75rem; color: var(--sfr-navy-600); }
/* stepper progress + completion banner */
.app-acc__progress { display: flex; align-items: center; gap: 12px; margin: 0 0 14px; }
.app-acc__bar { flex: 1; height: 7px; border-radius: var(--sfr-radius-pill); background: var(--sfr-gray-ground); overflow: hidden; }
.app-acc__bar > span { display: block; height: 100%; width: 0; background: var(--sfr-honey); transition: width 0.3s ease; }
.app-acc__count { flex: none; white-space: nowrap; font-family: var(--sfr-font-display); font-size: 0.6875rem; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; color: var(--sfr-navy-600); }
.app-acc__done { display: none; align-items: center; gap: 10px; background: var(--sfr-pale); border: 1px solid var(--sfr-honey); border-radius: var(--sfr-radius); padding: 12px 16px; margin-bottom: 14px; font-family: var(--sfr-font-body); font-size: 0.84375rem; color: var(--sfr-navy); }
.app-acc.is-complete .app-acc__done { display: flex; }
/* dark-mode coverage (chrome content sits on the #0e141d ground) */
.dark .app-acc__item { background: #141c28; border-color: rgba(255, 255, 255, 0.10); }
.dark .app-acc__item.is-open { border-color: var(--sfr-honey); }
.dark .app-acc__head { color: #e8eaed; }
.dark .app-acc__head:hover { background: rgba(255, 255, 255, 0.05); }
.dark .app-acc__marker { background: #0e141d; color: #c3ccd6; border-color: rgba(255, 255, 255, 0.18); }
.dark .app-acc__item.is-open .app-acc__marker,
.dark .app-acc__item.is-done .app-acc__marker { background: var(--sfr-honey); color: var(--sfr-navy); border-color: var(--sfr-honey); }
.dark .app-acc__title { color: #e8eaed; }
.dark .app-acc__status { color: #c3ccd6; }
.dark .app-acc__chevron { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23c3ccd6' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E"); }
.dark .app-acc__body { color: #c3ccd6; }
.dark .app-acc__hint { color: #c3ccd6; }
.dark .app-acc__bar { background: rgba(255, 255, 255, 0.08); }
.dark .app-acc__count { color: #c3ccd6; }
.dark .app-acc__done { background: rgba(255, 255, 255, 0.05); border-color: var(--sfr-honey); color: #e8eaed; }
@media (prefers-reduced-motion: reduce) {
  .app-acc__panelwrap, .app-acc__chevron, .app-acc__bar > span { transition: none; }
}


/* PM/warranty pages have no <main>, so flip the app-ground-pale BODY in dark mode
   (chrome content + accordions are dark-aware; without this the ground stays pale). */
.dark .app-ground-pale { background-color: #0e141d; }
