/* Arrow Disability Appeals — navy/gold/bone, from the 2026-08-27 design system.
   Navy 900 hero as the default (dark) ground; bone/warm-grey companion for light. */
:root {
  /* Arrow Disability Appeals — palette sampled directly from the design-system
     PDF, not matched by eye. Navy 900 is the hero field, Navy 800 the closing
     band one step lighter, gold the single accent, bone and warm grey the two
     light grounds. */
  --bg: #081C2F; --bg2: #0B2438; --surface: #0F2D4A; --surface2: #143756;
  --border: rgba(201,165,106,.20); --border-strong: rgba(201,165,106,.36);
  --ink: #F7F5F1; --muted: #93A3B4;
  --gold: #C9A56A; --gold-ink: #081C2F;
  --emerald: #4FB89A; --emerald-ink: #052A22;
  --danger: #E8736B; --amber: #D9A441;
  --glass: rgba(15,45,74,.76); --shadow: 0 14px 34px rgba(0,0,0,.48);
  --series-eaja: #C9A56A; --series-406b: #4FB89A; --series-expense: #E8736B; --series-contrib: #8E9BE0;
  --tile-blue-bg: #143756; --tile-blue-border: #2F5F8C; --tile-pink-bg: #3A2436; --tile-pink-border: #8A5570;
  --radius: 14px; --serif: "Playfair Display", Georgia, "Iowan Old Style", "Times New Roman", serif;
  --sans: Montserrat, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  --mono: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
}
@media (prefers-color-scheme: light) {
  :root {
  /* Light companion: bone ground, white cards, warm grey for the alternating
     band. Gold is DARKENED here — #C9A56A on bone is about 2:1, nowhere near
     readable as text, so the accent token carries a deeper value in light mode
     while the charts keep the true brand gold on their own fills. */
  --bg: #F7F5F1; --bg2: #EFEBE2; --surface: #FFFFFF; --surface2: #F7F5F1;
  --border: #E3DED3; --border-strong: #CFC7B6;
  --ink: #0F2D4A; --muted: #6F6A5E;
  --gold: #8A6A2A; --gold-ink: #FFFFFF;
  --emerald: #16785E; --emerald-ink: #FFFFFF;
  --danger: #B8402F; --amber: #8A6118;
  --glass: rgba(255,255,255,.86); --shadow: 0 10px 26px rgba(15,45,74,.10);
  --series-eaja: #B08A3E; --series-406b: #16785E; --series-expense: #C24A38; --series-contrib: #5B54A8;
  --tile-blue-bg: #EAF0F7; --tile-blue-border: #BCD0E4; --tile-pink-bg: #F9EEF2; --tile-pink-border: #E4BFCE;
  }
}
:root[data-theme="dark"] {
  /* Arrow Disability Appeals — palette sampled directly from the design-system
     PDF, not matched by eye. Navy 900 is the hero field, Navy 800 the closing
     band one step lighter, gold the single accent, bone and warm grey the two
     light grounds. */
  --bg: #081C2F; --bg2: #0B2438; --surface: #0F2D4A; --surface2: #143756;
  --border: rgba(201,165,106,.20); --border-strong: rgba(201,165,106,.36);
  --ink: #F7F5F1; --muted: #93A3B4;
  --gold: #C9A56A; --gold-ink: #081C2F;
  --emerald: #4FB89A; --emerald-ink: #052A22;
  --danger: #E8736B; --amber: #D9A441;
  --glass: rgba(15,45,74,.76); --shadow: 0 14px 34px rgba(0,0,0,.48);
  --series-eaja: #C9A56A; --series-406b: #4FB89A; --series-expense: #E8736B; --series-contrib: #8E9BE0;
  --tile-blue-bg: #143756; --tile-blue-border: #2F5F8C; --tile-pink-bg: #3A2436; --tile-pink-border: #8A5570;
}
:root[data-theme="light"] {
  /* Light companion: bone ground, white cards, warm grey for the alternating
     band. Gold is DARKENED here — #C9A56A on bone is about 2:1, nowhere near
     readable as text, so the accent token carries a deeper value in light mode
     while the charts keep the true brand gold on their own fills. */
  --bg: #F7F5F1; --bg2: #EFEBE2; --surface: #FFFFFF; --surface2: #F7F5F1;
  --border: #E3DED3; --border-strong: #CFC7B6;
  --ink: #0F2D4A; --muted: #6F6A5E;
  --gold: #8A6A2A; --gold-ink: #FFFFFF;
  --emerald: #16785E; --emerald-ink: #FFFFFF;
  --danger: #B8402F; --amber: #8A6118;
  --glass: rgba(255,255,255,.86); --shadow: 0 10px 26px rgba(15,45,74,.10);
  --series-eaja: #B08A3E; --series-406b: #16785E; --series-expense: #C24A38; --series-contrib: #5B54A8;
  --tile-blue-bg: #EAF0F7; --tile-blue-border: #BCD0E4; --tile-pink-bg: #F9EEF2; --tile-pink-border: #E4BFCE;
}

* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }
html, body { height: 100%; }
body {
  margin: 0; background: var(--bg); color: var(--ink); font-family: var(--sans);
  font-size: 15px; overflow: hidden; -webkit-text-size-adjust: 100%;
}
a { color: var(--gold); }
button, input, select, textarea { font-family: inherit; font-size: inherit; color: inherit; }
[hidden] { display: none !important; }
::selection { background: var(--gold); color: var(--gold-ink); }
:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }
.num { font-variant-numeric: tabular-nums; }

/* The starfield is gone (2026-08-27). It belonged to the old night-sky theme,
   it ran a permanent requestAnimationFrame loop on every device, and twinkling
   dots have nothing to do with a federal-court practice. The ground is now flat
   brand colour with the arrow motif over it. */
