/* Shared app shell (UI audit B1, 2026-07-19).
 *
 * The bug: every page defined its own content container at a different
 * max-width (dashboard 1040, coverage 980, catalog/valuation/sources 1280,
 * archive 1100, settings 760...), all centered - so the content's left
 * edge, the H1, and the nav logo landed at a different x on every page.
 * Clicking between pages made the whole layout jump.
 *
 * The fix: ONE container width and ONE horizontal padding, shared by every
 * app page and by the nav's inner row (assets/nav.js centers to the same
 * --maxw with the same padding). Result: logo, nav items, and content
 * column are pixel-identical page to page. Loaded LAST on every app page;
 * the !important on exactly the four layout properties guarantees it wins
 * over each page's own inline container rule without editing 13 stylesheets.
 *
 * ACCEPTANCE: getBoundingClientRect of the logo, first nav item, and the
 * content container are identical across all app pages.
 */
/* ── DESIGN TOKENS (audit Phase 3 step 1, 2026-07-17) ─────────────────────
 * ONE palette + type + shape system for every app page. shell.css loads LAST
 * in every <head>, and each declaration carries !important, so these values
 * beat every page-local :root block by cascade order - the three drifted
 * palettes (sage/green/lime "good", three warns, three blues) collapse to one
 * without editing any page. Legacy alias names (--dim/--mute/--mono/--sans/
 * --blue) are pinned to the same canonical values so older pages resolve
 * identically. Values come from the dashboard's ratified treatment: the
 * flagship page does not change; the others converge on it.
 *
 * Money-truth colors are semantic law, not decoration:
 *   --fact  ice       = statement-backed figures
 *   --est   champagne = estimated figures (the ONLY warn family)
 *   --good  sage      = collecting / positive state
 */
