/* Edparrow CRM — one stylesheet, two surfaces. THE DEPARTURES BOARD, 20 Sep 2026.

   Every order line is a departure: it has a time, a gate, a seat and a status,
   and the CRM is the board that says what leaves next and what is late. The
   board is the TOP of every page — the espresso strip that carries the jump
   box, the clock and the day's counts — and on the two pages where time is the
   axis (Dashboard, Schedule) it simply extends downward into rows. One dark
   region per page, continuous, never two. Everything under it is the terminal
   hall: ivory paper, 1px warm rules, brass as the only accent.

   Rules this file keeps:
   - Status is a split-flap chip in one of FOUR tensions — owed by us (amber),
     waiting on them (outline), delivered (green), failed (red). Never a fifth.
   - Numbers are tabular everywhere; dates and counts right-align in columns.
   - One 8px module. Rows are 44px. Gutters are 24px. Nothing is spaced by feel.
   - Rarely used actions live in a <details class="menu">; secondary forms in a
     <details class="drawer">. Both are real HTML first and enhanced after.
   - Light and dark are three blocks in a fixed order (see below); a colour that
     exists only in one mode is a test failure.

   Class names the old templates used (.chip, .tbox, .pcard, .tile, .phead,
   .note, .kv, .copyrow …) are kept as aliases so a page is never unstyled
   between two commits. */

:root{
  --paper:#F6F0E8; --paper-2:#EDE5D9; --card:#FBF8F3; --hover:#F1EADF;
  --ink:#221B17; --ink-2:#5C5148; --ink-3:#6E6154;
  --rule:#E3D9CB; --rule-2:#CFC1AE;

  /* THE BOARD. In LIGHT it is a paper panel a shade deeper than the hall,
     edged in brass — a light theme does not carry a dark band. In DARK it is
     the espresso panel, lit from within (see the dark blocks). */
  --board:#EFE7DA; --board-2:#E7DDCE; --board-3:#DFD3BF;
  --board-ink:#221B17; --board-ink-2:#5C5148; --board-ink-3:#6E6154;
  --board-rule:#E3D9CB;

  /* BRASS, the only accent. Surfaces take the metal; text takes the darker
     bronze so it clears 4.5:1 on ivory. */
  --brass:#B8862B; --brass-2:#A2741F; --brass-ink:#8A5A19; --brass-soft:#F3E7CF;
  --sel-ink:#221B17;   /* on --brass, light: 5.24:1 */
  --brass-on-board:#8A5A19;

  /* The four tensions. */
  --owed:#8A5610;  --owed-soft:#F7E8CF;
  --good:#176B46;  --good-soft:#DDF0E5;  --good-ink:#FFFFFF;
  --bad:#A3301E;   --bad-soft:#F8DED8;  --bad-ink:#FFFFFF;
  --warn:#8A5610;  --warn-soft:#F7E8CF;

  --seam:rgba(34,27,23,.13);
  --shadow:0 1px 2px rgba(34,27,23,.06), 0 8px 24px -12px rgba(34,27,23,.22);
  --shadow-lg:0 2px 6px rgba(34,27,23,.08), 0 24px 56px -24px rgba(34,27,23,.35);
  --r:6px; --r-sm:4px; --r-xs:3px;
  --side:232px; --strip:52px; --gut:24px;
  color-scheme:light;
}

/* DARK IS A CHOICE, NOT ONLY A SYSTEM SETTING. Three blocks, this order:
     1. :root                          light, always defined
     2. prefers-color-scheme: dark     follow the OS unless light was chosen
     3. [data-theme="dark"]            an explicit choice beats everything

   THE CUSTOMER PORTAL IS THE ONE EXCEPTION TO BLOCK 2 (founder, 30 Sep 2026:
   "light mode is the default on customer portals"). `:not([data-surface=
   "portal"])` below means a portal page on a dark-OS machine still opens
   light — the staff board is unaffected, and the toggle (base.html, stored
   per-origin in localStorage) still overrides either way via block 3. */
@media (prefers-color-scheme:dark){:root:not([data-theme="light"]):not([data-surface="portal"]){
  --paper:#1F1915; --paper-2:#28211C; --card:#251E19; --hover:#2E2620;
  --ink:#F1E9DD; --ink-2:#BFB2A3; --ink-3:#9A8E82;
  --rule:#3A302A; --rule-2:#4B3F37;

  /* THE BOARD IS THE LIT PANEL. In a dark hall it sits ABOVE the ground in
     value, not below it, or the one espresso region reads as a hole rather
     than as the board. */
  --board:#382E27; --board-2:#43382F; --board-3:#4A3F36;
  --board-ink:#F6EFE4; --board-ink-2:#BBAC99; --board-ink-3:#B0A290;
  --board-rule:rgba(246,239,228,.14);

  --brass:#D2A24A; --brass-2:#E0B562; --brass-ink:#E4BC6B; --brass-soft:#3A2E1A;
  --sel-ink:#1F1915;   /* on --brass, dark: 7.46:1 */
  --brass-on-board:#E7BC60;

  --owed:#E0A54A;  --owed-soft:#3E2E15;
  --good:#4CBF86;  --good-soft:#1E3A2C;  --good-ink:#0E2B1D;
  --bad:#EE6F5C;   --bad-soft:#452420;  --bad-ink:#2A1512;
  --warn:#E0A54A;  --warn-soft:#3E2E15;

  --seam:rgba(0,0,0,.30);
  --shadow:0 1px 2px rgba(0,0,0,.4), 0 8px 24px -12px rgba(0,0,0,.6);
  --shadow-lg:0 2px 6px rgba(0,0,0,.45), 0 24px 56px -24px rgba(0,0,0,.8);
  color-scheme:dark;
}}

:root[data-theme="dark"]{
  --paper:#1F1915; --paper-2:#28211C; --card:#251E19; --hover:#2E2620;
  --ink:#F1E9DD; --ink-2:#BFB2A3; --ink-3:#9A8E82;
  --rule:#3A302A; --rule-2:#4B3F37;

  --board:#382E27; --board-2:#43382F; --board-3:#4A3F36;
  --board-ink:#F6EFE4; --board-ink-2:#BBAC99; --board-ink-3:#B0A290;
  --board-rule:rgba(246,239,228,.14);

  --brass:#D2A24A; --brass-2:#E0B562; --brass-ink:#E4BC6B; --brass-soft:#3A2E1A;
  --sel-ink:#1F1915;   /* on --brass, dark: 7.46:1 */
  --brass-on-board:#E7BC60;

  --owed:#E0A54A;  --owed-soft:#3E2E15;
  --good:#4CBF86;  --good-soft:#1E3A2C;  --good-ink:#0E2B1D;
  --bad:#EE6F5C;   --bad-soft:#452420;  --bad-ink:#2A1512;
  --warn:#E0A54A;  --warn-soft:#3E2E15;

  --seam:rgba(0,0,0,.30);
  --shadow:0 1px 2px rgba(0,0,0,.4), 0 8px 24px -12px rgba(0,0,0,.6);
  --shadow-lg:0 2px 6px rgba(0,0,0,.45), 0 24px 56px -24px rgba(0,0,0,.8);
  color-scheme:dark;
}

*{box-sizing:border-box}
html{scrollbar-color:var(--rule-2) transparent;caret-color:var(--brass)}
body{margin:0;background:var(--paper);color:var(--ink);
  font-family:Barlow,ui-sans-serif,system-ui,-apple-system,"Segoe UI",sans-serif;
  font-size:14px;line-height:1.5;-webkit-font-smoothing:antialiased;
  font-variant-numeric:tabular-nums;
  transition:background-color .25s ease,color .25s ease}
/*  SELECTION HAS TO BE VISIBLE AS A SELECTION.
    It was --brass-soft, which is 1.16:1 against the card in light mode and
    1.24:1 in dark — the text stayed readable and the HIGHLIGHT was the thing
    you could not see, so selecting looked like nothing had happened.
    Measured: --brass is 3.06:1 against the card in light and 7.05:1 in dark,
    with the text on it at 5.24:1 and 7.46:1. --sel-ink is the near-black or
    near-white that each theme needs on top of it. */
::selection{background:var(--brass);color:var(--sel-ink)}
::-moz-selection{background:var(--brass);color:var(--sel-ink)}
h1,h2,h3{margin:0;font-weight:600;letter-spacing:-.01em;text-wrap:balance;line-height:1.3}
h1{font-size:22px}
h2{font-size:17px}
h3{font-size:15px}
p{margin:0 0 8px}
a{color:var(--brass-ink);text-underline-offset:2px;text-decoration-thickness:1px}
a:hover{color:var(--ink)}
:focus-visible{outline:2px solid var(--brass);outline-offset:2px}
button,input,select,textarea{font:inherit;color:inherit}

/* Mono ONLY for things a human compares character by character. */
code,.mono{font-family:"JetBrains Mono",ui-monospace,SFMono-Regular,monospace;
  font-size:.86em;background:var(--paper-2);padding:1px 5px;border-radius:var(--r-xs);color:var(--ink-2)}
.num{font-variant-numeric:tabular-nums;text-align:right}
.s{font-size:12px;color:var(--ink-3)}
.muted{color:var(--ink-3)}
.cond{font-family:"Barlow Semi Condensed",Barlow,system-ui,sans-serif}

/* =========================================================================
   THE SHELL — rail · strip · hall
   ====================================================================== */
.shell{display:grid;grid-template-columns:var(--side) minmax(0,1fr);min-height:100vh}

.side{background:var(--paper-2);border-right:1px solid var(--rule);
  display:flex;flex-direction:column;padding:12px 10px;gap:8px;
  position:sticky;top:0;height:100vh;overflow-y:auto}
.side .brand{display:flex;align-items:center;gap:10px;padding:6px 8px 14px;
  font-family:"Barlow Semi Condensed",Barlow,sans-serif;font-size:17px;font-weight:700;
  letter-spacing:.02em;text-transform:uppercase;color:var(--ink)}
.side .brand .mark{width:26px;height:26px;flex:0 0 26px;border-radius:var(--r-sm);
  background:var(--board);color:var(--brass-on-board);display:grid;place-items:center;
  font-size:14px;font-weight:700;letter-spacing:0}
.side nav{display:flex;flex-direction:column;gap:1px}
.side nav a{position:relative;display:flex;align-items:center;gap:10px;padding:8px 10px;
  border-radius:var(--r-sm);text-decoration:none;color:var(--ink-2);font-size:14px;
  font-weight:500;line-height:1.3;min-height:36px}
.side nav a:hover{background:var(--hover);color:var(--ink)}
.side nav a.on{background:var(--brass-soft);color:var(--ink);font-weight:600}
.side nav a.on::before{content:"";position:absolute;left:0;top:8px;bottom:8px;width:2px;
  border-radius:2px;background:var(--brass)}
.side nav a .ico{width:18px;flex:0 0 18px;display:grid;place-items:center;opacity:.9}
.side nav a .ico svg{width:16px;height:16px;stroke-width:1.8}
.side nav a .tally{margin-left:auto;font-size:11px;font-weight:600;min-width:20px;
  text-align:center;padding:1px 6px;border-radius:10px;background:var(--paper);
  color:var(--ink-3);border:1px solid var(--rule)}