.brand-ground {
  position: fixed; inset: 0; z-index: 0; pointer-events: none;
  background:
    radial-gradient(ellipse at 12% -8%, color-mix(in srgb, var(--gold) 12%, transparent), transparent 58%),
    radial-gradient(ellipse at 88% 108%, color-mix(in srgb, var(--gold) 8%, transparent), transparent 52%),
    var(--bg);
}

#app {
  position: relative; z-index: 1; height: 100dvh; display: flex; flex-direction: column;
  padding-top: env(safe-area-inset-top); padding-left: env(safe-area-inset-left); padding-right: env(safe-area-inset-right);
}

/* ---------- header / nav ---------- */
header.topbar {
  display: flex; align-items: center; gap: 14px; padding: 12px 18px;
  border-bottom: 1px solid var(--border); background: var(--glass); backdrop-filter: blur(8px);
  flex-wrap: wrap;
}
.brand { display: flex; align-items: center; gap: 8px; font-family: var(--serif); font-size: 18px; font-weight: 600; white-space: nowrap; }
.brand .mark { color: var(--ink); }
/* Tabs size to their LABEL, not to an equal share of the strip. `flex: 1`
   gave every tab the same cell, so padding swung from 4px a side on
   "Dashboard" to 15px on "Plan" — the strip read as accidental rather than
   designed. Content-sized tabs with one padding value make the rhythm even
   however many tabs there are, which matters now that there are seven. */
nav.tabs {
  display: flex; gap: 2px; background: var(--surface); border: 1px solid var(--border);
  border-radius: 11px; padding: 3px; flex: 0 1 auto; min-width: 0;
}
nav.tabs button {
  flex: 0 1 auto; background: none; border: 0; padding: 7px 12px; border-radius: 8px; cursor: pointer;
  color: var(--muted); font-size: 12.5px; font-weight: 600; letter-spacing: .01em; white-space: nowrap;
  transition: color .13s, background-color .13s;
}
nav.tabs button:hover { color: var(--ink); }
nav.tabs button.on { background: var(--gold); color: var(--gold-ink); }
nav.tabs button.on:hover { color: var(--gold-ink); }
.spacer { flex: 1; }
.theme-toggle { display: flex; border: 1px solid var(--border); border-radius: 999px; overflow: hidden; }
.theme-toggle button { border: 0; background: var(--surface); color: var(--muted); padding: 5px 9px; font-size: 11px; font-weight: 700; cursor: pointer; }
.theme-toggle button.on { background: var(--gold); color: var(--gold-ink); }
.icon-btn { background: var(--surface); border: 1px solid var(--border); border-radius: 9px; color: var(--ink); padding: 6px 10px; cursor: pointer; font-size: 13px; }
.icon-btn:hover { border-color: var(--border-strong); }

/* ---------- views ---------- */
main { flex: 1; min-height: 0; }
.view { height: 100%; overflow-y: auto; padding: 20px 18px calc(24px + env(safe-area-inset-bottom)); }
/* Wide enough to use a big monitor (more case columns = less scrolling)
   without letting the layout sprawl edge-to-edge on an ultrawide. */
.view-inner { max-width: 1600px; margin: 0 auto; display: flex; flex-direction: column; gap: 18px; }
/* Keep AI prose at a readable measure even when the card gets very wide. */
.briefing .clamp p { max-width: 72ch; }
h1.page-title { font-family: var(--serif); font-size: 22px; margin: 0; }
.page-sub { color: var(--muted); font-size: 13px; margin: 0; }
/* pull-up applies ONLY directly under a page title — reusing .page-sub inside
   cards must not inherit the negative margin (it overlapped card meta lines) */
h1.page-title + .page-sub { margin-top: -10px; }

/* ---------- stat tiles ----------
   The minimum track scales with the viewport. A flat 150px min was tuned for
   phones, but on a wide screen it packs 8 columns of ~160px — and these tiles
   carry a full explanatory sentence in .sub, so at that width the text wraps
   into a column and the tile ends up TALLER THAN IT IS WIDE (measured
   2026-08-28: 160px wide x 309px tall on the Growth model card at 1440px).
   Widening the minimum trades column count for a readable line length: the
   same tile lands near 270x190 at 1440px. Phones keep the narrow min so two
   tiles still share a row. */
.stat-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 10px; }
@media (min-width: 700px)  { .stat-grid { grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); } }
@media (min-width: 1100px) { .stat-grid { grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: 12px; } }
.stat-tile { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); padding: 14px 16px; box-shadow: var(--shadow); }
.stat-tile .k { font-size: 10.5px; font-weight: 700; letter-spacing: .07em; text-transform: uppercase; color: var(--muted); }
.stat-tile .v { font-family: var(--mono); font-size: 20px; font-weight: 700; margin-top: 4px; }
.stat-tile .v.gold { color: var(--gold); } .stat-tile .v.emerald { color: var(--emerald); } .stat-tile .v.danger { color: var(--danger); }
/* Matches the voluntary-remand series in the conceded-vs-litigated chart so the
   tile and the legend read as the same thing. */
.stat-tile .v.violet { color: var(--series-contrib); }
.stat-tile.tint-blue { background: var(--tile-blue-bg); border-color: var(--tile-blue-border); }
.stat-tile.tint-pink { background: var(--tile-pink-bg); border-color: var(--tile-pink-border); }
.stat-tile .sub { font-size: 11.5px; color: var(--muted); margin-top: 3px; }

