/* CourtWatch — "Counsel" (light) + "Midnight" (dark) design system.
   ALL color is driven from CSS custom properties: light is the :root default,
   dark is applied either by the OS signal (prefers-color-scheme) when no explicit
   choice is stamped, or by the [data-theme] attribute the toggle writes (which wins). */

:root {
  /* surfaces */
  --bg: #f3f3ee;            /* paper ground */
  --bg2: #f3f3ee;
  --panel-solid: #ffffff;   /* card surface */
  --surface2: #f4f5f1;      /* secondary surface */
  --line: #e3e4dd;          /* hairline border */
  --glass: rgba(255, 255, 255, .82);

  /* text */
  --ink: #16203a;           /* deep navy */
  --muted: #5a6478;

  /* accent (emerald) */
  --accent: #0e7a5c;
  --accent-deep: #0b5e47;
  --brand1: #0e7a5c;        /* legacy aliases used across the app */
  --brand2: #12916e;
  --btn-ink: #ffffff;       /* text on an accent fill */
  --soft-accent: #e7f1ec;   /* accent tint for chips/bubbles */
  --soft-accent-ink: #0c5c46;
  --accent-shadow: rgba(14, 122, 92, .26);

  /* roles */
  --green: #12916e; --green-bg: #e7f1ec; --green-ink: #0c5c46;
  --amber: #b0832a; --amber-bg: #f6edd8; --amber-ink: #8a6722;
  --red: #c0452f;   --red-bg: #f7e4df;
  --gold: #b0832a;  --gold-deep: #8a6722; --gold-ink: #4a3500;

  /* chart palette (read by JS at render time so charts follow the theme) */
  --c1: #0e7a5c; --c2: #b0832a; --c3: #c0452f; --c4: #12916e;
  --c5: #5a6478; --c6: #7a5ea8; --c7: #0b5e47; --c8: #9a6a2f;

  /* topbar */
  --topbar-bg: linear-gradient(135deg, #0e7a5c 0%, #0b5e47 100%);
  --topbar-ink: #ffffff;
  --topbar-shadow: 0 2px 14px rgba(11, 94, 71, .28);

  /* feature-card gradients */
  --feature-grad: linear-gradient(135deg, #ffffff 0%, #e7f1ec 100%);
  --success-grad: linear-gradient(135deg, #ffffff 0%, #e7f1ec 100%);

  --focus-ring: rgba(14, 122, 92, .18);
  --shadow: 0 6px 20px rgba(20, 27, 46, .07);
  --radius: 15px;
}

/* Dark tokens — applied automatically only when the user hasn't made a choice. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme]) {
    --bg: #12141c; --bg2: #12141c; --panel-solid: #1b1e29; --surface2: #232733;
    --line: #2a2e3d; --glass: rgba(20, 22, 30, .72);
    --ink: #e9ebf4; --muted: #969bb0;
    --accent: #8f7ff2; --accent-deep: #b3a6ff; --brand1: #8f7ff2; --brand2: #b3a6ff;
    --btn-ink: #14161f; --soft-accent: #262247; --soft-accent-ink: #c9c0ff;
    --accent-shadow: rgba(143, 127, 242, .34);
    --green: #37e0c8; --green-bg: #173a36; --green-ink: #37e0c8;
    --amber: #e0b24d; --amber-bg: #3a3320; --amber-ink: #e0b24d;
    --red: #ff6b78; --red-bg: #3d2530;
    --gold: #e0b24d; --gold-deep: #e0b24d; --gold-ink: #14161f;
    --c1: #8f7ff2; --c2: #37e0c8; --c3: #e0b24d; --c4: #ff6b78;
    --c5: #969bb0; --c6: #b3a6ff; --c7: #5ad0bd; --c8: #c9a24a;
    --topbar-bg: linear-gradient(135deg, #1b1e29 0%, #232733 100%);
    --topbar-ink: #e9ebf4; --topbar-shadow: 0 2px 14px rgba(0, 0, 0, .5);
    --feature-grad: linear-gradient(135deg, #1b1e29 0%, #232733 100%);
    --success-grad: linear-gradient(135deg, #1b1e29 0%, #173a36 100%);
    --focus-ring: rgba(143, 127, 242, .30);
    --shadow: 0 10px 26px rgba(0, 0, 0, .42);
  }
}

/* Explicit choice from the toggle — wins over the OS signal, in both directions. */
:root[data-theme="dark"] {
  --bg: #12141c; --bg2: #12141c; --panel-solid: #1b1e29; --surface2: #232733;
  --line: #2a2e3d; --glass: rgba(20, 22, 30, .72);
  --ink: #e9ebf4; --muted: #969bb0;
  --accent: #8f7ff2; --accent-deep: #b3a6ff; --brand1: #8f7ff2; --brand2: #b3a6ff;
  --btn-ink: #14161f; --soft-accent: #262247; --soft-accent-ink: #c9c0ff;
  --accent-shadow: rgba(143, 127, 242, .34);
  --green: #37e0c8; --green-bg: #173a36; --green-ink: #37e0c8;
  --amber: #e0b24d; --amber-bg: #3a3320; --amber-ink: #e0b24d;
  --red: #ff6b78; --red-bg: #3d2530;
  --gold: #e0b24d; --gold-deep: #e0b24d; --gold-ink: #14161f;
  --c1: #8f7ff2; --c2: #37e0c8; --c3: #e0b24d; --c4: #ff6b78;
  --c5: #969bb0; --c6: #b3a6ff; --c7: #5ad0bd; --c8: #c9a24a;
  --topbar-bg: linear-gradient(135deg, #1b1e29 0%, #232733 100%);
  --topbar-ink: #e9ebf4; --topbar-shadow: 0 2px 14px rgba(0, 0, 0, .5);
  --feature-grad: linear-gradient(135deg, #1b1e29 0%, #232733 100%);
  --success-grad: linear-gradient(135deg, #1b1e29 0%, #173a36 100%);
  --focus-ring: rgba(143, 127, 242, .30);
  --shadow: 0 10px 26px rgba(0, 0, 0, .42);
}

:root[data-theme="light"] { color-scheme: light; }
:root[data-theme="dark"] { color-scheme: dark; }

* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
body {
  background: var(--bg);
  min-height: 100vh;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  color: var(--ink);
  font: 16px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  -webkit-font-smoothing: antialiased;
  transition: background .2s ease, color .2s ease;
}

.topbar {
  position: sticky; top: 0; z-index: 5; overflow: hidden; flex: 0 0 auto;
  display: flex; align-items: center; justify-content: space-between;
  /* Pad all safe-area sides so the brand/pill clear the notch in landscape too. */
  padding: calc(env(safe-area-inset-top) + var(--notch-bleed) + 12px) max(16px, env(safe-area-inset-right)) 12px max(16px, env(safe-area-inset-left));
  background: var(--topbar-bg);
  box-shadow: var(--topbar-shadow);
}
.brand { display: flex; align-items: center; gap: 9px; font-weight: 800; font-size: 19px; color: var(--topbar-ink); letter-spacing: .2px; z-index: 1; }
.brand svg { width: 26px; height: 26px; display: block; }
.topbar .deco { position: absolute; right: -8px; bottom: -14px; width: 130px; height: 72px; opacity: .14; color: var(--topbar-ink); pointer-events: none; }
.topbar-right { display: flex; align-items: center; gap: 10px; z-index: 1; }

/* L / D / A theme pill */
.theme-seg { display: inline-flex; background: rgba(255, 255, 255, .18); border-radius: 999px; padding: 2px; gap: 2px; }
.theme-seg button { all: unset; cursor: pointer; font-size: 11px; font-weight: 800; line-height: 1; padding: 5px 8px; border-radius: 999px; color: var(--topbar-ink); opacity: .7; transition: opacity .15s, background .15s; }
.theme-seg button:hover { opacity: 1; }
.theme-seg button.on { background: var(--topbar-ink); color: var(--accent-deep); opacity: 1; }

.status-dot { width: 11px; height: 11px; border-radius: 50%; background: rgba(255, 255, 255, .5); box-shadow: 0 0 0 3px rgba(255, 255, 255, .16); }
.status-dot.ok { background: #6ff0a8; }
.status-dot.bad { background: #ffb1b1; }

/* Fill the full window width — no stranded narrow column, no dead side margins on a PC.
   Side/bottom padding respects the safe-area insets (landscape notch + home indicator). */
.view {
  flex: 1 0 auto; width: 100%; margin: 0 auto;
  padding-top: 16px;
  padding-bottom: max(16px, env(safe-area-inset-bottom));
  padding-left: max(16px, env(safe-area-inset-left));
  padding-right: max(16px, env(safe-area-inset-right));
}
@media (min-width: 640px) {
  .view {
    padding-top: 20px;
    padding-left: max(clamp(20px, 3.5vw, 46px), env(safe-area-inset-left));
    padding-right: max(clamp(20px, 3.5vw, 46px), env(safe-area-inset-right));
  }
}
/* Fluid card grid: 1 column on iPhone, more as the window grows — fills the space and
   reflows live on resize / rotation / split-view. min(100%,…) keeps it from ever forcing
   horizontal overflow at narrow widths. */
.cards {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 340px), 1fr));
  gap: 14px; align-items: start;
}
.cards > .card { margin-bottom: 0; }
/* Headings, prose/feature cards, notes, and anything tagged .span-all take a full row. */
.cards > h2, .cards > h3, .cards > h4,
.cards > .empty, .cards > .note, .cards > .span-all,
.cards > .card.feature, .cards > .card.success { grid-column: 1 / -1; }
/* Reading column for form / conversation views where full-window-wide lines would hurt. */
.reading { width: 100%; max-width: 860px; margin: 0 auto; }
/* AI summary bodies flow into readable multi-column text on wide screens, so a long report
   fills the full card width (~3 columns) instead of stranding a tall column beside empty space.
   Column-width auto-collapses to 1 column on phones. The meta line and lead headline span all
   columns; headings/bullets never split across a column break. */
[data-execbody], [data-briefbody] { column-width: 21rem; column-gap: 40px; }
/* Case-file chat answer: cap the line length now that the view spans the full window. */
#cf-answer { column-width: 24rem; column-gap: 40px; }
#cf-answer > :first-child { margin-top: 0 !important; }
[data-execbody] > :first-child, [data-briefbody] > :first-child,
[data-execbody] > h3, [data-briefbody] > h3 { column-span: all; }
[data-execbody] h3, [data-briefbody] h3 { margin-top: 0; }
[data-execbody] :is(h4, li), [data-briefbody] :is(h4, li) { break-inside: avoid; }
.empty { color: var(--muted); text-align: center; padding: 36px 16px; }
.empty .art { width: 96px; height: 96px; margin: 0 auto 12px; color: var(--accent); opacity: .9; }
h2 { font-family: Georgia, "Iowan Old Style", "Times New Roman", serif; font-weight: 600; font-size: 22px; margin: 4px 0 14px; letter-spacing: .2px; }
h3 { font-size: 15px; margin: 0 0 6px; }
h4 { font-size: 14px; margin: 8px 0 4px; }

.card {
  background: var(--panel-solid); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 15px; margin-bottom: 12px; box-shadow: var(--shadow);
  overflow-wrap: break-word; /* long labels/captions wrap instead of overflowing sideways */
  min-width: 0;              /* let the card shrink inside a grid track (prevents overflow) */
}
.card.feature { background: var(--feature-grad); }
.card.success { background: var(--success-grad); border-color: color-mix(in srgb, var(--green) 40%, var(--line)); }
.card.bubble-me { background: var(--soft-accent); }
.card.high { border-color: var(--amber); box-shadow: 0 0 0 1px var(--amber) inset, var(--shadow); }
.row { display: flex; align-items: center; gap: 10px; justify-content: space-between; }
/* Action button cluster that wraps cleanly on narrow (iPhone) widths instead of
   squeezing buttons onto stacked half-rows. */
.card-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-top: 10px; }
.muted { color: var(--muted); font-size: 13px; }
.small { font-size: 12px; }
.mono { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; overflow-wrap: anywhere; }

/* Compact list of related sub-sections inside ONE card (e.g. Settings → Notifications) —
   a hairline divider between rows instead of separate cards, so related settings don't each
   pay full card chrome (padding/border/shadow/margin) and stack into a long scroll. */
.notif-row { padding: 10px 0; border-top: 1px solid var(--line); }
.notif-row:first-child { padding-top: 0; border-top: none; }
.notif-row-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; font-weight: 700; }

/* Collapsible reference/log sub-sections (e.g. Settings → System) — collapsed by default so a
   status card's log + reference text don't force a long scroll on first look. Native <details>
   keeps the content in the DOM while closed, so it never needs its own JS wiring. */
.status-details { border-top: 1px solid var(--line); padding-top: 8px; }
.status-details summary { cursor: pointer; font-weight: 600; padding: 9px 0; list-style-position: outside; }
.status-details summary:hover { color: var(--accent); }
.status-details[open] summary { margin-bottom: 2px; }

/* Ask chat: one card holding all exchanges, hairline-separated, newest first.
   Previously every message was its own full card (padding + border + shadow + 12px margin),
   which doubled the chrome per exchange and pushed answers off-screen. */
.qa-log { padding: 4px 15px; }
.qa { padding: 11px 0; border-top: 1px solid var(--line); }
.qa:first-child { border-top: none; }
.qa-q {
  font-weight: 700; font-size: 13.5px; line-height: 1.4; color: var(--ink);
  display: flex; gap: 7px; align-items: baseline;
}
.qa-q::before { content: "❯"; color: var(--accent); font-weight: 800; flex: 0 0 auto; }
.qa-a { font-size: 14px; margin-top: 5px; }
.qa-thinking { padding: 11px 0; }
/* mdToHtml emits inline margins, which beat class selectors — override them here so AI
   answers render tight inside the chat without changing how they look elsewhere. */
.qa-a > :first-child { margin-top: 0 !important; }
.qa-a > :last-child { margin-bottom: 0 !important; }
.qa-a p { margin: 4px 0 !important; }
.qa-a ul { margin: 4px 0 !important; padding-left: 17px !important; }
.qa-a li { margin: 1px 0; }
.qa-a h3, .qa-a h4 { margin: 9px 0 3px !important; font-size: 13.5px; }

/* Document action strip under an AI answer — open it, or go get it. */
.doc-actions { margin-top: 8px; padding-top: 7px; border-top: 1px dashed var(--line); }
.doc-actions-head { font-weight: 700; text-transform: uppercase; letter-spacing: .4px; font-size: 10.5px; margin-bottom: 4px; }
.doc-act { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; justify-content: space-between; padding: 3px 0; font-size: 12.5px; }
.doc-act-name { flex: 1 1 190px; min-width: 0; }
.doc-act-btns { display: flex; gap: 6px; flex: 0 0 auto; }
.chipbtn {
  font-size: 11.5px; font-weight: 700; padding: 4px 9px; border-radius: 999px;
  border: 1px solid var(--line); background: var(--panel-solid); color: var(--accent);
  text-decoration: none; white-space: nowrap;
}
.chipbtn:hover { border-color: var(--accent); text-decoration: none; }

/* Drag-and-drop upload target (§8) */
.dropzone {
  margin-top: 10px; padding: 18px 14px; text-align: center;
  border: 2px dashed var(--line); border-radius: 12px; background: var(--surface2);
  transition: border-color .15s, background .15s;
}
.dropzone.over { border-color: var(--accent); background: var(--soft-accent); }
.linkish { all: unset; cursor: pointer; color: var(--accent); font-weight: 700; text-decoration: underline; }

/* Dense-list helpers: a compact icon button and a 2-line title clamp. A full-size button
   per card cost ~44px × 65 cards in the alert feed; the title often ran to 3+ lines. */
button.mini { padding: 3px 8px; font-size: 12px; line-height: 1.2; border-radius: 8px; }
.clamp2 { display: -webkit-box; -webkit-line-clamp: 2; line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }

/* Collapsed rich sub-content inside a repeating list row (§17) — AI briefs, alert details.
   Native <details> keeps the content in the DOM and survives re-renders. */
.row-details { margin-top: 5px; }
.row-details > summary {
  cursor: pointer; font-size: 11.5px; font-weight: 700; color: var(--accent);
  letter-spacing: .3px; padding: 2px 0; list-style-position: outside;
}
.row-details > summary:hover { text-decoration: underline; }

/* Long document manifest flows into columns on wide screens instead of one tall stack. */
.doc-list { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 330px), 1fr)); gap: 0 22px; align-items: start; }
.doc-list > .file-row { border-top: 1px solid var(--line); }

