/* ============================================================================
   TCH design system — canonical
   SOURCE OF TRUTH. Vendored into apps by scripts/sync_core.py. Never edit a copy.
   Shared vocabulary with rent-ledger (same tokens, same components) so the
   after-hours screen looks like the rest of the TCH suite. Tokens are declared
   once below; nothing hardcodes a hex.

   Rules inherited from turn-inspection/DESIGN.md and NOT negotiable:
     · Teal is the only primary action colour.
     · Gold is advisory only — banners and attention tints, never a button fill.
     · Status colour is always paired with a glyph and a word. Colour is
       reinforcement, never the carrier of meaning. This matters more here than
       anywhere: the reader is half-awake, and a page that is only "red" says
       nothing.
     · "We didn't look" is never rendered as "it isn't there" — an untriaged
       call gets a dashed, colourless treatment of its own, never the calm of a
       routine one.
   ========================================================================= */

:root {
  /* --- brand ------------------------------------------------------------ */
  --bg:#f8feff;              /* Off-white  #F8FEFF — page                    */
  --card:#ffffff;
  --line:#cfdcdc;
  --line-soft:#e3ecec;
  --ink:#20333b;             /* Slate, darkened — 13:1 on white. The brand    
                                slate #485C66 is a 7:1 mid-tone that reads as 
                                grey-on-grey once a page is mostly whitespace.*/
  --muted:#51656d;           /* derived    slate — secondary text, 6.4:1      */
  --neutral:#525252;         /* Gray       #525252 — icons, dark borders     */
  --brand:#126b69;           /* Teal       #126B69 — primary                 */
  --brand-ink:#0e544f;       /* derived    teal darkened — hover/pressed     */
  --brand-tint:#e7f1f0;      /* derived    teal 8% — chips, ok states        */
  --brand-line:#cfe6e3;
  --gold:#ffbd15;            /* Gold       #FFBD15 — advisory accent         */
  --gold-tint:#fff6db;
  --gold-ink:#6b4e00;        /* readable text on gold-tint                   */
  --accent:var(--brand); --accent-ink:var(--brand-ink);
  --chip:#eef3f2;

  /* --- status (outside the brand, universal meaning) -------------------- */
  --red:#b3261e; --red-tint:#fef2f2; --red-line:#fecaca;
  --amber:#b45309; --amber-tint:#fffbeb; --amber-line:#fde68a;

  --shadow:0 1px 2px rgba(16,24,40,.06), 0 1px 3px rgba(16,24,40,.10);
  --radius:12px;
  --mono:ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
}

* { box-sizing:border-box; }

body {
  margin:0; background:var(--bg); color:var(--ink);
  font:15px/1.55 "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
       Helvetica, Arial, sans-serif;
  -webkit-font-smoothing:antialiased;
}
a { color:var(--accent); text-decoration:none; }
a:hover { text-decoration:underline; }
h1,h2,h3 { letter-spacing:-.01em; margin:0; }
h1 { font-size:22px; font-weight:680; }
h2 { font-size:18px; font-weight:650; }
h3 { font-size:15px; font-weight:650; }
.muted { color:var(--muted); }
.right { text-align:right; }
.nowrap { white-space:nowrap; }

/* --- layout -------------------------------------------------------------- */
.wrap { max-width:1680px; margin:0 auto; padding:0 22px; }   /* wide: this is a grid app */
main.wrap { padding-top:20px; padding-bottom:56px; }
.card { background:var(--card); border:1px solid var(--line);
        border-radius:var(--radius); padding:18px; box-shadow:var(--shadow); }
.card + .card { margin-top:18px; }
.row { display:flex; align-items:center; gap:10px; flex-wrap:wrap; }
.spread { display:flex; align-items:baseline; justify-content:space-between; gap:14px; }
.grid2 { display:grid; grid-template-columns:1fr 1fr; gap:18px; }
.grid4 { display:grid; grid-template-columns:repeat(4,1fr); gap:12px; }
/* Grid children default to min-width:auto, so one wide child (the raw payload
   <pre>) stretches its column and pushes the page sideways. min-width:0 makes the
   child scroll inside its own box instead. */
.grid2 > *, .grid4 > * { min-width:0; }
@media (max-width:900px){ .grid2,.grid4 { grid-template-columns:1fr; } }
.section-title { font-size:12px; font-weight:700; letter-spacing:.05em;
                 text-transform:uppercase; color:var(--muted); margin:24px 0 10px; }

