/* ============================================================================
   FixedLending Controller Dashboard — design system

   Chrome deliberately matches the Lendr web app the Controller uses all day:
   deep teal header, cool light-gray canvas, white cards with a soft shadow and
   large teal numerals. Lendr already puts this company's warm earth-toned seal
   on a teal header, so the pairing is the one they actually look at — matching it
   removes the context-switch between the two tools.

   The status vocabulary is kept from the earlier pass (it survives the palette
   change because Lendr colours its own numbers the same way: red for aged
   receivables, amber for expiring insurance, green for active):
     · Status is never carried by colour alone — always colour + fill + glyph.
     · "Due" carries no colour. It is the default state of everything today;
       colouring it would drown the states that actually mean something.
     · If it is a number or a time, it is mono/tabular. If it is prose, it is sans.
   ========================================================================== */

@font-face { font-family: 'Inter'; src: url('fonts/inter-400.woff2') format('woff2'); font-weight: 400; font-display: swap; }
@font-face { font-family: 'Inter'; src: url('fonts/inter-500.woff2') format('woff2'); font-weight: 500; font-display: swap; }
@font-face { font-family: 'Inter'; src: url('fonts/inter-600.woff2') format('woff2'); font-weight: 600; font-display: swap; }
@font-face { font-family: 'Inter'; src: url('fonts/inter-700.woff2') format('woff2'); font-weight: 700; font-display: swap; }
@font-face { font-family: 'Poppins'; src: url('fonts/poppins-600.woff2') format('woff2'); font-weight: 600; font-display: swap; }
@font-face { font-family: 'JetBrains Mono'; src: url('fonts/jetbrainsmono-400.woff2') format('woff2'); font-weight: 400; font-display: swap; }
@font-face { font-family: 'JetBrains Mono'; src: url('fonts/jetbrainsmono-500.woff2') format('woff2'); font-weight: 500; font-display: swap; }
@font-face { font-family: 'JetBrains Mono'; src: url('fonts/jetbrainsmono-700.woff2') format('woff2'); font-weight: 700; font-display: swap; }

:root {
  /* chrome — Lendr's teal + cool neutrals */
  --teal-900: #14536F;
  --teal-800: #1A6284;
  --teal-700: #1F7096;   /* header base */
  --teal-600: #2A82AA;
  --teal-500: #3D97BF;   /* big numerals */
  --teal-050: #E9F3F8;
  --teal-line: rgba(255,255,255,.16);

  --ink:      #1E2A32;
  --ink-2:    #526270;
  --ink-3:    #7E8C98;
  --canvas:   #F1F4F6;
  --surface:  #FFFFFF;
  --surface-2:#F7F9FA;
  --rule:     #E2E8EC;
  --rule-2:   #CFD8DE;

  --accent:     #1F7096;
  --accent-ink: #14536F;
  --accent-bg:  var(--teal-050);
  --data:       #2A6C8C;   /* numerals, timestamps, ids */

  /* status vocabulary */
  --ok:    #2E7D4F;  --ok-bg:   #E8F4EC;  --ok-bar:  #3D9A63;
  --due:   #526270;  --due-bg:  #F0F3F5;
  --exc:   #B3261E;  --exc-bg:  #FCEBE9;
  --miss:  #9A6408;  --miss-bg: #FDF3E2;  --miss-bar:#C6890F;
  --stale: #55707E;  --stale-bg:#EDF2F5;

  /* Cadence coding. Hues are spread ~45° apart so they are separable at a glance,
     and every chip also carries a D/W/M/E letter — colour is never the only cue.
     All stay cool/violet so none can be mistaken for a warm status alarm. */
  --cad-daily:   #0E8390;   /* teal    */
  --cad-weekly:  #2B5FD9;   /* blue    */
  --cad-monthly: #8138C9;   /* purple  */
  --cad-event:   #C2359B;   /* magenta */

  /* Lendr's action-items panel is a warm cream card with a yellow rule */
  --act-bg:   #FFFCEB;
  --act-line: #E8C95C;
  --act-ink:  #6B5410;
  --act-pill: #FBF0C4;

  --sans: 'Inter', 'Segoe UI Variable Text', 'Segoe UI', system-ui, sans-serif;
  --display: 'Poppins', 'Inter', 'Segoe UI', system-ui, sans-serif;
  --mono: 'JetBrains Mono', 'Cascadia Mono', Consolas, ui-monospace, monospace;

  --r: 8px;      /* Lendr's cards are softly rounded */
  --r-sm: 5px;
  --shadow: 0 1px 2px rgba(30,42,50,.06), 0 1px 3px rgba(30,42,50,.04);
  --shadow-lift: 0 2px 6px rgba(30,42,50,.10), 0 1px 3px rgba(30,42,50,.06);
}

* { box-sizing: border-box; }
html, body { height: 100%; }
body {
  margin: 0; background: var(--canvas); color: var(--ink);
  font: 400 14px/1.5 var(--sans);
  -webkit-font-smoothing: antialiased;
}
.hidden { display: none !important; }

.num, .ts, td.num, .mono { font-family: var(--mono); font-variant-numeric: tabular-nums; }
.ts { font-size: 11.5px; color: var(--stale); letter-spacing: -0.01em; white-space: nowrap; }
.ts::before { content: '◷ '; opacity: .75; }
.ts.plain::before { content: none; }

:focus-visible { outline: 2px solid var(--teal-600); outline-offset: 2px; }