.side nav a .tally.hot{background:var(--bad-soft);color:var(--bad);border-color:transparent}
.side .group{font-family:"Barlow Semi Condensed",Barlow,sans-serif;font-size:11px;
  font-weight:600;letter-spacing:.08em;text-transform:uppercase;color:var(--ink-3);
  padding:14px 10px 4px}
.side .spacer{flex:1}
.side .me{display:flex;align-items:center;gap:10px;padding:16px 8px 8px;border-top:1px solid var(--rule)}
.side .me .who{min-width:0;line-height:1.35}
.side .me .who b{display:block;font-size:13px;font-weight:600;white-space:nowrap;
  overflow:hidden;text-overflow:ellipsis}
.side .me .who span{display:block;font-size:12px;line-height:1.4;color:var(--ink-3);text-transform:capitalize}
.side .me a{margin-left:auto;font-size:12px;color:var(--ink-3);text-decoration:none}
.side .me a:hover{color:var(--bad)}

.avatar{width:32px;height:32px;flex:0 0 32px;border-radius:50%;display:grid;
  place-items:center;font-size:12px;font-weight:600;color:var(--board-ink);
  background:var(--board);letter-spacing:.02em}
.avatar.sm{width:26px;height:26px;flex-basis:26px;font-size:10px}
.avatar.lg{width:48px;height:48px;flex-basis:48px;font-size:17px;border-radius:var(--r)}

.main{min-width:0;display:flex;flex-direction:column}

/* THE STRIP: the top of the board, on every page. Sticky, espresso, one brass
   hairline underneath. On Dashboard and Schedule a .board.top sits flush under
   it and the two read as one panel. */
.strip{background:var(--board);color:var(--board-ink);min-height:var(--strip);
  display:flex;align-items:center;gap:12px;padding:8px var(--gut);
  position:sticky;top:0;z-index:30;border-bottom:1px solid var(--brass);flex-wrap:wrap}
.strip .push{flex:1}
.strip a{color:var(--brass-on-board)}
.strip .wsform{display:flex;align-items:center;gap:8px}
.strip .wsform label{font-size:12px;color:var(--board-ink-2)}
.strip select,.strip input{background:var(--board-2);border:1px solid var(--board-rule);
  color:var(--board-ink);border-radius:var(--r-sm);height:32px;padding:0 10px}
.strip select{font-weight:600;padding-right:28px;cursor:pointer;appearance:none;max-width:220px;
  background-image:linear-gradient(45deg,transparent 50%,currentColor 50%),
                   linear-gradient(135deg,currentColor 50%,transparent 50%);
  background-position:calc(100% - 14px) 55%,calc(100% - 9px) 55%;
  background-size:5px 5px,5px 5px;background-repeat:no-repeat}
.strip select:focus,.strip input:focus{border-color:var(--brass-on-board);outline:none}
.strip .jump{position:relative;flex:1 1 220px;max-width:420px}
.strip .jump input{width:100%;padding-left:32px}
.strip .jump input::placeholder{color:var(--board-ink-3)}
.strip .jump svg{position:absolute;left:10px;top:50%;transform:translateY(-50%);
  width:15px;height:15px;color:var(--board-ink-3);pointer-events:none}
.strip .clock{display:flex;flex-direction:column;line-height:1.15;text-align:right;
  font-variant-numeric:tabular-nums;white-space:nowrap}
.strip .clock b{font-weight:600;font-size:14px;letter-spacing:.02em}
.strip .clock span{font-size:12px;line-height:1.4;color:var(--board-ink-2)}
.strip .clock span.stale{color:var(--owed)}

/* Mail switch: a setting a person can read, not a rail that is armed. */
.mailpill{display:inline-flex;align-items:center;gap:7px;font-size:12px;font-weight:500;
  padding:0 10px;height:28px;border-radius:14px;border:1px solid var(--board-rule);
  color:var(--board-ink-2);white-space:nowrap}
.mailpill .led{width:6px;height:6px;border-radius:50%;background:var(--board-ink-3)}
.mailpill.on{color:var(--good);border-color:transparent;background:var(--good-soft)}
.mailpill.on .led{background:var(--good)}

/* Automation card header: OFF / SHADOW / LIVE, by lightness not a second hue. */
.modeflag{font-size:12px;font-weight:600}
.modeflag.live{color:var(--good)}
.modeflag.shadow{color:var(--owed)}
.modeflag.off{color:var(--ink-3)}

/* SOMEBODY IS WAITING ON AN ANSWER. Only rendered when the number is above zero. */
.waitpill{display:inline-flex;align-items:center;gap:7px;text-decoration:none;
  background:var(--owed-soft);color:var(--owed);font-weight:600;font-size:12px;
  padding:0 10px 0 8px;height:28px;border-radius:14px;border:1px solid transparent;transition:.15s}
.waitpill:hover{background:var(--owed);color:var(--board)}
.waitpill .ico{width:14px;height:14px;display:inline-grid}
.waitpill .ico svg{width:14px;height:14px}
.waitpill .n{font-variant-numeric:tabular-nums}
.waitpill .lbl{font-weight:500}

/* FITS ANY SCREEN (founder, 31 Oct 2026): capped and CENTRED, not left-stuck
   against the sidebar — 1320px on a 2560px monitor left half the glass empty.
   2200px still reads as a column, not edge-to-edge, and leaves even gutters
   on a 2560px screen either side; below that `width:100%` plus `margin:auto`
   already centres a column narrower than the viewport, and `--gut` shrinking
   to 16px at 720px (further down) gets a full-width column with even gutters
   on a phone. The board's own negative margin (`.board.top` below) still only
   cancels this element's OWN padding, so it bleeds to `.wrap`'s edge, never
   past it — unaffected by the centring. */
.wrap{padding:var(--gut);max-width:2200px;width:100%;margin:0 auto}
/* PORTAL — left exactly as it was: a narrower, still-centred measure for
   sign-in, home, packages. */
[data-surface="portal"] .wrap{max-width:1120px;margin:0 auto}
.foot{padding:8px var(--gut) 32px;color:var(--ink-3);font-size:12px}

/* =========================================================================
   THE BOARD — the strip's continuation. Rows of departures.
   ====================================================================== */
.board{background:var(--board);color:var(--board-ink);border-bottom:1px solid var(--brass)}
.board.top{margin:calc(-1 * var(--gut)) calc(-1 * var(--gut)) var(--gut)}
.board-head{display:flex;align-items:center;gap:20px;flex-wrap:wrap;
  padding:14px var(--gut) 12px;border-bottom:1px solid var(--board-rule)}
.board-head h2{font-family:"Barlow Semi Condensed",Barlow,sans-serif;font-size:14px;
  font-weight:600;letter-spacing:.12em;text-transform:uppercase;color:var(--board-ink)}
.board-head .sub{font-size:12px;line-height:1.4;color:var(--board-ink-2)}
.board-head .push{flex:1}
.counts{display:flex;gap:20px;flex-wrap:wrap}
.counts a,.counts span.count{display:flex;align-items:baseline;gap:6px;text-decoration:none;
  color:var(--board-ink-2);font-size:12px;letter-spacing:.02em}
.counts b{font-size:18px;font-weight:600;color:var(--board-ink);font-variant-numeric:tabular-nums;
  letter-spacing:-.01em}
.counts .hot b{color:var(--owed)}
.counts .bad b{color:var(--bad)}
.counts a:hover{color:var(--board-ink)}
.board table{width:100%;border-collapse:collapse;font-size:14px}
.board th{font-family:"Barlow Semi Condensed",Barlow,sans-serif;font-size:11px;font-weight:600;
  letter-spacing:.1em;text-transform:uppercase;color:var(--board-ink-3);text-align:left;
  padding:10px 12px;border-bottom:1px solid var(--board-rule);white-space:nowrap;background:transparent}
/* The hall's `td b` is dark ink; on the board a bold word must stay ivory. */
.board td b,.board td strong{color:var(--board-ink)}
.board td{padding:0 12px;height:44px;border-bottom:1px solid var(--board-rule);
  color:var(--board-ink);vertical-align:middle}
.board th:first-child,.board td:first-child{padding-left:var(--gut)}
.board th:last-child,.board td:last-child{padding-right:var(--gut)}
.board tbody tr:last-child td{border-bottom:none}
/* The board keeps its own flat espresso panel — the hall's zebra tint below
   is for the ivory tables, never this one. */
.board tbody tr:nth-child(even) td{background:transparent}
.board tbody tr:hover td{background:var(--board-2)}
.board tr[data-href]:hover td{background:var(--board-3)}
.board td .s,.board .s{color:var(--board-ink-2)}
/* A SECONDARY LINE ON THE BOARD takes the BOARD's dim ink, not the hall's.
   The hall's --ink-3 over the lit espresso panel is 4.13:1; the board's own
   is 5.30:1. Only visible at phone width, which is where it matters most. */