/* Case Files: compact manifest rows + spend meter */
.file-row { padding: 9px 0; border-top: 1px solid var(--line); }
.file-row:first-child { border-top: none; padding-top: 0; }
.spend-meter { height: 8px; border-radius: 999px; background: var(--surface2); overflow: hidden; }
.spend-fill { height: 100%; border-radius: 999px; background: linear-gradient(90deg, var(--brand1), var(--brand2)); transition: width .3s; }

/* Quick-prompt pills (e.g. Ask → "Try asking") — wrapping chip row instead of one full
   card per one-line prompt, so 4 short suggestions don't cost 4x card padding/border/shadow. */
.sugg-chips { display: flex; flex-wrap: wrap; gap: 8px; margin: 0 2px 12px; }
.sugg-chip {
  font: inherit; font-size: 13px; font-weight: 600; color: var(--ink); text-align: left;
  background: var(--panel-solid); border: 1px solid var(--line); border-radius: 999px;
  padding: 10px 16px; cursor: pointer; box-shadow: 0 1px 2px rgba(20, 27, 46, .05); transition: border-color .15s, filter .15s;
}
.sugg-chip:hover { border-color: var(--accent); filter: brightness(.98); }

.hero {
  background: var(--feature-grad);
  border: 1px solid var(--line); border-radius: 18px; box-shadow: var(--shadow);
  padding: 16px 18px; margin-bottom: 16px; display: flex; align-items: center; gap: 14px;
}
.hero .art { flex: 0 0 76px; width: 76px; height: 76px; color: var(--accent); }
.hero h2 { margin: 0 0 2px; }
.hero p { margin: 0; color: var(--muted); font-size: 13.5px; }