/* ===================== sign-in ========================================== */
.gate { position: fixed; inset: 0; z-index: 60; display: grid; place-items: center; padding: 24px;
  background: linear-gradient(160deg, var(--teal-800) 0%, var(--teal-700) 55%, #2E8CA8 100%); }
.gate-card { width: 430px; max-width: 100%; background: var(--surface);
  border-radius: 12px; padding: 34px 36px 30px; box-shadow: 0 18px 48px rgba(10,40,55,.28); }
.gate-logo { width: 226px; height: auto; display: block; margin-bottom: 24px; }
.gate-card h1 { font: 600 16px/1.3 var(--display); margin: 0 0 6px; letter-spacing: -0.01em; }
.gate-card p.sub { margin: 0 0 22px; color: var(--ink-2); font-size: 13px; }
.field { display: block; margin-bottom: 14px; }
.field > span { display: block; font-size: 11px; font-weight: 600; letter-spacing: .06em;
  text-transform: uppercase; color: var(--ink-3); margin-bottom: 5px; }
/* A hint is a sentence, not a label — it must not inherit the all-caps treatment. */
.field > span.hint { text-transform: none; letter-spacing: 0; font-weight: 400; font-size: 11.5px;
  margin: 5px 0 0; line-height: 1.45; }
.field input, .field select { width: 100%; padding: 9px 11px; font: 400 14px var(--sans); color: var(--ink);
  background: var(--surface); border: 1px solid var(--rule-2); border-radius: var(--r-sm); }
.field input:focus, .field select:focus { border-color: var(--teal-600); outline-offset: 0; }
.gate-note { margin: 18px 0 0; padding-top: 14px; border-top: 1px solid var(--rule);
  font-size: 12px; color: var(--ink-3); line-height: 1.55; }

/* ===================== header (single row) ============================== */
.topbar { background: var(--teal-700); color: #fff; position: sticky; top: 0; z-index: 30;
  display: flex; align-items: center; gap: 16px; padding: 10px 20px; flex-wrap: wrap; }
.topbar .spacer { flex: 1; }
.brand { display: flex; align-items: center; gap: 10px; flex: none; }
/* Monochrome white seal on the teal header — no backing shape needed, the mark
   is white and the rhino stays transparent. */
.brand img { width: 34px; height: 34px; flex: none; }
.brand .name { font: 600 16px/1 var(--display); letter-spacing: -0.01em; color: #fff; }

/* Start My Day is an ACTION, not a destination. The active nav tab is a filled
   RECTANGLE, so this must not be one — two filled rectangles read as two
   selected tabs. A fully rounded pill plus a divider puts it in a different
   visual class entirely, so shape carries the distinction rather than colour
   alone (which would fail the moment it sits next to the active tab). */
.navlink.is-start { background: #E8C95C; color: #35290A; font-weight: 700;
  padding: 0 15px; height: 28px; border-radius: 999px; box-shadow: none; }
.navlink.is-start:hover { background: #F2D877; color: #35290A; }
.navlink.is-start[data-empty='1'] { background: transparent; color: rgba(255,255,255,.82);
  font-weight: 600; border: 1px solid rgba(255,255,255,.35); }
.navlink.is-start[data-empty='1']:hover { background: rgba(255,255,255,.14); color: #fff; }
.navlink.is-start[hidden] { display: none; }
.startcnt { font: 700 10.5px/1 var(--mono); background: rgba(0,0,0,.2); color: inherit;
  padding: 3px 5px; border-radius: 999px; }
/* divider: the pill belongs to the brand side, the tabs to the nav side */
.nav-sep { width: 1px; height: 20px; background: rgba(255,255,255,.22); margin: 0 10px 0 4px; flex: none; }

/* nav sits in one line beside the brand, not bunched in a corner */
.navrow { display: flex; align-items: center; gap: 2px; flex-wrap: wrap; }
/* fixed height so a count badge inside one item can't make it taller than its
   siblings — the row has to read as a single clean line */
.navlink, .navitem > button { background: none; border: 0; color: rgba(255,255,255,.9); cursor: pointer;
  font: 500 14px/1 var(--sans); height: 32px; padding: 0 12px; border-radius: var(--r-sm);
  display: flex; align-items: center; gap: 6px; white-space: nowrap; }
.navitem > button .chip { padding: 3px 6px; font-size: 10.5px; }
.navlink:hover, .navitem > button:hover { background: rgba(255,255,255,.13); color: #fff; }
.navlink[aria-current='page'], .navitem[data-open='1'] > button,
.navitem > button[aria-current='page'] { background: rgba(255,255,255,.2); color: #fff; }
#nav { display: flex; align-items: center; gap: 2px; }
.navitem { position: relative; }
.navitem .caret { font-size: 9px; opacity: .8; }
.navmenu { position: absolute; top: calc(100% + 7px); left: 0; min-width: 316px; background: var(--surface);
  border: 1px solid var(--rule); border-radius: var(--r); box-shadow: 0 12px 32px rgba(20,50,65,.22);
  padding: 7px; z-index: 40; }
.navmenu button { display: flex; align-items: center; gap: 11px; width: 100%; text-align: left; background: none;
  border: 0; padding: 9px 10px; border-radius: var(--r-sm); color: var(--ink); cursor: pointer; }
.navmenu button:hover { background: var(--surface-2); }
.navmenu button[aria-current='page'] { background: var(--teal-050); }
.navmenu button[aria-current='page'] .nm-label { color: var(--accent-ink); font-weight: 700; }
/* The icon reuses the calendar's cadence colours, so D/W/M/E mean the same
   thing in the menu as they do on a chip. */
.nm-ico { flex: none; width: 26px; height: 26px; border-radius: 6px; display: grid; place-items: center;
  background: var(--ink-3); color: #fff; font: 700 11px/1 var(--sans); font-style: normal; }
.nm-ico[data-cad='daily']   { background: var(--cad-daily); }
.nm-ico[data-cad='weekly']  { background: var(--cad-weekly); }
.nm-ico[data-cad='monthly'] { background: var(--cad-monthly); }
.nm-ico[data-cad='event']   { background: var(--cad-event); }
.nm-txt { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.nm-label { font: 600 13.5px/1.2 var(--sans); color: var(--ink); }
.nm-desc { font: 400 11.5px/1.3 var(--sans); color: var(--ink-3); }
.navmenu .cnt { margin-left: auto; flex: none; align-self: center;
  font: 600 11px var(--mono); color: var(--ink-3); background: var(--surface-2);
  padding: 3px 7px; border-radius: 999px; }
.navmenu .cnt[data-tone='exc'] { color: var(--exc); font-weight: 700; }
.navmenu .cnt[data-tone='miss'] { color: var(--miss); font-weight: 700; }
/* Home (calendar) is icon-only — square rather than the text tabs beside it,
   since a label would just repeat what its position already says. */
.navlink.is-home { width: 32px; padding: 0; justify-content: center; }
.navlink.is-home svg { display: block; }
.topbar .pulls { display: flex; align-items: center; gap: 10px; flex: none; }
.topbar .ts { color: rgba(255,255,255,.75); }
.signout { background: rgba(255,255,255,.12); border: 1px solid var(--teal-line); color: #fff;
  font: 500 12.5px var(--sans); padding: 6px 11px; border-radius: var(--r-sm); cursor: pointer; }
.signout:hover { background: rgba(255,255,255,.22); }
.role-tag { font: 500 10px/1 var(--mono); letter-spacing: .06em; padding: 4px 6px; border-radius: 3px;
  text-transform: uppercase; background: rgba(255,255,255,.16); color: #fff; }
.role-tag[data-role='cfo'] { background: rgba(255,255,255,.1); color: rgba(255,255,255,.8); }

/* ===================== page ============================================= */
.page { max-width: 1400px; margin: 0 auto; padding: 18px 20px 60px; }
h1.view-title { font: 600 20px/1.2 var(--display); margin: 0 0 2px; letter-spacing: -0.015em; }
.lede { color: var(--ink-2); font-size: 13px; margin: 0 0 16px; max-width: 80ch; }
.section-h { display: flex; align-items: baseline; gap: 10px; margin: 24px 0 9px; }
.section-h:first-child { margin-top: 0; }
.section-h h2 { font: 600 11px/1 var(--sans); letter-spacing: .09em; text-transform: uppercase;
  color: var(--ink-3); margin: 0; }
.section-h .rulefill { flex: 1; height: 1px; background: var(--rule); }
.section-h .tally { font: 500 11.5px var(--mono); color: var(--ink-3); }
/* The one section that opens the Snapshot page in the exception colour — it
   earns the emphasis precisely because everything below it deliberately
   doesn't get it. */
.section-h[data-tone='exc'] h2 { color: var(--exc); }
.section-h[data-tone='exc'] .rulefill { background: var(--exc); opacity: .35; }
.section-h[data-tone='exc'] .tally { color: var(--exc); }

/* ===================== Snapshot page ==================================== */
/* Source pill — a mixed Lendr+Tracker card still has to say where a figure
   came from, since sections group by topic rather than by system. */
.src-tag { display: inline-block; font: 600 9px/1 var(--sans); letter-spacing: .05em;
  text-transform: uppercase; color: var(--ink-3); background: var(--surface-2);
  border-radius: 3px; padding: 3px 6px; vertical-align: middle; }

/* ===== KPI tiles — Lendr's own idiom: a flat white card, a plain label, one
   big number. Everything on the Snapshot page that used to be a chip, a
   strip item, or a card header is now this ONE component, so the whole page
   reads as one visual language instead of three. */
.ktile-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
  gap: 16px; margin-bottom: 22px; align-items: stretch; }
.ktile-grid:last-child { margin-bottom: 0; }
.ktile { display: flex; flex-direction: column; justify-content: center; gap: 8px;
  min-height: 108px; padding: 20px 22px; background: var(--surface); border: none;
  border-radius: var(--r); box-shadow: var(--shadow); text-align: left;
  font-family: inherit; color: inherit; position: relative; }
button.ktile { cursor: pointer; transition: box-shadow .12s ease, transform .05s ease; }
button.ktile:hover { box-shadow: var(--shadow-lift); }
button.ktile:active { transform: translateY(1px); }
.ktile-label { font: 500 13.5px/1.3 var(--sans); color: var(--ink-2); }
.ktile-sub { display: block; font: 400 11px/1.35 var(--sans); color: var(--ink-3); margin-top: 2px; }
.ktile-val { font: 600 28px/1.15 var(--sans); letter-spacing: -0.01em;
  font-variant-numeric: tabular-nums; color: var(--teal-500); white-space: nowrap; }
/* "Needs you" tiles carry the exception tone — the one place colour marks
   something overdue rather than just being a metric. */
.ktile[data-tone='exc'] .ktile-val { color: var(--exc); }
.ktile-go { position: absolute; top: 16px; right: 18px; font-size: 13px; color: var(--ink-3);
  opacity: 0; transition: opacity .12s; }
button.ktile:hover .ktile-go, button.ktile:focus-visible .ktile-go { opacity: 1; }
/* The hero row (Loans outstanding, Trust balance, …) gets a slightly larger
   numeral — it's the one row visible with nothing collapsed, so it can afford
   to lead a little louder than the tiles inside a folded section. */
.ktile-grid.is-hero .ktile-val { font-size: 32px; }
.ktile.filtered-out { display: none; }
.ktile.is-hit { box-shadow: 0 0 0 2px var(--teal-600), var(--shadow); }

/* Snapshot toolbar — filter + exports, acting on the whole page. */
.snap-bar { display: flex; align-items: center; gap: 10px; margin-bottom: 16px; }
/* Bulk-action bar — appears once ≥1 row is checked, for applying one status
   change (and an optional appended note) to a whole selection at once instead
   of one row at a time. */
.bulk-bar { display: flex; align-items: center; gap: 10px; margin-bottom: 12px;
  padding: 9px 12px; background: var(--teal-050); border: 1px solid var(--teal-600);
  border-radius: var(--r-sm); }
.bulk-bar #oi-bulk-count { font-weight: 600; color: var(--accent-ink); white-space: nowrap; }
#snap-filter { flex: 0 1 340px; padding: 8px 12px; font: 400 13px var(--sans); color: var(--ink);
  background: var(--surface); border: 1px solid var(--rule); border-radius: var(--r-sm); }
#snap-filter:focus { outline: none; border-color: var(--teal-600); box-shadow: 0 0 0 3px var(--teal-050); }
#snap-filter-n { font-size: 11.5px; }
.filtered-out { display: none !important; }

/* Movement vs the previous refresh. Neutral grey on purpose — whether a rise
   is good or bad depends entirely on the figure, and the page can't know. */
.delta { margin-left: 7px; font: 600 10.5px var(--mono); color: var(--ink-3);
  background: var(--surface-2); border-radius: 3px; padding: 2px 5px; vertical-align: middle; }
.delta.is-flat { opacity: .55; }
.bs-since { margin: -12px 0 20px; text-align: right;
  font: 500 10px var(--sans); color: var(--ink-3); }
/* Cash direction on trust categories. Neutral-toned on purpose: money leaving
   the trust account is normal operations (draws, distributions), not an alarm. */
.flow-in, .flow-out { margin-left: 8px; font: 600 9.5px var(--sans); letter-spacing: .04em;
  padding: 2px 6px; border-radius: 999px; vertical-align: middle; }
.flow-in { background: var(--ok-bg); color: var(--ok); }
.flow-out { background: var(--surface-2); color: var(--ink-3); }
.arcat-plan { opacity: 0; }
.arcat > summary:hover .arcat-plan, .arcat-plan:focus-visible { opacity: 1; }

/* Print / save-as-PDF: drop the app chrome and interactive affordances, force
   every disclosure open so a printed copy is complete rather than a snapshot
   of whatever happened to be expanded on screen. */
@media print {
  .topbar, .no-print, .qplan, .chip-v, .chip-x, .addbtn, #toast, .cal-under { display: none !important; }
  .page { padding: 0; max-width: none; }
  details { break-inside: avoid; }
  details:not([open]) > *:not(summary) { display: revert !important; }
  details > summary { list-style: none; }
  .qf-caret { display: none; }
  .ktile, .qfold, .arcat { break-inside: avoid; box-shadow: none; }
  .qrow:hover, .arcat > summary:hover { background: transparent; }
  a[href^="https://joinlendr.com"]::after { content: " (" attr(href) ")"; font-size: 8px; color: #666; }
  body { background: #fff; }
}

/* The row of controls above a detail list inside the viewer dialog — export
   button for AR/Trust, item count for an exception category. */
.viewer-toolbar { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; }
/* AR/Trust category rows, reused inside the viewer dialog: each category is
   its own details/summary row, so however many loans sit inside one cost
   nothing until that category is actually opened. */
.arcat { border-bottom: 1px solid var(--rule); }
.arcat:last-child { border-bottom: 0; }
.arcat > summary { display: flex; align-items: center; gap: 12px; padding: 10px 14px;
  cursor: pointer; list-style: none; }
.arcat > summary::-webkit-details-marker { display: none; }
.arcat > summary:hover { background: var(--teal-050); }
.arcat-amt { flex: none; width: 100px; font: 600 13px/1.1 var(--mono); font-variant-numeric: tabular-nums; color: var(--ink); }
.arcat-name { flex: 1; font: 500 12.5px var(--sans); color: var(--ink); }
.arcat-n { flex: none; font: 500 11px var(--mono); color: var(--ink-3); }
.arcat .qf-caret { transition: transform .15s; }
.arcat[open] > summary { background: var(--teal-050); border-bottom: 1px solid var(--rule); }
.arcat[open] .qf-caret { transform: rotate(180deg); }
.arcat .qlist { background: var(--surface-2); }

/* One row = one piece of work, laid out like a bank-statement line: what it is
   plus the amount on the first line, context muted beneath. A single flex line
   forced the address, meta, amount and button to fight over ~370px, wrapping
   addresses onto three lines. */
.qlist { list-style: none; margin: 0; padding: 0; }
.qrow { display: grid; grid-template-columns: minmax(0, 1fr) auto auto;
  column-gap: 12px; row-gap: 1px; align-items: center; padding: 8px 14px;
  border-bottom: 1px solid var(--rule); font-size: 12.5px; }
.qrow:last-child { border-bottom: 0; }
.qrow:hover { background: var(--teal-050); }
.qmain { grid-column: 1; min-width: 0; font-weight: 600; color: var(--accent-ink); text-decoration: none;
  display: flex; align-items: baseline; gap: 5px; }
.qmain:hover { text-decoration: underline; }
.qmain.is-plain { color: var(--ink); font-weight: 500; }
.qext { font-size: 9px; opacity: .7; }
.qmeta { grid-column: 1; min-width: 0; color: var(--ink-3); font-size: 11px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.qamt { grid-column: 2; grid-row: 1 / span 2; font: 600 12px var(--mono);
  font-variant-numeric: tabular-nums; color: var(--ink); }
/* Plan stays hidden until hover so a card reads as information first and a
   menu of buttons second. */
.qplan { grid-column: 3; grid-row: 1 / span 2; opacity: 0; border: 1px solid var(--rule-2);
  background: var(--surface); color: var(--accent-ink); border-radius: 4px; padding: 3px 8px;
  cursor: pointer; font: 600 10.5px var(--sans); white-space: nowrap; transition: opacity .12s; }
.qrow:hover .qplan, .qplan:focus-visible { opacity: 1; }
.qplan:hover { background: var(--teal-050); border-color: var(--teal-600); }
.qempty { padding: 16px 14px; margin: 0; color: var(--ink-3); font-size: 12.5px; }
.qnote { padding: 8px 14px; margin: 0; border-top: 1px solid var(--rule);
  color: var(--ink-3); font-size: 11px; background: var(--surface-2); }

/* Everything that isn't an exception is folded away by default. */
.qfold { border: 1px solid var(--rule); border-radius: var(--r); background: var(--surface);
  margin-bottom: 12px; }
.qfold > summary { display: flex; align-items: center; gap: 10px; padding: 12px 15px;
  cursor: pointer; list-style: none; font: 600 12.5px var(--sans); color: var(--ink); }
.qfold > summary::-webkit-details-marker { display: none; }
.qfold > summary:hover { background: var(--surface-2); }
.qf-label { flex: 1; }
.qf-n { font: 600 11px var(--mono); color: var(--ink-3); background: var(--surface-2);
  border-radius: 999px; padding: 3px 8px; }
.qf-caret { font-size: 10px; color: var(--ink-3); transition: transform .15s; }
.qfold[open] > summary { border-bottom: 1px solid var(--rule); }
.qfold[open] .qf-caret { transform: rotate(180deg); }
.qfold .ktile-grid { padding: 14px; margin-bottom: 0; }

/* Freshness: meta-information, so it sits last and quiet. */
.fresh-row { display: flex; flex-wrap: wrap; align-items: center; gap: 16px; padding: 14px 2px 2px;
  margin-top: 8px; border-top: 1px solid var(--rule); }
.fresh-item { font: 500 12px var(--sans); color: var(--ink-2); display: flex; align-items: center; gap: 7px; }

/* ===================== banners ========================================= */
.banner { display: flex; align-items: flex-start; gap: 10px; padding: 11px 14px; border-radius: var(--r);
  font-size: 13px; margin-bottom: 14px; background: var(--miss-bg); color: var(--miss);
  box-shadow: inset 3px 0 0 var(--miss-bar); }
.banner b { font-weight: 600; }
.banner.stale-banner { background: var(--stale-bg); color: var(--stale); box-shadow: inset 3px 0 0 var(--stale); }
.notice { padding: 10px 14px; border-radius: var(--r); font-size: 12.5px; background: var(--surface);
  color: var(--ink-2); border: 1px solid var(--rule); margin-bottom: 14px; }
.notice.readonly { background: var(--stale-bg); color: var(--stale); border-color: #D8E2E8; }

/* Day-build's morning digest — see dayDigest() in app.js. */
.digest { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; padding: 10px 14px;
  border-radius: var(--r); background: var(--surface); border: 1px solid var(--rule); margin-bottom: 14px; }
.digest.is-clear { color: var(--ink-3); font-size: 13px; }
.digest-lead { font: 600 11px var(--sans); text-transform: uppercase; letter-spacing: .03em; color: var(--ink-3); }
.digest-chip { display: inline-flex; align-items: baseline; gap: 5px; padding: 6px 11px;
  border-radius: var(--r-sm); border: 1px solid var(--exc); background: var(--exc-bg); color: var(--exc);
  font: 400 12.5px var(--sans); cursor: pointer; }
.digest-chip:hover { background: var(--exc); color: #fff; }
.digest-chip b { font: 700 14px var(--mono); }

/* ===================== KPI / stat cards (Lendr look) ==================== */
.stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 12px; margin-bottom: 18px; }
.stat { background: var(--surface); border: 1px solid var(--rule); border-radius: var(--r);
  padding: 15px 17px 16px; box-shadow: var(--shadow); }
.stat .k { font-size: 13px; color: var(--ink-2); margin-bottom: 8px; font-weight: 500; }
.stat .v { font: 600 27px/1.1 var(--sans); font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em; color: var(--teal-500); }
.stat .v small { font-size: 15px; color: var(--ink-3); font-weight: 500; }
.stat[data-tone='ok']   .v { color: var(--ok); }
.stat[data-tone='exc']  .v { color: var(--exc); }
.stat[data-tone='miss'] .v { color: var(--miss); }
.stat[data-tone='flat'] .v { color: var(--ink); }
.stat .note { font-size: 12px; color: var(--ink-3); margin-top: 6px; line-height: 1.4; }

/* ===================== calendar ======================================== */
.cal-bar { display: flex; align-items: center; gap: 10px; margin-bottom: 14px; flex-wrap: wrap; }
.cal-bar .range { font: 600 15px var(--display); letter-spacing: -0.01em; }
.seg { display: inline-flex; border: 1px solid var(--rule-2); border-radius: var(--r-sm); overflow: hidden; background: var(--surface); }
.seg button { border: 0; background: none; font: 500 12.5px var(--sans); padding: 6px 13px; cursor: pointer; color: var(--ink-2); }
.seg button[aria-pressed='true'] { background: var(--teal-700); color: #fff; }
.seg button:disabled { cursor: not-allowed; opacity: .4; }
.iconbtn { width: 30px; height: 30px; border-radius: var(--r-sm); border: 1px solid var(--rule-2);
  background: var(--surface); cursor: pointer; color: var(--ink-2); font-size: 14px; line-height: 1; }
.iconbtn:hover { border-color: var(--teal-600); color: var(--accent-ink); }

/* The rail lives BELOW the grid so the calendar owns the full page width —
   at 1280px a 7-column split left only ~120px per day, which is unreadable. */
.cal-under { display: grid; grid-template-columns: 320px minmax(0,1fr); gap: 16px; align-items: start; margin-top: 16px; }
.cal-under .rail-card { margin-bottom: 0; }

/* week: one column per day, column count set inline (5 for Mon–Fri, 7 for all) */
.week { display: grid; gap: 10px; }
.daycol { background: var(--surface); border: 1px solid var(--rule); border-radius: var(--r);
  box-shadow: var(--shadow); display: flex; flex-direction: column; min-height: 330px; overflow: hidden; }
.daycol.is-today { border-color: var(--teal-600); box-shadow: 0 0 0 2px rgba(31,112,150,.16), var(--shadow); }
.daycol.is-weekend { background: var(--surface-2); }
.daycol.in-window { border-top: 3px solid var(--miss-bar); }
.dayhead { padding: 10px 12px 9px; border-bottom: 1px solid var(--rule); cursor: pointer; }
.dayhead:hover { background: var(--surface-2); }
.dayhead .dow { font: 600 11px/1 var(--sans); letter-spacing: .09em; text-transform: uppercase; color: var(--ink-3); }
.dayhead .dnum { font: 600 22px/1.1 var(--sans); font-variant-numeric: tabular-nums; margin-top: 4px; }
.daycol.is-today .dayhead { background: var(--teal-050); }
.daycol.is-today .dayhead .dnum { color: var(--accent-ink); }
.dayhead .cnt { font: 500 11px var(--mono); color: var(--ink-3); }
.dayhead .is-today-pill { background: var(--teal-600); color: #fff; border-radius: 999px;
  padding: 2px 7px; font: 600 9.5px/1 var(--sans); letter-spacing: .04em; text-transform: uppercase;
  vertical-align: middle; margin-left: 4px; }
/* One line per day that answers "is this day done?" before you read any chip. */
.daystat { display: block; margin-top: 5px; font: 500 11px/1.2 var(--sans); color: var(--ink-2); }
.daystat b { font-weight: 700; color: var(--ink); }
.daystat[data-all-done='true'] { color: var(--ok); }
.daystat.is-clear { color: var(--ink-3); }
.daybody { padding: 8px; display: flex; flex-direction: column; gap: 6px; flex: 1; }
.day-empty { padding: 10px 6px; font: 400 11.5px var(--sans); color: var(--ink-3); font-style: italic; }
/* Finished + skipped history, collapsed to one line. It stays reachable (the
   audit trail is the point of this tool) but stops competing with live work. */
.day-settled { display: flex; align-items: center; gap: 5px; width: 100%; margin-top: 2px;
  border: 0; border-top: 1px dashed var(--rule); background: transparent; cursor: pointer;
  padding: 7px 4px 2px; font: 500 10.5px/1 var(--sans); color: var(--ink-3); text-align: left; }
.day-settled:hover { color: var(--accent-ink); }
.day-settled .caret { font-size: 8px; }

/* ===== Day build — the unified single-day view =========================
   One flat list mixing three normally-separate things (controls, event-run
   steps, reminders). Controls/steps reuse .task (instanceCard) wholesale for
   the full checklist treatment; reminders and not-yet-real controls get a
   lighter row of their own since there's nothing to expand. */
.dbuild { max-width: 760px; margin: 0 auto; }
.dblist { display: flex; flex-direction: column; gap: 8px; margin-bottom: 4px; }
.dbrow { display: flex; align-items: flex-start; gap: 10px; }
.dbrow-side { display: flex; align-items: center; gap: 4px; flex: none; padding-top: 12px; }
.dbrow-body { flex: 1; min-width: 0; }
.dbrow-body .task { margin-bottom: 0; }
.dbrow.is-proj, .dbrow.is-adhoc, .dbrow.is-run {
  align-items: center; background: var(--surface); border: 1px solid var(--rule);
  border-radius: var(--r); padding: 10px 14px; box-shadow: var(--shadow); flex-wrap: wrap; }
.dbrow.is-adhoc { border-style: dashed; }
.dbrow.is-proj { border-style: dashed; opacity: .85; }
.dbrow-main { flex: 1; min-width: 200px; display: flex; flex-direction: column; gap: 2px; }
.dbrow-main b { font: 600 13px var(--sans); color: var(--ink); }
.dbrow-detail { flex-basis: 100%; margin-left: 34px; }
.dbrow-detail .task { margin-top: -2px; }

/* A chip carries TWO signals: a cadence stripe on the left edge (what kind of
   task) and the fill/text colour (its status). They never collide because
   cadence hues are cool and status hues are warm. */
.chip-task { display: flex; align-items: center; gap: 7px; width: 100%; text-align: left;
  border: 1px solid var(--rule); background: var(--surface); border-radius: 5px; min-height: 30px;
  padding: 5px 9px 5px 5px; font: 400 12.5px/1.3 var(--sans); color: var(--ink); cursor: pointer; }
.chip-task:hover { border-color: var(--teal-600); background: var(--teal-050); }
.chip-task .g { font-size: 9px; flex: none; }
/* cadence letter badge — unambiguous even if the hues read alike */
.chip-task .cad { flex: none; width: 18px; height: 18px; border-radius: 4px;
  display: grid; place-items: center; background: var(--cad, var(--ink-3));
  color: #fff; font: 700 10px/1 var(--sans); letter-spacing: 0; }
.chip-task[data-s='past'] .cad { opacity: .45; }
/* Wrap to two lines rather than ellipsing on one. A day column is narrow
   enough that "Bank-to-ledger reconc…" and "Bank-to-ledger recor…" are the
   same string — the second line is what makes them different tasks.
   Excludes .is-lendr: that column already shows the full, unclamped text
   (its own rule sets overflow:visible for exactly that reason), and the two
   rules fighting over `overflow` is what broke it — line-clamp still applied
   from this rule while visibility won from the more specific one, an
   inconsistent half-state rather than either full text or a clean clip. */
.chip-task:not(.is-lendr) .lbl { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden; overflow-wrap: anywhere; }
.chip-task .cad, .chip-task .g { align-self: flex-start; margin-top: 1px; }
.chip-main { align-items: flex-start; }
.chip-task.is-lendr .chip-main { align-items: flex-start; }
.chip-task[data-cad='daily']   { --cad: var(--cad-daily); }
.chip-task[data-cad='weekly']  { --cad: var(--cad-weekly); }
.chip-task[data-cad='monthly'] { --cad: var(--cad-monthly); }
.chip-task[data-cad='event']   { --cad: var(--cad-event); }
.chip-task[data-s='ok']    { background: var(--ok-bg);   color: var(--ok); }
.chip-task[data-s='exc']   { background: var(--exc);     color: #fff; font-weight: 600; }
.chip-task[data-s='miss']  { background: var(--miss-bg); color: var(--miss); font-weight: 500; }
.chip-task[data-s='past']  { background: transparent; color: var(--ink-3); opacity: .55; }
.chip-task[data-s='dismissed'] { background: transparent; color: var(--ink-3); text-decoration: line-through; }
.chip-task.is-run { background: var(--teal-050); color: var(--accent-ink); font-weight: 500; }
/* One-off reminders: grey, dashed, no cadence badge. Structurally and visually
   distinct from controls so a note can't be misread as a verified control.
   Two-part layout: .chip-main carries the click-to-open behaviour that used to
   live on the whole chip, .chip-x is a sibling so a button never nests inside
   a button. */
.chip-task.is-adhoc { background: var(--surface-2); color: var(--ink-2);
  border: 1px dashed var(--rule-2); border-left: 1px dashed var(--rule-2); font-style: italic;
  padding: 0 5px 0 5px; }
.chip-task.is-adhoc[data-s='ok'] { color: var(--ink-3); text-decoration: line-through; }
.chip-task.is-adhoc[data-s='miss'] { border-color: var(--miss-bar); color: var(--miss); font-style: normal; }
/* A control moved off its natural day. The dashed left edge says "this isn't
   where the recurrence put it" without implying the deadline changed — the
   status colour still comes from the real due date. */
.chip-task.is-planned { border-left: 3px dashed var(--teal-600); }
.planned-dot { flex: none; margin-left: auto; font-size: 9px; color: var(--accent-ink); opacity: .8; }
.chip-main, .mrow-main { flex: 1; display: flex; align-items: center; gap: 7px; min-width: 0;
  border: 0; background: transparent; padding: 5px 0; font: inherit; color: inherit;
  text-align: left; cursor: pointer; }
.mrow-main { gap: 5px; padding: 0; }
/* The action row. Sits BELOW the name rather than beside it — a day column is
   ~167px wide and the inline version left the task name 0px and invisible.
   Always visible, never hover-revealed: hover doesn't fire reliably on every
   input device, and a control you can't see is a control you don't have.
   The × arms on first click (turns solid red, "click again") and confirms on
   a second within ~2.5s — deliberate enough not to fire by accident. */
.chip-acts { display: flex; align-items: center; gap: 3px; padding: 3px 5px 4px;
  border: 1px solid var(--rule); border-top: 0; border-radius: 0 0 5px 5px;
  background: var(--surface-2); margin-top: -1px; }
.cact-gap { flex: 1; }
.cact { border: 1px solid transparent; background: transparent; border-radius: 4px;
  color: var(--ink-2); font: 600 10px/1 var(--sans); font-style: normal; cursor: pointer;
  padding: 4px 5px; min-width: 20px; white-space: nowrap;
  transition: background-color .12s, color .12s, border-color .12s; }
.cact:hover:not(:disabled) { background: var(--surface); border-color: var(--rule-2); color: var(--ink); }
.cact:disabled { opacity: .28; cursor: default; }
.cact.is-done { color: var(--ok); border-color: rgba(46,125,79,.35); background: var(--ok-bg); }
.cact.is-done:hover { background: var(--ok); color: #fff; border-color: var(--ok); }
.cact.is-done[data-done='true'] { background: var(--ok); color: #fff; border-color: var(--ok); }
.cact.is-drop { color: var(--ink-3); font-size: 13px; padding: 2px 6px; }
.cact.is-drop:hover { background: var(--miss-bg); color: var(--miss); border-color: var(--miss-bar); }
.cact.is-drop[data-armed='1'] { background: var(--miss); color: #fff; border-color: var(--miss); }
/* A chip with an action row loses its own bottom rounding so the two read as
   one object rather than two stacked ones. */
.chip-wrap:has(> .chip-acts) > .chip-task { border-bottom-left-radius: 0; border-bottom-right-radius: 0; }
/* Position badge. Doubles as the drag affordance — the whole chip is
   draggable, but this is the part that looks grabbable. */
.chip-ord { flex: none; min-width: 15px; height: 15px; border-radius: 3px; display: grid; place-items: center;
  background: rgba(30,42,50,.06); font: 700 9.5px/1 var(--mono); color: var(--ink-3); cursor: grab; }
/* On the solid-fill exception state, inherit its white text — ink-3 grey on a
   solid red chip is close to unreadable. */
.chip-task[data-s='exc'] .chip-ord { background: rgba(255,255,255,.22); color: inherit; }
/* Month view keeps its own compact inline buttons — narrower rows, no room for
   an action strip, and nothing there is being reordered. */
.chip-x { flex: none; width: 16px; height: 16px; border: 0; border-radius: 3px; background: transparent;
  color: var(--ink-3); font: 600 13px/1 var(--sans); font-style: normal; cursor: pointer;
  transition: background-color .12s, color .12s; }
.chip-x:hover { background: var(--miss-bg); color: var(--miss); }
.chip-x[data-armed='1'] { background: var(--miss); color: #fff; }
.chip-check { flex: none; width: 16px; height: 16px; border: 0; border-radius: 3px; background: transparent;
  color: var(--ink-3); font: 700 11px/1 var(--sans); cursor: pointer; padding: 0;
  transition: background-color .12s, color .12s; }
.chip-check:hover { background: var(--ok-bg); color: var(--ok); }
.chip-check[data-done='true'] { color: var(--ok); }
/* ---- inline checklist in the week column ---- */
.chip-wrap { display: block; }
/* With the checklist open the action row is mid-stack, so it gives up its own
   bottom rounding to the checklist below it. */
.chip-acts:has(+ .cl-inline) { border-radius: 0; }
.chip-task.is-open { border-bottom-left-radius: 0; border-bottom-right-radius: 0;
  border-bottom-color: transparent; }
.cl-inline { border: 1px solid var(--rule); border-top: 0; border-radius: 0 0 5px 5px;
  background: var(--surface-2); padding: 7px 8px 8px; margin-bottom: 2px; }
.cl-head { display: flex; align-items: center; gap: 6px; font: 500 10.5px var(--sans);
  color: var(--ink-2); margin-bottom: 6px; }
.cl-link { border: 0; background: transparent; padding: 0; cursor: pointer;
  font: 500 10.5px var(--sans); color: var(--accent-ink); }
.cl-link:hover { text-decoration: underline; }
.cl-sec { font: 700 8.5px var(--sans); letter-spacing: .07em; text-transform: uppercase;
  color: var(--ink-3); margin: 7px 0 3px; }
.cl-item { display: flex; align-items: flex-start; gap: 6px; padding: 3px 0; cursor: pointer;
  font: 400 11px/1.35 var(--sans); color: var(--ink); }
.cl-item input { flex: none; margin: 1px 0 0; width: 13px; height: 13px; cursor: pointer; accent-color: var(--ok); }
.cl-item input:disabled { cursor: default; }
.cl-item.is-done .cl-txt { color: var(--ink-3); text-decoration: line-through; }
.cl-item.is-exc { color: var(--exc); }
.cl-txt { min-width: 0; }
/* A tie-out names two things that must agree — show the balance inline, not
   just the instruction text, or ticking it means nothing. */
.cl-tie { display: block; margin-top: 2px; font: 500 9.5px var(--mono); color: var(--tie, var(--accent-ink)); }
.cl-tie b { color: var(--ink-3); }
.cl-excnote { display: block; margin-top: 2px; font: 500 9.5px var(--sans); color: var(--exc); }
.cl-done { margin-top: 8px; }

/* the tie-out balance, restated in the confirm so you see what you're signing */
.vf-list { margin-top: 10px; border: 1px solid var(--rule); border-radius: 6px;
  background: var(--surface-2); padding: 6px 0; max-height: 190px; overflow-y: auto; }
.vf-row { display: flex; align-items: center; gap: 8px; padding: 5px 11px;
  font: 400 11.5px var(--sans); color: var(--ink-2); }
.vf-src, .vf-tgt { flex: 1; min-width: 0; }
.vf-tgt { text-align: right; }
.vf-eq { flex: none; font: 700 12px var(--mono); color: var(--tie, var(--accent-ink)); }
/* Drag affordance — only draggable items (adhoc + event runs) get the grab
   cursor; fixed-cadence controls are never draggable, their date comes from
   the recurrence rule, not a place you'd drop them. */
[draggable='true'] { cursor: grab; }
[draggable='true']:active { cursor: grabbing; }
.dragging { opacity: .4; }
.daycol.drop-hover, .mcell.drop-hover { box-shadow: inset 0 0 0 2px var(--teal-600); background: var(--teal-050); }
/* Insertion line: hovering a specific chip while dragging shows exactly which
   edge the drop lands on, so reordering by priority is precise, not a guess. */
.chip-wrap, .chip-task.is-adhoc, .chip-task.is-run { position: relative; }
[data-chip-key].drop-before::before, [data-chip-key].drop-after::after {
  content: ''; position: absolute; left: 2px; right: 2px; height: 2px;
  background: var(--teal-600); border-radius: 2px; z-index: 5;
}
[data-chip-key].drop-before::before { top: -3px; }
[data-chip-key].drop-after::after { bottom: -3px; }
.chip-time { flex: none; font: 700 9.5px var(--mono); color: var(--ink-3);
  background: var(--surface); border: 1px solid var(--rule-2); border-radius: 3px; padding: 1px 4px; }

/* From-Lendr column — amber like the old rail, so it still reads as "someone
   else's system" rather than as one of your own control days. It is not a drop
   target: things move OUT of Lendr onto your days, never back. */
.daycol.is-lendr { background: var(--act-bg); border-left: 2px solid var(--act-line); }
.daycol.is-lendr .dayhead { border-bottom-color: rgba(232,201,92,.5); }
.daycol.is-lendr .dow { color: var(--act-ink); font-weight: 700; letter-spacing: .06em; }
.daycol.is-lendr .dnum { color: var(--act-ink); font-weight: 600; }
.chip-task.is-lendr { background: rgba(255,255,255,.75); border-color: rgba(232,201,92,.65);
  align-items: flex-start; padding: 6px 7px; }
.chip-task.is-lendr .lbl { white-space: normal; overflow: visible; text-overflow: clip;
  font-size: 11.5px; line-height: 1.35; color: #4A3C08; }
.chip-task.is-lendr .chip-main { align-items: flex-start; padding: 0; }
.lendr-foot { display: flex; align-items: center; gap: 6px; margin-top: 5px; }
/* Explicit "pick a day" alongside dragging. Dragging only reaches days visible
   in the current week; this opens a date picker, so an item can be pinned to
   any day at all when planning ahead. */
.pin-btn { margin-left: auto; flex: none; border: 1px solid rgba(232,201,92,.8);
  background: rgba(255,255,255,.9); color: #4A3C08; border-radius: 4px;
  padding: 2px 7px; font: 600 10.5px var(--sans); cursor: pointer; white-space: nowrap; }
.pin-btn:hover { background: var(--teal-050); border-color: var(--teal-600); color: var(--accent-ink); }
.chip-task.is-lendr[data-s='miss'] { border-color: var(--miss-bar); }
.seg.mini button { font-size: 10px; padding: 2px 6px; }

/* bulk backlog dialog */
.bk-list { max-height: 168px; overflow-y: auto; border: 1px solid var(--rule);
  border-radius: 6px; padding: 4px 0; background: var(--surface-2); }
.bk-row { display: flex; align-items: center; gap: 8px; padding: 5px 10px;
  font: 400 12px var(--sans); color: var(--ink-2); }
.bk-n { font: 600 11px var(--mono); color: var(--miss); min-width: 26px; }

/* + on each day header */
.addbtn { float: right; width: 19px; height: 19px; line-height: 1; border-radius: 4px; border: 1px solid var(--rule-2);
  background: var(--surface); color: var(--ink-3); cursor: pointer; font: 600 13px/1 var(--sans); padding: 0; }
.addbtn:hover { border-color: var(--teal-600); color: var(--accent-ink); background: var(--teal-050); }

/* add / edit dialog */
.dlg-box { background: var(--surface); border-radius: var(--r); width: min(460px, 100%);
  max-height: 88vh; display: flex; flex-direction: column; box-shadow: 0 20px 50px rgba(10,35,50,.3); }
.dlg-body { padding: 16px 20px 20px; overflow: auto; }
.dlg-body .lede { font-size: 12.5px; margin: 0; }
.dlg-body .field { margin-bottom: 13px; }
.dlg-body input[type=date], .dlg-body input[type=text], .dlg-body select {
  width: 100%; padding: 8px 10px; font: 400 13.5px var(--sans); color: var(--ink);
  background: var(--surface); border: 1px solid var(--rule-2); border-radius: var(--r-sm); }
.dlg-body input:focus, .dlg-body select:focus, .dlg-body textarea:focus { border-color: var(--teal-600); }

/* legend, so the cadence colours are learnable rather than guessed at */
.cad-legend { display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  margin: 0 0 12px; font-size: 12px; color: var(--ink-2); }
.cad-legend .key { display: inline-flex; align-items: center; gap: 6px; }
.cad-legend .swatch { width: 17px; height: 17px; border-radius: 4px; background: var(--sw); flex: none;
  display: grid; place-items: center; color: #fff; font: 700 9.5px/1 var(--sans); font-style: normal; }
.cad-legend .sep { width: 1px; height: 14px; background: var(--rule); }
.window-band { grid-column: 1 / -1; display: flex; align-items: center; gap: 7px; padding: 5px 11px;
  background: var(--miss-bg); color: var(--miss); border-radius: var(--r-sm); font-size: 12px;
  box-shadow: inset 3px 0 0 var(--miss-bar); margin-bottom: 2px; }

/* month grid */
.month { display: grid; grid-template-columns: repeat(7, minmax(0,1fr)); gap: 6px; }
.month .dowhead { font: 600 10px/1 var(--sans); letter-spacing: .09em; text-transform: uppercase;
  color: var(--ink-3); text-align: center; padding-bottom: 3px; }
.mcell { background: var(--surface); border: 1px solid var(--rule); border-radius: var(--r-sm);
  min-height: 132px; padding: 8px 9px; cursor: pointer; box-shadow: var(--shadow); }
.mcell:hover { border-color: var(--teal-600); }
.mcell.is-today { border-color: var(--teal-600); box-shadow: 0 0 0 2px rgba(31,112,150,.16), var(--shadow); }
.mcell.is-other { background: var(--surface-2); opacity: .5; }
.mcell.in-window { border-top: 3px solid var(--miss-bar); }
.mtop { display: flex; align-items: baseline; gap: 6px; }
.mcell .dnum { font: 600 15px var(--sans); font-variant-numeric: tabular-nums; }
.mcell .mcount { margin-left: auto; font: 500 10.5px var(--mono); color: var(--ink-3); }
.mcell.is-today .dnum { color: var(--accent-ink); }
/* Month cells carry real task rows — a cadence letter plus the short label —
   because a row of coloured dots conveyed almost nothing. */
.mrows { display: flex; flex-direction: column; gap: 3px; margin-top: 7px; }
.mrow { display: flex; align-items: center; gap: 5px; min-width: 0;
  font: 400 11px/1.3 var(--sans); color: var(--ink-2); }
.mcad { flex: none; width: 14px; height: 14px; border-radius: 3px; display: grid; place-items: center;
  background: var(--mc, var(--ink-3)); color: #fff; font: 700 8.5px/1 var(--sans); font-style: normal; }
.mrow[data-cad='daily']   { --mc: var(--cad-daily); }
.mrow[data-cad='weekly']  { --mc: var(--cad-weekly); }
.mrow[data-cad='monthly'] { --mc: var(--cad-monthly); }
.mrow[data-cad='event']   { --mc: var(--cad-event); }
.mlbl { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mrow[data-s='ok']   { color: var(--ok); }
.mrow[data-s='exc']  { color: var(--exc); font-weight: 600; }
.mrow[data-s='miss'] { color: var(--miss); font-weight: 500; }
.mrow[data-s='past'] { opacity: .5; }
.mrow[data-s='dismissed'] { opacity: .5; text-decoration: line-through; }
/* One-off reminders: hollow grey marker, italic, no cadence hue. Same visual
   contract as .chip-task.is-adhoc in the week view. */
.mrow.is-adhoc { font-style: italic; color: var(--ink-3); }
.mrow.is-adhoc .mcad { background: transparent; color: var(--ink-3);
  border: 1px dashed var(--ink-3); font-size: 8px; }
.mrow.is-adhoc[data-s='ok'] { text-decoration: line-through; }
.mcell .more { font: 500 10px var(--sans); color: var(--ink-3); margin-top: 5px;
  border: 0; background: transparent; padding: 2px 0; cursor: pointer; text-align: left; }
.mcell .more:hover { color: var(--accent-ink); text-decoration: underline; }
/* An expanded cell grows past the normal row height so every item is reachable. */
.mcell:has(.more) { overflow: visible; }
/* The + only appears on hover so 40-odd month cells don't turn into a wall of
   buttons; it stays keyboard-reachable via :focus-visible. .mcount already
   carries margin-left:auto, so the + only needs its own when the cell is empty
   and the + directly follows the day number. */
.mcell .addbtn { flex: none; width: 17px; height: 17px; opacity: 0; transition: opacity .12s; }
.mcell .dnum + .addbtn { margin-left: auto; }
.mcell:hover .addbtn, .mcell .addbtn:focus-visible { opacity: 1; }

/* ===================== agenda / action rail ============================= */
.rail-card { background: var(--surface); border: 1px solid var(--rule); border-radius: var(--r);
  box-shadow: var(--shadow); margin-bottom: 14px; overflow: hidden; }
.rail-card > header { display: flex; align-items: center; gap: 8px; padding: 12px 14px 11px;
  border-bottom: 1px solid var(--rule); }
.rail-card > header h3 { font: 600 13.5px var(--display); margin: 0; letter-spacing: -0.01em; }
.rail-card > header .cnt { margin-left: auto; font: 500 11.5px var(--mono); color: var(--ink-3); }
.rail-body { padding: 10px 14px 13px; }
.agenda-line { display: flex; align-items: flex-start; gap: 8px; width: 100%; text-align: left;
  background: none; border: 0; border-radius: var(--r-sm); padding: 7px 8px; cursor: pointer;
  font: 400 13px/1.4 var(--sans); color: var(--ink); }
.agenda-line:hover { background: var(--surface-2); }
.agenda-line .g { flex: none; font-size: 11px; margin-top: 2px; }
.agenda-line[data-s='ok'] { color: var(--ink-3); }
.agenda-line[data-s='ok'] .g { color: var(--ok); }
.agenda-line[data-s='exc'] .g { color: var(--exc); }
.agenda-line[data-s='miss'] .g { color: var(--miss); }
.agenda-line .frac { margin-left: auto; font: 500 10.5px var(--mono); color: var(--ink-3); flex: none; }

/* Lendr's action-items panel: cream card, yellow rule */
.act-card { background: var(--act-bg); border: 1px solid var(--act-line); box-shadow: inset 4px 0 0 var(--act-line), var(--shadow); }
.act-card > header { border-bottom-color: rgba(232,201,92,.5); }
.act-card > header h3 { color: var(--act-ink); }
.act-item { padding: 10px 0; border-bottom: 1px solid rgba(232,201,92,.4); }
.act-item:last-child { border-bottom: 0; }
.act-item .txt { font: 500 12.5px/1.45 var(--sans); color: #4A3C08; }
.act-item .meta { display: flex; align-items: center; gap: 7px; margin-top: 6px; flex-wrap: wrap; }
.due-pill { font: 500 10.5px/1 var(--sans); padding: 4px 7px; border-radius: 999px;
  background: var(--act-pill); color: var(--act-ink); white-space: nowrap; }
.due-pill[data-tone='over'] { background: var(--exc); color: #fff; }
.due-pill[data-tone='today'] { background: var(--miss-bar); color: #fff; }
.act-item a.out { font-size: 11.5px; color: var(--accent-ink); text-decoration: none; }
.act-item a.out:hover { text-decoration: underline; }
/* "Plan a day" — same weight as the Lendr deep-link beside it. Planning an item
   onto your calendar is a scheduling choice, not a verification, so it stays a
   quiet text button rather than a primary action. */
.act-item button.act-add { border: 0; background: transparent; padding: 0; cursor: pointer;
  font: 500 11.5px var(--sans); color: var(--accent-ink); }
.act-item button.act-add:hover { text-decoration: underline; }

/* refresh dialog */
.rfr-row { display: flex; align-items: center; gap: 8px; padding: 9px 0;
  border-bottom: 1px solid var(--rule); font: 400 12.5px var(--sans); }
.rfr-row:last-of-type { border-bottom: 0; }
.rfr-row b { font-weight: 600; min-width: 62px; }
.rfr-cmd { display: flex; align-items: center; gap: 8px; background: var(--surface-2);
  border: 1px solid var(--rule); border-radius: 6px; padding: 8px 10px; }
.rfr-cmd code { flex: 1; font: 500 12px var(--mono); color: var(--ink); }
.act-empty { font-size: 12.5px; color: var(--act-ink); opacity: .8; padding: 4px 0; }
.seg.mini button { padding: 4px 9px; font-size: 11.5px; }

/* ===================== task cards ====================================== */
.task { background: var(--surface); border: 1px solid var(--rule); border-radius: var(--r);
  margin-bottom: 8px; box-shadow: var(--shadow); }
.task[data-s='exc']  { border-color: #E7B7B2; }
.task[data-s='miss'] { box-shadow: inset 3px 0 0 var(--miss-bar), var(--shadow); }
.task > summary { display: flex; align-items: center; gap: 10px; min-height: 44px; padding: 9px 14px;
  cursor: pointer; list-style: none; }
.task > summary::-webkit-details-marker { display: none; }
.task > summary:hover { background: var(--surface-2); }
.task[open] > summary { border-bottom: 1px solid var(--rule); }
.task[open] { box-shadow: var(--shadow-lift); }
.task .mark { flex: none; width: 16px; text-align: center; font-size: 12px; line-height: 1; }
.task[data-s='ok'] .mark { color: var(--ok); }
.task[data-s='exc'] .mark { color: var(--exc); }
.task[data-s='miss'] .mark { color: var(--miss); }
.task[data-s='due'] .mark { color: var(--ink-3); }
.task .title { font-weight: 500; font-size: 14px; min-width: 0; }
.task[data-s='ok'] .title { color: var(--ink-2); }
.task .grow { flex: 1; }
.task .frac { font: 500 11.5px var(--mono); color: var(--ink-3); }
.task-body { padding: 14px 16px 15px 40px; }

.substeps { margin: 0 0 12px; padding-left: 18px; color: var(--ink-2); font-size: 13px; }
.substeps li { margin: 3px 0; }
.meta-line { font-size: 12.5px; color: var(--ink-2); margin: 0 0 8px; }
.meta-line b { font-weight: 600; color: var(--ink); }

/* ===================== checklist ======================================= */
.cl-head { display: flex; align-items: center; gap: 8px; margin: 15px 0 6px; }
.cl-head span { font: 600 10.5px/1 var(--sans); letter-spacing: .09em; text-transform: uppercase; color: var(--ink-3); }
.cl-head .rulefill { flex: 1; height: 1px; background: var(--rule); }
.cl-head .tally { font: 500 11px var(--mono); color: var(--ink-3); }
.cl-head[data-kind='tieout'] span { color: var(--data); }
.item { display: flex; gap: 10px; padding: 6px 0; align-items: flex-start; }
.item input[type=checkbox] { flex: none; width: 15px; height: 15px; margin: 2px 0 0; accent-color: var(--ok); cursor: pointer; }
.item input[type=checkbox]:disabled { cursor: not-allowed; }
.item .txt { flex: 1; min-width: 0; font-size: 13px; line-height: 1.45; }
.item.done .txt > .t { color: var(--ink-3); }
.item .stamp { display: block; margin-top: 2px; }

/* the tie-out balance: SOURCE ── = ── TARGET, the centre glyph carries state */
.tieout { --rel: var(--rule-2); display: flex; gap: 10px; align-items: flex-start;
  padding: 9px 11px; margin: 5px 0; border-radius: var(--r-sm);
  background: var(--surface-2); border: 1px solid var(--rule); }
.tieout[data-s='ok']  { --rel: var(--ok-bar); background: var(--ok-bg);  border-color: #CFE6D8; }
.tieout[data-s='exc'] { --rel: var(--exc);    background: var(--exc-bg); border-color: #EEC4C0; }
.tieout > input[type=checkbox] { flex: none; width: 15px; height: 15px; margin: 3px 0 0; accent-color: var(--ok); cursor: pointer; }
.tie-body { flex: 1; min-width: 0; }
.balance { display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; margin-bottom: 5px; }
.side { font: 500 12.5px/1.35 var(--sans); color: var(--ink); display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.side .lbl { font: 600 9px/1 var(--sans); letter-spacing: .1em; text-transform: uppercase; color: var(--ink-3); }
.side.src { text-align: right; align-items: flex-end; padding-right: 12px; }
.side.tgt { text-align: left; align-items: flex-start; padding-left: 12px; }
.rel { display: flex; align-items: center; min-width: 76px; flex: none; }
.rel::before, .rel::after { content: ''; flex: 1; height: 1.5px; background: var(--rel); }
.tieout[data-s='open'] .rel::before, .tieout[data-s='open'] .rel::after { height: 1px; }
.rel .g { font: 700 15px/1 var(--mono); color: var(--rel); padding: 0 8px; }
.tie-text { margin: 0; font-size: 12.5px; line-height: 1.45; color: var(--ink-2); }
.tieout[data-s='ok'] .tie-text { color: var(--ink-3); }
.exc-note { margin: 6px 0 0; padding: 7px 9px; border-radius: var(--r-sm); background: var(--surface);
  border: 1px solid #EEC4C0; font-size: 12.5px; color: var(--exc); line-height: 1.45; }
.exc-note b { display: block; font: 600 10px/1 var(--sans); letter-spacing: .09em; text-transform: uppercase; margin-bottom: 4px; }

/* ===================== buttons ========================================= */
.btn { display: inline-flex; align-items: center; gap: 6px; font: 500 13px var(--sans);
  padding: 7px 13px; border-radius: var(--r-sm); border: 1px solid var(--rule-2);
  background: var(--surface); color: var(--ink); cursor: pointer; text-decoration: none; white-space: nowrap; }
.btn:hover:not(:disabled) { border-color: var(--teal-600); color: var(--accent-ink); }
.btn.primary { background: var(--teal-700); border-color: var(--teal-700); color: #fff; }
.btn.primary:hover:not(:disabled) { background: var(--teal-800); border-color: var(--teal-800); color: #fff; }
.btn.big { font-size: 14px; padding: 10px 16px; width: 100%; justify-content: center; }
.btn.sm { font-size: 12px; padding: 4px 9px; }
.btn.quiet { border-color: transparent; background: none; color: var(--ink-2); }
.btn.quiet:hover:not(:disabled) { background: var(--surface-2); }
.btn.danger { border-color: #E5BFBA; color: var(--exc); }
.btn.danger:hover:not(:disabled) { background: var(--exc-bg); border-color: var(--exc); color: var(--exc); }
.btn:disabled { opacity: .45; cursor: not-allowed; }
.row { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.row.sep { margin-top: 13px; padding-top: 12px; border-top: 1px solid var(--rule); }
.field-inline { font: 400 13px var(--sans); padding: 6px 9px; border: 1px solid var(--rule-2);
  border-radius: var(--r-sm); background: var(--surface); color: var(--ink); min-width: 170px; }
textarea.field-inline { width: 100%; min-height: 48px; resize: vertical; line-height: 1.45; }
.soplink { font-size: 12.5px; color: var(--accent-ink); background: none; border: 0; padding: 0;
  cursor: pointer; text-decoration: underline; text-underline-offset: 2px; font-family: var(--sans); }
.soplink::before { content: '▤ '; opacity: .6; }
details.helper { margin: 10px 0 0; }
details.helper > summary { font-size: 12px; color: var(--ink-2); cursor: pointer; list-style: none; }
details.helper > summary::before { content: '▸ '; }
details.helper[open] > summary::before { content: '▾ '; }
details.helper pre { margin: 8px 0 0; padding: 12px; background: var(--surface-2); border: 1px solid var(--rule);
  border-radius: var(--r-sm); font: 400 12px/1.55 var(--mono); white-space: pre-wrap; color: var(--ink-2);
  max-height: 260px; overflow: auto; }

/* ===================== chips =========================================== */
.chip { display: inline-flex; align-items: center; gap: 4px; flex: none; font: 500 11px/1 var(--sans);
  letter-spacing: .03em; text-transform: uppercase; padding: 4px 7px; border-radius: 3px; white-space: nowrap; }
.chip .g { font-size: 9px; line-height: 1; }
.chip[data-s='ok']    { color: var(--ok);    background: var(--ok-bg); }
.chip[data-s='due']   { color: var(--due);   background: transparent; border: 1px solid var(--rule-2); }
.chip[data-s='exc']   { color: #fff;         background: var(--exc); font-weight: 600; }
.chip[data-s='miss']  { color: var(--miss);  background: transparent; border: 1px solid var(--miss-bar);
                        box-shadow: inset 3px 0 0 var(--miss-bar); padding-left: 10px; }
.chip[data-s='stale'] { color: var(--stale); background: transparent; border: 1px dashed var(--stale); }
.chip[data-s='late']  { color: var(--miss);  background: var(--miss-bg); }
.chip[data-s='info']  { color: var(--ink-3); background: var(--surface-2); }
.chip[data-s='seq']   { color: var(--data);  background: var(--teal-050); font-family: var(--mono); text-transform: none; }
.progress { height: 4px; background: var(--rule); border-radius: 3px; overflow: hidden; margin-bottom: 16px; }
.progress > i { display: block; height: 100%; background: var(--ok-bar); }

/* ===================== focus mode (Start my day) ======================= */
.focus { position: fixed; inset: 0; z-index: 55; background: var(--canvas); display: flex; flex-direction: column; }
.focus-bar { background: var(--teal-700); color: #fff; padding: 11px 20px; display: flex; align-items: center; gap: 14px; }
.focus-bar .ftitle { font: 600 14px var(--display); }
.focus-bar .spacer { flex: 1; }
.focus-steps { display: flex; gap: 4px; flex: 1; max-width: 460px; }
.focus-steps i { flex: 1; height: 5px; border-radius: 3px; background: rgba(255,255,255,.25); }
.focus-steps i[data-s='ok']   { background: #7FD3A0; }
.focus-steps i[data-s='exc']  { background: #F2A29A; }
.focus-steps i[data-s='cur']  { background: #fff; }
.focus-scroll { flex: 1; overflow: auto; }
.focus-inner { max-width: 900px; margin: 0 auto; padding: 22px 20px 40px; }
.focus-inner > h2 { font: 600 21px/1.25 var(--display); margin: 0 0 4px; letter-spacing: -0.015em; }
.focus-inner > .sub { color: var(--ink-2); font-size: 13px; margin: 0 0 18px; }
.focus-card { background: var(--surface); border: 1px solid var(--rule); border-radius: var(--r);
  box-shadow: var(--shadow); padding: 18px 20px 20px; }
.focus-foot { border-top: 1px solid var(--rule); background: var(--surface); padding: 12px 20px;
  display: flex; align-items: center; gap: 10px; }
.focus-foot .spacer { flex: 1; }
.focus-done { text-align: center; padding: 50px 20px; }
.focus-done .big { font: 600 24px var(--display); color: var(--ok); margin-bottom: 8px; }

/* ===================== tables ========================================== */
.tbl-wrap { border: 1px solid var(--rule); border-radius: var(--r); overflow: auto; background: var(--surface);
  box-shadow: var(--shadow); }
table { width: 100%; border-collapse: collapse; }
thead th { position: sticky; top: 0; background: var(--surface-2); text-align: left;
  font: 600 10.5px/1 var(--sans); letter-spacing: .08em; text-transform: uppercase; color: var(--ink-3);
  padding: 10px 13px; border-bottom: 1px solid var(--rule-2); white-space: nowrap; }
tbody td { padding: 9px 13px; border-bottom: 1px solid var(--rule); font-size: 13px; vertical-align: top; line-height: 1.45; }
tbody tr:last-child td { border-bottom: 0; }
tbody tr:hover { background: var(--surface-2); }
td.num, th.num { text-align: right; font-family: var(--mono); font-variant-numeric: tabular-nums; }
td .sub { display: block; font-size: 12px; color: var(--ink-3); margin-top: 2px; line-height: 1.4; }
.empty { padding: 24px 16px; text-align: center; color: var(--ink-3); font-size: 13px;
  background: var(--surface); border: 1px dashed var(--rule-2); border-radius: var(--r); }
.empty b { display: block; color: var(--ink-2); font-weight: 600; margin-bottom: 4px; }

/* ===================== groups, snapshot, viewer, toast ================== */
.group { background: var(--surface); border: 1px solid var(--rule); border-radius: var(--r);
  margin-bottom: 12px; box-shadow: var(--shadow); }
.group-head { display: flex; align-items: center; gap: 10px; padding: 11px 14px; border-bottom: 1px solid var(--rule); flex-wrap: wrap; }
.group-head .gtitle { font: 600 13.5px var(--display); letter-spacing: -0.01em; }
.group-body { padding: 11px 14px 13px; }
.group-body .task:last-child { margin-bottom: 0; }
.task.locked { opacity: .55; }
.task.locked > summary { cursor: default; }

.snap { background: var(--surface); border: 1px solid var(--rule); border-radius: var(--r);
  margin-bottom: 14px; box-shadow: var(--shadow); }
.snap-head { display: flex; align-items: center; gap: 10px; padding: 12px 15px; border-bottom: 1px solid var(--rule); flex-wrap: wrap; }
.snap-head h3 { font: 600 14px var(--display); margin: 0; letter-spacing: -0.01em; }
.snap-head .desc { font-size: 12px; color: var(--ink-3); }
.snap-body { padding: 14px 15px 16px; }
.snap-body > .stats { margin-bottom: 14px; }
.snap-body h4 { font: 600 10.5px/1 var(--sans); letter-spacing: .09em; text-transform: uppercase;
  color: var(--ink-3); margin: 18px 0 7px; }
.snap-body h4:first-child { margin-top: 0; }
.snap[data-stale='1'] .snap-head { background: repeating-linear-gradient(135deg, transparent, transparent 6px,
  rgba(85,112,126,.07) 6px, rgba(85,112,126,.07) 12px); }
.readonly-badge { display: inline-flex; align-items: center; gap: 7px; padding: 8px 13px; border: 1px solid var(--rule);
  border-radius: var(--r); background: var(--surface); font-size: 12.5px; color: var(--ink-2); margin-bottom: 16px; }
.readonly-badge code { font: 500 12px var(--mono); color: var(--data); }

.viewer { position: fixed; inset: 0; z-index: 58; background: rgba(20,40,52,.5); display: grid; place-items: center; padding: 28px; }
.viewer-box { background: var(--surface); border-radius: var(--r); width: min(880px, 100%); max-height: 88vh;
  display: flex; flex-direction: column; box-shadow: 0 20px 50px rgba(10,35,50,.3); }
.viewer-head { display: flex; align-items: center; gap: 12px; padding: 13px 18px; border-bottom: 1px solid var(--rule); }
.viewer-head h3 { flex: 1; font: 600 14px var(--display); margin: 0; }
.viewer-body { padding: 6px 26px 26px; overflow: auto; font-size: 13.5px; line-height: 1.6; }
.viewer-body h1, .viewer-body h2, .viewer-body h3 { font: 600 15px var(--display); margin: 20px 0 7px; }
.viewer-body p { margin: 7px 0; }
.viewer-body .ts-line { margin: 3px 0; }
.viewer-body .ts-line .ts { margin-right: 6px; }
.viewer-body .sop-kind-note { color: var(--ink-3); font-size: 12.5px; font-style: italic; }
.viewer-body .sop-warning { background: var(--exc-bg); color: var(--exc); border: 1px solid #EEC4C0;
  padding: 11px 14px; border-radius: var(--r-sm); font-weight: 500; font-size: 13px; }
.viewer-body img { max-width: 100%; }
.viewer-body code { font: 400 12.5px var(--mono); background: var(--surface-2); padding: 1px 4px; border-radius: 3px; }

.toast { position: fixed; bottom: 22px; left: 50%; transform: translateX(-50%); background: var(--ink);
  color: #F4F8FA; padding: 10px 16px; border-radius: var(--r-sm); font-size: 13px; z-index: 70; max-width: 520px;
  box-shadow: 0 6px 20px rgba(10,35,50,.3); }
.toast[data-tone='exc'] { background: var(--exc); }
.toast[data-tone='ok']  { background: var(--ok); }

/* ===================== responsive ====================================== */
@media (max-width: 1060px) {
  .cal-under { grid-template-columns: minmax(0,1fr); }
  .week { grid-template-columns: repeat(3, minmax(0,1fr)) !important; }
  .daycol { min-height: 220px; }
}
@media (max-width: 760px) {
  .week { grid-template-columns: repeat(2, minmax(0,1fr)) !important; }
  .balance { grid-template-columns: 1fr; gap: 4px; }
  .side.src, .side.tgt { text-align: left; align-items: flex-start; padding: 0; }
  .rel { min-width: 0; padding: 1px 0; }
  .rel::before { flex: none; width: 14px; }
  .rel::after { display: none; }
}

@media (prefers-reduced-motion: no-preference) {
  .task, .tieout, .chip, .chip-task, .mcell, .daycol { transition: background-color .14s ease, border-color .14s ease, box-shadow .14s ease; }
  .rel .g { transition: color .16s ease; }
}

/* Boot failure — the one screen that must work when nothing else does, so it
   depends on no app state and no fetched data. #app stays hidden behind it. */
.boot-fail { position: fixed; inset: 0; z-index: 100; display: grid; place-items: center;
  padding: 24px; background: var(--canvas); }
.boot-fail-card { max-width: 460px; background: var(--surface); border: 1px solid var(--rule);
  border-radius: var(--r); box-shadow: var(--shadow-lift); padding: 26px 28px; text-align: center; }
.boot-fail-card h1 { font: 600 17px/1.35 var(--display); margin: 0 0 10px; color: var(--ink); }
.boot-fail-card p { font-size: 13px; line-height: 1.6; color: var(--ink-2); margin: 0 0 18px; }
.boot-fail-card code { font: 400 12px var(--mono); background: var(--surface-2);
  padding: 2px 5px; border-radius: 3px; }

/* Which day-build rows "Start this day" will actually walk. The view can show
   six rows and walk two — every skip individually correct, collectively
   baffling without this. Both marks come from dayItemSkipReason(). */
.db-walk, .db-skip { flex: none; font: 600 9.5px/1 var(--sans); letter-spacing: .04em;
  text-transform: uppercase; padding: 4px 7px; border-radius: 999px; white-space: nowrap; }
.db-walk { background: var(--ok-bg); color: var(--ok); }
.db-skip { background: var(--surface-2); color: var(--ink-3); text-transform: none;
  letter-spacing: 0; font-weight: 500; font-size: 10px; }
.dbrow.is-skipped { opacity: .72; }
.dbrow.is-skipped .dbrow-main b { font-weight: 500; }
.db-count { font: 500 11.5px var(--sans); color: var(--ink-3); margin-right: 4px; }
