/* ─────────────────────────────────────────────────────────────────────────
   base.css — the primitive layer.

   Rail puts one day on one spine. Sections stopped being destinations, so
   this file owns everything that used to be duplicated seven ways: the
   sheet, the field, the row, the chip, the chart track. Surfaces compose
   these; they do not restyle them.

   Order: tokens → reset → type → layout → chrome → spine → primitives →
   dataviz → utilities.
   ───────────────────────────────────────────────────────────────────────── */

/* ══ 1. Tokens ═══════════════════════════════════════════════════════════
   The palette is isolated here on purpose: swapping Rail's cool daylight
   back to the old amber identity is an edit to this block alone. */

:root {
  /* Surfaces */
  --paper:    #EDEFF2;
  --card:     #FFFFFF;
  --card-2:   #F6F7F9;
  --sunk:     #E4E7EC;

  /* Ink */
  --ink:      #13161B;
  --ink-2:    #596070;
  --ink-3:    #8D94A3;

  /* Lines */
  --rule:     #D6DAE1;
  --rule-2:   #E7EAEF;

  /* Semantics */
  --now:      #4B3FE4;  --now-soft:  rgba(75, 63, 228, .10);
  --done:     #0C7A57;  --done-soft: rgba(12, 122, 87, .11);
  --warn:     #AF4D07;  --warn-soft: rgba(175, 77, 7, .11);
  --bad:      #B3261E;  --bad-soft:  rgba(179, 38, 30, .10);

  /* Categorical — food / training / people / markets / tasks.
     Used by chips, node marks and charts so one thing is one colour app-wide. */
  --c-task:   #4B3FE4;
  --c-food:   #AF4D07;
  --c-train:  #0C7A57;
  --c-people: #7A3FAF;
  --c-money:  #1F6FA8;

  /* Type */
  --f-disp: 'Bricolage Grotesque', 'Public Sans', -apple-system, BlinkMacSystemFont, sans-serif;
  --f-body: 'Public Sans', -apple-system, BlinkMacSystemFont, 'SF Pro Text', 'Segoe UI', sans-serif;
  --f-mono: 'IBM Plex Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace;

  /* Space — 4pt grid */
  --s1: 4px;  --s2: 8px;  --s3: 12px; --s4: 16px;
  --s5: 20px; --s6: 24px; --s7: 32px; --s8: 44px;

  /* Radius */
  --r1: 8px; --r2: 11px; --r3: 14px; --r4: 20px; --r-pill: 999px;

  /* Chrome */
  --spine:    34px;
  --tabbar-h: 56px;
  --ledger-h: 60px;
  --tap:      44px;

  /* The anti-zoom rule. iOS Safari zooms the viewport whenever a focused
     field is under 16px, and every field in the old build was. 17px here,
     and no component may override it downward. */
  --field-fs: 17px;
  --field-h:  48px;

  --ease: cubic-bezier(.2, .8, .3, 1);
  --ease-sheet: cubic-bezier(.32, .72, 0, 1);
}

@media (prefers-color-scheme: dark) {
  :root {
    --paper:   #0F1115;
    --card:    #181B21;
    --card-2:  #1E222A;
    --sunk:    #222630;

    --ink:     #EDEFF3;
    --ink-2:   #9BA3B2;
    --ink-3:   #6B7383;

    --rule:    #2A2F38;
    --rule-2:  #222730;

    --now:     #8B80FF;  --now-soft:  rgba(139, 128, 255, .14);
    --done:    #3DD39C;  --done-soft: rgba(61, 211, 156, .14);
    --warn:    #E8913F;  --warn-soft: rgba(232, 145, 63, .14);
    --bad:     #F2776D;  --bad-soft:  rgba(242, 119, 109, .14);

    --c-task:   #8B80FF;
    --c-food:   #E8913F;
    --c-train:  #3DD39C;
    --c-people: #C08BFF;
    --c-money:  #5BAEE0;
  }
}

/* ══ 2. Reset ════════════════════════════════════════════════════════════ */

*, *::before, *::after { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }
html, body { margin: 0; padding: 0; height: 100%; }