/* ---------- staffing roadmap: vertical timeline ---------- */
.hire-timeline { position: relative; margin-top: 12px; padding-left: 22px; }
.hire-timeline::before { content: ""; position: absolute; left: 5px; top: 4px; bottom: 4px; width: 2px; background: var(--border-strong); }
.hire-timeline-row { position: relative; padding: 8px 0 14px; }
.hire-timeline-row:last-child { padding-bottom: 0; }
.hire-timeline-row .dot {
  position: absolute; left: -22px; top: 6px; width: 12px; height: 12px; border-radius: 50%;
  background: var(--gold); border: 2px solid var(--surface); box-shadow: 0 0 0 1px var(--border-strong);
}
.hire-timeline-row.dot-lb .dot { background: var(--tile-pink-border); }

/* Dashboard two-up: collapses to one column on its own, no JS breakpoint. */
.dash-grid { display: grid; gap: 16px; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); }

/* ---------- cards ---------- */
.card { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); padding: 16px 18px; box-shadow: var(--shadow); }
.card h2 { font-family: var(--serif); font-size: 16px; margin: 0 0 10px; font-weight: 600; }
.card-row { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }

/* Collapsible subsection INSIDE a card (Growth model's five estimate groups).
   Lighter chrome than details.settings-group — no surface/shadow of its own,
   since it already sits on a card; just a rule and a caret so the groups read
   as one stack. JS opens them on wide windows and leaves them shut on phones,
   where the card was measured at 3.8 viewports fully expanded. */
details.subsec { border-top: 1px solid var(--border); }
details.subsec:first-of-type { border-top: 0; }
details.subsec > summary {
  list-style: none; cursor: pointer; padding: 11px 0 9px; display: flex; gap: 10px;
  align-items: center; justify-content: space-between;
  font-size: 10px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--muted);
}
details.subsec > summary::-webkit-details-marker { display: none; }
details.subsec > summary::after { content: "+"; font-size: 15px; line-height: 1; flex: none; }
details.subsec[open] > summary { color: var(--ink); }
details.subsec[open] > summary::after { content: "\2212"; }
details.subsec > summary:hover { color: var(--ink); }
.subsec-body { padding-bottom: 14px; display: flex; flex-direction: column; gap: 8px; }

/* ---------- case cards + milestone constellation ---------- */
.case-grid { display: grid; gap: 12px; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); }
.case-card { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); padding: 16px 18px; box-shadow: var(--shadow); cursor: pointer; transition: border-color .15s; }
.case-card:hover { border-color: var(--border-strong); }
.case-card h3 { margin: 0 0 2px; font-size: 16px; font-weight: 600; }
.case-card .meta { font-size: 12px; color: var(--muted); font-family: var(--mono); }
.case-card .outcome-pill { display: inline-block; font-size: 10px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase; padding: 2px 8px; border-radius: 999px; margin-left: 6px; vertical-align: middle; }
.pill-favorable { background: color-mix(in srgb, var(--emerald) 18%, transparent); color: var(--emerald); }
.pill-unfavorable { background: color-mix(in srgb, var(--danger) 18%, transparent); color: var(--danger); }
.pill-pending { background: color-mix(in srgb, var(--gold) 18%, transparent); color: var(--gold); }
.pill-writing { background: color-mix(in srgb, var(--muted) 18%, transparent); color: var(--muted); }

.milestones { display: flex; justify-content: space-between; margin: 16px 0 4px; }
.mrow { display: flex; align-items: center; flex: 1; }
.mrow .ln { flex: 1; height: 1px; background: var(--border-strong); }
.mrow .ln.done { background: var(--gold); box-shadow: 0 0 4px color-mix(in srgb, var(--gold) 60%, transparent); }
.mstar { width: 13px; height: 13px; border-radius: 50%; background: var(--surface2); border: 1px solid var(--border-strong); flex: none; position: relative; }
.mstar.done { background: var(--gold); border-color: var(--gold); box-shadow: 0 0 8px 2px color-mix(in srgb, var(--gold) 55%, transparent); }
.mstar.next { background: var(--emerald); border-color: var(--emerald); animation: pulse 1.8s ease-in-out infinite; }
.mstar.na { opacity: .3; }
@media (prefers-reduced-motion: reduce) { .mstar.next { animation: none; } }
@keyframes pulse { 0%,100%{box-shadow:0 0 4px 1px color-mix(in srgb, var(--emerald) 50%, transparent);} 50%{box-shadow:0 0 12px 5px color-mix(in srgb, var(--emerald) 70%, transparent);} }
.mlabels { display: flex; justify-content: space-between; font-size: 8.5px; color: var(--muted); text-transform: uppercase; letter-spacing: .02em; margin-top: 4px; }
.mlabels span { flex: 1; text-align: center; }

.case-stat-row { display: flex; gap: 20px; margin-top: 14px; padding-top: 12px; border-top: 1px dashed var(--border); }
.case-stat-row .k { font-size: 9.5px; color: var(--muted); text-transform: uppercase; letter-spacing: .06em; font-weight: 700; }
.case-stat-row .v { font-family: var(--mono); font-size: 14px; font-weight: 700; color: var(--gold); margin-top: 2px; }

/* ---------- US map (cases by state) ----------
   Lives inside a collapsed-by-default <details class="settings-group"> (see
   renderCases()), so the card chrome (surface/border/shadow) comes from that
   wrapper now — #case-map-wrap only needs its own internal spacing. */
#case-map-wrap { padding-top: 4px; }
.us-map { display: block; width: 100%; max-width: 640px; margin: 0 auto; height: auto; }
.us-state { fill: var(--surface2); stroke: var(--border-strong); stroke-width: .75; }
.us-state.has-cases { fill: var(--gold); cursor: pointer; transition: filter .12s; }
.us-state.has-cases:hover { filter: brightness(1.25); }
.us-state.selected { stroke: var(--emerald); stroke-width: 2; }
.map-legend { display: flex; align-items: center; gap: 8px; font-size: 11px; color: var(--muted); padding: 8px 2px 4px; }
.map-ramp { display: inline-block; width: 90px; height: 8px; border-radius: 4px;
  background: linear-gradient(90deg, color-mix(in srgb, var(--gold) 25%, var(--surface2)), var(--gold)); }