:root {
  --maxw: 1200px !important;

  /* surfaces */
  --bg: #000000 !important;
  --bg-2: #0A0A0A !important;
  --card: #121212 !important;
  --line: rgba(255, 255, 255, 0.10) !important;
  --line-strong: rgba(255, 255, 255, 0.22) !important;

  /* text (contrast-fixed: #555 failed WCAG at 2.5:1, #888 was borderline) */
  --white: #FFFFFF !important;
  --text: #DDDDDD !important;      /* 13.8:1 on card */
  --text-dim: #999999 !important;  /*  6.6:1 on card (was #888) */
  --text-mute: #8A8A8A !important; /*  5.4:1 on card (was #555 = 2.5:1 FAIL) */
  --dim: #999999 !important;       /* legacy alias */
  --mute: #8A8A8A !important;      /* legacy alias */

  /* semantics */
  --fact: #A9C7E8 !important;
  --est: #D9B87A !important;
  --warn: #D9B87A !important;      /* single warn family = champagne */
  --good: #8FC7A0 !important;
  --bad: #FF6B6B !important;
  --link: #A9C7E8 !important;
  --blue: #A9C7E8 !important;      /* legacy alias: kills the ad-hoc #4A9EFF */

  /* type — new-UI reskin Phase-0 ruling ③ (2026-07-22): the kit's real look is
   * Helvetica-class display + body; a TRUE mono (Overpass Mono) carries every
   * figure/label/eyebrow ("certainty is a column"); Spectral italic for accents.
   * (Prior display face was Archivo Black; the kit renders Helvetica Neue.)
   * Fallback chains stay safe on pages that load no webfonts. */
  --ff-display: 'Helvetica Neue', Helvetica, Arial, sans-serif !important;
  --ff-body: 'Helvetica Neue', Helvetica, Arial, -apple-system, sans-serif !important;
  /* 2026-07-22 (Joe, dashboard gate): the kit's "mono" is NOT a monospace —
   * every kit label/figure is Helvetica. Overpass Mono was the OLD UI's
   * signature voice; keeping it (Phase-0 (3) default) is what made every
   * ported page still read as the old UI. Flipped to the kit's real stack;
   * numeric slots keep alignment via font-variant-numeric (below). */
  --ff-mono: 'Helvetica Neue', Helvetica, Arial, sans-serif !important;
  --ff-accent: 'Spectral', Georgia, serif !important;
  --mono: 'Helvetica Neue', Helvetica, Arial, sans-serif !important; /* legacy alias */
  --sans: 'Helvetica Neue', Helvetica, Arial, -apple-system, sans-serif !important; /* legacy alias */

  /* shape + elevation (consumed as later steps normalize components) */
  --pad: clamp(20px, 4vw, 44px) !important;
  --r-card: 12px;
  --r-control: 8px;
  --r-stamp: 3px;
  --shadow-raised: 0 14px 34px rgba(0, 0, 0, 0.55);

  /* type scale (audit A3): one ladder, no accidental half-pixels.
   * 10 is reserved for mono numerals in dense tables; 11 is the label floor. */
  --fs-10: 10px;   /* mono numerals only */
  --fs-11: 11px;   /* labels, eyebrows, pills */
  --fs-12: 12px;   /* secondary UI, subtitles */
  --fs-13: 13px;   /* body-small */
  --fs-14: 14px;   /* body */
  --fs-16: 16px;   /* lead */
  --fs-20: 20px;
  --fs-26: 26px;
  --fs-34: 34px;   /* page title (see .page-title) */
  --lh-tight: 1.03;  /* display */
  --lh-ui: 1.4;      /* labels, single lines */
  --lh-prose: 1.6;   /* paragraphs */

  /* ── new-UI reskin tokens (Phase 1, 2026-07-22) ─────────────────────
   * Extracted from the kit exports; additive, no change to existing pages
   * until each page's markup is ported. One owner for each value that
   * drifted per-page in the kit (audit S11). */
  --rail-w: 236px;                 /* left app rail (kit: grid col 1) */
  --rail-header-h: 60px;           /* top bar height */
  --bp-rail: 1080px;               /* below this the rail collapses (audit L3) */
  --attention: #FFB347;            /* attention-orange: bell dot, "needs you"
                                    * — DISTINCT from --est champagne so it never
                                    * reads as an estimate marker (audit S11/C10) */
  --select-bg: #2a2a30;            /* one canonical ::selection (audit S11/C3) */
  --select-fg: #FFFFFF;
  --maxw-wide: 1280px;             /* dashboard may run wide; app default = --maxw */
}

/* Canonical text selection — one color site-wide (audit S11/C3). */
::selection { background: var(--select-bg); color: var(--select-fg); }