html { color-scheme: light dark; -webkit-text-size-adjust: 100%; }

body {
  background: var(--paper);
  color: var(--ink);
  font: 400 15px/1.5 var(--f-body);
  overflow: hidden;              /* surfaces scroll, the page never does */
  overscroll-behavior-y: contain;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

button, input, select, textarea { font: inherit; color: inherit; }
button { background: none; border: 0; padding: 0; cursor: pointer; }
a { color: var(--now); text-decoration: none; }
svg { display: block; }
[hidden] { display: none !important; }

::selection { background: var(--now); color: #fff; }

:focus-visible { outline: 2px solid var(--now); outline-offset: 2px; border-radius: 4px; }

::-webkit-scrollbar { width: 6px; height: 6px; }
::-webkit-scrollbar-thumb { background: var(--rule); border-radius: 3px; }
::-webkit-scrollbar-track { background: transparent; }

/* ══ 3. Type ═════════════════════════════════════════════════════════════ */

h1, h2, h3 { margin: 0; font-family: var(--f-disp); letter-spacing: -.018em; font-weight: 700; }
h1 { font-size: 28px; line-height: 1.05; }
h2 { font-size: 20px; line-height: 1.15; }
h3 { font-size: 16px; line-height: 1.2; }

/* Mono eyebrow — the app's label voice. Used for stations, keys, meta. */
.eyebrow {
  font: 500 10px/1 var(--f-mono);
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.num { font-family: var(--f-mono); font-variant-numeric: tabular-nums; }

/* ══ 4. Layout ═══════════════════════════════════════════════════════════ */

.app { display: flex; flex-direction: column; height: 100%; }

/* One per destination; only the active one is visible. */
.surface { display: none; flex-direction: column; flex: 1 1 auto; min-height: 0; }
.surface.on { display: flex; }

.scroll {
  flex: 1 1 auto;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior-y: contain;
  padding: var(--s1) var(--s4) var(--s6);
}

.pad-top { padding-top: calc(env(safe-area-inset-top, 0px) + var(--s4)); }

/* ══ 5. Chrome ═══════════════════════════════════════════════════════════ */

.topbar {
  flex: 0 0 auto;
  background: var(--paper);
  padding: calc(env(safe-area-inset-top, 0px) + var(--s4)) var(--s4) 0;
  z-index: 6;
}
.topbar-row { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--s3); }
.topbar-meta { margin-top: 5px; }

/* Icon button — the square 42px control used across all chrome. */
.iconbtn {
  width: 42px; height: 42px; flex: 0 0 auto;
  display: grid; place-items: center;
  border: 1px solid var(--rule);
  background: var(--card);
  border-radius: var(--r2);
  color: var(--ink-2);
}
.iconbtn svg { width: 19px; height: 19px; stroke: currentColor; stroke-width: 1.8; fill: none; }
.iconbtn:active { background: var(--card-2); }
.iconbtn.ghost { border-color: transparent; background: none; }

/* Bottom tab bar — Today / Review / Ask. Thumb reach, always. */
.tabbar {
  flex: 0 0 auto;
  display: flex;
  background: var(--card);
  border-top: 1px solid var(--rule);
  padding-bottom: env(safe-area-inset-bottom, 0px);
  z-index: 6;
}
.tabbar button {
  flex: 1;
  display: flex; flex-direction: column; align-items: center; gap: 4px;
  padding: var(--s2) 0 6px;
  min-height: var(--tap);
  color: var(--ink-3);
  font: 500 10px/1.1 var(--f-mono);
  letter-spacing: .12em; text-transform: uppercase;
  transition: color .18s var(--ease);
}
.tabbar button svg { width: 21px; height: 21px; stroke: currentColor; stroke-width: 1.8; fill: none; }
.tabbar button.on { color: var(--now); }
.tabbar button:active { transform: scale(.95); }

/* Ledger — live day totals. Today only; the design's argument made visible.
   Goals are a track under the number rather than inline text: at 393px the
   inline "1,259 / 2,200" and "124 / 182g" collided into each other. */
.ledger {
  flex: 0 0 auto;
  display: flex; align-items: flex-end; gap: var(--s3);
  padding: 9px var(--s4) 10px;
  background: var(--card);
  border-top: 1px solid var(--rule);
  z-index: 6;
}
.led { flex: 1; min-width: 0; }
.led-k { font: 500 8.5px/1 var(--f-mono); letter-spacing: .12em; text-transform: uppercase; color: var(--ink-3); }
.led-v {
  font: 600 16px/1.1 var(--f-mono);
  font-variant-numeric: tabular-nums;
  margin-top: 5px; white-space: nowrap;
  overflow: hidden; text-overflow: clip;
}
.led-v small { font-size: 9.5px; font-weight: 400; color: var(--ink-3); margin-left: 1px; }
.led-track { height: 3px; border-radius: 2px; background: var(--sunk); overflow: hidden; margin-top: 6px; }
.led-track > i { display: block; height: 100%; border-radius: 2px; background: var(--now); width: 0; transition: width .6s var(--ease); }
.led.over .led-v { color: var(--warn); }
.led.over .led-track > i { background: var(--warn); }

/* ══ 6. The spine ════════════════════════════════════════════════════════
   Stations are ordinal day-phases, never clock times — nothing in COS
   carries a timestamp. Station order comes from the checklist `period` and
   health `slot` enums interleaved. */

.rail { position: relative; padding-left: var(--spine); }
.rail::before {
  content: ""; position: absolute; left: 11px; top: 6px; bottom: 10px; width: 2px;
  background: linear-gradient(180deg, var(--rule-2), var(--rule) 12%, var(--rule) 88%, transparent);
}

.station { position: relative; margin: var(--s5) 0 var(--s2); }
.station:first-child { margin-top: var(--s1); }
.station::before {
  content: ""; position: absolute; left: calc(-1 * var(--spine) + 5px); top: 3px;
  width: 14px; height: 14px; border-radius: 50%;
  background: var(--paper); border: 2px solid var(--rule);
}
.station.past::before { background: var(--done); border-color: var(--done); }
.station.here::before { border-color: var(--now); background: var(--paper); box-shadow: 0 0 0 4px var(--now-soft); }
.station-k { font: 600 11px/1 var(--f-mono); letter-spacing: .16em; text-transform: uppercase; color: var(--ink-2); }
.station.here .station-k { color: var(--now); }
.station-n { font: 400 10px/1 var(--f-mono); color: var(--ink-3); margin-top: 4px; }

/* Node — anything that sits on a day. */
.node {
  position: relative;
  display: flex; align-items: center; gap: var(--s3);
  min-height: 54px; padding: 13px var(--s3) 13px var(--s4);
  margin-bottom: 7px;
  background: var(--card);
  border: 1px solid var(--rule-2);
  border-radius: var(--r3);
  transition: border-color .2s var(--ease), background .2s var(--ease), opacity .25s var(--ease);
}
.node::before {
  content: ""; position: absolute; left: calc(-1 * var(--spine) + 8px); top: 50%; margin-top: -4px;
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--rule); border: 2px solid var(--paper);
}
.node:active { background: var(--card-2); }
.node.done::before { background: var(--done); }
.node-b { flex: 1; min-width: 0; }
/* Two lines for a title, one for its meta — an interaction's first line can
   be 90 characters and would otherwise push the node to four rows tall. */
.node-t {
  font-size: 14.5px; line-height: 1.35; font-weight: 500;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
}
.node.done .node-t { color: var(--ink-3); text-decoration: line-through; }
.node-s {
  font: 400 10.5px/1.4 var(--f-mono); letter-spacing: .04em; color: var(--ink-3); margin-top: 3px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.node-v { flex: 0 0 auto; font: 600 13px/1 var(--f-mono); font-variant-numeric: tabular-nums; color: var(--ink-2); }

/* Per-kind mark, for nodes that aren't checkable. */
.kind { width: 26px; height: 26px; flex: 0 0 auto; border-radius: var(--r1); display: grid; place-items: center; }
.kind svg { width: 14px; height: 14px; stroke-width: 1.9; fill: none; }
.k-food   { background: var(--warn-soft); } .k-food   svg { stroke: var(--c-food); }
.k-train  { background: var(--done-soft); } .k-train  svg { stroke: var(--c-train); }
.k-people { background: rgba(122, 63, 175, .11); } .k-people svg { stroke: var(--c-people); }
.k-news   { background: rgba(31, 111, 168, .11); } .k-news  svg { stroke: var(--c-money); }

/* Now marker. */
.now-mark { position: relative; display: flex; align-items: center; gap: 9px; margin: var(--s4) 0; }
.now-mark::before {
  content: ""; position: absolute; left: calc(-1 * var(--spine) + 7px); top: 50%; margin-top: -5px;
  width: 10px; height: 10px; border-radius: 50%; background: var(--now);
  animation: nowPulse 2.4s ease-out infinite;
}
@keyframes nowPulse {
  0%   { box-shadow: 0 0 0 0 var(--now-soft); }
  70%  { box-shadow: 0 0 0 11px transparent; }
  100% { box-shadow: 0 0 0 0 transparent; }
}
.now-l { font: 600 10px/1 var(--f-mono); letter-spacing: .16em; text-transform: uppercase; color: var(--now); }
.now-line { flex: 1; height: 1px; background: linear-gradient(90deg, var(--now), transparent); }

/* Checkbox used by task nodes. */
.box {
  width: 22px; height: 22px; flex: 0 0 auto;
  border: 1.6px solid var(--rule); border-radius: 6px;
  display: grid; place-items: center;
  transition: background .18s, border-color .18s;
}
.box svg {
  width: 13px; height: 13px; stroke: #fff; stroke-width: 3.2; fill: none;
  opacity: 0; transform: scale(.4);
  transition: opacity .16s, transform .22s cubic-bezier(.2, 1.5, .4, 1);
}
.node.done .box { background: var(--done); border-color: var(--done); }
.node.done .box svg { opacity: 1; transform: scale(1); }

/* Swipe-right-to-complete, carried over from the old interactions.js. */
.swipe { position: relative; overflow: hidden; border-radius: var(--r3); margin-bottom: 7px; background: var(--done); }
.swipe .node { margin-bottom: 0; transition: transform .28s var(--ease), border-color .2s, background .2s; }
.swipe.dragging .node { transition: border-color .2s; }
.swipe-act {
  position: absolute; inset: 0 auto 0 0; width: 92px;
  display: flex; align-items: center; gap: 6px; padding-left: var(--s5);
  color: #fff; font: 600 10px/1 var(--f-mono); letter-spacing: .12em; text-transform: uppercase;
  pointer-events: none;
}
.swipe-act svg { width: 16px; height: 16px; stroke: #fff; stroke-width: 2.6; fill: none; }

/* ══ 7. Primitives ═══════════════════════════════════════════════════════ */

/* Card + ruled row — the two list idioms. */
.card { background: var(--card); border: 1px solid var(--rule-2); border-radius: var(--r3); padding: var(--s4); }
.card + .card { margin-top: var(--s2); }

.rows { background: var(--card); border: 1px solid var(--rule-2); border-radius: var(--r3); overflow: hidden; }
.row {
  display: flex; align-items: center; gap: var(--s3);
  min-height: var(--tap); padding: 13px var(--s4);
  position: relative;
}
.row + .row::before { content: ""; position: absolute; left: var(--s4); right: 0; top: 0; height: 1px; background: var(--rule-2); }
.row:active { background: var(--card-2); }
.row-b { flex: 1; min-width: 0; }
.row-t { font-size: 14.5px; line-height: 1.35; }
.row-s { font: 400 10.5px/1.4 var(--f-mono); color: var(--ink-3); margin-top: 2px; }
.row-v { flex: 0 0 auto; font: 500 13px/1 var(--f-mono); font-variant-numeric: tabular-nums; color: var(--ink-2); }
.chev { width: 7px; height: 12px; flex: 0 0 auto; opacity: .35; stroke: currentColor; stroke-width: 2; fill: none; }

/* Section heading inside a scroll surface. */
.shead { display: flex; align-items: center; gap: var(--s3); margin: var(--s6) 0 var(--s3); }
.shead:first-child { margin-top: var(--s2); }
.shead h2 { font: 600 11px/1 var(--f-mono); letter-spacing: .18em; text-transform: uppercase; color: var(--ink-2); }
.shead .rule-fill { flex: 1; height: 1px; background: var(--rule-2); }
.shead .n { font: 400 10px/1 var(--f-mono); color: var(--ink-3); }

/* Chip row — filters and lenses. */
.chips { display: flex; gap: 6px; overflow-x: auto; padding: var(--s3) 0; scrollbar-width: none; -ms-overflow-style: none; }
.chips::-webkit-scrollbar { display: none; }
.chip {
  flex: 0 0 auto;
  border: 1px solid var(--rule); background: var(--card); color: var(--ink-2);
  font: 500 11px/1 var(--f-mono); letter-spacing: .1em; text-transform: uppercase;
  padding: 10px 13px; border-radius: var(--r1); min-height: 36px;
  transition: background .18s, color .18s, border-color .18s;
}
.chip.on { background: var(--ink); color: var(--paper); border-color: var(--ink); }

/* Segmented control — view switching inside a surface. */
.seg { display: flex; background: var(--sunk); border-radius: var(--r2); padding: 3px; gap: 2px; }
.seg button {
  flex: 1; min-height: 38px; border-radius: var(--r1);
  font: 500 11px/1 var(--f-mono); letter-spacing: .08em; text-transform: uppercase;
  color: var(--ink-2); transition: background .18s, color .18s;
}
.seg button.on { background: var(--card); color: var(--ink); box-shadow: 0 1px 3px rgba(0,0,0,.10); }

/* Buttons. */
.btn {
  min-height: 50px; padding: var(--s4);
  border: 1px solid var(--rule); background: var(--card); color: var(--ink-2);
  border-radius: var(--r2);
  font: 600 11px/1 var(--f-mono); letter-spacing: .14em; text-transform: uppercase;
  display: inline-flex; align-items: center; justify-content: center; gap: var(--s2);
  transition: background .18s, opacity .18s;
}
.btn:active { opacity: .75; }
.btn[disabled] { opacity: .45; pointer-events: none; }
.btn.prim { background: var(--ink); color: var(--paper); border-color: var(--ink); }
.btn.danger { color: var(--bad); border-color: var(--bad-soft); background: var(--bad-soft); }
.btn.sm { min-height: 38px; padding: 0 var(--s3); font-size: 10px; }
.btn-row { display: flex; gap: var(--s2); margin-top: var(--s4); }
.btn-row .btn { flex: 1; }

/* Add button in the ledger. */
.add-btn {
  width: 46px; height: 46px; flex: 0 0 auto;
  border-radius: var(--r2); background: var(--ink);
  display: grid; place-items: center;
}
.add-btn svg { width: 21px; height: 21px; stroke: var(--paper); stroke-width: 2.3; fill: none; }
.add-btn:active { transform: scale(.93); }

/* Fields. Every input in the app routes through here — that is what keeps
   the 17px anti-zoom rule true. */
.f { margin-bottom: var(--s3); }
.f label { display: block; font: 500 9.5px/1 var(--f-mono); letter-spacing: .15em; text-transform: uppercase; color: var(--ink-3); margin-bottom: 6px; }
.f input, .f select, .f textarea {
  width: 100%;
  font: 400 var(--field-fs)/1.35 var(--f-body);
  background: var(--card); color: var(--ink);
  border: 1px solid var(--rule); border-radius: var(--r2);
  padding: 13px var(--s3);
  min-height: var(--field-h);
  appearance: none;
  transition: border-color .18s, box-shadow .18s;
}
.f textarea { resize: vertical; min-height: 92px; line-height: 1.5; }
/* A checkbox inside a field is a control, not a text input. Without this it
   inherits the rule above — appearance:none erases the tick completely, and
   the 48px min-height, border and padding turn a picker list into a column of
   blank boxes. Applies to the people pickers in both Today and the Library. */
.f input[type="checkbox"], .f input[type="radio"] {
  width: 22px; height: 22px; min-height: 0; flex: 0 0 auto;
  padding: 0; border: 0; background: none;
  appearance: auto; -webkit-appearance: auto;
  accent-color: var(--now);
}
.f input:focus, .f select:focus, .f textarea:focus { outline: none; border-color: var(--now); box-shadow: 0 0 0 3px var(--now-soft); }
.f .hint { font: 400 10.5px/1.4 var(--f-mono); color: var(--ink-3); margin-top: 5px; }
.f.bad input, .f.bad select, .f.bad textarea { border-color: var(--bad); }
.f-grid { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s2); }
.f-check { display: flex; align-items: center; gap: var(--s3); min-height: var(--tap); }
.f-check input { width: 22px; height: 22px; min-height: 0; flex: 0 0 auto; accent-color: var(--now); }
.f-check label { margin: 0; font-size: 14px; letter-spacing: 0; text-transform: none; color: var(--ink); font-family: var(--f-body); }

/* Sheet — the single overlay primitive. Replaces the five duplicated
   sheet/modal/slide-panel implementations the old sections each carried. */
.backdrop {
  position: fixed; inset: 0; z-index: 20;
  background: rgba(19, 22, 27, .45);
  opacity: 0; pointer-events: none; transition: opacity .28s var(--ease);
}
.backdrop.on { opacity: 1; pointer-events: auto; }
.sheet {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 21;
  background: var(--paper);
  border-radius: var(--r4) var(--r4) 0 0;
  padding: 0 var(--s4) calc(env(safe-area-inset-bottom, 0px) + var(--s5));
  transform: translateY(100%);
  transition: transform .38s var(--ease-sheet);
  max-height: 92%; overflow-y: auto;
  box-shadow: 0 -14px 44px rgba(19, 22, 27, .18);
}
.sheet.on { transform: translateY(0); }
.sheet.dragging { transition: none; }
.grab { width: 36px; height: 4px; border-radius: 2px; background: var(--rule); margin: 9px auto var(--s4); }
.sheet-h { margin-bottom: var(--s4); }
.sheet-h h2 { margin-bottom: 4px; }

/* Toast — replaces window.alert(), which the old sections used for every error. */
.toast {
  position: fixed; left: var(--s4); right: var(--s4);
  bottom: calc(env(safe-area-inset-bottom, 0px) + var(--tabbar-h) + var(--s3));
  z-index: 40;
  background: var(--ink); color: var(--paper);
  border-radius: var(--r2); padding: 13px var(--s4);
  font-size: 14px; line-height: 1.4;
  box-shadow: 0 8px 28px rgba(19, 22, 27, .28);
  transform: translateY(140%); opacity: 0;
  transition: transform .34s var(--ease-sheet), opacity .2s;
  /* Never interactive. It is fixed above the tab bar, so without this the
     invisible resting state still swallows taps aimed at the chrome beneath
     it — translateY(140%) does not move it clear of the viewport. */
  pointer-events: none;
}
.toast.on { transform: translateY(0); opacity: 1; }
.toast.bad { background: var(--bad); color: #fff; }

/* Empty state — an invitation, not a dead end. */
.empty {
  border: 1px dashed var(--rule); border-radius: var(--r3);
  padding: var(--s4); min-height: 52px;
  display: flex; align-items: center;
  font-size: 13.5px; color: var(--ink-3);
}
.empty:active { background: var(--card-2); }

/* Skeleton — the old build had no loading state at all. */
.skel { background: var(--sunk); border-radius: var(--r1); animation: skel 1.4s ease-in-out infinite; }
@keyframes skel { 0%, 100% { opacity: 1; } 50% { opacity: .5; } }
.skel-node { height: 54px; border-radius: var(--r3); margin-bottom: 7px; }

/* Disclosure — collapsible day/group sections. */
.disc-h { display: flex; align-items: center; gap: var(--s3); width: 100%; min-height: var(--tap); padding: var(--s3) 0; }
.disc-h .tw { width: 10px; height: 10px; stroke: var(--ink-3); stroke-width: 2.4; fill: none; transition: transform .2s var(--ease); }
.disc.open .disc-h .tw { transform: rotate(90deg); }
.disc-body { display: none; }
.disc.open .disc-body { display: block; }

/* ══ 8. Dataviz ══════════════════════════════════════════════════════════
   Shared by the ledger, Review charts and every progress readout, so a
   macro bar looks the same wherever it appears. */

.track { height: 7px; border-radius: 4px; background: var(--sunk); overflow: hidden; }
.track > i { display: block; height: 100%; border-radius: 4px; background: var(--now); width: 0; transition: width .6s var(--ease); }
.track.thin { height: 4px; }
.track > i.good { background: var(--done); }
.track > i.over { background: var(--warn); }

/* Labelled bar row — "P ▓▓▓░ 96 / 180 g". */
.meter { display: flex; align-items: center; gap: var(--s3); margin-bottom: var(--s3); }
.meter:last-child { margin-bottom: 0; }
.meter-k { width: 26px; flex: 0 0 auto; font: 500 11px/1 var(--f-mono); color: var(--ink-2); }
.meter .track { flex: 1; }
.meter-n { width: 102px; flex: 0 0 auto; text-align: right; font: 400 11px/1 var(--f-mono); font-variant-numeric: tabular-nums; color: var(--ink-2); }

/* Chart frame — Review's bar/line/diverging charts draw into this. */
.chart { width: 100%; overflow-x: auto; }
.chart svg { display: block; width: 100%; height: auto; overflow: visible; }
.chart .grid-l { stroke: var(--rule-2); stroke-width: 1; }
.chart .axis-t { font: 400 9px/1 var(--f-mono); fill: var(--ink-3); }
.chart .bar { fill: var(--now); }
.chart .bar.neg { fill: var(--warn); }
.chart .bar.pos { fill: var(--done); }
.chart .line { fill: none; stroke: var(--now); stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
.chart .dot { fill: var(--now); }
.chart .area { fill: var(--now-soft); }

/* Stat cell — the 2×N summary grids above every chart. */
.stats { display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--s2); }
.stats.c4 { grid-template-columns: repeat(4, 1fr); }
.stat { background: var(--card); border: 1px solid var(--rule-2); border-radius: var(--r3); padding: var(--s3) var(--s4); }
.stat-k { font: 500 9px/1 var(--f-mono); letter-spacing: .14em; text-transform: uppercase; color: var(--ink-3); }
.stat-v { font: 700 21px/1.1 var(--f-disp); margin-top: 6px; font-variant-numeric: tabular-nums; }
.stat-v small { font: 400 10px/1 var(--f-mono); color: var(--ink-3); margin-left: 2px; }

/* Ring — due-date arcs and goal dials. */
.ring { width: 26px; height: 26px; flex: 0 0 auto; }
.ring circle { fill: none; stroke-width: 3; }
.ring .bg { stroke: var(--sunk); }
.ring .fg { stroke: var(--now); stroke-linecap: round; transform: rotate(-90deg); transform-origin: 50% 50%; }
.ring .fg.warn { stroke: var(--warn); }
.ring .fg.bad  { stroke: var(--bad); }

/* Badge / pill. */
.badge {
  flex: 0 0 auto;
  font: 500 9.5px/1 var(--f-mono); letter-spacing: .1em; text-transform: uppercase;
  padding: 5px 8px; border-radius: var(--r1);
  background: var(--sunk); color: var(--ink-2);
}
.badge.now  { background: var(--now-soft);  color: var(--now); }
.badge.done { background: var(--done-soft); color: var(--done); }
.badge.warn { background: var(--warn-soft); color: var(--warn); }
.badge.bad  { background: var(--bad-soft);  color: var(--bad); }

/* ══ 9. Utilities ════════════════════════════════════════════════════════ */

.mt2 { margin-top: var(--s2); } .mt4 { margin-top: var(--s4); } .mt6 { margin-top: var(--s6); }
.dim { color: var(--ink-3); }
.sr {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
  }
}