/* ---------- filters / toolbar ---------- */
.toolbar { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
/* Every text-like control, by exclusion rather than an allow-list. The old
   allow-list (text/search/date/number) silently missed type=month and
   type=time, which then rendered as the BROWSER DEFAULT — a white box with a
   gray 2px border, 26px tall — inside a dark-themed app (found 2026-08-28
   auditing layout: 6 month inputs + 2 time inputs + the PIN password field
   were all unstyled). Exclusion means a control type added later inherits the
   house style instead of breaking the theme. Inline styles still win, so the
   borderless editable tiles are unaffected. */
input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="color"]):not([type="file"]):not([type="submit"]):not([type="button"]),
select, textarea {
  background: var(--surface); border: 1px solid var(--border); border-radius: 8px; padding: 8px 10px; color: var(--ink);
}
input:focus, select:focus, textarea:focus { border-color: var(--gold); }
.btn { background: var(--gold); color: var(--gold-ink); border: 0; border-radius: 8px; padding: 9px 14px; font-weight: 700; font-size: 13px; cursor: pointer; }
.btn:disabled { opacity: .55; cursor: default; }
.btn.secondary { background: var(--surface); color: var(--ink); border: 1px solid var(--border-strong); }
.btn.danger { background: var(--danger); color: #fff; }
.chip { background: var(--surface2); border: 1px solid var(--border); border-radius: 999px; padding: 4px 11px; font-size: 12px; color: var(--muted); cursor: pointer; }
.chip.on { background: var(--gold); color: var(--gold-ink); border-color: var(--gold); }

/* ---------- revenue chart ---------- */
.chart-wrap { position: relative; height: 260px; }
.chart-wrap canvas { width: 100%; height: 100%; }
.legend { display: flex; gap: 8px 16px; font-size: 12px; color: var(--muted); flex-wrap: wrap; min-width: 0; }
.legend .sw { display: inline-block; width: 10px; height: 10px; border-radius: 3px; margin-right: 5px; vertical-align: -1px; }
/* Same swatch, for the bare <i> legend markers several cards use instead of
   .sw (remand split, cash/capital, trendlines) — with no sizing rule an <i>
   has no intrinsic box, so "background: <color>" alone painted nothing
   visible. Found while wiring the state-trendline legends (2026-08-29); fixes
   every existing usage of the pattern, not just the new one. */
.legend i { display: inline-block; width: 10px; height: 10px; border-radius: 3px; margin-right: 5px; vertical-align: -1px; }

/* ---------- tables ----------
   A long table is the single biggest reason a card grows past the screen (the
   expansion table alone measured 1017px on a phone, pushing its card to 2.3
   viewports). Cap the wrapper and let the table scroll INSIDE its own
   container — David's house rule: never make the whole page scroll to get
   past one panel's data. The header sticks so the columns stay identifiable
   while scrolling; thead already carries an opaque background, which sticky
   positioning requires. */
.tblwrap { overflow: auto; max-height: min(68vh, 640px); border: 1px solid var(--border); border-radius: var(--radius); overscroll-behavior: contain; }
table { border-collapse: collapse; width: 100%; font-size: 13px; min-width: 480px; }
th, td { padding: 8px 12px; text-align: left; border-bottom: 1px solid var(--border); white-space: nowrap; }
thead th { font-family: var(--sans); font-size: 10px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); background: var(--surface2); position: sticky; top: 0; z-index: 2; }
tbody tr:last-child td { border-bottom: 0; }
tbody tr:hover { background: var(--surface2); }
td.num, th.num { text-align: right; font-family: var(--mono); font-variant-numeric: tabular-nums; }

/* ---------- two-column row list (recently received) ---------- */
ul.row-list { list-style: none; margin: 0; padding: 0; }
ul.row-list li { display: flex; justify-content: space-between; align-items: baseline; gap: 10px; padding: 9px 0; border-top: 1px solid var(--border); font-size: 13.5px; }
ul.row-list li:first-child { border-top: 0; }

/* ---------- AI briefing ---------- */
.briefing p { font-size: 14.5px; line-height: 1.65; margin: 0; }
.briefing .engine { font-size: 10.5px; color: var(--muted); margin-top: 10px; text-transform: uppercase; letter-spacing: .05em; }

/* ---------- settings sections (collapsible, native details) ---------- */
details.settings-group { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; }
details.settings-group summary { list-style: none; cursor: pointer; padding: 14px 18px; font-family: var(--serif); font-size: 15px; font-weight: 600; display: flex; justify-content: space-between; align-items: center; }
details.settings-group summary::-webkit-details-marker { display: none; }
details.settings-group summary::after { content: "+"; color: var(--muted); font-size: 18px; }
details.settings-group[open] summary::after { content: "\2212"; }
details.settings-group .body { padding: 4px 18px 18px; border-top: 1px solid var(--border); }
.field-row { display: grid; grid-template-columns: 1fr auto; gap: 10px; align-items: center; padding: 7px 0; }
.field-row label { font-size: 13px; color: var(--muted); }
.field-row input { width: 130px; text-align: right; }
.lag-row { display: flex; justify-content: space-between; align-items: center; gap: 10px; padding: 8px 0; border-top: 1px solid var(--border); font-size: 13px; flex-wrap: wrap; }
.lag-row > div:first-child { min-width: 0; flex: 1 1 180px; }
.lag-controls { display: flex; align-items: center; gap: 8px; flex: 0 0 auto; }
.lag-controls input { width: 84px; text-align: right; }
.lag-row:first-child { border-top: 0; }
.conf-pill { font-size: 9.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; padding: 2px 7px; border-radius: 999px; margin-left: 8px; }
.conf-measured { background: color-mix(in srgb, var(--emerald) 18%, transparent); color: var(--emerald); }
.conf-override { background: color-mix(in srgb, var(--gold) 22%, transparent); color: var(--gold); }
.conf-fallback { background: color-mix(in srgb, var(--danger) 16%, transparent); color: var(--danger); }