/* ── Button system (audit S12: collapse ~13 drifted button classes into one).
 * Casing law ④: app action + form-save buttons are UPPERCASE letter-spaced
 * mono. Additive — existing pages keep their inline buttons until each is
 * ported to `.btn`, so this changes nothing on render yet. ≥44px hit target
 * (audit L4). */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  font-family: var(--ff-mono);
  font-size: var(--fs-12);
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  line-height: 1;
  padding: 12px 18px;            /* + line-box ≈ 44px min hit height */
  min-height: 40px;
  border-radius: var(--r-control);
  border: 1px solid transparent;
  cursor: pointer;
  text-decoration: none;
  transition: background .15s, border-color .15s, color .15s, opacity .15s;
  -webkit-appearance: none; appearance: none;
}
.btn:focus-visible { outline: 2px solid var(--est); outline-offset: 2px; }
.btn:disabled, .btn[aria-disabled="true"] { opacity: .45; cursor: not-allowed; }
.btn.primary   { background: var(--white); color: #000; border-color: var(--white); }
.btn.primary:hover   { background: #e6e6e6; border-color: #e6e6e6; }
.btn.secondary { background: transparent; color: var(--white); border-color: var(--line-strong); }
.btn.secondary:hover { border-color: var(--white); background: rgba(255,255,255,0.04); }
.btn.ghost     { background: transparent; color: var(--text-dim); border-color: transparent; padding-left: 8px; padding-right: 8px; }
.btn.ghost:hover     { color: var(--white); }
@media (prefers-reduced-motion: reduce) { .btn { transition: none; } }

/* ── PROVENANCE STAMPS (shared; mirrors the dashboard's ratified .stamp) ──
 * The money-truth marks. FACT (ice) = statement-backed. EST. (champagne) =
 * estimated. GOOD (sage) = collecting/positive. The document-ingestion tiers
 * are siblings of the same law:
 *   .stamp.doc      "FROM YOUR CONTRACT"  (ice - document-cited, checkable)
 *   .stamp.derived  "DERIVED"             (sage - computed from your docs)
 *   .stamp.default  "DEFAULT"             (champagne - an assumption; every
 *                    DEFAULT figure must advertise its own replacement path)
 * Keep the machine tier word (DOCUMENT-SOURCED / DERIVED / DEFAULTED) in a
 * title attr for traceability; the stamp face is user language. */
.stamp {
  display: inline-block;
  font-family: var(--ff-mono);
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  padding: 2px 7px;
  border: 1px solid;
  border-radius: 3px;
  vertical-align: middle;
}
.stamp.fact,
.stamp.doc { color: var(--fact); border-color: rgba(169, 199, 232, 0.55); }
.stamp.est,
.stamp.default { color: var(--est); border-color: rgba(217, 184, 122, 0.55); }
.stamp.good,
.stamp.derived { color: var(--good); border-color: rgba(143, 199, 160, 0.55); }

/* Prose helper (audit A4): explanatory PARAGRAPHS read in the body face at a
 * readable size/measure, never small monospace. Opt-in class; adopted where
 * paragraph copy currently sits in cramped mono (valuation copy lands in
 * step 5). Mono stays the right choice for numbers, labels, and identifiers. */
.prose {
  font-family: var(--ff-body) !important;
  font-size: var(--fs-14) !important;
  line-height: var(--lh-prose) !important;
  color: var(--text-dim) !important;
  max-width: 68ch;
}

/* --blue is now ice (light). Coverage's .cta hover used it as a fill under
 * white text, which would be illegible on a light fill - keep the button's
 * resting text color (black on light fill) through the hover. */
.cta:hover { color: #000 !important; }

/* ── CANONICAL PAGE HEADER (audit F1, Phase 3 step 2) ─────────────────────
 * ONE title treatment for every section page, so navigating no longer jumps
 * between the 26/28/30/32/44/48px hand-built headers the audit found. Three
 * classes: .page-eyebrow (optional) / .page-title / .page-sub. !important on
 * the type props so a page's own higher-specificity rule (e.g. .page-header
 * h1) can't win. Dashboard keeps its greeting hero (it is the home, not a
 * section title); case.html keeps its print-document header. */
.page-eyebrow {
  font-family: var(--ff-mono) !important;
  font-size: 11px !important;
  font-weight: 400 !important;
  letter-spacing: 0.14em !important;
  text-transform: uppercase !important;
  color: var(--text-mute) !important;
  margin: 0 0 8px 0 !important;
}
.page-title {
  /* 2026-07-22 ratified (Fable checkpoint + Joe): ONE editorial header app-wide.
   * Promoted from the ported pages' .page-h1; weight 800 is the kit face. */
  font-family: var(--ff-display) !important;
  font-size: clamp(34px, 4.4vw, 46px) !important;
  font-weight: 800 !important;
  color: var(--white) !important;
  line-height: 1.03 !important;
  letter-spacing: -0.02em !important;
  margin: 0 0 10px 0 !important;
}
.page-sub {
  font-family: var(--ff-mono) !important;
  font-size: 12px !important;
  color: var(--text-dim) !important;
  line-height: 1.55 !important;
  max-width: 68ch !important;
  margin: 0 0 32px 0 !important;
}
/* catalog/sources/instructions nested title+sub in .page-header (mb:32);
 * .page-sub now owns that bottom gap, so zero the wrapper's to avoid 64px. */
.page-header { margin-bottom: 0 !important; }

/* Kit numerals: tabular lining figures wherever money/counts render, so the
 * Helvetica flip never breaks column alignment (kit .num does exactly this). */
table, td, th, [class*="amt"], [class*="num"], [class*="total"], [class*="statnum"],
[class*="band-v"], [class*="range"], [class*="rev-"], [id^="t-"] {
  font-variant-numeric: tabular-nums lining-nums;
}

html { scrollbar-gutter: stable; }               /* B2: no scrollbar shift */

/* ── ACCESSIBILITY (audit E, Phase 3 step 7) ─────────────────────────────
 * One keyboard-focus indicator for every app page (was on the dashboard
 * only). Champagne 2px ring at a 2px offset - 3:1+ against black and against
 * the white primary buttons, distinct from every hover state. :focus-visible
 * so it shows for keyboard/AT users without ringing on mouse click. */
:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
  outline: 2px solid var(--est);
  outline-offset: 2px;
  border-radius: 3px;
}
/* Target size (WCAG 2.2 SC 2.5.8): the brand wordmark is a 13px-tall image;
 * pad its link so the tap area clears 24px without resizing the logo. */
#sr-shared-nav a[aria-label="StreamRev dashboard"] { padding-block: 6px; }

/* The shared nav is a <body> child, so ANY body padding insets the whole
 * sticky bar and drops it below a top gap - and every page set a different
 * body padding (24px / 20px 32px / 12px 0 / none), so the bar frame + its
 * top position jumped page to page even though the centered content did not.
 * Zero it here; the shell container below owns every inset now, so the nav is
 * flush + full-bleed and the content column is identical on every page. */
body { margin: 0 !important; padding: 0 !important; }

/* B4/B7: pin the shared nav's line boxes to a fixed height so the bar is the
 * SAME height on every page whether or not the webfont has swapped in yet.
 * Default line-height:normal is font-metric dependent, which made the bar
 * 39px before the webfont loaded and 41.5px after - a cross-page drift AND a
 * layout shift on every page. A fixed line-height removes both. (The alerts
 * badge keeps its own inline line-height:14px - inline wins, no !important.) */
#sr-shared-nav a,
#sr-shared-nav button { line-height: 20px; }

/* The two container patterns in the app: .wrap (most pages) and <main>
 * (catalog, sources, instructions use <main class="wrap"> - one element,
 * both classes, so no double-constraint). Both unified. */
.wrap,
main {
  max-width: var(--maxw) !important;
  margin-inline: auto !important;
  padding-inline: clamp(20px, 4vw, 44px) !important;
  padding-block: 26px 64px !important;   /* uniform gap below the nav + scroll room, every page */
  width: 100% !important;
  box-sizing: border-box !important;
}

/* ── B5/B6 shared skeletons ────────────────────────────────────────────
 * ONE skeleton primitive for every app page, so a loading slot on the
 * dashboard looks identical to one on Coverage. Replaces the literal
 * "Loading..." text the audit flagged (B6). Give each instance an explicit
 * width/height matched to the content it stands in for so nothing reflows
 * when the real value arrives (B4: reserved space -> CLS ~ 0). */
.sr-skel {
  display: inline-block;
  border-radius: 6px;
  background: linear-gradient(
    100deg,
    rgba(255, 255, 255, 0.05) 30%,
    rgba(255, 255, 255, 0.11) 50%,
    rgba(255, 255, 255, 0.05) 70%
  );
  background-size: 220% 100%;
  animation: sr-skel-sheen 1.25s ease-in-out infinite;
  vertical-align: middle;
}
.sr-skel--line { height: 0.72em; width: 8em; border-radius: 4px; }
@keyframes sr-skel-sheen {
  0%   { background-position: 180% 0; }
  100% { background-position: -60% 0; }
}
@media (prefers-reduced-motion: reduce) {
  .sr-skel { animation: none; }
}
