/* ================================================================================================
   THE DESK OVERVIEW — the home page that answers "how is the work going".

   THIS FILE IS A SURFACE (R9). Every number it draws is a byte `/api/overview` sent, computed by
   `overview_stats.py` from the records that already exist. It computes nothing, decides nothing,
   and never shows a duration that could read as staff time (PROJECT.md §6).

   THE WORLD IS THIS CONSOLE'S OWN (DESIGN.md). The tokens below are not a new palette — they are
   the palette the desk already ships (`web/app.css` `:root`), restated as local fallbacks ONLY so
   this file renders even if it is ever loaded before `app.css`. One accent, used only for
   meaning; semantic colour never decorates. Light is the default (DESIGN.md: the OS never seeds
   it); `[data-theme="dark"]` is the desk's own opt-in toggle, not a preference query, so the two
   themes follow the console's own switch.

   The apple-design layer lives in the motion: every movement is a short, quiet settle — an
   opacity cross-fade and a few pixels of rise, spring-like easing with no overshoot (an Operate
   surface is flicked by nobody). `prefers-reduced-motion` collapses all of it to fades, per both
   the skill and DESIGN.md.
   ================================================================================================ */

/* -- the overview's local token restatements (fallbacks only; app.css is the authority) --------- */
.ovw {
  --ovw-bg: var(--bg, #eef0ef);
  --ovw-surface: var(--surface, #fbfcfb);
  --ovw-raised: var(--raised, #ffffff);
  --ovw-sunken: var(--sunken, #f2f4f3);
  --ovw-ink: var(--ink, #14171b);
  --ovw-ink-2: var(--ink-2, #454a51);
  --ovw-ink-3: var(--ink-3, #5f656d);
  --ovw-line: var(--line, #dfe3e2);
  --ovw-line-2: var(--line-2, #cbd1cf);
  --ovw-accent: var(--accent, #1b4d8f);
  --ovw-accent-soft: var(--accent-soft, #e3ecf7);
  --ovw-accent-line: var(--accent-line, #b7cbe8);
  --ovw-ok: var(--ok, #1f6b45);
  --ovw-ok-soft: var(--ok-soft, #e2efe7);
  --ovw-ok-line: var(--ok-line, #b5d4c3);
  --ovw-warn: var(--warn, #8a5a0b);
  --ovw-warn-soft: var(--warn-soft, #f6ecd9);
  --ovw-warn-line: var(--warn-line, #e0cfa5);
  --ovw-danger: var(--danger, #a32a1f);
  --ovw-danger-soft: var(--danger-soft, #f7e4e1);
  --ovw-danger-line: var(--danger-line, #e3b8b2);
  --ovw-mono: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;
  --ovw-dur: 240ms;
  --ovw-rise: 6px;
}

/* -- the page -------------------------------------------------------------------------------- */
.ovw {
  color: var(--ovw-ink);
  font: 400 14px/1.5 "Public Sans", system-ui, sans-serif;
  padding: 4px 2px 24px;
  animation: ovw-in var(--dur, 240ms) cubic-bezier(0.22, 1, 0.36, 1) both;
}
@keyframes ovw-in {
  from { opacity: 0; transform: translateY(var(--ovw-rise)); }
  to   { opacity: 1; transform: none; }
}

.ovw-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 8px 14px; margin-bottom: 6px; }
.ovw-title { font-size: 23px; font-weight: 600; letter-spacing: -0.02em; line-height: 1.15; margin: 0; }
.ovw-sub { color: var(--ovw-ink-2); font-size: 13px; margin: 0; }
.ovw-head .ovw-computed { margin-left: auto; color: var(--ovw-ink-3); font-size: 12px;
  font-family: var(--ovw-mono, monospace); font-variant-numeric: tabular-nums; }

.ovw-banner {
  border: 1px solid var(--ovw-warn-line);
  background: var(--ovw-warn-soft);
  color: var(--ovw-warn);
  border-radius: 8px;
  padding: 8px 12px;
  font-size: 13px;
  margin: 10px 0 14px;
}
.ovw-banner.is-gap { border-color: var(--ovw-danger-line); background: var(--ovw-danger-soft);
  color: var(--ovw-danger); }

/* -- the three workflow cards ------------------------------------------------------------------
   NOT three same-size cards of icon-plus-heading-plus-text: the row is a table-like strip — one
   column per workflow, one line per fact, the counts in record type. The card is a banded panel
   (surface + hairline), the desk's own vocabulary (DESIGN.md: grouped panels, banded headers). */
.ovw-row { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 14px; }

.ovw-card {
  background: var(--ovw-surface);
  border: 1px solid var(--ovw-line);
  border-radius: 12px;
  overflow: hidden;
  min-width: 0;
}
.ovw-card-head {
  display: flex; align-items: center; gap: 8px;
  padding: 10px 14px;
  background: var(--ovw-sunken);
  border-bottom: 1px solid var(--ovw-line);
}
.ovw-card-head h3 { margin: 0; font-size: 15px; font-weight: 600; letter-spacing: -0.01em; }
.ovw-card-count { margin-left: auto; font-family: var(--ovw-mono, monospace); font-size: 13px;
  color: var(--ovw-ink-2); font-variant-numeric: tabular-nums; }

.ovw-card-body { padding: 10px 14px 12px; }

/* the state strip: one chip per status the workflow's records actually hold */
.ovw-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 10px; }
.ovw-chip {
  display: inline-flex; align-items: baseline; gap: 6px;
  font-size: 12px; line-height: 1;
  padding: 4px 9px;
  border-radius: 999px;
  border: 1px solid var(--ovw-line-2);
  background: var(--ovw-raised);
  color: var(--ovw-ink-2);
  font-family: var(--ovw-mono, monospace);
  font-variant-numeric: tabular-nums;
}
.ovw-chip b { font-weight: 600; color: var(--ovw-ink); }
.ovw-chip[data-tone="accent"] { color: var(--ovw-accent); background: var(--ovw-accent-soft);
  border-color: var(--ovw-accent-line); }
.ovw-chip[data-tone="accent"] b { color: var(--ovw-accent); }
.ovw-chip[data-tone="ok"] { color: var(--ovw-ok); background: var(--ovw-ok-soft);
  border-color: var(--ovw-ok-line); }
.ovw-chip[data-tone="ok"] b { color: var(--ovw-ok); }
.ovw-chip[data-tone="warn"] { color: var(--ovw-warn); background: var(--ovw-warn-soft);
  border-color: var(--ovw-warn-line); }
.ovw-chip[data-tone="warn"] b { color: var(--ovw-warn); }
.ovw-chip[data-tone="danger"] { color: var(--ovw-danger); background: var(--ovw-danger-soft);
  border-color: var(--ovw-danger-line); }
.ovw-chip[data-tone="danger"] b { color: var(--ovw-danger); }

.ovw-kv { display: grid; grid-template-columns: auto 1fr; gap: 3px 12px; margin: 0; }
.ovw-kv > dt { color: var(--ovw-ink-3); font-size: 12px; }
.ovw-kv > dd { margin: 0; font-family: var(--ovw-mono, monospace); font-size: 12.5px;
  color: var(--ovw-ink); font-variant-numeric: tabular-nums; text-align: right; }
.ovw-kv > dd.ovw-zero { color: var(--ovw-ink-3); }

/* destinations: the countries this workflow's records name, most work first */
.ovw-dests { margin-top: 10px; display: flex; flex-direction: column; gap: 4px; }
.ovw-dest { display: flex; align-items: baseline; gap: 8px; font-size: 12.5px; }
.ovw-dest .n { flex: 1; color: var(--ovw-ink-2); min-width: 0; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; }
.ovw-dest .c { font-family: var(--ovw-mono, monospace); color: var(--ovw-ink);
  font-variant-numeric: tabular-nums; }
.ovw-dest .bar { height: 3px; border-radius: 2px; background: var(--ovw-accent);
  opacity: 0.35; align-self: center; }

/* the attention list: needs-attention and unreadable records, by name — the queue's first
   question ("which of these needs me?") answered before anything else (PRODUCT.md principle 5) */
.ovw-attention { margin-top: 10px; display: flex; flex-direction: column; gap: 4px; }
.ovw-att {
  display: flex; align-items: center; gap: 8px;
  width: 100%;
  text-align: left;
  background: var(--ovw-raised);
  border: 1px solid var(--ovw-line);
  border-radius: 8px;
  padding: 6px 10px;
  font: inherit; font-size: 13px;
  color: var(--ovw-ink);
  cursor: pointer;
  transition: background 120ms ease-out, border-color 120ms ease-out, transform 100ms ease-out;
}
.ovw-att:hover { background: var(--ovw-hover, #f0f2f1); }
.ovw-att:active { transform: scale(0.99); }
.ovw-att:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--ring, rgba(27, 77, 143, 0.25)); }
.ovw-att .dot { width: 7px; height: 7px; border-radius: 50%; background: var(--ovw-ink-4, #8b9199);
  flex: none; }
/* A ROW THAT NEEDS THE OPERATOR CARRIES THE WARN DOT; A ROW THAT DOES NOT CARRIES A NEUTRAL ONE.
   The list is now every case, not only the flagged ones (`Kazim, 2026-09-27`), so a warn-coloured dot
   by default would mark six healthy informal jobs as needing attention. The marker column still exists
   on every row so the names align — it is only its colour that means something. */
.ovw-att[data-kind="flag"] .dot { background: var(--ovw-warn); }
.ovw-att[data-kind="unread"] .dot { background: var(--ovw-danger); }
.ovw-att .name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; font-weight: 550; }
.ovw-att .st { font-family: var(--ovw-mono, monospace); font-size: 11px;
  color: var(--ovw-ink-3); flex: none; }
/* THE CHIP CARRIES THE SAME COLOUR AS THE SAME CASE'S CHIP ON ITS OWN TAB.
   
   Kazim, 2026-09-27: *"make the hague one match colours of the actual cards in the tab just like
   informal."* Informal's rows already matched; Hague's did not, and MEASURED why: the row only set
   `data-state` when the workflow sent a `stage` (informal does, Hague does not), so every Hague row
   fell to the grey default above — `(none)`, `rgb(95,101,109)` — while the identical case on the Hague
   tab wore `review`→`rgb(27,77,143)` and `ready`→`rgb(31,107,69)`. One case, two colours, two surfaces.

   The keys below are the CONSOLE's status keys and the meanings are the console's own (app.css,
   `.state[data-state=…]`): in progress is accent, finished work is ok, a thing waiting on a human is
   warn, a failure is danger. They are written in this file rather than inherited because
   `overview_home.css` is a page of its own and must not depend on app.css having been parsed first —
   the fallbacks in the token block above exist for the same reason. The VALUES are the tokens, so the
   dark theme follows app.css's dark values with no second rule here.

   TWO DELIBERATE OMISSIONS, each the same shape as informal's `intake`:
     * `new` (Hague's "Draft") is left UNNAMED, so it keeps the quiet grey default — a case nothing has
       happened to yet is not progress and must not look like it. This is the ask Kazim made for
       informal on 2026-09-26 ("make it grey for the draft but coloured for the other steps, like
       Hague"), applied to Hague's own draft rung.
     * `confirmed` is "Courier not sent" — a case whose work is DONE but whose courier has not gone. It
       stays warn-coloured here, which is what the console's own rules do (`.state[data-state=
       "confirmed"]` is warn, and its later ok rule is the same duplicate app.css carries).
   A status no rule names (an unknown one, R1) is drawn as it arrives and stays grey: never blanked,
   never reclassified into a meaning this file cannot stand behind. */
.ovw-att .st[data-state="review"]   { color: var(--ovw-accent); }
.ovw-att .st[data-state="running"]  { color: var(--ovw-accent); }
.ovw-att .st[data-state="ready"]    { color: var(--ovw-ok); }
.ovw-att .st[data-state="printed"]  { color: var(--ovw-ok); }
.ovw-att .st[data-state="shipped"]  { color: var(--ovw-ok); }
.ovw-att .st[data-state="sent"]     { color: var(--ovw-ok); }
.ovw-att .st[data-state="signed"]   { color: var(--ovw-ok); }
.ovw-att .st[data-state="awaiting_signature"] { color: var(--ovw-warn); }
.ovw-att .st[data-state="confirmed"] { color: var(--ovw-warn); }
.ovw-att .st[data-state="error"]    { color: var(--ovw-danger); }
/* AN INFORMAL JOB'S STEP IS COLOURED BY ITS STAGE KEY, grey only for the draft rung — the console's
   own ask of 2026-09-26. `intake` is deliberately unnamed (the grey default above). */
.ovw-att .st[data-state="details"],
.ovw-att .st[data-state="affidavit"] { color: var(--accent); }
.ovw-att .st[data-state="delivery"]  { color: var(--ovw-warn, #8a5a0b); }
.ovw-att .st[data-state="done"]      { color: var(--ok, #1f6b45); }
/* THE CAP, STATED. A card names a bounded number of jobs; this says the list continues and where.
   It is a line of text inside the boxed list, not a control — the tab is the way to the rest, and a
   second "show all" door beside the tab that does the same thing would be two answers to one question.
   `Kazim, 2026-09-27`: the list is ONE list in the card's own boxed style on every workflow; an
   earlier pass added a second, flatter list beside this one, which is not what was asked for. */
.ovw-more { padding: 5px 10px 1px; font-size: 12px; color: var(--ovw-ink-3); }

.ovw-blanket { margin-top: 10px; font-size: 12.5px; color: var(--ovw-ink-2);
  border: 1px solid var(--ovw-line); background: var(--ovw-sunken);
  border-radius: 8px; padding: 7px 10px; }

/* -- the second band: people + activity + the desk's own state --------------------------------- */
.ovw-cols { display: grid; grid-template-columns: minmax(0, 4fr) minmax(0, 3fr) minmax(0, 3fr);
  gap: 14px; margin-top: 14px; align-items: start; }

.ovw-panel {
  background: var(--ovw-surface);
  border: 1px solid var(--ovw-line);
  border-radius: 12px;
  overflow: hidden;
  min-width: 0;
}
.ovw-panel-head { display: flex; align-items: baseline; gap: 8px; padding: 10px 14px;
  background: var(--ovw-sunken); border-bottom: 1px solid var(--ovw-line); }
.ovw-panel-head h3 { margin: 0; font-size: 13px; font-weight: 600; }
.ovw-panel-head .n { margin-left: auto; font-family: var(--ovw-mono, monospace); font-size: 12px;
  color: var(--ovw-ink-3); font-variant-numeric: tabular-nums; }
.ovw-panel-body { padding: 10px 14px 12px; }

/* people: the office, from the account store. The viewer's own row is marked; the counts are
   per person because "how is the work going" is also "who is carrying it". */
.ovw-people { display: flex; flex-direction: column; gap: 2px; }
.ovw-person { display: grid; grid-template-columns: minmax(0, 1fr) auto auto auto;
  gap: 4px 12px; align-items: baseline; padding: 5px 2px; border-bottom: 1px solid
  var(--ovw-line); font-size: 12.5px; }
.ovw-person:last-child { border-bottom: none; }
.ovw-person.me .name { color: var(--ovw-accent); }
.ovw-person .name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-weight: 550; color: var(--ovw-ink); }
.ovw-person .who { color: var(--ovw-ink-3); font-size: 11.5px; }
.ovw-person .role { font-size: 11px; text-transform: uppercase; letter-spacing: 0.04em;
  color: var(--ovw-ink-3); }
.ovw-person .held { font-family: var(--ovw-mono, monospace); font-variant-numeric: tabular-nums;
  color: var(--ovw-ink-2); }
.ovw-person .held b { color: var(--ovw-ink); font-weight: 600; }
.ovw-person .live { font-size: 11px; color: var(--ovw-ok); }
.ovw-person .idle { font-size: 11px; color: var(--ovw-ink-3); }
.ovw-person .inactive { color: var(--ovw-ink-3); font-style: italic; }
.ovw-people-foot { margin-top: 8px; color: var(--ovw-ink-3); font-size: 12px; }

/* activity: one bar per day the records were touched; today at the left, mono date beneath */
/* the 14-day chart is an inline SVG (2026-09-24, see overview_home.js): the bars are <rect>s
   with explicit coordinates, so the only CSS they need is colour and height. The old flex/grid
   DOM chart fought the console's `:root { zoom: 1.1 }` — bars resolved on the pre-zoom line and
   overlapped their tracks — and is gone. */
svg.ovw-days { display: block; width: 100%; height: 56px; margin: 2px 0 4px; }
svg.ovw-days .ovw-day { fill: var(--ovw-accent); opacity: 0.85; }
svg.ovw-days .ovw-day.empty { fill: var(--ovw-line-2); opacity: 0.9; }
.ovw-day-labels { display: flex; gap: 3px; }
.ovw-day-labels span { flex: 1 1 0; text-align: center; font-family: var(--ovw-mono, monospace);
  font-size: 10px; color: var(--ovw-ink-3); font-variant-numeric: tabular-nums; }
.ovw-recent { margin-top: 10px; display: flex; flex-direction: column; gap: 4px; }
.ovw-recent-row { font-size: 12.5px; color: var(--ovw-ink-2); display: flex; gap: 8px;
  align-items: baseline; }
.ovw-recent-row .at { font-family: var(--ovw-mono, monospace); font-size: 11px;
  color: var(--ovw-ink-3); flex: none; font-variant-numeric: tabular-nums; }
.ovw-recent-row .tx { min-width: 0; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; }

/* the desk's own state: runs in flight + seams + blocks, each honestly worded.
   Rows align on the first line: the key column holds one width so the values start at the same x
   (measured ragged otherwise), and the dot rides the row's top line when a value wraps. */
.ovw-desk-list { display: flex; flex-direction: column; gap: 6px; font-size: 12.5px; }
.ovw-desk-item { display: flex; gap: 8px; align-items: flex-start; }
.ovw-desk-item .dot { width: 7px; height: 7px; border-radius: 50%; flex: none;
  margin-top: 5px; }
.ovw-desk-item .dot.ok { background: var(--ovw-ok); }
.ovw-desk-item .dot.warn { background: var(--ovw-warn); }
.ovw-desk-item .dot.off { background: var(--ovw-line-2); }
.ovw-desk-item .k { color: var(--ovw-ink-2); flex: none; min-width: 92px; }
.ovw-desk-item .v { color: var(--ovw-ink-3); min-width: 0; overflow-wrap: anywhere;
  /* the seam's wording is the VALUE — clipped with an ellipsis it reads as hidden (measured:
     "no printer configu…" at desk width). Two lines, then an ellipsis, never mid-word. */
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden; }
.ovw-desk-item .v strong { color: var(--ovw-ink); font-weight: 600; }

/* -- empty state, loading, error --------------------------------------------------------------- */
.ovw-empty { color: var(--ovw-ink-3); font-size: 13px; padding: 6px 0; }
.ovw-error { color: var(--ovw-danger); font-size: 13px; padding: 6px 0; }
.ovw-skeleton { height: 120px; border-radius: 12px; border: 1px solid var(--ovw-line);
  background: var(--ovw-sunken); }

/* -- phone (the console stacks at 980px; the overview follows the same boundaries) -------------- */
@media (max-width: 1120px) {
  .ovw-cols { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
  .ovw-cols .ovw-panel:last-child { grid-column: 1 / -1; }
}
@media (max-width: 980px) {
  .ovw-row { grid-template-columns: minmax(0, 1fr); }
  .ovw-cols { grid-template-columns: minmax(0, 1fr); }
  .ovw-cols .ovw-panel:last-child { grid-column: auto; }
  .ovw { padding-bottom: 18px; }
}

/* -- a REFRESH is not an arrival (Kazim, 2026-09-24) -------------------------------------------- */
/* "it should just refresh info but nothing else changes, no animation."
   The poll re-draws the overview every 2s. The ENTRY animation belongs to arriving on Home — the
   operator should see the page settle into place once — and replaying it on every refresh made an
   idle screen flash four times in ten seconds. `draw({soft:true})` marks the rebuilt root with
   `ovw-soft`, and this is the one rule that stops a refresh from re-entering. Nothing else about
   the refresh is suppressed: the numbers still repaint, they simply do not move the page. */
.ovw.ovw-soft { animation: none; }

/* -- reduced motion: opacity only, nothing travels (apple-design §14; DESIGN.md motion) --------- */
@media (prefers-reduced-motion: reduce) {
  .ovw, svg.ovw-days .ovw-day { animation: none !important; transition: none !important; }
  .ovw-att, .ovw-att:active { transition: none; transform: none !important; }
}

/* dark theme follows the console's own toggle — same tokens, dark values are app.css's job;
   these overrides only retint what this file hard-falls-back for. */
[data-theme="dark"] .ovw {
  --ovw-bg: var(--bg, #16191c);
  --ovw-surface: var(--surface, #1c2024);
  --ovw-raised: var(--raised, #232830);
  --ovw-sunken: var(--sunken, #191d21);
  --ovw-ink: var(--ink, #eef0f2);
  --ovw-ink-2: var(--ink-2, #b7bdc4);
  --ovw-ink-3: var(--ink-3, #9aa1a9);
  --ovw-line: var(--line, #2a3037);
  --ovw-line-2: var(--line-2, #363d45);
  --ovw-accent: var(--accent, #7dabef);
  --ovw-accent-soft: var(--accent-soft, #223350);
  --ovw-accent-line: var(--accent-line, #33507e);
  --ovw-ok: var(--ok, #6fc094);
  --ovw-ok-soft: var(--ok-soft, #1e3529);
  --ovw-ok-line: var(--ok-line, #2e5342);
  --ovw-warn: var(--warn, #e0b467);
  --ovw-warn-soft: var(--warn-soft, #3a2f1a);
  --ovw-warn-line: var(--warn-line, #5c4c27);
  --ovw-danger: var(--danger, #ef897a);
  --ovw-danger-soft: var(--danger-soft, #3a2320);
  --ovw-danger-line: var(--danger-line, #5f3630);
  --ovw-hover: var(--hover, #262b30);
}

/* THE CHART NEVER OUTGROWS ITS PANEL (2026-09-24, measured): with 14 days of history the
   day bars laid out on a ~620px line inside a 253px `.ovw-days` box — the last bars poked
   past the viewport (caught by the session-identity check's overflow assert). `flex: 1 1 0`
   alone left a stale wide line; the equal-column pattern is basis 0 with `min-width: 0`
   (already on `.ovw-day`) — width: 0 was measured collapsing the bars to NOTHING at desk
   width (each day computed 0px wide, the chart drew only its date labels), so it is NOT
   repeated here. The chart shrinks to its panel at any day count. */
.ovw-days { max-width: 100%; }
.ovw-day-labels { max-width: 100%; }