.board td .two{color:var(--board-ink-3)}
.board td a{color:var(--board-ink);text-decoration:none}
.board td a:hover{color:var(--brass-on-board)}
.board .when{font-variant-numeric:tabular-nums;white-space:nowrap}
.board .when b{display:block;font-weight:600}
.board .when span{font-size:12px;color:var(--board-ink-2)}
.board .btn.ghost{background:transparent;color:var(--board-ink);border-color:var(--board-rule)}
.board .btn.ghost:hover{border-color:var(--brass-on-board);color:var(--brass-on-board)}
.board .btn{background:var(--brass-on-board);color:var(--board)}
.board .btn:hover{background:#F0C46A}
.board .empty{background:transparent;border:none;color:var(--board-ink-2);padding:32px var(--gut)}
.board .empty h2{color:var(--board-ink)}
.board .brandtag{color:var(--board-ink-2)}
.board .flap.waiting{background:transparent;border-color:var(--rule-2);color:var(--board-ink-3)}
/* ON THE ESPRESSO BOARD ONLY — in dark the chip takes the board's own raised
   surface and the ink carries the tension, because a tint of its own hue over
   espresso cannot clear 4.5:1 at any board value. In light the board is paper,
   so a chip behaves exactly like every other chip on the page. */
@media (prefers-color-scheme:dark){:root:not([data-theme="light"]) .board .flap{
  background:var(--board-3);border-color:transparent}
  :root:not([data-theme="light"]) .board .flap.owed{color:#E0A54A}
  :root:not([data-theme="light"]) .board .flap.done{color:#58C892}
  :root:not([data-theme="light"]) .board .flap.failed{color:#FF9484}
  :root:not([data-theme="light"]) .board .flap.waiting{border-color:var(--board-rule);color:var(--board-ink-2)}}
:root[data-theme="dark"] .board .flap{background:var(--board-3);border-color:transparent}
:root[data-theme="dark"] .board .flap.owed{color:#E0A54A}
:root[data-theme="dark"] .board .flap.done{color:#58C892}
:root[data-theme="dark"] .board .flap.failed{color:#FF9484}
:root[data-theme="dark"] .board .flap.waiting{border-color:var(--board-rule);color:var(--board-ink-2)}
.board .foot-link{display:block;padding:10px var(--gut);font-size:12px;color:var(--board-ink-2);
  text-decoration:none;border-top:1px solid var(--board-rule)}
.board .foot-link:hover{color:var(--brass-on-board)}
.board .menu-list{color:var(--ink)}

/* =========================================================================
   PAGE HEAD — one line: title, count, primary action, ⋯, About
   ====================================================================== */
.pagehead{display:flex;align-items:center;gap:12px;margin:0 0 16px;min-height:36px;flex-wrap:wrap}
.pagehead h1{display:flex;align-items:baseline;gap:8px}
.pagehead h1 .count{font-size:14px;font-weight:500;color:var(--ink-3);font-variant-numeric:tabular-nums}
.pagehead .crumb{font-size:12px;color:var(--ink-3)}
.pagehead .crumb a{color:var(--ink-3);text-decoration:none}
.pagehead .crumb a:hover{color:var(--ink)}
.pagehead .actions{margin-left:auto;display:flex;gap:8px;align-items:center;flex-wrap:wrap}
.pagehead p{margin:0;color:var(--ink-3);font-size:13px;flex-basis:100%}
.sect{margin:28px 0 10px;font-size:15px;color:var(--ink)}
.sect .s{margin-left:8px;font-weight:400}

/* Filters: one row that wraps, compact controls. */
.filters{display:flex;gap:8px;flex-wrap:wrap;align-items:center;margin:0 0 12px}
.filters .search{position:relative;flex:1 1 200px;max-width:360px}
.filters .search input{width:100%;padding-left:30px}
.filters .search svg{position:absolute;left:9px;top:50%;transform:translateY(-50%);
  width:14px;height:14px;color:var(--ink-3);pointer-events:none}
.filters label{display:flex;align-items:center;gap:6px;font-size:12px;color:var(--ink-3)}
.filters .push{flex:1}
.filters .n{font-size:12px;color:var(--ink-3);white-space:nowrap}

/* =========================================================================
   TABLES — the grid. Dates first, numbers right, one row one thing.
   ====================================================================== */
.tbl{border:1px solid var(--rule);border-radius:var(--r);background:var(--card);overflow:hidden}
.tbl.scroll{overflow-x:auto}
table.grid,table{border-collapse:collapse;width:100%;font-size:14px}
th{text-align:left;padding:8px 12px;font-family:"Barlow Semi Condensed",Barlow,sans-serif;
  font-size:11px;font-weight:600;letter-spacing:.09em;text-transform:uppercase;color:var(--ink-3);
  border-bottom:1px solid var(--rule);white-space:nowrap;background:var(--paper-2)}
td{padding:6px 12px;height:44px;border-bottom:1px solid var(--rule);vertical-align:middle;color:var(--ink-2);
  /* A long e-mail or title breaks inside the CELL, never pushes the table
     past the page — overflow-wrap:anywhere also lets it break mid-word,
     which ellipsis-less long tokens (addresses, titles) otherwise would not. */
  overflow-wrap:anywhere}
/* ...except a number: "$8,091.00" broken across two lines reads as two
   figures (31 Oct 2026, phone screenshot). */
td.num,th.num{white-space:nowrap;overflow-wrap:normal}
th:first-child,td:first-child{padding-left:16px}
th:last-child,td:last-child{padding-right:16px}
tbody tr:last-child td{border-bottom:none}
/* ALTERNATE-ROW SHADING, so a wide row of numbers does not need to be
   re-traced to find which cell belongs to which row. Derived from --card and
   --ink with color-mix rather than a fixed hex, so it is correct in both
   themes without a second rule — the board keeps its own espresso hover and
   is not touched here. */
tbody tr:nth-child(even) td{background:color-mix(in srgb, var(--card) 95%, var(--ink) 5%)}
tbody tr:hover td{background:var(--hover)}
td b,td strong{color:var(--ink);font-weight:600}
td a{text-decoration:none;color:var(--brass-ink)}
td a:hover{text-decoration:underline}
/* A LINK ON A SECONDARY LINE IS STILL A LINK. `td .two` is declared after
   `td a` at the same specificity, so an <a class="two"> silently lost its
   colour and read as plain ink — the row's way in looked like a label. */
td a.two,td .two a{color:var(--brass-ink);text-decoration:underline;
  text-decoration-thickness:1px;text-underline-offset:2px;
  text-decoration-color:color-mix(in srgb,var(--brass-ink) 45%,transparent)}
td a.two:hover,td .two a:hover{text-decoration-color:currentColor;color:var(--ink)}
td.num,th.num{text-align:right;font-variant-numeric:tabular-nums}
td.when,th.when{white-space:nowrap;font-variant-numeric:tabular-nums}
td.act,th.act{text-align:right;white-space:nowrap}
td.act .btn,td.act .menu{vertical-align:middle}
td .two{display:block;font-size:12px;color:var(--ink-3);line-height:1.3}
.clamp,td .two.clamp,td .s.clamp{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
tr[data-href]{cursor:pointer}
tr[data-href]:hover td{background:var(--brass-soft)}
tr[data-href]:focus-visible{outline:2px solid var(--brass);outline-offset:-2px}
tr.faded td{color:var(--ink-3)}
tr.faded td b{color:var(--ink-2)}

/* A name with its email under it, the pattern every row in this CRM uses. */
.person{display:flex;align-items:center;gap:10px;min-width:0}
.person .who{min-width:0}
.person .who b{display:block;line-height:1.3;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:26ch}
.person .who .s{display:block;line-height:1.3;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:30ch}

/* A brand, said quietly beside a row. */
.brandtag{font-family:"Barlow Semi Condensed",Barlow,sans-serif;font-size:11px;font-weight:600;
  letter-spacing:.06em;text-transform:uppercase;color:var(--ink-3);white-space:nowrap}

/* The same brand, as a 16px mark before a class/course title (T7). */
.bmark{width:16px;height:16px;border-radius:3px;vertical-align:-3px;margin-right:6px}

/* =========================================================================
   FLAPS — state must read at a glance, in one of four tensions
   ====================================================================== */
.flap,.chip{display:inline-flex;align-items:center;justify-content:center;gap:5px;
  font-family:"Barlow Semi Condensed",Barlow,sans-serif;font-size:11px;font-weight:600;
  letter-spacing:.06em;text-transform:uppercase;line-height:1.3;min-width:7.5em;
  padding:4px 8px;border-radius:var(--r-xs);white-space:nowrap;
  background:var(--paper-2);color:var(--ink-2);border:1px solid transparent;
  transform-origin:50% 0;backface-visibility:hidden}
.flap{overflow:hidden}
/* The split, which is the whole reason it is called a flap. It is drawn as
   part of the chip's BACKGROUND, not as an overlay: an ::after hairline at
   50% crosses the glyphs and reads as a strikethrough the moment the ground
   is pale. As a gradient stop it passes behind the letters, which is where a
   real flap's seam is. */
.flap{background-image:linear-gradient(var(--seam),var(--seam));
  background-size:100% 1px;background-position:0 50%;background-repeat:no-repeat}
.flap.waiting{background-image:none}
.flap.owed,.chip.warn{background:var(--owed-soft);color:var(--owed)}
.flap.waiting,.chip.hold{background:transparent;border-color:var(--rule-2);color:var(--ink-3)}
.flap.done,.chip.live{background:var(--good-soft);color:var(--good)}
.flap.failed,.chip.bad{background:var(--bad-soft);color:var(--bad)}
.flap.door,.chip.door{background:var(--brass-soft);color:var(--brass-ink);min-width:0}
.flap.sm,.chip.sm{min-width:0;padding:4px 6px;font-size:11px}
.flap .led,.chip .led{width:5px;height:5px;border-radius:50%;background:currentColor;opacity:.85}
/* THE FLIP. Only the row you just changed, once. */
@keyframes flip{0%{transform:rotateX(-90deg);opacity:.2}60%{transform:rotateX(12deg)}100%{transform:none;opacity:1}}
.flap.flip{animation:flip .55s cubic-bezier(.2,.8,.2,1) both}
tr.flash td,.card.flash{animation:flash 1.6s ease-out both}
@keyframes flash{0%{background:var(--brass-soft)}100%{background:transparent}}

/* A quiet progress bar, for "3 of 5 delivered". */
.bar{height:4px;border-radius:2px;background:var(--paper-2);overflow:hidden;min-width:64px}
.bar i{display:block;height:100%;background:var(--brass)}
.bar.good i{background:var(--good)}

/* =========================================================================
   BUTTONS & FORMS — compact, 32px, brass plate for the primary
   ====================================================================== */
button,.btn{font-family:inherit;font-size:13px;font-weight:600;height:32px;padding:0 12px;
  border-radius:var(--r-sm);border:1px solid transparent;background:var(--brass);
  color:#1E1610;cursor:pointer;text-decoration:none;display:inline-flex;align-items:center;
  justify-content:center;gap:6px;line-height:1.3;white-space:nowrap;
  transition:background .15s ease,color .15s ease,border-color .15s ease,transform .1s ease}
button:hover,.btn:hover{background:var(--brass-2);color:#1E1610}
button:active,.btn:active{transform:translateY(1px)}
button.ghost,.btn.ghost{background:transparent;color:var(--ink-2);border-color:var(--rule-2)}
button.ghost:hover,.btn.ghost:hover{background:var(--hover);color:var(--ink);border-color:var(--rule-2)}
button.quiet,.btn.quiet{background:transparent;color:var(--brass-ink);border-color:transparent;padding:0 8px}
button.quiet:hover,.btn.quiet:hover{background:var(--brass-soft);color:var(--ink)}
button.danger,.btn.danger{background:var(--bad);color:var(--bad-ink)}
button.danger:hover,.btn.danger:hover{filter:brightness(1.08);color:var(--bad-ink)}
button.sm,.btn.sm{height:28px;padding:0 10px;font-size:12px}
button.lg,.btn.lg{height:40px;padding:0 18px;font-size:14px}
button.icon,.btn.icon{width:32px;padding:0}
button.icon.sm,.btn.icon.sm{width:28px}
button.icon svg,.btn.icon svg{width:16px;height:16px}
button:disabled,.btn[aria-disabled="true"]{opacity:.45;cursor:not-allowed}
.btn .ico svg,button .ico svg{width:15px;height:15px}
.linky{background:none;border:0;color:var(--brass-ink);font-size:12px;cursor:pointer;padding:0;height:auto;font-weight:500}
.linky:hover{background:none;color:var(--ink);text-decoration:underline}

input,select,textarea{font-family:inherit;font-size:14px;height:32px;padding:0 10px;
  border-radius:var(--r-sm);border:1px solid var(--rule-2);background:var(--card);
  color:var(--ink);max-width:100%}
textarea{height:auto;padding:8px 10px;line-height:1.45;min-height:96px}
input::placeholder,textarea::placeholder{color:var(--ink-3)}
input:focus,select:focus,textarea:focus{border-color:var(--brass);outline:none;
  box-shadow:0 0 0 3px var(--brass-soft)}
input[type=checkbox],input[type=radio]{height:auto;width:auto;accent-color:var(--brass);margin:0 4px 0 0}
select{padding-right:28px;appearance:none;cursor:pointer;
  background-image:linear-gradient(45deg,transparent 50%,currentColor 50%),
                   linear-gradient(135deg,currentColor 50%,transparent 50%);
  background-position:calc(100% - 14px) 55%,calc(100% - 9px) 55%;
  background-size:5px 5px,5px 5px;background-repeat:no-repeat}
.row{display:flex;gap:10px;flex-wrap:wrap;align-items:flex-end;margin-bottom:16px}
.field{display:flex;flex-direction:column;gap:5px;min-width:0}
.field label{font-size:12px;font-weight:600;color:var(--ink-2)}
.field .hint{font-size:12px;color:var(--ink-3);font-weight:400}
.field.grow{flex:1 1 200px}
.formgrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:12px;margin-bottom:12px}
.inline{display:inline-flex;gap:6px;align-items:center;flex-wrap:wrap}
.inline input{height:28px;font-size:13px}
.code-input{font-family:"JetBrains Mono",ui-monospace,monospace;font-size:24px;height:auto;
  padding:8px 12px;letter-spacing:.3em;text-align:center;width:11ch}
.search{position:relative;flex:1;min-width:200px;max-width:420px}
.search input{width:100%;padding-left:32px}
.search svg{position:absolute;left:10px;top:50%;transform:translateY(-50%);width:15px;height:15px;color:var(--ink-3);pointer-events:none}

/* THE RICH-TEXT BODY (Letters, T5): a contenteditable div dressed to match
   the textarea beside it, since no <textarea> can hold the b/i/a/ul a letter
   actually carries. Same tokens, so it never reads as a second design system. */
.rtebar{display:flex;gap:6px;margin-bottom:6px}
.rte{min-height:160px;padding:8px 10px;line-height:1.45;font-size:14px;
  border-radius:var(--r-sm);border:1px solid var(--rule-2);background:var(--card);color:var(--ink)}
.rte:focus{outline:none;border-color:var(--brass);box-shadow:0 0 0 3px var(--brass-soft)}
.rte p{margin:0 0 .8em}
.rte:empty::before{content:attr(aria-label);color:var(--ink-3)}
/* THE INSERT ROW. Reuses the ghost-button look rather than inventing a chip:
   a placeholder you click is a small ACTION, not a label. */
.insertrow{display:flex;gap:6px;flex-wrap:wrap;margin:4px 0 2px}

/* A link shown to be COPIED. Compact: the address is the field, Copy beside it. */
.copyrow{display:inline-flex;gap:4px;align-items:center;min-width:0;max-width:100%}
.copyrow .copytext{flex:1 1 auto;min-width:0;width:200px;height:28px;font-size:12px;
  padding:0 8px;border:1px solid var(--rule);border-radius:var(--r-xs);
  background:var(--paper-2);color:var(--ink-2);text-overflow:ellipsis}
.copyrow .copytext:focus{outline:2px solid var(--brass);outline-offset:1px;color:var(--ink)}
.copyrow .btn{flex:0 0 auto}
/* A confirmation flips its ink with the theme for the same reason the
   destructive button does: white on the dark theme's lighter green was
   2.31:1, and it only exists for the 1.4s after a click, which is exactly
   how it stayed invisible to a sweep of the page at rest. */
.copybtn.ok{background:var(--good);color:var(--good-ink);border-color:transparent}

/* =========================================================================
   MENUS (⋯) and DRAWERS — real HTML first, enhanced after
   ====================================================================== */
.menu{position:relative;display:inline-block}
.menu>summary{list-style:none;cursor:pointer}
.menu>summary::-webkit-details-marker{display:none}
.menu>summary:focus-visible{outline:2px solid var(--brass);outline-offset:2px}
.menu-list{position:absolute;right:0;top:calc(100% + 4px);min-width:200px;max-width:320px;
  background:var(--card);border:1px solid var(--rule-2);border-radius:var(--r);
  box-shadow:var(--shadow);padding:4px;z-index:60;text-align:left}
.menu.up .menu-list{top:auto;bottom:calc(100% + 4px)}
.menu-list[popover]{position:fixed;inset:auto;margin:0;left:0;top:0}
.menu-list>a,.menu-list>button,.menu-list form>button,.menu-list>label{display:flex;align-items:center;gap:8px;
  width:100%;height:auto;min-height:34px;padding:7px 10px;text-align:left;background:none;
  border:0;border-radius:var(--r-sm);color:var(--ink);font-weight:500;font-size:13px;
  text-decoration:none;cursor:pointer;justify-content:flex-start;white-space:normal;line-height:1.3}
.menu-list>a:hover,.menu-list>button:hover,.menu-list form>button:hover{background:var(--hover);color:var(--ink)}
.menu-list .danger{color:var(--bad)}
.menu-list .danger:hover{background:var(--bad-soft);color:var(--bad)}
.menu-list hr{border:0;border-top:1px solid var(--rule);margin:4px 0}
.menu-list .head{font-size:11px;font-weight:600;letter-spacing:.08em;text-transform:uppercase;
  color:var(--ink-3);padding:6px 10px 2px;font-family:"Barlow Semi Condensed",Barlow,sans-serif}
.menu-list form{margin:0}
.menu-list .mini{padding:8px 10px;display:flex;flex-direction:column;gap:6px}
.menu-list .mini input,.menu-list .mini select{width:100%;height:30px;font-size:13px}
.menu-list .ico svg{width:15px;height:15px;color:var(--ink-3)}

.drawer{display:inline-block}
.drawer>summary{list-style:none;cursor:pointer}
.drawer>summary::-webkit-details-marker{display:none}
.drawer[open]::before{content:"";position:fixed;inset:0;background:rgba(18,15,13,.42);z-index:70;
  animation:fade .2s ease-out both}
@keyframes fade{from{opacity:0}}
.drawer-panel{position:fixed;top:0;right:0;bottom:0;width:min(520px,100vw);background:var(--paper);
  border-left:1px solid var(--rule-2);box-shadow:var(--shadow-lg);z-index:71;overflow:auto;
  padding:0;display:flex;flex-direction:column;animation:slidein .25s cubic-bezier(.2,.8,.2,1) both;
  text-align:left;font-weight:400;color:var(--ink)}
@keyframes slidein{from{transform:translateX(24px);opacity:0}}
.drawer-head{display:flex;align-items:center;gap:12px;padding:16px var(--gut);
  border-bottom:1px solid var(--rule);position:sticky;top:0;background:var(--paper);z-index:1}
.drawer-head h2{flex:1;font-size:17px}
.drawer-body{padding:var(--gut);display:flex;flex-direction:column;gap:14px}
.drawer-body p{color:var(--ink-2);font-size:14px;line-height:1.55;max-width:62ch}
.drawer-body .field{width:100%}
.drawer-body input,.drawer-body select,.drawer-body textarea{width:100%}
.drawer-foot{display:flex;gap:8px;justify-content:flex-end;padding:12px var(--gut) var(--gut)}
.drawer.wide .drawer-panel{width:min(760px,100vw)}
/* About this page: the same drawer, opened from the (i) in the page head. */
.about>summary{width:28px;height:28px;border-radius:50%;display:inline-grid;place-items:center;
  color:var(--ink-3);border:1px solid var(--rule-2);background:transparent;transition:.15s}
.about>summary:hover{color:var(--brass-ink);border-color:var(--brass)}
.about>summary svg{width:14px;height:14px}
.about .drawer-body h3{margin-top:6px}
.about .drawer-body ul{margin:0;padding-left:18px;color:var(--ink-2)}
.about .drawer-body li{margin-bottom:6px}

/* =========================================================================
   TABS — anchors that work without JavaScript, panels that hide with it
   ====================================================================== */
.tabs{display:flex;gap:2px;border-bottom:1px solid var(--rule);margin:0 0 16px;overflow-x:auto;scrollbar-width:none}
.tabs::-webkit-scrollbar{display:none}
.tabs a{display:inline-flex;align-items:center;gap:6px;padding:0 12px;height:38px;
  text-decoration:none;color:var(--ink-3);font-weight:500;font-size:14px;white-space:nowrap;
  border-bottom:2px solid transparent;margin-bottom:-1px}
.tabs a:hover{color:var(--ink)}
.tabs a.on{color:var(--ink);border-bottom-color:var(--brass);font-weight:600}
.tabs a .n{font-size:11px;font-weight:600;min-width:18px;text-align:center;padding:1px 5px;
  border-radius:9px;background:var(--paper-2);color:var(--ink-3);font-variant-numeric:tabular-nums}
.tabs a.on .n{background:var(--brass-soft);color:var(--brass-ink)}
.tabs a .n.hot{background:var(--bad-soft);color:var(--bad)}
.panel[hidden]{display:none}
.panel>h2:first-child{margin-bottom:10px}

/* =========================================================================
   RECORD PAGES — ticket · rail + tabs · related
   ====================================================================== */
.record{display:grid;grid-template-columns:minmax(0,3fr) minmax(0,6fr) minmax(0,3fr);gap:var(--gut);align-items:start}
.record>*{min-width:0}
.ticket{background:var(--card);border:1px solid var(--rule);border-top:2px solid var(--brass);
  border-radius:var(--r);padding:16px}
.ticket+.ticket{margin-top:var(--gut)}
.ticket h3{display:flex;align-items:center;gap:8px;margin-bottom:12px;font-size:13px;
  font-family:"Barlow Semi Condensed",Barlow,sans-serif;letter-spacing:.08em;text-transform:uppercase;color:var(--ink-3)}
.ticket h3 .push{flex:1}
.ticket .who{display:flex;align-items:center;gap:12px;margin-bottom:12px}
.ticket .who b{display:block;font-size:16px;font-weight:600}
.ticket .who .s{display:block}
.ticket .stats{display:grid;grid-template-columns:1fr 1fr;gap:10px 12px;margin:12px 0}
.ticket .stats div{display:flex;flex-direction:column}
.ticket .stats b{font-size:17px;font-weight:600;font-variant-numeric:tabular-nums;letter-spacing:-.01em}
.ticket .stats span{font-size:11px;color:var(--ink-3)}
.ticket .acts{display:flex;gap:6px;flex-wrap:wrap;margin-top:12px}
.related{display:flex;flex-direction:column;gap:var(--gut)}
.related .tbl table{font-size:13px}
.related td{height:40px}
dl.kv{display:grid;grid-template-columns:max-content minmax(0,1fr);gap:7px 14px;margin:0;font-size:13px;align-items:baseline}
dl.kv dt{color:var(--ink-3)}
dl.kv dd{margin:0;color:var(--ink-2);overflow-wrap:anywhere}
dl.kv dd b{color:var(--ink)}
.more>summary{list-style:none;cursor:pointer;font-size:12px;color:var(--brass-ink);margin-top:8px;font-weight:500}
.more>summary::-webkit-details-marker{display:none}
.more[open]>summary{margin-bottom:8px}

/* THE STAGE RAIL — ordered → confirmed → link → attended → certificate → IRS. */
.rail{display:flex;list-style:none;margin:0 0 var(--gut);padding:14px 16px;gap:0;
  background:var(--card);border:1px solid var(--rule);border-radius:var(--r);overflow-x:auto}
.rail li{flex:1 1 0;min-width:88px;position:relative;text-align:center;padding:0 4px;font-size:12px;color:var(--ink-3);line-height:1.3}
.rail li::before{content:"";display:block;width:10px;height:10px;border-radius:50%;margin:0 auto 8px;
  background:var(--paper);border:2px solid var(--rule-2);position:relative;z-index:1}
.rail li::after{content:"";position:absolute;top:5px;left:calc(50% + 7px);right:calc(-50% + 7px);height:2px;background:var(--rule)}
.rail li:last-child::after{display:none}
.rail li.done{color:var(--ink-2)}
.rail li.done::before{background:var(--good);border-color:var(--good)}
.rail li.done::after{background:var(--good)}
.rail li.now{color:var(--ink);font-weight:600}
.rail li.now::before{background:var(--brass);border-color:var(--brass);box-shadow:0 0 0 4px var(--brass-soft)}
.rail li.fail::before{background:var(--bad);border-color:var(--bad)}
.rail li.skip{opacity:.55}
.rail li small{display:block;font-weight:400;color:var(--ink-3);font-variant-numeric:tabular-nums}

/* =========================================================================
   TWO COLUMNS, NOTES, EMPTY, TIMELINE
   ====================================================================== */
.cols{display:grid;grid-template-columns:minmax(0,7fr) minmax(0,5fr);gap:var(--gut);align-items:start}
.cols.even{grid-template-columns:1fr 1fr}
.cols>*{min-width:0}
.stack{display:flex;flex-direction:column;gap:var(--gut)}
.block{background:var(--card);border:1px solid var(--rule);border-radius:var(--r)}
.block>h2,.block>h3{display:flex;align-items:center;gap:8px;padding:12px 16px;font-size:13px;
  font-family:"Barlow Semi Condensed",Barlow,sans-serif;letter-spacing:.08em;text-transform:uppercase;
  color:var(--ink-3);border-bottom:1px solid var(--rule)}
.block>h2 .n,.block>h3 .n{font-size:12px;color:var(--ink-3);font-weight:500;letter-spacing:0;text-transform:none}
.block>h2 .push,.block>h3 .push{flex:1}
.block>h2 a,.block>h3 a{font-size:12px;letter-spacing:0;text-transform:none;font-weight:500}
.block .tbl{border:none;border-radius:0;background:transparent}
.block .body{padding:16px}
.block .list{list-style:none;margin:0;padding:0}
.block .list li{display:flex;align-items:center;gap:12px;min-height:44px;padding:6px 16px;border-bottom:1px solid var(--rule);font-size:14px}
.block .list li:last-child{border-bottom:none}
.block .list li .push{flex:1;min-width:0}
.block .list li b{color:var(--ink);font-weight:600}
.block .list li .s{display:block}
.block .list li.faded{opacity:.6}
/* MORE BREATHING ROOM on the dashboard's four cards (founder, 31 Oct 2026). */
.block .list li{padding:10px 16px}

/* =========================================================================
   CHARTS — plain inline SVG bars, no library. One hue (brass), a second
   series told apart by lightness/outline rather than a second colour —
   "never two dark colours together" (ravit-design-language). Refunds use
   --bad, matching the red this app already uses for a failed/negative state.
   ====================================================================== */
.chartfig{margin:0;padding:12px 16px 2px}
.chartfig svg{width:100%;height:auto;display:block}
.chart-axis{stroke:var(--rule-2);stroke-width:1}
.chart-bar{fill:var(--brass)}
.chart-bar.outline{fill:var(--card);stroke:var(--brass);stroke-width:2}
.chart-bar.bad{fill:var(--bad)}
.chart-catlabel{font-size:10px;fill:var(--ink-3);font-family:"Barlow Semi Condensed",Barlow,sans-serif}
.chart-legend{display:flex;gap:14px;flex-wrap:wrap;padding:4px 16px 0;font-size:12px;color:var(--ink-2)}
.chart-legend-item{display:inline-flex;align-items:center;gap:6px}
.chart-swatch{width:10px;height:10px;border-radius:2px;background:var(--brass);display:inline-block}
.chart-swatch.outline{background:var(--card);border:2px solid var(--brass)}
.chart-swatch.bad{background:var(--bad)}

.note{border:1px solid var(--rule);background:var(--card);border-radius:var(--r);padding:12px 14px;
  margin-bottom:16px;color:var(--ink-2);font-size:13px;display:flex;gap:10px;align-items:flex-start;line-height:1.5}
.note .ico{flex:0 0 18px;width:18px;margin-top:2px;color:var(--ink-3)}
.note .ico svg{width:18px;height:18px;stroke-width:1.8}
.note b{color:var(--ink);font-weight:600}
.note>div{min-width:0}
.note p:last-child{margin-bottom:0}
.note.warn{background:var(--owed-soft);border-color:transparent;color:var(--ink)}
.note.warn .ico,.note.warn b{color:var(--owed)}
.note.bad{background:var(--bad-soft);border-color:transparent;color:var(--ink)}
.note.bad .ico,.note.bad b{color:var(--bad)}
.note.good{background:var(--good-soft);border-color:transparent;color:var(--ink)}
.note.good .ico,.note.good b{color:var(--good)}
.note.sm{padding:8px 12px;font-size:12px;margin-bottom:12px}

.empty{padding:40px 24px;text-align:center;color:var(--ink-3);background:var(--card);
  border:1px solid var(--rule);border-radius:var(--r)}
.empty h2{color:var(--ink);margin-bottom:4px;font-size:15px}
.empty p{max-width:48ch;margin:0 auto 6px;font-size:13px}
.empty .ico{width:36px;height:36px;margin:0 auto 12px;border-radius:50%;
  background:var(--paper-2);display:grid;place-items:center;color:var(--ink-3)}
.empty .ico svg{width:18px;height:18px;stroke-width:1.7}
.empty.inline{padding:20px;border:none;background:transparent}

.tl{list-style:none;margin:0;padding:0;position:relative}
.tl li{position:relative;padding:0 0 14px 22px;font-size:13px}
.tl li::before{content:"";position:absolute;left:2px;top:6px;width:8px;height:8px;border-radius:50%;
  background:var(--brass);box-shadow:0 0 0 3px var(--brass-soft)}
.tl li::after{content:"";position:absolute;left:5px;top:18px;bottom:0;width:1px;background:var(--rule)}
.tl li:last-child{padding-bottom:0}
.tl li:last-child::after{display:none}
.tl .when{font-size:12px;color:var(--ink-3);font-variant-numeric:tabular-nums}

/* Messages: a ledger of who said what. */
.msgs{display:flex;flex-direction:column;gap:10px}
.daymark{display:flex;align-items:center;gap:12px;margin:10px 0 0;color:var(--ink-3);font-size:11px;
  font-weight:600;letter-spacing:.08em;text-transform:uppercase;font-family:"Barlow Semi Condensed",Barlow,sans-serif}
.daymark::before,.daymark::after{content:"";height:1px;background:var(--rule);flex:1}
.msg{border:1px solid var(--rule);border-radius:var(--r);padding:12px 14px;background:var(--card)}
.msg.them{border-color:var(--rule-2);background:var(--paper-2)}
.msg header{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-bottom:4px}
.msg .tag{font-family:"Barlow Semi Condensed",Barlow,sans-serif;font-size:11px;font-weight:600;letter-spacing:.06em;text-transform:uppercase;color:var(--ink-3)}
.msg.them .tag{color:var(--brass-ink)}
.msg .t{font-size:12px;color:var(--ink-3);font-variant-numeric:tabular-nums}
.msg header a{margin-left:auto}
.msg .subj{font-weight:600;font-size:14px;color:var(--ink);margin-bottom:4px}
.msg .text{white-space:pre-wrap;overflow-wrap:anywhere;word-break:break-word;font-size:13px;line-height:1.55;color:var(--ink-2);max-width:78ch}
.msg .text a{overflow-wrap:anywhere}
.reply{display:flex;flex-direction:column;gap:8px;margin-top:12px}
.reply textarea{width:100%}

/* =========================================================================
   THE TO-DO LANES (the kanban) — three columns that become one on a phone
   ====================================================================== */
.lanes{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--gut);align-items:start}
.lane{background:var(--paper-2);border:1px solid var(--rule);border-radius:var(--r);padding:10px;min-height:120px}
.lane>header{display:flex;gap:8px;align-items:baseline;margin:4px 6px 10px}
.lane>header h2{font-family:"Barlow Semi Condensed",Barlow,sans-serif;font-size:12px;font-weight:600;letter-spacing:.1em;text-transform:uppercase;color:var(--ink-3)}
.lane>header .n{font-size:12px;color:var(--ink-3);font-variant-numeric:tabular-nums}
.lane .empty-lane{margin:6px;color:var(--ink-3);font-size:12px}
.card{background:var(--card);border:1px solid var(--rule);border-radius:var(--r-sm);padding:10px 12px;margin-bottom:8px}
.card.urgent{border-color:var(--bad)}
.card .what{display:flex;gap:6px;align-items:flex-start;justify-content:space-between}
.card .what b{font-size:14px;line-height:1.35;font-weight:600}
.card p.s{margin:4px 0 0;color:var(--ink-2)}
.card .meta{margin-top:6px;color:var(--ink-3);font-size:12px;display:flex;gap:8px;flex-wrap:wrap}
.card .meta .due.late{color:var(--bad);font-weight:600}
.card .acts{margin-top:10px;display:flex;gap:6px;flex-wrap:wrap;align-items:center}
.card .subs{list-style:none;margin:8px 0 0;padding:0;border-top:1px solid var(--rule)}
.card .subs li{display:flex;gap:6px;align-items:center;padding:6px 0;font-size:13px}
.card .subs .tick{color:var(--good)} .card .subs .tick.open{color:var(--ink-3)}
.card .subs .done{color:var(--ink-3);text-decoration:line-through}
.card[draggable="true"]{cursor:grab}
.card.dragging{opacity:.45;cursor:grabbing}
.lane.over{background:var(--brass-soft);border-color:var(--brass)}
.lane.over .card{pointer-events:none}
.finish summary{cursor:pointer;font-size:12px;color:var(--ink-2)}
.finish form{margin-top:8px;display:flex;gap:6px;flex-wrap:wrap}
.finish input[type=text]{flex:1 1 190px}
.frow{display:flex;gap:12px;flex-wrap:wrap;margin-bottom:12px}
.frow label{display:flex;flex-direction:column;gap:5px;font-size:12px;color:var(--ink-2)}

/* =========================================================================
   THE LIGHT / DARK SWITCH
   ====================================================================== */
.themetoggle{position:relative;flex:0 0 auto;width:52px;height:28px;padding:0;
  border:1px solid var(--board-rule);border-radius:14px;background:var(--board-2);
  cursor:pointer;display:inline-flex;align-items:center;justify-content:space-between;
  transition:background .25s ease,border-color .25s ease}
.themetoggle:hover{border-color:var(--brass-on-board)}
.themetoggle .knob{position:absolute;top:2px;left:2px;width:22px;height:22px;border-radius:50%;
  background:var(--board-ink);transition:transform .28s cubic-bezier(.16,1,.3,1)}
.themetoggle.isdark .knob{transform:translateX(24px)}
.themetoggle svg{width:12px;height:12px;position:relative;z-index:1;margin:0 7px;transition:opacity .25s ease,color .25s ease}
.themetoggle .sun{color:var(--brass-on-board);opacity:1}
.themetoggle .moon{color:var(--board-ink-2);opacity:.5}
.themetoggle.isdark .sun{opacity:.35;color:var(--board-ink-2)}
.themetoggle.isdark .moon{opacity:1;color:var(--brass-on-board)}
[data-surface="portal"] .themetoggle{background:var(--paper-2);border-color:var(--rule-2)}
[data-surface="portal"] .themetoggle .knob{background:var(--card);box-shadow:var(--shadow)}
[data-surface="portal"] .themetoggle .sun{color:var(--brass)}
[data-surface="portal"] .themetoggle .moon{color:var(--ink-3)}

/* =========================================================================
   SIGN-IN — a centred ticket on ivory, no board strip
   ====================================================================== */
.gate{min-height:100vh;display:grid;place-items:center;padding:24px}
.gate .ticket{width:min(400px,100%);padding:24px}
.gate .brand{display:flex;align-items:center;gap:10px;margin-bottom:18px;
  font-family:"Barlow Semi Condensed",Barlow,sans-serif;font-size:18px;font-weight:700;letter-spacing:.02em;text-transform:uppercase}
.gate .brand .mark{width:28px;height:28px;border-radius:var(--r-sm);background:var(--board);color:var(--brass-on-board);display:grid;place-items:center;font-size:15px}
.gate .field{margin-bottom:12px}
.gate input{width:100%}
.gate .btn{width:100%;height:38px}

/* =========================================================================
   PORTAL — a customer document, calmer and wider-set; inherits the tokens
   ====================================================================== */
[data-surface="portal"] .topbar{display:flex;align-items:center;justify-content:space-between;gap:12px;
  padding:14px var(--gut);border-bottom:2px solid var(--brand-accent,var(--brass));background:var(--card)}
[data-surface="portal"] .wordmark{font-size:17px;font-weight:700;color:var(--brand-accent,var(--brass-ink));letter-spacing:-.01em}
[data-surface="portal"] .pcard{padding:20px 22px}
/* THE CUSTOMER'S PRIMARY BUTTON. The brand accent is the brand's, and it stays
   the brand's on the wordmark and the header rule — but two of the three give
   white text 4.05:1 and 4.41:1 as a button surface, under the 4.5:1 floor on
   the one control the portal exists to offer. The button darkens its own
   surface by 15%, which keeps the hue and clears the floor on all three
   (5.51 / 5.08 / 6.82); nothing else on the page changes. */
[data-surface="portal"] .btn{color:#fff;
  background:color-mix(in srgb, var(--brand-accent,var(--brass)) 85%, #1E1610)}
@supports not (color: color-mix(in srgb, red 50%, blue)){
  [data-surface="portal"] .btn{background:var(--brand-accent,var(--brass))}
}
[data-surface="portal"] .btn.ghost{background:transparent;color:var(--ink-2)}
.previewband{display:flex;align-items:center;gap:10px;flex-wrap:wrap;background:var(--owed-soft);color:var(--owed);
  border-bottom:1px solid color-mix(in srgb,var(--owed) 35%,transparent);padding:8px 20px;font-size:13px;line-height:1.45}
.previewband .tag{background:var(--owed);color:#1E1610;border-radius:999px;padding:2px 10px;font-weight:600;font-size:11px;letter-spacing:.04em;text-transform:uppercase;flex:none}
.previewband b{color:var(--owed)}
.previewband .push{flex:1}
.ws-none{padding:40px 24px;text-align:center;background:var(--card);border:1px solid var(--owed);border-radius:var(--r);color:var(--ink-2)}

/* =========================================================================
   PASS CARD — Book a live class / Choose products rows (T6, 30 Sep 2026).
   The hero card itself is plain .tiles/.tile, already declared above; this is
   only the two row shapes that needed more than one control on the right.
   ====================================================================== */
/* A row whose right side can carry a badge, a Join button AND Cancel (or a
   format button per format) wraps onto its own line instead of forcing them
   all into one 44px strip. */
[data-surface="portal"] .pass-row{flex-wrap:wrap;row-gap:6px}
[data-surface="portal"] .pass-row .acts{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
/* CHOOSE PRODUCTS: a compact group, not a wall of buttons — the formats for
   one course name wrap together as a unit under the title. */
[data-surface="portal"] .fmtgroup{display:flex;align-items:center;gap:6px;flex-wrap:wrap}
@media (max-width:720px){
  /* ONE COLUMN (his standing mobile rule): `.push`'s own `flex:1;min-width:0`
     shrinks the title down to a sliver ("Form 109…") beside the actions
     rather than wrapping — flex-wrap only fires once shrinking is exhausted,
     and min-width:0 means it never is. A column stack sidesteps that: the
     title always gets the row's own full width, the actions/format group
     sit below it. */
  [data-surface="portal"] .pass-row{flex-direction:column;align-items:stretch}
  [data-surface="portal"] .pass-row>.push{flex:none;width:100%}
}
@media (max-width:480px){
  /* Full-width buttons under 480px (his standing rule — he checks on his
     phone): a lone action stretches; a row of several stays a compact group
     rather than each one going full width and stacking into a ladder. */
  [data-surface="portal"] .pass-row .acts:has(> :only-child) .btn,
  [data-surface="portal"] .pass-row .acts:has(> :only-child) form.mini{width:100%}
  [data-surface="portal"] .pass-row .acts form.mini .btn{width:100%}
}

/* =========================================================================
   LEGACY ALIASES — old class names still render while pages are rebuilt
   ====================================================================== */
.tbox{border:1px solid var(--rule);border-radius:var(--r);background:var(--card);overflow-x:auto}
.pcard{background:var(--card);border:1px solid var(--rule);border-radius:var(--r);padding:16px;display:flex;flex-direction:column;gap:10px}
.pcard>h3{display:flex;align-items:center;gap:8px}
.pcard .tbox{border:none;border-radius:0;background:transparent;margin:0 -16px -16px;width:calc(100% + 32px)}
.cards{display:grid;grid-template-columns:repeat(auto-fit,minmax(300px,1fr));gap:var(--gut)}
.tiles{display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));gap:12px;margin-bottom:16px}
.tile{background:var(--card);border:1px solid var(--rule);border-radius:var(--r);padding:12px 14px;display:flex;flex-direction:column;gap:2px}
.tile .k{font-size:12px;color:var(--ink-3)}
.tile .v{font-size:22px;font-weight:600;letter-spacing:-.01em;line-height:1.15;font-variant-numeric:tabular-nums}
.tile .s{font-size:12px}
.tile.accent{border-color:var(--brass)}
.tile.good .v{color:var(--good)} .tile.warn .v{color:var(--owed)} .tile.bad .v{color:var(--bad)}
.phead{display:flex;align-items:center;gap:12px;margin-bottom:16px;flex-wrap:wrap}
.phead h1{margin:0}
.phead p{margin:0;color:var(--ink-3);font-size:13px;flex-basis:100%}
.phead .actions{margin-left:auto;display:flex;gap:8px;align-items:center}
.phead.split{align-items:flex-start}
.infopop{display:inline-block}
.ovr{display:inline-block;position:relative;text-align:left}
.ovr>summary{list-style:none;cursor:pointer;display:inline-block}
.ovr>summary::-webkit-details-marker{display:none}
.ovrbox{position:relative;z-index:5;margin-top:8px;padding:12px;width:330px;background:var(--card);
  border:1px solid var(--rule-2);border-radius:var(--r);box-shadow:var(--shadow-lg);display:flex;flex-direction:column;gap:8px}
.ovrbox label{display:flex;flex-direction:column;gap:4px;font-size:12px;font-weight:600;color:var(--ink-2)}
.ovrbox select,.ovrbox input{width:100%}
.ovract{display:flex;gap:8px;margin-top:2px}
.issuerow{display:flex;gap:6px;align-items:center;justify-content:flex-end;flex-wrap:wrap}
.issuerow input{height:28px;font-size:13px}
.issuerow input[type=email]{width:180px} .issuerow input[type=text]{width:140px}
.schedform{display:flex;gap:12px;align-items:flex-end;flex-wrap:wrap}
.schedform label{display:flex;flex-direction:column;gap:5px;font-size:12px;font-weight:600;color:var(--ink-2)}
.journey{display:flex;flex-direction:column;gap:10px}
.chat .thread{display:flex;flex-direction:column;gap:10px;max-height:620px;overflow-y:auto}
.bubble{padding:10px 12px;border-radius:var(--r);border:1px solid var(--rule);background:var(--card)}
.bubble .who{font-size:11px;font-weight:600;color:var(--ink-3);margin-bottom:4px}
.bubble .text{white-space:pre-wrap;font-size:13px;color:var(--ink-2)}

/* =========================================================================
   NARROW — the rail becomes icons, then a row; the strip wraps; tables shed
   ====================================================================== */
/* Phone-only. `td .two` is (0,1,1) and would out-specify a bare .show-sm,
   which is how a phone-only line ended up visible at 1440. */
.show-sm,td .show-sm,td .two.show-sm{display:none}
.hide-md{display:revert}

@media (max-width:1080px){
  :root{--side:60px}
  /* Five tabs with counts do not fit a half-width pane; wrapping beats a
     scrollbar the browser hides. */
  .tabs{flex-wrap:wrap}
  /* The ticket needs enough width for an e-mail address not to break. */
  .record{grid-template-columns:minmax(0,5fr) minmax(0,7fr)}
  .side{padding:12px 8px;align-items:center}
  .side .brand{padding:6px 0 12px}
  .side .brand span,.side nav a span.lbl,.side .group,.side .me .who,.side .me a{display:none}
  .side nav a{justify-content:center;padding:10px;width:44px}
  .side nav a.on::before{display:none}
  .side nav a .tally{position:absolute;margin:0;top:3px;right:2px;font-size:11px;padding:0 4px;min-width:16px}
  .side .me{justify-content:center;padding-left:0;padding-right:0}
  .record{grid-template-columns:minmax(0,4fr) minmax(0,8fr)}
  .record .related{grid-column:1 / -1}
  .cols{grid-template-columns:1fr}
}
@media (max-width:720px){
  :root{--side:0px;--gut:16px}
  .shell{display:flex;flex-direction:column}
  .side{position:static;width:100%;height:auto;border-right:none;border-bottom:1px solid var(--rule);
    flex-direction:row;align-items:center;gap:6px;overflow-x:auto;padding:8px 12px;scrollbar-width:none}
  .side::-webkit-scrollbar{display:none}
  /* Ten destinations do not fit 390px. A 28px fade landed in the gap between
     two labels and dissolved empty space, so it said nothing. Wide enough now
     that a label is always mid-cut, and a chevron that is there whatever the
     labels happen to measure. */
  .side{position:relative;padding-right:30px;
    -webkit-mask-image:linear-gradient(to right,#000 calc(100% - 64px),transparent);
            mask-image:linear-gradient(to right,#000 calc(100% - 64px),transparent)}
  .shell>.side::after{content:"";position:absolute;right:8px;top:50%;width:7px;height:7px;
    margin-top:-5px;border-right:2px solid var(--ink-3);border-bottom:2px solid var(--ink-3);
    transform:rotate(-45deg);pointer-events:none}
  .side .brand{padding:0 6px 0 0}
  .side .brand span{display:none}
  .side nav{flex-direction:row;gap:2px}
  .side nav a{width:auto;padding:8px 10px}
  .side nav a span.lbl{display:inline;font-size:13px}
  .side nav a .tally{position:static;margin-left:4px;font-size:11px;padding:0 5px}
  .side .spacer,.side .group{display:none}
  .side .me{border-top:none;margin:0;padding:0 0 0 6px}
  .side .me .who{display:none}
  .strip{padding:8px var(--gut);gap:8px}
  .strip .wsform label,.strip .clock span,.mailpill,.waitpill .lbl{display:none}
  .strip .jump{flex:1 1 140px;order:5;max-width:none}
  .strip .push{display:none}
  .wrap{padding:var(--gut) var(--gut) 40px}
  .board.top{margin:calc(-1 * var(--gut)) calc(-1 * var(--gut)) var(--gut)}
  .board-head{padding:12px var(--gut) 10px;gap:12px}
  .counts{gap:14px}
  .counts b{font-size:16px}
  .board th:first-child,.board td:first-child,th:first-child,td:first-child{padding-left:12px}
  .board th:last-child,.board td:last-child,th:last-child,td:last-child{padding-right:12px}
  td,th{padding-left:10px;padding-right:10px}
  .hide-sm{display:none!important}
  .show-sm,td .show-sm,td .two.show-sm{display:block}
  td img.bmark.show-sm{display:inline-block}
  .record{grid-template-columns:1fr}
  .lanes{grid-template-columns:1fr}
  .tbl{overflow-x:auto}
  /* An action cell with more than one control wraps onto a second line
     instead of forcing the row wider than the phone. */
  td.act{white-space:normal}
  h1{font-size:19px}
  .pagehead .actions{margin-left:0;flex-basis:100%}
  .drawer-panel{width:100vw}
  .person .who b,.person .who .s{max-width:20ch}
  .side nav a{white-space:nowrap}
  .flap,.chip{min-width:5.5em;padding:5px 6px}
  .board .when span{display:none}
}
/* =========================================================================
   AFTER THE FIRST BUILD — what nine page builders needed from the system
   ====================================================================== */
/* A page with no rail (sign-in, password, 404) is the shell's only child and
   must own the whole width, not the rail's column. */
.shell>.main:only-child{grid-column:1 / -1}
.gate{min-height:calc(100vh - 88px)}
.gate .help{max-width:40ch;margin:12px auto 0;text-align:center}
/* The About (i) inside the board head sits on espresso, not ivory. */
.board .about>summary{color:var(--board-ink-2);border-color:var(--board-rule);background:transparent}
.board .about>summary:hover{color:var(--brass-on-board);border-color:var(--brass-on-board)}
/* A drawer whose opener lives inside a ⋯ menu reads as a menu item. */
.menu-list>.drawer{display:block}
.menu-list>.drawer>summary.btn,.menu-list>.drawer>summary.btn.quiet{width:100%;justify-content:flex-start;height:auto;
  min-height:34px;padding:7px 10px;color:var(--ink);font-weight:500;font-size:13px;border-radius:var(--r-sm);
  background:none;border:0}
.menu-list>.drawer>summary.btn:hover{background:var(--hover);color:var(--ink)}
/* A .mini form inside a menu that sits in a no-wrap action cell. */
.menu-list .mini{white-space:normal}
.menu-list .mini .btn{width:auto}
/* Checkboxes inside drawers and minis keep their own size. */
.drawer-body input[type=checkbox],.drawer-body input[type=radio],
.menu-list .mini input[type=checkbox],.menu-list .mini input[type=radio]{width:auto;height:auto}
/* Compact selects inside a row form, capped so the column stays honest. */
.inline select{height:28px;font-size:13px;max-width:13em}
/* An identifier cell: no wrap, tabular. */
td.id,th.id{white-space:nowrap;font-variant-numeric:tabular-nums}
td .mono,.board td .mono{white-space:nowrap}
/* A plain-text letter, shown as typed. */
.letter{white-space:pre-wrap;overflow-wrap:anywhere;font-size:13px;line-height:1.55;color:var(--ink-2);max-width:78ch}
/* Portal: the gate sits under a branded topbar; the wordmark never wraps. */
[data-surface="portal"] .gate{min-height:0;padding:8vh 0 24px}
[data-surface="portal"] .wordmark{white-space:nowrap}
[data-surface="portal"] .block .list li{align-items:flex-start}
@media (max-width:720px){
  /* The name may wrap; the address stays one ellipsised line with its full
     value on the element's title. Breaking an address every four characters is
     less readable than truncating it, not more. */
  td .person .who b{white-space:normal;max-width:none}
  .person .who b,.person .who .s{max-width:16ch}
  /* A date and its time stack instead of forcing the column wide. */
  .copyrow .copytext{width:96px}
  /* A DATE NEVER BREAKS. Letting td.when b wrap turned every date into a
     three-line hyphen ladder — the tabular column is this world's spine. */
  td .two,td .s{overflow-wrap:anywhere}
  td.when,td.when b{white-space:nowrap}
  td.when .two{white-space:normal}
  /* The board keeps its own voice on a phone: "in 2 days" is the board
     speaking, the numeric date is only the stamp under it. */
  .board .when span{display:block}
  /* Two courses can share a prefix, so the phone line is not ellipsised at all. */
  .board td .show-sm{-webkit-line-clamp:none;display:block}
  [data-surface="portal"] .topbar .s{display:none}
}
/* =========================================================================
   AFTER THE REVIEW — seven pages read against the captures
   ====================================================================== */
/* The board and the strip are espresso in BOTH themes, so they always carry
   the dark theme's tension inks; the hall's light inks are dark-on-dark there. */
/* A note's bold is ink; only its icon takes the tension colour. */
.note.warn b,.note.bad b,.note.good b{color:var(--ink)}
/* The macro already wraps its svg in .ico; a second wrapper must not double the offset. */
.note .ico .ico,.empty .ico .ico{margin:0;width:auto;flex:none}
/* A clipped table is never better than one that scrolls. */
.tbl{overflow-x:auto}
/* IN A TABLE the address field is not shown at all. `display:none` rather than
   a 1px transparent box, because an invisible input still sits in the tab order
   and the accessibility tree — 53 of them, one between every Copy button. The
   clipboard fallback makes its own element now, so nothing depends on this one. */
td .copyrow .copytext{display:none}
td .copyrow{flex-wrap:nowrap}
.lane>header h2{white-space:nowrap}
@media (max-width:1080px){
  /* Three lanes share ~280px here, which is narrower than one card wants. */
  .lanes{grid-template-columns:1fr}
}
@media (max-width:900px){
  .hide-md{display:none!important}
}
@media (max-width:720px){
  /* A lone (i) stays on the title line instead of taking a row of its own. */
  .pagehead .actions:has(> .about:only-child){flex-basis:auto;margin-left:auto}
  .filters label{flex:1 1 45%}
  /* The stage rail: two rows of three, the connector broken at the wrap. */
  .rail{flex-wrap:wrap;overflow:visible;row-gap:14px}
  .rail li{flex:1 1 33.33%;min-width:0}
  .rail li:nth-child(3)::after{display:none}
  /* A phone opens to what is owed, then the facts, then the related lists. */
  .record>*{order:2}
  .record>.ticket{order:3}
  .record>.related{order:4}
  .strip .clock span{display:inline}
}
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation:none!important;transition:none!important}
}

/* Bulk select: the tick column and the bar above the table. Deliberately quiet
   — a bar that shouts sits above every certificate row all day. */
.bulkbar{display:flex;align-items:center;gap:12px;flex-wrap:wrap;
  padding:10px 16px;margin:0 0 10px;background:var(--card);
  border:1px solid var(--rule);border-radius:var(--r);font-size:13px}
.bulkbar .push{flex:1}
.bulkbar select{font-size:13px}
.tbl th.tick,.tbl td.tick{width:34px;padding-left:14px;padding-right:0}
.tbl td.tick input{cursor:pointer}
/* The Abandoned page's Follow up / Completed checklist. */
.tbl th.check,.tbl td.check{text-align:center;white-space:nowrap}
.tbl td.check input{cursor:pointer}

/* Sync, in the top bar. Ghost on purpose: it runs every five minutes anyway,
   so the button is a shortcut and not the main way anything happens. */
.syncnow{display:inline-flex}
/* While it is running. No spinner: the label already says "Syncing…", and a
   moving thing in the chrome of every page is a thing you learn to ignore.
   Tokens only, so the two dark blocks need no new declaration. */
.syncnow .btn[disabled]{opacity:.55;cursor:progress;pointer-events:none}
@media (max-width:900px){ .syncnow .lbl{display:none} }
@media (max-width:900px){ .histlink .lbl{display:none} }

/* =========================================================================
   THE AUTOMATION CANVAS — Trigger -> Wait -> Only-if -> Letter -> Otherwise
   (AUTOMATION-AND-LETTERS-SPEC.md v2 §5.2, T9). The chips reuse .tabs a's
   OWN script ([data-tabs] in base.html) — only their look is new here.
   ====================================================================== */
.canvas{display:grid;grid-template-columns:7fr 3fr;gap:var(--gut);align-items:start}
.cv-chain{display:flex;flex-wrap:wrap;align-items:center;gap:6px}
.cv-block{display:block;background:var(--card);border:1px solid var(--rule);border-radius:var(--r);
  padding:8px 12px;font-size:13px;color:var(--ink-2);text-decoration:none;min-width:120px;
  line-height:1.3;cursor:pointer}
.cv-block b{display:block;font-size:11px;letter-spacing:.06em;text-transform:uppercase;color:var(--ink-3)}
.cv-block.on{border-color:var(--brass);box-shadow:0 0 0 2px var(--brass-soft)}
.cv-arrow{color:var(--ink-3);flex:0 0 auto;display:flex;align-items:center}
.cv-arrow svg{width:22px;height:14px}
.cv-section{margin-bottom:18px}
.cv-section:last-child{margin-bottom:0}
.cv-section h3{font-size:13px;font-family:"Barlow Semi Condensed",Barlow,sans-serif;
  letter-spacing:.08em;text-transform:uppercase;color:var(--ink-3);margin-bottom:8px}
.cv-filter-row{display:flex;align-items:center;gap:8px;margin-bottom:6px;flex-wrap:wrap}
.cv-filter-row b{min-width:110px;font-weight:600;font-size:13px}
@media (max-width:720px){
  .canvas{grid-template-columns:1fr}
  .cv-arrow svg{transform:rotate(90deg)}
}

/* =========================================================================
   THE TIMELINE STRIP (AUTOMATION-AND-LETTERS-SPEC.md v2 §4.9, T10). One
   SVG line, shared by the list page and the canvas — a filled dot is Live,
   a hollow one is Shadow, same two colours .modeflag already uses above.
   ====================================================================== */
.tl-strip{margin:4px 0}
.tl-line{stroke:var(--rule-2);stroke-width:2}
.tl-dot{stroke-width:2}
.tl-dot.live{fill:var(--good);stroke:var(--good)}
.tl-dot.shadow{fill:var(--card);stroke:var(--owed)}
.tl-label{font-size:10px;fill:var(--ink-2)}
.tl-sub{font-size:9px;fill:var(--ink-3)}


/* =========================================================================
   PORTAL RAIL + SHELVES (1 Nov 2026). The customer portal took the staff
   rail — same component, five stops — so the only new rules are the brand's
   accent on the mark and two list shapes the staff surface never needed.
   Every colour is an existing token; nothing here needs a dark-theme twin.
   ====================================================================== */
/* The mark takes the brand accent, darkened exactly as the primary button is
   so a white letter clears 4.5:1 on all three brands. */
[data-surface="portal"] .side .brand .mark{color:#fff;
  background:color-mix(in srgb,var(--brand-accent,var(--brass)) 85%,#1E1610)}
@supports not (color: color-mix(in srgb, red 50%, blue)){
  [data-surface="portal"] .side .brand .mark{background:var(--brand-accent,var(--brass))}
}
[data-surface="portal"] .side .brand .wordmark{font-size:15px}
[data-surface="portal"] .side .me a{white-space:nowrap}
/* The avatar plate was the rail's own colour — a ring instead, so the initials
   read as a badge and not as stray text. */
[data-surface="portal"] .side .me .avatar{background:var(--card);color:var(--ink-2);border:1px solid var(--rule-2)}
/* On a phone the rail is a scroller: the avatar steps aside and Sign out —
   which the 1080px rule above hides — comes back, because a customer must be
   able to leave from the page they are on. */
@media (max-width:720px){
  [data-surface="portal"] .side .me .avatar{display:none}
  [data-surface="portal"] .side .me a{display:inline;padding:0 6px}
}
.railtools{display:flex;justify-content:flex-end;padding:0 8px 4px}
@media (max-width:1080px){.railtools{justify-content:center;padding:0 0 4px}}
@media (max-width:720px){.railtools{padding:0 0 0 6px}}
/* The product shelves: each row is the target, as every clickable row is. */
.shelves{list-style:none;margin:0;padding:0}
.shelves li+li{border-top:1px solid var(--rule)}
.shelves a{display:flex;align-items:center;gap:12px;min-height:56px;padding:10px 16px;
  text-decoration:none;color:var(--ink);transition:background .15s}
.shelves a:hover{background:var(--brass-soft)}
.shelves a:focus-visible{outline:2px solid var(--brass);outline-offset:-2px}
.shelves a .push{flex:1;min-width:0}
.shelves a b{display:block;font-weight:600}
.shelves a .s{display:block}
.shelves a .n{font-size:12px;font-weight:600;min-width:24px;text-align:center;padding:2px 8px;
  border-radius:12px;background:var(--paper);color:var(--ink-3);border:1px solid var(--rule);
  font-variant-numeric:tabular-nums}
.shelves a .ico{width:16px;flex:0 0 16px;color:var(--ink-3);display:grid;place-items:center}
.shelves a .ico svg{width:16px;height:16px;transform:rotate(-90deg)}
.shelves a.faded b{color:var(--ink-2);font-weight:500}
/* The account's facts: label column, value column, one warm rule between rows. */
.pfacts{margin:0;padding:4px 16px}
.pfacts>div{display:grid;grid-template-columns:150px minmax(0,1fr);gap:12px;padding:10px 0;
  border-bottom:1px solid var(--rule);font-size:14px}
.pfacts>div:last-child{border-bottom:none}
.pfacts dt{font-family:"Barlow Semi Condensed",Barlow,sans-serif;font-size:11px;font-weight:600;
  letter-spacing:.09em;text-transform:uppercase;color:var(--ink-3);padding-top:3px}
.pfacts dd{margin:0;color:var(--ink);overflow-wrap:anywhere}
@media (max-width:720px){.pfacts>div{grid-template-columns:1fr;gap:2px}}
/* The in-portal player (1 Nov 2026): the engine's page in a 16:9 frame on
   black, the one place black is the right ground; the rail keeps its place. */
.watchframe{display:block;width:100%;aspect-ratio:16/9;min-height:320px;border:1px solid var(--rule);
  border-radius:var(--r);background:#000}
.watchnote{margin-top:10px}
/* Live: fill the window under the page head so the engine's Answer/Chat panel
   is in view beside or under the video; never shorter than 640px. */
.watchframe.live{aspect-ratio:auto;height:calc(100vh - 150px);min-height:640px;
  /* ...and the page's side gutters too. The engine puts the panel BESIDE the
     video only at 1024px of frame width; on a 1280px laptop the gutters were
     the difference (1000px → 1048px). Edge to edge, so square and unruled at
     the sides, like the board. */
  width:calc(100% + 2 * var(--gut));margin-left:calc(-1 * var(--gut));
  border-radius:0;border-left:0;border-right:0}

/* A customer's other addresses under the Email row (crm/shared/addresses.py):
   one per line, quieter than the address itself. */
.kv dd .addr{display:block;margin-top:4px;font-size:12px;line-height:1.35;color:var(--ink-3);overflow-wrap:anywhere}
.kv dd .addr b{color:var(--ink)}

/* ---- WEBINARS BOARD (WEBINARS-BOARD-SPEC.md v1.1, 6 Nov 2026) -------------
   One card per class. Status flaps follow the founder's ruling: live green,
   upcoming yellow, ended red — always with the word, never colour alone.
   Everything else is the hall's own tokens; nothing new is invented here. */
.flap.live{background:var(--good-soft);color:var(--good)}
.flap.live::before{content:"";width:8px;height:8px;border-radius:50%;background:var(--good);display:inline-block;margin-right:6px}
.flap.soon{background:var(--owed-soft);color:var(--owed)}
.flap.ended{background:var(--bad-soft);color:var(--bad)}
.chips{display:flex;gap:8px;flex-wrap:wrap;align-items:center}
.chips a{display:inline-flex;gap:6px;align-items:center;height:32px;padding:0 10px 0 6px;border-radius:var(--r);border:1px solid var(--rule-2);color:var(--ink);text-decoration:none;font-weight:500}
.chips a.on{border-color:var(--brass);background:var(--brass-soft)}
.chips a.off{opacity:.6}
.wcards{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:16px;margin:0 0 16px}
.wcard{background:var(--card);border:1px solid var(--rule);border-radius:var(--r);padding:16px;display:flex;flex-direction:column;gap:12px;min-width:0}
.wcard.live{border-color:var(--good)}
.wcard .head{display:flex;gap:10px;align-items:flex-start}
.wcard .head h3{margin:0;font-size:16px;line-height:22px;font-weight:600;flex:1 1 auto;min-width:0}
.wcard .head h3 a{color:inherit;text-decoration:none}
.wcard .head h3 a:hover{color:var(--brass-ink)}
.wcard .when{font-size:12px;line-height:16px;color:var(--ink-3)}
.wcard .when .date{color:var(--ink);font-weight:600;background:var(--brass-soft);padding:0 4px;border-radius:3px}
.wnums{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:12px;border-top:1px solid var(--rule);border-bottom:1px solid var(--rule);padding:10px 0}
.wnums small,.wprod small,.wbar small{display:block;font-size:11px;line-height:14px;color:var(--ink-3);text-transform:uppercase;letter-spacing:.03em;font-family:"Barlow Semi Condensed",Barlow,sans-serif;font-weight:600}
.wnums b{font-size:22px;line-height:28px;font-weight:600;font-variant-numeric:tabular-nums}
.wnums .of,.wprod em{font-size:13px;color:var(--ink-3);font-weight:400;font-style:normal;font-variant-numeric:tabular-nums}
.wnums .stale b{color:var(--owed)}
.wprods{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:8px}
.wprod{display:block;text-decoration:none;color:inherit;background:var(--paper);border-radius:var(--r-sm);padding:8px 10px;min-width:0}
.wprod b{font-size:16px;font-variant-numeric:tabular-nums;font-weight:600}
.wprod em.all{color:var(--good)}
.wcard .acts{display:flex;gap:8px;flex-wrap:wrap}
.wstrip{display:grid;grid-template-columns:repeat(5,minmax(0,1fr));gap:16px;padding:16px;border:1px solid var(--rule);border-radius:var(--r);background:var(--card);margin:0 0 16px}
.wstrip small{display:block;font-size:11px;line-height:14px;color:var(--ink-3);text-transform:uppercase;letter-spacing:.03em;font-family:"Barlow Semi Condensed",Barlow,sans-serif;font-weight:600}
.wstrip b{font-size:24px;line-height:30px;font-weight:600;font-variant-numeric:tabular-nums}
.wstrip .of{font-size:13px;color:var(--ink-3);font-weight:400}
.wstrip .sub{display:block;font-size:12px;color:var(--ink-3)}
.wbars{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:12px}
.wbar{background:var(--card);border:1px solid var(--rule);border-radius:var(--r);padding:12px 14px}
.wbar b{font-size:20px;font-variant-numeric:tabular-nums;font-weight:600}
.wbar i{display:block;height:6px;border-radius:3px;background:var(--rule);margin-top:8px;overflow:hidden}
.wbar i em{display:block;height:100%;background:var(--good)}
.wbar.part i em{background:var(--owed)}
.wbar.no i em{background:var(--bad)}
.wbar.wait i em{background:var(--rule-2)}
.pills{display:flex;gap:4px;flex-wrap:wrap}
.pill{font-size:11px;line-height:18px;padding:0 6px;border-radius:3px;background:var(--paper);border:1px solid var(--rule);color:var(--ink-2);white-space:nowrap}
.pill.sent{background:var(--good-soft);border-color:var(--good-soft);color:var(--good)}
.wsec{margin:0 0 24px}
.wsec h2{margin:0 0 12px;font-family:"Barlow Semi Condensed",Barlow,sans-serif;font-size:15px;font-weight:700}
.wsec h2 small{font-weight:400;color:var(--ink-3);font-family:Barlow,sans-serif;font-size:13px;margin-left:8px}
@media (max-width:900px){.wcards{grid-template-columns:1fr}.wprods{grid-template-columns:repeat(2,minmax(0,1fr))}.wstrip{grid-template-columns:repeat(2,minmax(0,1fr))}.wbars{grid-template-columns:repeat(2,minmax(0,1fr))}}

/* Card frames on the Webinars board: coffee, 2 px (Ravit picked option C, 6 Nov
   2026). Coffee lifts in the dark theme so a dark line never sits on a dark
   card. The live card keeps its green edge, so live still jumps out. */
:root{--coffee:#6F4E37}
@media (prefers-color-scheme:dark){:root:not([data-theme="light"]):not([data-surface="portal"]){--coffee:#B08968}}
[data-theme="dark"]{--coffee:#B08968}
.wcard{border:2px solid var(--coffee)}
.wcard.live{border-color:var(--good)}