.chip { font-size: 11.5px; font-weight: 800; padding: 4px 10px; border-radius: 999px; white-space: nowrap; letter-spacing: .2px; }
.chip.no { background: var(--green-bg); color: var(--green-ink); }
.chip.move { background: var(--amber-bg); color: var(--amber-ink); }
.chip.off { background: var(--surface2); color: var(--muted); }
.chip.high { background: var(--red-bg); color: var(--red); }

.ai { background: var(--soft-accent); border-left: 3px solid var(--accent); padding: 9px 11px; border-radius: 10px; margin: 9px 0; font-size: 14px; color: var(--ink); }
.ai .lbl { color: var(--accent); font-weight: 800; font-size: 11px; letter-spacing: .5px; text-transform: uppercase; }

a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }
button {
  font: inherit; font-weight: 700; color: var(--ink);
  background: var(--panel-solid); border: 1px solid var(--line); border-radius: 11px;
  padding: 9px 14px; cursor: pointer; box-shadow: 0 1px 2px rgba(20, 27, 46, .05); transition: transform .05s, filter .15s;
}
button:hover { filter: brightness(.98); }
button.primary { background: linear-gradient(135deg, var(--brand1), var(--brand2)); border: none; color: var(--btn-ink); box-shadow: 0 2px 8px var(--accent-shadow); }
button.gold { background: linear-gradient(135deg, var(--gold), var(--gold-deep)); border: none; color: var(--gold-ink); box-shadow: 0 2px 8px rgba(176, 131, 42, .30); }
button:active { transform: translateY(1px); }
button:disabled { opacity: .5; }