/* ---------- itemized expense editor ---------- */
.expense-list { display: flex; flex-direction: column; gap: 6px; margin-top: 10px; }
.expense-row { display: grid; grid-template-columns: minmax(120px, 2fr) 130px 130px 100px 40px; gap: 8px; align-items: center; }
.expense-row input { width: 100%; }
.expense-row input[type="number"] { text-align: right; }
.expense-row.expense-new input { opacity: .75; }
.expense-row.expense-new input:focus { opacity: 1; }
.expense-head { font-size: 10px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); padding-bottom: 2px; }
.expense-summary { display: flex; gap: 26px; flex-wrap: wrap; margin-top: 14px; padding-top: 12px; border-top: 1px dashed var(--border); }
.expense-summary .k { display: block; font-size: 10px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); }
.expense-summary .v { display: block; font-family: var(--mono); font-size: 16px; font-weight: 700; color: var(--series-expense); margin-top: 3px; }
@media (max-width: 640px) {
  .expense-row { grid-template-columns: 1fr 1fr; gap: 6px; padding-bottom: 10px; border-bottom: 1px solid var(--border); }
  .expense-row > *:first-child { grid-column: 1 / -1; }
  .expense-head { display: none; }
}
/* Date inputs carry a wide intrinsic minimum — below this they can't sit two
   to a row without pushing past the viewport. */
@media (max-width: 420px) {
  .expense-row { grid-template-columns: 1fr; }
}
/* Never let a form control's intrinsic width blow out its grid/flex track. */
input, select, textarea { min-width: 0; max-width: 100%; }

/* Filing-plan step row — wraps so the Remove button can never land off-screen. */
.plan-row { display: flex; align-items: center; gap: 10px; padding: 6px 0; flex-wrap: wrap; }
.plan-row input[type="month"] { min-width: 0; flex: 1 1 130px; }
.plan-row input[type="number"] { width: 78px; text-align: right; flex: none; }

.dropzone { border: 2px dashed var(--border-strong); border-radius: var(--radius); padding: 26px; text-align: center; color: var(--muted); font-size: 13px; cursor: pointer; }
.dropzone.drag { border-color: var(--gold); color: var(--gold); background: color-mix(in srgb, var(--gold) 6%, transparent); }

.toast-wrap { position: fixed; bottom: calc(18px + env(safe-area-inset-bottom)); left: 50%; transform: translateX(-50%); z-index: 50; display: flex; flex-direction: column; gap: 8px; align-items: center; }
.toast { background: var(--surface2); border: 1px solid var(--border-strong); color: var(--ink); padding: 10px 16px; border-radius: 999px; font-size: 13px; box-shadow: var(--shadow); }
.toast.err { border-color: var(--danger); color: var(--danger); }

/* ---------- modal (case detail / add case) ---------- */
.modal-backdrop { position: fixed; inset: 0; background: rgba(3,6,14,.55); backdrop-filter: blur(2px); z-index: 40; display: flex; align-items: center; justify-content: center; padding: 16px; }
.modal { background: var(--surface); border: 1px solid var(--border-strong); border-radius: var(--radius); max-width: 640px; width: 100%; max-height: 88vh; overflow-y: auto; padding: 22px 24px; box-shadow: var(--shadow); }
.modal h2 { font-family: var(--serif); margin: 0 0 4px; }
.modal .close { position: sticky; top: 0; float: right; background: none; border: 0; color: var(--muted); font-size: 20px; cursor: pointer; }
.form-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px 14px; margin-top: 14px; }
.form-grid label { display: block; font-size: 11px; color: var(--muted); text-transform: uppercase; letter-spacing: .05em; margin-bottom: 3px; }
.form-grid input, .form-grid select, .form-grid textarea { width: 100%; }
.form-grid .full { grid-column: 1 / -1; }

/* ---------- PIN gate ---------- */
.pin-gate { position: fixed; inset: 0; z-index: 100; display: flex; align-items: center; justify-content: center; background: var(--bg); }
.pin-card { background: var(--surface); border: 1px solid var(--border-strong); border-radius: var(--radius); padding: 32px 28px; width: min(320px, 90vw); text-align: center; box-shadow: var(--shadow); }
.pin-card h1 { font-family: var(--serif); font-size: 22px; margin: 0 0 4px; }
.pin-card p { color: var(--muted); font-size: 13px; margin: 0 0 18px; }
.pin-card input { width: 100%; text-align: center; letter-spacing: .3em; font-size: 18px; padding: 11px; }
.pin-card button { width: 100%; margin-top: 12px; }
.pin-err { color: var(--danger); font-size: 12.5px; min-height: 18px; margin-top: 8px; }