/* --- advisory banner (gold — never a button) ----------------------------- */
.aid { background:var(--gold-tint); border-bottom:1px solid var(--gold);
       color:var(--gold-ink); font-size:12.5px; padding:7px 22px; text-align:center; }
.aid strong { font-weight:700; }

/* --- header -------------------------------------------------------------- */
header.app { background:var(--card); border-bottom:1px solid var(--line); }
.brandbar { display:flex; align-items:center; gap:12px; padding:11px 22px 0; }
.brandbar .logo { height:26px; width:auto; display:block; }
.appbar { display:flex; justify-content:space-between; align-items:flex-start;
          gap:16px; padding:10px 22px 12px; }
.appbar .title { font-size:19px; font-weight:680; }
.appbar .sub { color:var(--muted); font-size:13px; margin-top:1px; }
.appbar .actions { display:flex; gap:8px; flex-wrap:wrap; justify-content:flex-end; }
nav.views { display:flex; gap:2px; padding:0 22px; flex-wrap:wrap; }
nav.views a { padding:9px 13px; font-size:13.5px; font-weight:600; color:var(--muted);
              border-bottom:2px solid transparent; }
nav.views a:hover { color:var(--ink); text-decoration:none; }
nav.views a[aria-current="page"] { color:var(--brand); border-bottom-color:var(--brand); }
.metabar { display:flex; flex-wrap:wrap; gap:6px; padding:10px 22px 12px; }

/* --- buttons (teal primary; gold is never a fill) ------------------------ */
.btn { display:inline-flex; align-items:center; gap:6px; padding:9px 15px;
       border-radius:9px; border:1px solid var(--line); background:var(--card);
       color:var(--ink); font:inherit; font-weight:600; font-size:14px; cursor:pointer; }