label { display: block; font-size: 13px; color: var(--muted); margin: 10px 0 4px; font-weight: 600; }
input, select, textarea {
  width: 100%; font: inherit; color: var(--ink);
  background: var(--panel-solid); border: 1px solid var(--line); border-radius: 11px; padding: 10px;
}
input:focus, select:focus, textarea:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--focus-ring); }
textarea { min-height: 84px; resize: vertical; }
.hint { font-size: 12px; color: var(--muted); margin-top: 4px; }
.note { background: var(--amber-bg); border: 1px solid color-mix(in srgb, var(--amber) 45%, var(--line)); color: var(--amber-ink); padding: 10px 12px; border-radius: 11px; font-size: 13px; }

/* Segmented control (Settings → Appearance) */
.seg { display: inline-flex; border: 1px solid var(--line); border-radius: 11px; overflow: hidden; }
.seg button { all: unset; cursor: pointer; padding: 8px 18px; font-weight: 700; font-size: 13px; color: var(--muted); background: var(--panel-solid); text-align: center; }
.seg button + button { border-left: 1px solid var(--line); }
.seg button.on { background: var(--accent); color: var(--btn-ink); }
.grid2b { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }

svg.chart text { font-family: inherit; }

.tabbar {
  position: sticky; bottom: 0; z-index: 5; flex: 0 0 auto;
  display: flex; background: var(--glass); backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
  border-top: 1px solid var(--line); box-shadow: 0 -2px 12px rgba(20, 27, 46, .05);
  /* Clear the home indicator (bottom) and the notch/rounded corners in landscape (left/right). */
  padding-bottom: env(safe-area-inset-bottom);
  padding-left: env(safe-area-inset-left);
  padding-right: env(safe-area-inset-right);
}
.tabbar a {
  flex: 1; text-align: center; padding: 11px 2px 9px; font-size: 11.5px; font-weight: 700;
  color: var(--muted); text-decoration: none; position: relative; border-top: 2px solid transparent;
}
.tabbar a:hover { text-decoration: none; }
.tabbar a.active { color: var(--accent); border-top-color: var(--accent); }
/* Unread count as a superscript beside the label. It used to sit centred at top:5px with a
   16px nudge, which on a 55px-wide phone tab put "154" squarely over the word "Inbox". */