@media (max-width: 720px) {
  header.topbar { padding: 10px 12px; gap: 8px 10px; }
  /* Phone: keep the mark and ARROW, drop the descender line and the hairline.
     The old rule hid a .txt span that no longer exists, so without this the
     full two-line lockup rode into a 12px-padded bar and shoved the tabs. */
  .brand .lock .n2 { display: none; }
  .brand .rule { display: none; }
  .brand .lock .n1 { font-size: 15px; letter-spacing: .13em; }
  /* Seven tabs no longer fit beside the brand and the theme toggle. Squeezed
     onto one row the strip was 116px wide holding 321px of tabs, so Plan,
     Market and Settings rendered OUTSIDE the container with no scroll
     affordance — invisible and untappable on a phone. Giving the strip its own
     full-width row below the brand lets every tab wrap into view; navigation
     is the wrong thing to hide behind a sideways scroll. */
  nav.tabs { order: 10; flex: 1 0 100%; flex-wrap: wrap; justify-content: center; min-width: 0; }
  nav.tabs button { padding: 7px 10px; font-size: 12px; }
  .form-grid { grid-template-columns: 1fr; }
}

/* ---------- phone: same information, less scrolling ---------- */
@media (max-width: 640px) {
  .view { padding: 14px 12px calc(18px + env(safe-area-inset-bottom)); }
  .view-inner { gap: 12px; }
  /* two stat tiles per row instead of one */
  .stat-grid { grid-template-columns: repeat(auto-fit, minmax(132px, 1fr)); gap: 8px; }
  .stat-tile { padding: 10px 12px; }
  .stat-tile .v { font-size: 17px; }
  .card { padding: 13px 14px; }
  .dash-grid { gap: 12px; grid-template-columns: 1fr; }
  /* charts stay legible but give back vertical space */
  .chart-wrap { height: 200px; }
  /* case cards: keep the star trail, drop the tiny labels that need the width */
  .case-grid { gap: 8px; grid-template-columns: 1fr; }
  .case-card { padding: 12px 14px; }
  .case-card .mlabels { display: none; }
  .case-card .milestones { margin: 12px 0 2px; }
  .case-stat-row { margin-top: 10px; padding-top: 9px; gap: 16px; }
  #case-map-wrap { padding: 10px 12px 4px; }
}

/* ---------- touch targets ----------
   Keyed off the INPUT DEVICE, not the width: an iPad in landscape is 1024px+
   and still driven by a thumb, so a width-only rule (the original max-width:
   640px) missed it entirely — controls stayed at 23-27px on the tablet this
   app is used on most. `pointer: coarse` catches every touch device at any
   size; the width clause keeps narrow desktop windows comfortable too.
   Scoped away from the header chrome (tabs, L/D/A toggle), which is
   deliberately compact and sits within easy reach regardless. */
@media (pointer: coarse), (max-width: 1024px) {
  .plan-row input, .plan-row button,
  .expense-row input, .expense-row button,
  .field-row input, .lag-controls input,
  .toolbar input, .toolbar select, .toolbar button { min-height: 38px; }
  /* Borderless in-tile estimate inputs and their "clear"/"use default" links. */
  .stat-tile input, .stat-tile button { min-height: 30px; }
  /* Chips: chart PNG/Copy actions, "View as table", filter chips. */
  .chip { min-height: 34px; display: inline-flex; align-items: center; }
  /* The chart's By fee / By source switch borrows .theme-toggle's chrome. In
     a card it's a primary control and needs a real tap target; the header's
     own L/D/A toggle stays compact, hence the .card scope. */
  .card .theme-toggle button { min-height: 34px; padding: 5px 12px; }
}

/* Long AI prose is the tallest thing on a phone dashboard — clamp it with an
   in-place expander rather than letting it push everything else off-screen. */
.briefing .clamp { max-height: 15.5em; overflow: hidden; position: relative; }
.briefing .clamp::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 3em;
  background: linear-gradient(to bottom, transparent, var(--surface));
}
.briefing .clamp.open { max-height: none; }
.briefing .clamp.open::after { display: none; }
.briefing .more { margin-top: 8px; }

/* Firm chips — every firm name is clickable to its profile card */
.firm-link {
  cursor: pointer;
  border-bottom: 1px dotted var(--gold);
  transition: color .15s;
}
.firm-link:hover, .firm-link:focus { color: var(--gold); outline: none; }
.firm-card-body { min-width: min(520px, 86vw); }

/* Arrow mark — the firm's logo, from David's tattoo: thin shaft, open head,
   fletching. Inline SVG so it inherits color and scales with the theme. */
.brand .mark {
  width: 23px; height: 21.4px; flex: none;  /* 112:104 viewBox — keep the ratio or the A squashes */
  color: var(--ink);
}
.pin-card h1 { display: flex; align-items: center; justify-content: center; gap: 9px; }
.pin-card h1 .mark {
  width: 30px; height: 27.9px; flex: none;
  color: var(--gold);
  filter: drop-shadow(0 0 10px color-mix(in srgb, var(--gold) 55%, transparent));
}

/* Sideways ink arrows — the tattoo motif as page furniture. Sits above the
   starfield gradient, below the app (#app is z-index 1), and never
   interactive. Kept very faint: it should register as texture, not compete
   with a chart. Light mode needs slightly more opacity to read on pale ground. */
.arrow-bg {
  /* display:block undoes index.html's unstyled-fallback guard. */
  display: block;
  position: fixed; inset: 0; z-index: 0; pointer-events: none; overflow: hidden;
  color: var(--gold); opacity: .085;
}
.arrow-bg svg { width: 100%; height: 100%; display: block; }
@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) .arrow-bg { opacity: .10; }
}
:root[data-theme="light"] .arrow-bg { opacity: .10; }
/* Phones: one arrow's worth of texture is plenty on a small screen. */
@media (max-width: 640px) { .arrow-bg { opacity: .06; } }

/* Inline verdict block — used where the app states a conclusion the reader
   would otherwise have to derive from the chart above it. Tokens are defined
   on :root in both themes, so no var() here can compute to transparent. */