.btn:hover { text-decoration:none; border-color:#d1d5db; background:#fafafa; }
.btn.sm { padding:6px 11px; font-size:13px; }
.btn.primary { background:var(--brand); border-color:var(--brand); color:#fff; }
.btn.primary:hover { background:var(--brand-ink); border-color:var(--brand-ink); }
.btn.red { color:var(--red); border-color:var(--red-line); }
.btn.red:hover { background:var(--red-tint); }
.btn.ghost { background:transparent; border-color:transparent; color:var(--brand); }
.btn[disabled] { opacity:.5; cursor:not-allowed; }

/* --- chips (context) ----------------------------------------------------- */
.chip { display:inline-flex; align-items:center; gap:5px; padding:3px 10px;
        border-radius:999px; font-size:12px; font-weight:550; background:var(--chip);
        color:#374151; border:1px solid var(--line); white-space:nowrap; }
.chip-live { background:var(--brand-tint); border-color:var(--brand-line);
             color:var(--brand-ink); font-weight:600; }
.chip-synthetic { background:var(--gold-tint); border-color:var(--gold); color:var(--gold-ink); }

/* --- pills (status) ------------------------------------------------------
   One vocabulary for both money legs. Every pill ships a glyph + a word; the
   `.dot` is decoration on top of that, never instead of it.                */
.pill { display:inline-flex; align-items:center; gap:5px; padding:2px 9px;
        border-radius:999px; font-size:12px; font-weight:600; line-height:1.6;
        border:1px solid var(--line); background:var(--chip); color:var(--ink);
        white-space:nowrap; }
.pill .dot { width:7px; height:7px; border-radius:999px; background:currentColor;
             flex:none; }

.pill.paid      { color:var(--brand-ink); background:var(--brand-tint); border-color:var(--brand-line); }
.pill.part      { color:var(--amber);     background:var(--amber-tint); border-color:var(--amber-line); }
.pill.pending   { color:#3a4a52;          background:#eef3f3;           border-color:#d5dee0; }
.pill.missing   { color:var(--red);       background:var(--red-tint);   border-color:var(--red-line); }
.pill.overdue   { color:var(--red);       background:var(--red-tint);   border-color:var(--red-line); font-weight:700; }
/* "We did not look." Colourless and dashed on purpose — an absence of evidence
   must never be able to be mistaken for evidence of absence. */
.pill.unchecked { color:var(--muted); background:transparent;
                  border-color:#cfd8da; border-style:dashed; font-weight:550; }

/* severity, for findings */
.pill.critical { color:var(--red);   background:var(--red-tint);   border-color:var(--red-line); }
.pill.high     { color:var(--red);   background:var(--red-tint);   border-color:var(--red-line); }
.pill.medium   { color:var(--amber); background:var(--amber-tint); border-color:var(--amber-line); }
.pill.low      { color:var(--muted); background:var(--chip); }

/* --- the four-step chain -------------------------------------------------
   ① invoiced → ② collected → ③ owner paid → ④ cleared bank.
   Discrete events, so: dots, not a progress bar.                            */
.chain { display:inline-flex; align-items:center; gap:4px; }
.chain i { width:11px; height:11px; border-radius:999px; display:block;
           border:1px solid transparent; }
.chain i.done    { background:var(--brand);     border-color:var(--brand-ink); }
.chain i.pending { background:var(--gold);      border-color:#d9a00f; }
.chain i.broken  { background:var(--red);       border-color:#8f1d17; }
.chain i.na      { background:transparent;      border-color:#c9d4d6; border-style:dashed; }
/* the run of dots reads left→right; a break is where the teal stops */
.chain b { width:6px; height:1px; background:var(--line); flex:none; }

/* --- dense ledger table --------------------------------------------------
   This is the app. Sticky head, tabular numerals, row hover, whole-row link. */
.tablewrap { overflow:auto; max-height:min(66vh, 720px);
             border:1px solid var(--line); border-radius:10px; background:var(--card); }
table.tbl { width:100%; border-collapse:separate; border-spacing:0; font-size:13.5px; }
table.tbl th, table.tbl td {
  text-align:left; padding:7px 10px; border-bottom:1px solid var(--line-soft);
  vertical-align:middle; }
table.tbl thead th {
  position:sticky; top:0; z-index:2; background:#fbfdfd;
  font-size:11px; font-weight:700; text-transform:uppercase; letter-spacing:.04em;
  color:var(--muted); border-bottom:1px solid var(--line); white-space:nowrap; }
table.tbl thead th a { color:inherit; }
table.tbl thead th[aria-sort] { color:var(--brand); }
table.tbl thead th[aria-sort="ascending"]::after  { content:" ▲"; font-size:9px; }
table.tbl thead th[aria-sort="descending"]::after { content:" ▼"; font-size:9px; }
table.tbl tbody tr:hover { background:#f4faf9; }
table.tbl tbody tr.active { background:var(--brand-tint); }
table.tbl tbody tr.flagged td:first-child { box-shadow:inset 3px 0 0 var(--red); }
table.tbl td.num { text-align:right; font-variant-numeric:tabular-nums;
                   font-feature-settings:"tnum" 1; white-space:nowrap; }
table.tbl td.num.zero { color:var(--muted); }
table.tbl td.key { font-weight:600; }
table.tbl td .sub { display:block; color:var(--muted); font-size:11.5px; }
table.tbl a.rowlink { color:var(--ink); display:block; }
table.tbl a.rowlink:hover { color:var(--brand); text-decoration:none; }
.tbl-foot { display:flex; justify-content:space-between; align-items:center;
            gap:12px; padding:9px 2px 0; font-size:12.5px; color:var(--muted); }

/* --- filter bar ---------------------------------------------------------- */
.filters { display:flex; flex-wrap:wrap; align-items:flex-end; gap:10px 14px;
           padding:12px 14px; background:var(--card); border:1px solid var(--line);
           border-radius:10px; margin-bottom:12px; }
.f { display:flex; flex-direction:column; gap:3px; }
.f > span { font-size:11px; font-weight:700; letter-spacing:.04em;
            text-transform:uppercase; color:var(--muted); }
.f input, .f select {
  font:inherit; font-size:13.5px; color:var(--ink); background:var(--card);
  border:1px solid var(--line); border-radius:8px; padding:6px 9px; min-height:32px; }
.f input:focus, .f select:focus {
  outline:none; border-color:var(--brand); box-shadow:0 0 0 3px var(--brand-tint); }
.f input[type=search] { min-width:230px; }
.f.check { flex-direction:row; align-items:center; gap:7px; padding-bottom:6px; }
.f.check > span { text-transform:none; letter-spacing:0; font-weight:500; font-size:13px; }
.filters .btn { align-self:flex-end; }

/* --- stat tiles (the funnel / headline numbers) -------------------------- */
.stat { border:1px solid var(--line); border-radius:10px; background:var(--card);
        padding:11px 13px; display:block; color:inherit; }
a.stat:hover { border-color:var(--brand-line); background:var(--brand-tint);
               text-decoration:none; }
.stat .lbl { font-size:11.5px; font-weight:600; letter-spacing:.03em;
             text-transform:uppercase; color:var(--muted); }
.stat .val { font-size:23px; font-weight:680; letter-spacing:-.02em; margin-top:2px;
             font-variant-numeric:tabular-nums; }
.stat .delta { font-size:12px; margin-top:2px; color:var(--muted); }
.stat .delta.bad { color:var(--red); font-weight:600; }
.stat.alert { border-color:var(--red-line); background:var(--red-tint); }
.stat.alert .val, .stat.alert .lbl { color:var(--red); }

/* --- stacked status bar (composition at a glance) ------------------------ */
.bar { display:flex; gap:2px; height:22px; margin:6px 0 8px; }
.bar > span { height:100%; border-radius:3px; display:block; }
.bar .s-paid      { background:var(--brand); }
.bar .s-part      { background:var(--amber); }
.bar .s-pending   { background:#9fb3b8; }
.bar .s-missing   { background:var(--red); }
.bar .s-unchecked { background:repeating-linear-gradient(45deg,#e3eaea 0 4px,#f4f8f8 4px 8px); }
.legend { display:flex; flex-wrap:wrap; gap:14px; font-size:12.5px; color:var(--muted); }
.legend span { display:inline-flex; align-items:center; gap:5px; white-space:nowrap; }
.legend i { width:9px; height:9px; border-radius:2px; display:inline-block; }
.legend b { color:var(--ink); }
/* thin progress meter, where a percentage really is the right mark */
.meter { height:7px; background:#e5e7eb; border-radius:999px; overflow:hidden; min-width:70px; }
.meter > span { display:block; height:100%; background:var(--brand); }

/* --- notices ------------------------------------------------------------- */
.notice { border-radius:10px; padding:11px 14px; font-size:14px; margin-bottom:16px;
          border:1px solid var(--line); background:var(--card); }
.notice.ok   { background:var(--brand-tint); border-color:var(--brand-line); color:var(--brand-ink); }
.notice.warn { background:var(--gold-tint);  border-color:var(--gold);       color:var(--gold-ink); }
.notice.err  { background:var(--red-tint);   border-color:var(--red-line);   color:var(--red); }

/* --- detail drawer (the drill-in) ---------------------------------------- */
.drawer { border:1px solid var(--line); border-radius:var(--radius); background:var(--card);
          box-shadow:var(--shadow); padding:18px; margin-top:16px; }
.drawer > .hd { display:flex; justify-content:space-between; align-items:baseline;
                gap:12px; margin-bottom:4px; }
.steps { display:grid; grid-template-columns:repeat(4,1fr); gap:12px; margin-top:14px; }
@media (max-width:900px){ .steps { grid-template-columns:1fr; } }
.step { border:1px solid var(--line); border-radius:10px; padding:12px 13px; background:var(--bg); }
.step.done   { border-color:var(--brand-line); background:var(--brand-tint); }
.step.broken { border-color:var(--red-line);   background:var(--red-tint); }
.step.na     { border-style:dashed; }
.step .hd { display:flex; align-items:center; gap:8px; margin-bottom:6px; font-weight:650;
            font-size:13.5px; }
.step .num { flex:none; width:21px; height:21px; border-radius:999px; background:var(--brand);
             color:#fff; font-size:11.5px; font-weight:700;
             display:inline-flex; align-items:center; justify-content:center; }
.step.broken .num { background:var(--red); }
.step.na .num { background:#c9d4d6; color:#fff; }

/* key/value evidence list — replaces st.write(dict) */
dl.kv { display:grid; grid-template-columns:auto 1fr; gap:3px 12px; margin:0; font-size:12.5px; }
dl.kv dt { color:var(--muted); white-space:nowrap; }
dl.kv dd { margin:0; font-variant-numeric:tabular-nums; }
.why { margin-top:9px; font-size:12px; color:var(--muted); }
.why summary { cursor:pointer; font-weight:600; color:var(--brand); }
.why ul { margin:5px 0 0; padding-left:16px; }
code, .mono { font-family:var(--mono); font-size:12.5px; }

/* --- findings ------------------------------------------------------------ */
.finding { display:flex; gap:9px; align-items:flex-start; padding:8px 0;
           border-bottom:1px solid var(--line-soft); font-size:13.5px; }
.finding:last-child { border-bottom:0; }
.finding .code { font-weight:650; }

/* --- print (accounting prints things) ------------------------------------ */
@media print {
  header.app, nav.views, .filters, .btn, .aid { display:none !important; }
  .tablewrap { max-height:none; overflow:visible; border:0; }
  .card, .drawer { box-shadow:none; border-color:#ccc; }
  body { background:#fff; font-size:11px; }
}

/* --- after-hours severity ------------------------------------------------
   Three rungs, matching lib/triage.py. Each pill carries a glyph AND a word;
   the colour only reinforces. `untriaged` is the dashed, colourless state: the
   model did not read this call, and that must never look like "routine".      */
.pill.emergency { color:var(--red);   background:var(--red-tint);   border-color:var(--red-line); font-weight:700; }
.pill.urgent    { color:var(--amber); background:var(--amber-tint); border-color:var(--amber-line); }
.pill.routine   { color:var(--brand-ink); background:var(--brand-tint); border-color:var(--brand-line); }
.pill.untriaged { color:var(--muted); background:transparent; border-color:#cfd8da;
                  border-style:dashed; font-weight:550; }

/* --- page-out delivery state --------------------------------------------- */
.pill.sent    { color:var(--brand-ink); background:var(--brand-tint); border-color:var(--brand-line); }
.pill.failed  { color:var(--red);   background:var(--red-tint);   border-color:var(--red-line); font-weight:700; }
.pill.skipped { color:var(--red);   background:var(--red-tint);   border-color:var(--red-line); }
.pill.dry_run { color:var(--gold-ink); background:var(--gold-tint); border-color:var(--gold); }
.pill.pending { color:#3a4a52; background:#eef3f3; border-color:#d5dee0; }

/* --- header brand lockup -------------------------------------------------- */
.brandbar .logo { height:24px; }

/* --- the page-out preview -------------------------------------------------
   Rendered as a phone bubble, not a text field. The whole review question is
   "does this read right on a lock screen at 2am", and a textarea does not
   answer it.                                                                  */
.sms { max-width:420px; background:var(--brand-tint); border:1px solid var(--brand-line);
       border-radius:16px 16px 16px 4px; padding:12px 14px; white-space:pre-wrap;
       font-size:14px; line-height:1.5; color:var(--ink); }
.sms-meta { font-size:12px; color:var(--muted); margin-top:6px; max-width:420px; }

/* --- raw payload ---------------------------------------------------------- */
pre.raw { margin:0; padding:12px 14px; background:#fbfdfd; border:1px solid var(--line);
          border-radius:10px; overflow:auto; max-height:460px;
          font-family:var(--mono); font-size:12px; line-height:1.5; color:var(--ink); }

/* --- editable rows (recipients) -------------------------------------------
   The on-call list is edited in place: its fields are its display. Inputs sit
   in the cells and point at a <form> after the table by id, because a <form>
   inside a <tr> is invalid markup.                                           */
table.tbl td > input {
  font:inherit; font-size:13.5px; color:var(--ink); background:var(--card);
  border:1px solid transparent; border-radius:7px; padding:4px 7px; min-height:29px; }
table.tbl td > input:hover { border-color:var(--line); }
table.tbl td > input:focus { outline:none; background:var(--card);
                             border-color:var(--brand); box-shadow:0 0 0 3px var(--brand-tint); }
table.tbl td .btn + .btn { margin-left:4px; }
.opt { text-transform:none; letter-spacing:0; font-weight:400; color:var(--muted); }
.inline-form input {
  font:inherit; font-size:13.5px; color:var(--ink); background:var(--card);
  border:1px solid var(--line); border-radius:8px; padding:5px 8px; min-height:30px; }
.inline-form input:focus { outline:none; border-color:var(--brand);
                           box-shadow:0 0 0 3px var(--brand-tint); }
tr.off td { opacity:.55; }
tr.off td .pill { opacity:1; }

/* --- empty state ----------------------------------------------------------- */
.empty { text-align:center; padding:44px 20px; color:var(--muted); }
.empty h3 { color:var(--ink); margin-bottom:6px; }