.badge {
  /* Stacked ABOVE the label: a 7-tab bar leaves ~54px per tab on a phone, too narrow to set
     the count beside the word without touching it. top:0 + 12px height ends where the label begins. */
  position: absolute; top: 0; left: calc(50% + 2px); right: auto; transform: none;
  background: var(--red); color: #fff; border-radius: 999px; font-size: 9.5px; line-height: 12px;
  padding: 0 4px; font-weight: 800; pointer-events: none;
}

@media (min-width: 720px) {
  .grid2 { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
  .grid2 .card { margin-bottom: 0; }
}

.hidden { display: none !important; }

/* ===== Break-glass passcode lock (SSO is primary; keypad only shows if SSO didn't authenticate) ===== */
.lock-screen {
  position: fixed; inset: 0; z-index: 50;
  display: flex; align-items: center; justify-content: center;
  background: var(--topbar-bg); color: var(--topbar-ink);
  padding: calc(env(safe-area-inset-top) + 20px) 20px calc(env(safe-area-inset-bottom) + 20px);
}
.lock-card { width: 100%; max-width: 360px; text-align: center; }
.lock-logo {
  width: 78px; height: 78px; margin: 0 auto 14px; color: var(--topbar-ink);
  background: rgba(255, 255, 255, .16); border-radius: 22px;
  display: flex; align-items: center; justify-content: center; box-shadow: 0 8px 24px rgba(0, 0, 0, .18);
}
.lock-logo svg { width: 46px; height: 46px; display: block; }
.lock-title { margin: 0; font-family: Georgia, "Iowan Old Style", "Times New Roman", serif; font-size: 28px; font-weight: 600; letter-spacing: .3px; }
.lock-hint { margin: 6px 0 20px; opacity: .9; font-size: 15px; }
/* Boot splash: while we check Cloudflare Access, show only the logo/title — never the keypad. */
.lock-screen.booting .lock-hint,
.lock-screen.booting .pin-grp { display: none; }
.lock-hint { margin: 4px 0 clamp(8px, 2vh, 20px); }
.pin-grp { display: flex; flex-direction: column; align-items: center; gap: clamp(8px, 1.8vh, 18px);
  touch-action: manipulation; -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; }
.pin-dots { display: flex; gap: 10px; }
.pin-dots span { width: 14px; height: 14px; border-radius: 50%; border: 2px solid var(--topbar-ink); }
.pin-dots span.on { background: var(--topbar-ink); }
.pin-grp.busy .pin-dots span.on { animation: pinpulse .9s ease-in-out infinite; }
@keyframes pinpulse { 50% { opacity: .35; } }
.pin-grp.bad .pin-dots { animation: pinshake .35s; }
@keyframes pinshake { 20%, 60% { transform: translateX(-8px); } 40%, 80% { transform: translateX(8px); } }
.pin-msg { min-height: 1.3em; font-size: 16px; font-weight: 600; color: var(--topbar-ink); text-align: center; }
.pin-pad { --k: clamp(56px, min(22vw, 9vh), 84px); display: grid; grid-template-columns: repeat(3, var(--k)); gap: clamp(8px, 1.5vh, 16px); }
.pin-pad button { height: var(--k); border: none; border-radius: 50%; box-shadow: none; padding: 0;
  background: rgba(255, 255, 255, .16); color: var(--topbar-ink); font-weight: 600; font-size: clamp(26px, 4vh, 32px); line-height: 1;
  touch-action: manipulation; -webkit-tap-highlight-color: transparent; cursor: pointer; transition: background .15s; }
.pin-pad button:hover { filter: none; }
.pin-pad button:active { background: rgba(255, 255, 255, .34); }
.pin-pad button:disabled { opacity: .5; }
.pin-pad .pin-del { background: transparent; font-size: 24px; }

/* Height-capped AI prose with a Show more toggle (§17). Cap by RENDERED height, not
   character count — a low char count can still render very tall. */
.clampbox { max-height: var(--clamp-h, 250px); overflow: hidden; position: relative; }
.clampbox::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 54px;
  background: linear-gradient(to bottom, transparent, var(--panel-solid) 88%); pointer-events: none;
}
.clampbox.open { max-height: none; }
.clampbox.open::after { display: none; }
/* Feature cards have a gradient background — fade to their end colour instead. */
.card.feature .clampbox::after { background: linear-gradient(to bottom, transparent, var(--soft-accent) 92%); }