.callout {
  border: 1px solid var(--border);
  border-left: 3px solid var(--gold);
  background: var(--card-2, var(--card));
  border-radius: 10px;
  padding: 10px 12px;
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--ink);
}
.callout strong { color: var(--gold); }

/* ---------- click to expand ---------- */
/* Matches the sibling stats apps. The enlarge hint is a corner chip, NOT a
   title attribute: a browser draws title text at the cursor, which is exactly
   where a chart's own hover readout sits, so it would cover the value being
   read. */
.zoomable { position: relative; cursor: zoom-in; border-radius: 8px; }
.zoomable:hover, .zoomable:focus-visible { outline: 2px solid var(--gold); outline-offset: 3px; }
.zoomable::after {
  content: "⤢ enlarge & save";
  position: absolute; top: 4px; right: 6px; z-index: 2;
  font-size: 10.5px; padding: 2px 8px; border-radius: 999px;
  background: var(--gold); color: var(--bg, #12141c);
  opacity: 0; transition: opacity .12s; pointer-events: none; white-space: nowrap;
}
.zoomable:hover::after, .zoomable:focus-visible::after { opacity: .95; }
/* Coarse pointers get no hover, so the chip would never appear — show it. */
@media (pointer: coarse) { .zoomable::after { opacity: .8; } }

.chart-modal { position: fixed; inset: 0; z-index: 200; background: rgba(6, 9, 16, .72);
  display: flex; align-items: center; justify-content: center; padding: max(12px, env(safe-area-inset-top)) 12px max(12px, env(safe-area-inset-bottom)); }
.chart-modal[hidden] { display: none; }
.cm-panel { background: var(--card); border: 1px solid var(--border); border-radius: 14px;
  width: min(1200px, 96vw); max-height: 92vh; display: flex; flex-direction: column;
  padding: 14px 16px 12px; box-shadow: 0 18px 50px rgba(0,0,0,.45); }
.cm-head { display: flex; align-items: flex-start; gap: 12px; }
.cm-title { margin: 0; font-size: 16px; }
.cm-sub { margin: 3px 0 0; font-size: 12px; color: var(--muted); }
.cm-close { margin-left: auto; flex: 0 0 auto; background: transparent; border: 1px solid var(--border);
  color: var(--ink); border-radius: 8px; width: 34px; height: 34px; font-size: 15px; cursor: pointer; }
.cm-close:hover { border-color: var(--gold); color: var(--gold); }
.cm-figure { flex: 1 1 auto; min-height: 0; margin-top: 10px; overflow: auto; }
.cm-canvas-wrap { width: 100%; height: min(64vh, 620px); position: relative; }
.cm-canvas-wrap canvas { width: 100%; height: 100%; display: block; }
.cm-figure svg { width: 100%; height: auto; max-height: 64vh; display: block; }
.cm-foot { flex: 0 0 auto; }
@media (max-width: 720px) {
  .cm-panel { width: 100%; max-height: 94vh; padding: 12px; }
  .cm-canvas-wrap { height: 52vh; }
}

/* ---------- brand chrome (2026-08-27 design system) ---------- */

/* Header lockup: mark | ARROW over DISABILITY APPEALS, split by a hairline —
   the same construction as the printed lockup, at UI scale. */
.brand { align-items: center; gap: 10px; }
.brand .lock { display: flex; flex-direction: column; justify-content: center; line-height: 1; }
.brand .lock .n1 {
  font-family: var(--serif); font-size: 17px; font-weight: 600;
  letter-spacing: .17em; color: var(--ink);
}
.brand .lock .n2 {
  font-family: var(--sans); font-size: 8.2px; font-weight: 600;
  letter-spacing: .30em; color: var(--muted); margin-top: 3px;
}
.brand .rule { width: 1px; align-self: stretch; margin: 2px 2px; background: var(--border-strong); }

/* Nav reads as the site's nav: uppercase, letterspaced, gold underline on the
   active tab rather than a filled pill. One accent per section is the rule, and
   a row of filled gold pills broke it every time. */
nav.tabs { background: transparent; border: 0; border-radius: 0; padding: 0; gap: 2px; }
nav.tabs button {
  padding: 8px 11px 7px; border-radius: 0; font-size: 10.8px; font-weight: 600;
  letter-spacing: .13em; text-transform: uppercase; color: var(--muted);
  border-bottom: 2px solid transparent;
}
nav.tabs button:hover { color: var(--ink); }
nav.tabs button.on { background: transparent; color: var(--ink); border-bottom-color: var(--gold); }
nav.tabs button.on:hover { color: var(--ink); }

/* Figures set in Playfair, as the system specifies for the stat row. */
.stat-tile .v { font-family: var(--serif); font-size: 25px; font-weight: 600; letter-spacing: -.01em; }
.stat-tile .k { letter-spacing: .11em; }

/* A short gold rule under a card heading — the system's section-heading mark. */
.card h2 { position: relative; padding-bottom: 9px; letter-spacing: .005em; }
.card h2::after {
  content: ""; position: absolute; left: 0; bottom: 0;
  width: 34px; height: 2px; background: var(--gold); opacity: .85;
}
/* Headings that sit inline in a row shouldn't grow a rule. */
.card-row h2::after, .expense-head h2::after { display: none; }

/* NO first-card accent edge here, deliberately. The design system gives the
   first practice card a gold left edge, but in THIS app a gold left edge is
   already taken: the alert cards ("court activity not yet in the spreadsheet")
   set one inline to mean "look at this". Adding a decorative edge to whichever
   card happens to come first would make a real warning indistinguishable from
   chrome. The system's emphasis is carried by the gold heading rule instead.

   (The rule that briefly lived here was also inert: `.card:first-of-type`
   matches the first element of its TAG among siblings, not the first element
   carrying the class, and every view opens with an h1 and a couple of grids
   before its first card.) */

/* Page titles get the divider arrow the hero uses, at rule scale. */
h1.page-title { letter-spacing: .01em; }

/* PIN gate as the navy hero: this is the first thing seen, so it should look
   like the brand and not like a password box. */
.pin-gate { background: var(--bg); }
.pin-card h1 { font-family: var(--serif); letter-spacing: .12em; }
.pin-card { border-top: 3px solid var(--gold); }

/* ---------- brand kit (Settings) ---------- */
.brand-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(178px, 1fr)); gap: 12px; align-items: start; }
.brand-groupname {
  grid-column: 1 / -1; font-size: 10.5px; font-weight: 700; letter-spacing: .13em;
  text-transform: uppercase; color: var(--muted); margin-top: 6px;
}
.brand-groupname:first-child { margin-top: 0; }
.brand-tile { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); padding: 12px; }
/* The lockups are 4.3:1 — in a 178px cell they render as an unreadable sliver,
   so they take the full row instead of pretending to be square. */