/* CRITICAL: multi-column + a constrained height makes content flow SIDEWAYS into extra
   columns that overflow:hidden then clips — the clamped briefing was 326px wide holding
   8,744px of hidden columns, so most of the text was simply invisible. Force a single
   column whenever a block is clamped; restore columns only when it's expanded. */
[data-execbody].clampbox:not(.open),
[data-briefbody].clampbox:not(.open),
#cf-answer.clampbox:not(.open) { column-width: auto !important; column-count: 1 !important; }

/* ===== Landing dashboard (Watches tab) =================================
   The old landing screen stacked full-width cards: the executive summary ran
   ~1,900px lines on a wide monitor, a single watch card sat stranded in one
   narrow grid track, two empty sections each claimed a full-width card, and the
   bottom ~40% of the window was blank. This lays the screen out as a dashboard
   so the numbers, the read on the board, and what actually moved are all above
   the fold, and the space is used. */
.dash { display: flex; flex-direction: column; gap: 14px; }

/* Numbers first: fluid, collapses 5 -> 1 across down to iPhone width. */
.stat-strip { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 168px), 1fr)); gap: 12px; }
.stat {
  display: block; padding: 12px 14px; border-radius: var(--radius);
  background: var(--panel-solid); border: 1px solid var(--line); box-shadow: var(--shadow);
  text-decoration: none; color: inherit; transition: border-color .15s, transform .15s;
}
.stat:hover { border-color: var(--accent); text-decoration: none; transform: translateY(-1px); }
.stat .v { font-size: clamp(22px, 2.4vw, 30px); font-weight: 800; line-height: 1.05; color: var(--ink); font-variant-numeric: tabular-nums; }
.stat .l { font-size: 10.5px; font-weight: 800; letter-spacing: .5px; text-transform: uppercase; color: var(--muted); margin-top: 4px; }
.stat .s { font-size: 11.5px; color: var(--muted); margin-top: 2px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.stat.alert .v { color: var(--red); }
.stat.warn .v { color: var(--amber); }
.stat.good .v { color: var(--accent); }


/* On a phone the five tiles stacked ~485px tall and pushed everything below the fold.
   Two-up with tighter type keeps the numbers glanceable without owning the screen. */
/* Phone: all five numbers on ONE row with short labels. Two-up took three rows (~200px) and
   left the fifth tile alone on the last row. */
.stat .l .ls { display: none; }
@media (max-width: 560px) {
  .stat-strip { grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 6px; }
  .stat { padding: 8px 3px 7px; text-align: center; border-radius: 12px; }
  .stat .v { font-size: 17px; letter-spacing: -.3px; }
  .stat .l { font-size: 9px; letter-spacing: .2px; margin-top: 3px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .stat .l .lf { display: none; }
  .stat .l .ls { display: inline; }
  .stat .s { display: none; }
  [data-exec] { padding: 6px 12px; font-size: 13px; }
}
/* Summary beside the news. Single column under 1000px so nothing is squeezed. */
.dash-main { display: grid; grid-template-columns: minmax(0, 1.9fr) minmax(0, 1fr); gap: 14px; align-items: start; }
.dash-col { display: flex; flex-direction: column; gap: 14px; min-width: 0; }
/* Keep the two columns down to 900px. Collapsing at 1100 made iPad landscape (1024x768,
   a SHORT viewport) a single tall column, which fit worse than two side-by-side panels. */
@media (max-width: 900px) { .dash-main { grid-template-columns: 1fr; } }
.dash-col > .card { margin-bottom: 0; }

/* A long block that earns its own scroll (§3) rather than pushing the page down.
   Single column: a multi-column block with a constrained height flows SIDEWAYS
   into clipped columns, which hides most of the text. */
.scrollbox {
  /* 40vh keeps the whole dashboard inside a 1200px-tall window without page scroll,
     and still shows a generous slab of the summary on a taller monitor. */
  max-height: 40vh; overflow: auto; overscroll-behavior: contain; /* fallback; fitDashboard() overrides */
  column-width: auto !important; column-count: 1 !important;
  max-width: min(78ch, 100%); padding-right: 6px;
}
.scrollbox > :first-child { margin-top: 0 !important; }


/* The alert feed is live data (134 unread at the time of writing) — without its own scroll
   it became the tallest element on the page and pushed the dashboard into page scroll.
   Neither main card may drive page height; both scroll inside themselves (§3). */
.move-list { max-height: 34vh; /* fallback; fitDashboard() overrides */ overflow: auto; overscroll-behavior: contain; padding-right: 4px; }
/* Latest-movement rows */
.move-row { padding: 8px 0; border-top: 1px solid var(--line); }
.move-row:first-child { border-top: none; padding-top: 2px; }
.move-top { display: flex; align-items: center; gap: 7px; }
.move-sum { font-size: 12.5px; font-weight: 600; line-height: 1.35; margin-top: 2px; }

/* Section heading for the watch groups */
.dash-sec { display: flex; flex-direction: column; gap: 8px; }
.sec-h { margin: 4px 2px 0; color: var(--muted); text-transform: uppercase; font-size: 12px; letter-spacing: .6px; }

/* Tiny version badge (index.html, filled from version.js). Top-left inside the safe area, in the
   topbar's top padding above the brand, clear of the L/D/A toggle on the right. It always sits
   on the topbar gradient, and the passcode lock paints the same gradient, so it takes the
   topbar ink. Measured: white 5.31:1 on #0e7a5c and 7.76:1 on #0b5e47 (light); #e9ebf4 13.96:1
   on #1b1e29 and 12.53:1 on #232733 (dark). The failure state is a filled pill because no red
   text reaches 4.5:1 on the green: page paper on brick 4.56:1 light, #12141c on #ff6b78
   6.67:1 dark. */
.app-version {
  position: fixed; z-index: 60; pointer-events: none;   /* above the passcode lock (50) and bars (5) */
  top: env(safe-area-inset-top, 0px);
  left: calc(env(safe-area-inset-left, 0px) + 16px);
  font: 500 9px/9px ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  letter-spacing: .2px; white-space: nowrap;
  /* index.html carries an inline color:#fff so the badge is legible even if this file
     fails to load, where the page background is default WHITE; !important lets the themed
     token (white/light, for the green or navy topbar) win once the sheet has loaded. */
  color: var(--topbar-ink) !important;
}
.app-version.fail { background: var(--red); color: var(--bg); font-weight: 700; padding: 1px 4px; border-radius: 3px; }

/* ===== iPhone pass (2026-09-28) =====================================
   iOS draws a blurred wash behind the status bar in a standalone app that bleeds ~10px PAST
   the safe-area inset, smearing anything in that band (the version badge was unreadable).
   --notch-bleed adds that clearance only where there IS a notch: min() makes it 0 on a PC. */
:root { --notch-bleed: min(14px, env(safe-area-inset-top, 0px)); --statusfill: #0d7357; }
@media (prefers-color-scheme: dark) { :root:not([data-theme]) { --statusfill: #1b1e29; } }
:root[data-theme="dark"] { --statusfill: #1b1e29; }
/* iOS 26 skips that blur when an OPAQUE, FIXED, flat-colored box touches the top edge. The
   topbar is a gradient, so give WebKit a flat strip to sample. Above the topbar (5), below the
   passcode lock (50) so the lock is what gets sampled while it shows, below the badge (60).
   Not yet confirmed on a device; the --notch-bleed clearance is the belt to this suspender. */
#statusfill { position: fixed; top: 0; left: 0; right: 0; height: env(safe-area-inset-top, 0px);
  background: var(--statusfill); z-index: 6; pointer-events: none; }

/* Latest movement rows: meta line, then the filing, clamped to two lines. */
.move-row .chip { font-size: 9.5px; padding: 1px 6px; }
.move-top { flex-wrap: nowrap; min-width: 0; }
.move-top .muted { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.move-sum { margin-top: 3px; }

/* Single column (phone, iPad portrait): the page scrolls, so the alert list does not also
   scroll inside itself. Show the top five and let "Inbox →" carry the rest. */
@media (max-width: 900px) {
  .move-list { max-height: none !important; overflow: visible; }
  .move-list .move-row:nth-child(n+4) { display: none; }
}

/* Star = text me orders on this case. On-state reuses the .seg on colors (accent fill, --btn-ink). */
.star-btn { white-space: nowrap; font-size: 12.5px; padding: 6px 10px; }
.star-btn.on { background: var(--accent); color: var(--btn-ink); border-color: var(--accent); }