.brand-tile.wide { grid-column: 1 / -1; }
/* A checkerboard behind the preview, so the transparent variant is visibly
   transparent rather than looking like it has a white ground. */
.brand-prev {
  border-radius: 9px; overflow: hidden; margin-bottom: 9px; display: flex;
  align-items: center; justify-content: center; padding: 6px;
  background-color: var(--surface2);
  background-image:
    linear-gradient(45deg, var(--border) 25%, transparent 25%, transparent 75%, var(--border) 75%),
    linear-gradient(45deg, var(--border) 25%, transparent 25%, transparent 75%, var(--border) 75%);
  background-size: 12px 12px; background-position: 0 0, 6px 6px;
}
.brand-prev svg { width: 100%; height: auto; max-height: 150px; display: block; }
.brand-tile.wide .brand-prev svg { max-height: 96px; }
.brand-label { font-size: 12.5px; font-weight: 600; }
.brand-note { font-size: 11px; color: var(--muted); margin-top: 2px; line-height: 1.45; }
.brand-actions { display: flex; gap: 6px; margin-top: 9px; flex-wrap: wrap; }

/* ---------- video explainers (2026-09-20) ---------- */
.modal.xp-modal { max-width: 980px; }
.xp-stage { position: relative; background: #081C2F; border-radius: 10px; overflow: hidden; margin-top: 12px; aspect-ratio: 16 / 9; }
.xp-canvas { display: block; width: 100%; height: 100%; cursor: pointer; }
.xp-bigplay { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); width: 78px; height: 78px; border-radius: 50%; border: 0; background: rgba(201,165,106,.92); color: #081C2F; font-size: 30px; cursor: pointer; box-shadow: 0 6px 24px rgba(0,0,0,.35); }
.xp-stage.playing .xp-bigplay { display: none; }
.xp-controls { display: flex; align-items: center; gap: 10px; margin-top: 10px; }
.xp-play { width: 40px; height: 40px; border-radius: 50%; border: 1px solid var(--border-strong); background: var(--surface); color: var(--ink); font-size: 15px; cursor: pointer; flex: 0 0 auto; }
.xp-scrub { flex: 1 1 auto; accent-color: var(--gold); min-width: 0; }
.xp-time { font-family: var(--mono); font-size: 12px; color: var(--muted); flex: 0 0 auto; }
.xp-actions { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; margin-top: 12px; }
.xp-quality { flex: 1 1 160px; min-width: 0; }
.xp-progress { display: flex; align-items: center; gap: 10px; margin-top: 10px; font-size: 12px; color: var(--muted); }
.xp-bar { flex: 1 1 auto; height: 8px; border-radius: 4px; background: var(--surface2, rgba(127,127,127,.2)); overflow: hidden; }
.xp-fill { height: 100%; width: 0; background: var(--gold); transition: width .2s; }
.xp-gallery { margin-top: 14px; }
.xp-grid { display: grid; gap: 12px; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); margin-top: 10px; }
.xp-tile { display: flex; flex-direction: column; gap: 6px; text-align: left; padding: 0; border: 1px solid var(--border); border-radius: 10px; background: var(--surface); color: var(--ink); cursor: pointer; overflow: hidden; font: inherit; }
.xp-tile:hover { border-color: var(--gold); }
.xp-thumb { display: block; width: 100%; height: auto; aspect-ratio: 16 / 9; background: #081C2F; }
.xp-tile-title { font-family: var(--serif); font-weight: 600; font-size: 14px; padding: 2px 10px 0; }
.xp-tile-sub { font-size: 11.5px; color: var(--muted); padding: 0 10px 10px; line-height: 1.35; }
.xp-chip { border-color: var(--gold); color: var(--gold); }
@media (max-width: 480px) { .xp-controls { flex-wrap: wrap; } .xp-time { order: 3; } .xp-actions .btn { flex: 1 1 auto; } }
/* Mute affects this player only; every download carries the narration. */
.xp-mute { flex: 0 0 auto; line-height: 1; padding: 6px 10px; }
.xp-mute.muted { opacity: .55; }

/* "LB" marker on the explainers written for Laura Beth (2026-09-22). */
.xp-thumb-wrap { position: relative; display: block; }
.xp-tag { position: absolute; top: 8px; left: 8px; background: var(--emerald); color: var(--emerald-ink); font-size: 10.5px; font-weight: 700; letter-spacing: .06em; padding: 2px 7px; border-radius: 4px; }
.xp-tag-inline { position: static; display: inline-block; margin-right: 8px; vertical-align: 3px; }
.xp-tile-lb { border-color: var(--emerald); }
