/* Compass app shell.

   Every colour, type step, spacing step, radius and motion value comes from
   tokens.css, which is GENERATED by brand/tools/sync-household-tokens.py in
   kave-hub. Do not add a token here and do not hand-edit tokens.css: edit the
   hub and re-sync, or this app quietly disagrees with every other surface.

   Density tier: phone. Steps --sp-1 to --sp-4 do the work, --sp-5 is a
   section break. Type stops at --fs-display; the page-tier steps above it are
   for dashboards, not for a 375px screen. */

* { box-sizing: border-box; }
[hidden] { display: none !important; }
/* the mobile tap flash is a sharp rectangle that ignores border-radius */
* { -webkit-tap-highlight-color: transparent; }
html, body { overscroll-behavior-y: contain; }
html { scrollbar-gutter: stable; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--text);
  font: 16px/var(--lh-base) var(--font-ui);
}

/* One scrolling list between the header and the bar (prototype P4). The
   host may still let the page grow tall (a desktop window, a viewer), which
   is why scrolling uses scrollIntoView and loading needs a real scroll. */
html, body { height: 100%; }
.shell {
  height: 100%; height: 100dvh;
  display: flex; flex-direction: column;
  position: relative; overflow: hidden;
  max-width: 1120px; margin: 0 auto;
}

h1, h2, h3 {
  font-family: var(--font-ui);
  font-weight: 600;
  letter-spacing: var(--tracking-heading);
  margin: 0;
}

/* ---------- header: the tab's name only, Spoon's rounded header ---------- */
.app-header {
  flex: none;
  padding: calc(var(--sp-4) + env(safe-area-inset-top, 0px)) var(--sp-4) var(--sp-4);
}
.app-header h1 { font-size: var(--fs-display); }

.mn {
  flex: 1; min-height: 0;
  overflow-y: auto; overscroll-behavior: contain;
  background: var(--surface);
  border-radius: var(--r-sheet);
  padding: var(--sp-4) var(--sp-4) calc(var(--sp-7) * 2);
}

/* ---------- views ---------- */
main { padding: var(--sp-4); }
.view-title { font-size: var(--fs-lede); margin-bottom: var(--sp-2); }
.lede { color: var(--text-dim); font-size: var(--fs-ui); margin: 0 0 var(--sp-4); }

/* "not built yet" is a dashed box, the same signal Spoon uses on its Plan
   tab. It should look unfinished on purpose, never like an empty state. */
.stub {
  border: 1px dashed var(--rule-strong);
  border-radius: var(--r-card);
  padding: var(--sp-5) var(--sp-4);
  text-align: center;
  color: var(--text-dim);
  font-size: var(--fs-ui);
}
.stub b { display: block; color: var(--text); font-size: var(--fs-body); margin-bottom: var(--sp-1); }

/* ---------- settings: laid out like Spoon's. No cards and no section
   headings: a bold label per field, its controls straight on the page. ---------- */
input[type="password"], input[type="text"] {
  width: 100%;
  font: inherit; font-size: var(--fs-body);
  background: var(--surface-2);
  color: var(--text);
  border: none;
  border-radius: var(--r-control);
  padding: 10px 12px;
  min-height: var(--touch-min);
}
/* Spoon's button: surface-2, the control radius; a chosen one takes the accent */
button {
  font: inherit;
  background: var(--surface-2); color: var(--text);
  border: none; border-radius: var(--r-control);
  padding: 10px 14px;
  min-height: var(--touch-min);
  cursor: pointer;
}
button:active { transform: translateY(1px); }
button:disabled { opacity: .5; cursor: default; }
.row { display: flex; gap: var(--sp-2); align-items: center; flex-wrap: wrap; }
.hint { color: var(--text-dim); font-size: var(--fs-ui); margin: var(--sp-2) 0 0; }

.fields { max-width: 720px; display: flex; flex-direction: column; gap: var(--sp-5); }
.field { display: flex; flex-direction: column; align-items: flex-start; gap: var(--sp-2); }
.flabel { margin: 0; font-size: var(--fs-ui); font-weight: 600; }
.flabel label { font: inherit; }
.fhint { margin: 0; color: var(--text-dim); font-size: var(--fs-ui); }
.choices { display: flex; flex-wrap: wrap; gap: var(--sp-2); }
.choices button { display: inline-flex; align-items: center; gap: var(--sp-2); }
.choices button.on { background: var(--accent); color: var(--accent-text); }
.pal { width: 20px; height: 20px; border-radius: var(--r-round); border: 1px solid var(--rule-strong); flex: none; }
.choices button.on .pal { border-color: var(--accent-text); }
.opener { display: inline-flex; align-items: center; justify-content: space-between; gap: var(--sp-2); min-width: min(320px, 100%); text-align: left; }
.opener .chev { width: 16px; height: 16px; color: var(--text-dim); flex: none; }
/* sync, as in Spoon */
.sync-status { display: flex; flex-direction: column; gap: var(--sp-1); }
.sync-line { margin: 0; display: flex; align-items: center; gap: var(--sp-2); font-size: var(--fs-body); }
.sync-line i { width: 8px; height: 8px; border-radius: var(--r-round); flex: none; background: var(--text-dim); }
.sync-line.ok i { background: var(--accent); }
.sync-line.error i { background: var(--text); }
.sync-line.muted { color: var(--text-dim); }
.token-row { display: flex; gap: var(--sp-2); width: 75%; min-width: 240px; }
.token-row input { flex: 1; min-width: 0; }
.token-status { font-size: var(--fs-ui); margin: 0; font-weight: 600; }
/* Spoon's Advanced settings: a fold under a rule, so it reads as a divider */
.advanced-block { padding-top: var(--sp-4); border-top: 1px solid var(--rule); display: flex; flex-direction: column; gap: var(--sp-4); }
.adv-toggle { align-self: flex-start; background: none; padding-left: 0; font-size: var(--fs-body); font-weight: 500; }
.adv-toggle .caret { color: var(--text-dim); }
/* the Categories grid, straight on the sheet */
.grid { display: flex; flex-direction: column; }
.grid-h, .grid-r { display: grid; grid-template-columns: minmax(0, 1fr) repeat(3, 52px); align-items: center; column-gap: var(--sp-1); }
/* Free time: the same row, one tick column instead of one per view */
.grid-r.single { grid-template-columns: minmax(0, 1fr) 52px; }
.grid-h { position: sticky; top: calc(-1 * var(--sp-4)); background: var(--surface); padding: var(--sp-2) 0; font-size: var(--fs-micro); font-weight: 500; letter-spacing: var(--tracking-label); color: var(--text-dim); text-transform: uppercase; text-align: center; z-index: 1; }
.grid-h .full { display: none; }
.grid-r { padding: 6px 0; border-top: 1px solid var(--rule); }
.gl { display: flex; align-items: center; gap: var(--sp-2); min-width: 0; font-size: var(--fs-ui); }
.gi { font-size: 18px; line-height: 1; width: 22px; text-align: center; flex: none; }
.tick { justify-self: center; width: 36px; height: 36px; min-height: 0; border-radius: var(--r-round); border: 1.5px solid var(--rule-strong); background: none; display: grid; place-items: center; padding: 0; }
.tick.on { background: var(--accent); border-color: var(--accent); color: var(--accent-text); }
.tick svg { width: 18px; height: 18px; stroke-width: 2.5; }
@media (min-width: 900px) {
  .grid-h .full { display: inline; }
  .grid-h, .grid-r { grid-template-columns: minmax(0, 1fr) repeat(3, 88px); }
  .grid-r.single { grid-template-columns: minmax(0, 1fr) 88px; }
}
@media (prefers-reduced-motion: reduce) { button:active { transform: none; } }

/* ---------- bottom nav: exactly Spoon's. Page background, no top rule, a
   soft-accent pill behind the active tab's 24px icon, its label bold. ---------- */
.bottom-nav {
  flex: none; display: flex;
  background: var(--bg);
  padding-bottom: env(safe-area-inset-bottom, 0px);
}
.bottom-nav button {
  flex: 1; height: var(--nav-h);
  background: transparent; border: 0; border-radius: 0;
  color: var(--text-dim);
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: var(--sp-1); padding: 0; min-height: 0;
}
.nav-icon { position: relative; display: grid; place-items: center; width: 52px; height: 30px; border-radius: var(--r-pill); transition: background var(--motion-base) var(--ease-standard); }
/* F3: the Calendar's today's-event-count badge, exactly the nav count
   badge rule in household-look.md -- position and size are fixed, not
   invented per app. */
.nav-badge { position: absolute; top: -3px; left: calc(50% + 8px); min-width: 16px; height: 16px; padding: 0 4px; border-radius: var(--r-pill); background: var(--accent); color: var(--accent-text); font-size: var(--fs-micro); font-weight: 600; font-variant-numeric: tabular-nums; display: grid; place-items: center; line-height: 1; }
/* `.shell svg{width:18px}` further down has the same specificity (0,1,1)
   and comes later, so it was quietly shrinking every nav icon to 18px.
   `.shell .bottom-nav svg` (0,2,1) outranks it, as `.shell .fab` does.
   Same trap for colour: `.shell button{color:inherit}` was beating the
   dim inactive tab, hence `.shell .bottom-nav button` here. */
.shell .bottom-nav svg { width: 24px; height: 24px; }
.shell .bottom-nav button { color: var(--text-dim); }
.bottom-nav button[aria-current="page"] { color: var(--accent-ink); }
.bottom-nav button[aria-current="page"] .nav-icon { background: var(--accent-soft); }
.nav-label { font-size: var(--fs-micro); line-height: 1; letter-spacing: var(--tracking-label); }
.bottom-nav button[aria-current="page"] .nav-label { font-weight: 600; }

/* ---------- banner ---------- */
.banner {
  position: fixed; max-width: 720px; margin: 0 auto; left: var(--sp-3); right: var(--sp-3);
  bottom: calc(var(--nav-h) + env(safe-area-inset-bottom, 0px) + var(--sp-3));
  background: var(--text); color: var(--bg);
  border-radius: var(--r-control);
  padding: var(--sp-3) var(--sp-4);
  font-size: var(--fs-ui);
  box-shadow: var(--shadow-raised);
  z-index: 20;
}

:focus-visible { outline: var(--focus-ring); outline-offset: var(--focus-offset); }

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

/* ================= Calendar (ported from prototype P4) ================= */
.shell svg{width:18px;height:18px;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
.shell button{font:inherit;color:inherit;cursor:pointer}
/* `.shell button{color:inherit}` (0,1,1) would beat `.fab{color:...}`
   (0,1,0) and draw the icons in --text, failing the accent-text-on-accent
   contrast minimum; `.shell .fab` (0,2,0) wins without !important. */
.shell .fab{color:var(--accent-text)}
.fab.add svg{width:26px;height:26px;stroke-width:2.5}
.mn .card{padding:var(--sp-3)}
/* the first-run gate (js/gate.js): the hub site's own screen, so all three
   apps open alike. While it is up, nothing else of the shell shows. */
body.gated .app-header, body.gated .bottom-nav, body.gated #fabs{display:none}
body.gated .mn{background:transparent;border-radius:0;padding:var(--sp-4)}
.gate{min-height:100%;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--sp-5)}
.gate-mark{font-size:var(--fs-xl);font-weight:var(--fw-strong);letter-spacing:.06em;line-height:var(--lh-title);text-transform:uppercase}
.gate-field{width:min(340px,100%);height:48px;border-radius:var(--r-control);background:var(--surface);
  display:flex;align-items:center;padding:0 6px 0 var(--sp-5);gap:var(--sp-3)}
.gate-field:focus-within{box-shadow:inset 0 0 0 2px var(--accent)}
.gate-field input{flex:1;min-width:0;height:100%;border:0;background:transparent;outline:none;
  font:inherit;font-size:var(--fs-body);color:var(--text);letter-spacing:.2em}
.shell .gate-go{width:36px;height:36px;min-height:0;min-width:0;flex:none;border-radius:var(--r-round);border:0;cursor:pointer;padding:0;
  background:var(--accent);color:var(--accent-text);display:flex;align-items:center;justify-content:center}
.setup-row{display:flex;flex-wrap:wrap;justify-content:center;gap:var(--sp-3)}
.shell .setup-choice{width:140px;height:48px;border:0;border-radius:var(--r-pill);background:var(--surface);color:var(--text);
  font:inherit;font-size:var(--fs-body);font-weight:var(--fw-strong);letter-spacing:.06em;text-transform:lowercase;cursor:pointer}
.shell .setup-choice:hover{background:var(--accent);color:var(--accent-text)}
.shell .setup-swatch{width:48px;height:48px;min-height:0;border:0;border-radius:var(--r-round);cursor:pointer;padding:0;transition:transform 120ms var(--ease-standard)}
.setup-swatch:hover{transform:scale(1.06)}
.gate-go svg{width:20px;height:20px}
.setup-choice:focus-visible,.setup-swatch:focus-visible{outline:var(--focus-ring);outline-offset:var(--focus-offset)}
/* the sheet: one sheet, levels inside */
.sheet{position:absolute;left:0;right:0;top:var(--header-h,56px);bottom:0;margin:0 auto;max-width:720px;background:var(--surface);border-radius:var(--r-sheet) var(--r-sheet) 0 0;box-shadow:var(--shadow-raised);display:flex;flex-direction:column;overflow:hidden;z-index:8}
.sheet.in{animation:sheet-up var(--motion-slow) var(--ease-sheet)}
.sheet.out{animation:sheet-down var(--motion-base) var(--ease-standard) forwards}
.shade.out{animation:fade-out var(--motion-base) var(--ease-standard) forwards}
@keyframes sheet-up{from{transform:translateY(40%);opacity:0}}
@keyframes sheet-down{to{transform:translateY(60%);opacity:0}}
@keyframes fade-out{to{opacity:0}}
.sstage{flex:1;min-height:0;position:relative;display:flex;flex-direction:column;overflow:hidden}
.sbody{flex:1;min-height:0;overflow-y:auto;padding:var(--sp-4);display:flex;flex-direction:column;gap:var(--sp-3)}
.sbody.leaving{position:absolute;inset:0;pointer-events:none}
/* Archive: newest at the bottom, scrolled there on open/load, only scrolls
   up (js/calendar.js pins scrollTop, no CSS direction trick needed) --
   "Load more" is its own first child so it sits above the oldest month/week
   shown, exactly where scrolling further up leads. */
.archive-more{align-self:center;border:0;border-radius:var(--r-pill);background:var(--surface-2);color:var(--text-dim);font:inherit;font-size:var(--fs-ui);font-weight:var(--fw-medium);padding:var(--sp-2) var(--sp-4);margin-bottom:var(--sp-2)}
.archive-more[disabled]{opacity:.6}
.sheet.lv-day .sbody,.sheet.lv-event .sbody{padding:0;gap:0}
/* depth moves vertically: deeper, the old level leaves upwards and the new
   one rises from the bottom; Back reverses */
.sbody.out-up{animation:lv-out-up var(--motion-base) var(--ease-standard) forwards}
.sbody.in-up{animation:lv-in-up var(--motion-base) var(--ease-standard)}
.sbody.out-down{animation:lv-out-down var(--motion-base) var(--ease-standard) forwards}
.sbody.in-down{animation:lv-in-down var(--motion-base) var(--ease-standard)}
@keyframes lv-out-up{to{transform:translateY(-30%);opacity:0}}
@keyframes lv-in-up{from{transform:translateY(40%);opacity:0}}
@keyframes lv-out-down{to{transform:translateY(40%);opacity:0}}
@keyframes lv-in-down{from{transform:translateY(-30%);opacity:0}}
/* the single day level's own swipe (js/sheet.js dayEnd): sideways, not
   depth -- the old day leaves the way the finger swiped and the new one
   arrives from the far side, an actual page-turn rather than a snap. */
.sbody.out-left{animation:lv-out-left var(--motion-base) var(--ease-standard) forwards}
.sbody.in-left{animation:lv-in-left var(--motion-base) var(--ease-standard)}
.sbody.out-right{animation:lv-out-right var(--motion-base) var(--ease-standard) forwards}
.sbody.in-right{animation:lv-in-right var(--motion-base) var(--ease-standard)}
@keyframes lv-out-left{to{transform:translateX(-30%);opacity:0}}
@keyframes lv-in-left{from{transform:translateX(40%);opacity:0}}
@keyframes lv-out-right{to{transform:translateX(40%);opacity:0}}
@keyframes lv-in-right{from{transform:translateX(-30%);opacity:0}}
.todo-l.done{color:var(--text-dim);text-decoration:line-through}
a.ticket{color:inherit;text-decoration:none}
@media (prefers-reduced-motion: reduce){
  .sfield,.sheet.in,.sheet.out,.shade.out,.slide-left,.slide-right,.segment .seg-thumb,.sbody.out-up,.sbody.in-up,.sbody.out-down,.sbody.in-down,.sbody.out-left,.sbody.in-left,.sbody.out-right,.sbody.in-right{animation:none}
  .fab.up,.fab.down,.fab.up svg,.fab.down svg,.nav-icon{transition:none}
}
/* three round buttons, all one size: add, and above it up (scroll to top)
   and down (jump to today), the same icon mirrored */
/* F63: colour lives in the `.shell .fab` rule above, at a specificity that
   actually beats `.shell button{color:inherit}` -- not repeated here. */
.fab{position:absolute;width:56px;height:56px;border-radius:var(--r-round);border:0;background:var(--accent);box-shadow:var(--shadow-raised);z-index:4;display:grid;place-items:center;padding:0}
.fab.add{right:var(--sp-4);bottom:calc(var(--nav-h) + var(--sp-4) + env(safe-area-inset-bottom,0px));font-size:var(--fs-title-lg)}
/* F55: one fixed slot, always the same distance above "+" -- up and down
   share this single position (never two heights) and are shown mutually
   exclusively (calendar.js's onScroll), never both at once. */
.fab.up,.fab.down{right:var(--sp-4);bottom:calc(var(--nav-h) + var(--sp-4) + 56px + var(--sp-3) + env(safe-area-inset-bottom,0px));opacity:0;transform:translateY(8px);pointer-events:none;transition:opacity .18s var(--ease-standard),transform .18s var(--ease-standard)}
.fab.up svg,.fab.down svg{width:22px;height:22px;stroke-width:2.5;transition:transform .18s var(--ease-standard)}
.fab.up.show,.fab.down.show{opacity:1;transform:none;pointer-events:auto}
.fab.down svg{transform:rotate(180deg)}
/* F28: the control row scrolls with the page again (F5 reversed). */
.top{display:flex;flex-direction:column;gap:var(--sp-3)}
/* F36: matches Spoon's Trends chart button row (kave-food-app's
   .control-row) for spacing -- var(--sp-3), not --sp-2. */
/* F66: .ctl (the filter bar) is a direct child of .page, which already
   puts var(--sp-3) between it and .content -- the section heading is
   .content's first child. This rule's own padding-bottom:var(--sp-3)
   stacked on top of that flex gap, doubling the step to 24px where the
   household's standard control-row-to-content gap is one sp-3 (12px). No
   new value: just the duplicate removed. */
/* F65: gap between the segmented toggle and the round icon buttons is a
   deliberate one-off 6px, tighter than the spacing grid's --sp-2 (8px) --
   for a row of controls this closely related, per the approved round-6
   mock-up (calendar/mockups/round-6-filterbar.html). Not --sp-3 (12px,
   used elsewhere for control-row-to-content spacing) and not --sp-2. */
.ctl{display:flex;flex-wrap:wrap;align-items:center;gap:6px;width:100%}
/* F54: F26's sticky month/year title bar is removed entirely -- no more
   .sec-title, in any view. */
/* F71: tighter again than F66's fix -- .page's gap is the only space
   between .ctl (the filter/toggle row) and .content's first child (the
   section heading). Measured live before this change: 12px (var(--sp-3),
   F66's fix). Isa wants it closer still; 6px (F65's own deliberate
   closely-related-controls one-off) read as too tight for a control row to
   a full heading below it -- checked live, half of --sp-3 (var(--sp-2),
   8px) reads as tight but not cramped, so that's what's used here. */
.page{display:flex;flex-direction:column;gap:var(--sp-2)}
/* F34: only .content (the list) carries the swipe animation now -- the
   controls above it (outside .content) stay put, so a swipe visibly moves
   just the list, not the whole screen. */
.content{display:flex;flex-direction:column;gap:var(--sp-3)}
/* room below the last card, so a jump can always bring its target to the top */
.content::after{content:"";flex:none;height:50vh}
/* the view swipe: --motion-base and --ease-drag (the drag-release curve),
   and a short 18% travel, so the new page reads as a continuation of the
   finger rather than a slow snap from far off-screen */
.slide-left{animation:sl var(--motion-base) var(--ease-drag);will-change:transform,opacity}
.slide-right{animation:sr var(--motion-base) var(--ease-drag);will-change:transform,opacity}
@keyframes sl{from{transform:translateX(18%);opacity:0}}
@keyframes sr{from{transform:translateX(-18%);opacity:0}}
/* The control row stays put while the list scrolls under it, as floating
   controls (Apple Maps style, Isa 2026-10-11): no bar and no fade, each control
   its own small shadowed pill, the list visible between them. The row itself
   ignores taps so the list scrolls and taps through the gaps. .mn pads its top
   by --sp-4, so the row pulls itself up by that much and pads itself back down:
   it sits flush at the top edge when stuck. */
.ctl{position:sticky;top:calc(-1 * var(--sp-4));z-index:5;margin-top:calc(-1 * var(--sp-4));padding:var(--sp-4) 0;pointer-events:none}
.ctl > *{pointer-events:auto}
.ctl .segment,.ctl .ib,.ctl .sfield{box-shadow:0 1px 4px rgba(0,0,0,.22),0 0 0 .5px var(--rule)}
.ctl2{display:flex;gap:6px;align-items:center}
.ctl.searching .ctl2{flex:1}
/* F59: Spoon's real .segment/.seg-thumb/.segment button construction
   (kave-food-app/styles.css, its Period + Group-by segmented control),
   copied verbatim -- the same component Compass's view toggle has aimed
   at, and missed, for two prior rounds (F30, F36). Adapted only where the
   spec itself says to: Grid/Agenda, two options, so the thumb's width is
   calc(50% - 3px) and its translateX is 0/100% -- driven here by --i (0 or
   1, set per render in calendar.js) rather than fixed [data-on] selectors,
   the same value at each step. */
/* F69: display:grid with equal 1fr columns, not flex. Flex's flex:1 1 0 +
   min-width:0 (Spoon's own construction, F59) actively let a segment
   shrink below its own label's width. Grid's 1fr tracks default to an
   auto (content) floor: equal fr tracks are still sized equal to each
   other, but that shared size is bumped up to whatever the widest cell
   ("Agenda") actually needs, so no cell can truncate. */
/* --ctl-h makes the toggle and the round icon buttons equal by
   construction; two separate numbers drifted apart once a global
   min-height:44px overrode one of them. */
:root{--ctl-h:40px}
/* Grid was a third option once (F59/F69 above); since it's gone, this was
   still reserving a third column's worth of width -- the pill read as too
   long, with its trailing third empty. Two columns now, and a bit more
   horizontal padding per button (sp-2 -> sp-4) so "Agenda", the longer
   label, sits with real breathing room rather than a content-tight fit. */
.segment{position:relative;display:grid;grid-template-columns:repeat(2,1fr);height:var(--ctl-h);background:var(--surface-2);border-radius:var(--r-pill);padding:3px}
.seg-thumb{position:absolute;top:3px;bottom:3px;left:3px;width:calc(50% - 3px);border-radius:var(--r-pill);background:var(--accent);box-shadow:var(--shadow-card);transform:translateX(calc(var(--i) * 100%));animation:ind var(--motion-base) var(--ease-drag)}
@keyframes ind{from{transform:translateX(calc(var(--from) * 100%))}}
/* F36: matches Spoon's "6 months / all time" toggle's own text size,
   --fs-ui, not --fs-meta. */
/* .segment is a grid: its items fill equal columns, no truncation needed */
.segment button{position:relative;z-index:1;border:none;background:none;font:inherit;font-size:var(--fs-ui);font-weight:var(--fw-medium);color:var(--text-dim);padding:7px var(--sp-4);min-height:0;border-radius:var(--r-pill);white-space:nowrap}
/* F30/F59: the selected button's text is accent-text on the accent-filled
   thumb -- Compass's toggle is a tablist (aria-selected), not Spoon's plain
   toggle buttons (aria-pressed), so the same rule keys off aria-selected. */
.segment button[aria-selected="true"]{color:var(--accent-text);font-weight:var(--fw-strong)}
/* F65: both height and min-height set explicitly, from the same --ctl-h
   custom property that .segment reads -- the actual fix, so no ambient
   touch-target rule can push .ib taller than the toggle again. */
.ib{flex:none;width:var(--ctl-h);height:var(--ctl-h);min-height:var(--ctl-h);border:0;border-radius:var(--r-round);background:var(--surface-2);color:var(--text-dim);display:grid;place-items:center;padding:0}
.sfield{flex:1;display:flex;align-items:center;gap:var(--sp-2);height:40px;padding:0 var(--sp-1) 0 var(--sp-3);border-radius:var(--r-control);background:var(--surface-2);transform-origin:right center;animation:grow var(--motion-slow) var(--ease-sheet)}
@keyframes grow{from{clip-path:inset(0 0 0 calc(100% - 40px) round var(--r-round))}to{clip-path:inset(0 0 0 0 round var(--r-control))}}
.sfield .si{display:grid;color:var(--text-dim)}
.sfield svg{width:16px;height:16px}
.sfield input{flex:1;min-width:0;border:0;outline:0;background:transparent;color:var(--text);font:inherit;font-size:var(--fs-body)}
.clr{border:0;background:none;color:var(--text-dim);display:grid;place-items:center;padding:6px}
.menu{position:absolute;right:0;top:48px;width:240px;background:var(--panel);border-radius:var(--r-card);box-shadow:var(--shadow-raised);padding:var(--sp-3);display:flex;flex-direction:column;gap:var(--sp-2);z-index:6}
.mt{margin:0;font-size:var(--fs-micro);font-weight:var(--fw-medium);letter-spacing:var(--tracking-label);color:var(--text-dim);text-transform:uppercase}
.opt{border:0;text-align:left;padding:8px var(--sp-3);border-radius:var(--r-pill);background:var(--surface-2)}
.opt.on{background:var(--accent);color:var(--accent-text);font-weight:var(--fw-strong)}
.mh{margin:0;color:var(--text-dim);font-size:var(--fs-meta)}
/* #today is a bare, invisible scroll anchor */
#today{display:block;height:0}
.chev{width:14px;height:14px;stroke-width:2.5;vertical-align:-2px;margin-left:2px;color:var(--text-dim)}
/* rows: the icon cell is as wide as the row's own icons; dates share one column */
.rows{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:5px;min-width:0}
.rows li{display:grid;grid-template-columns:calc(var(--n) * 20px) minmax(0,1fr) auto;align-items:center;column-gap:var(--sp-2);min-width:0}
.rows.dated li{grid-template-columns:52px calc(var(--n) * 20px) minmax(0,1fr) auto}
.rows li.note{column-gap:0}
.rows.dated li.note{grid-template-columns:52px 0 minmax(0,1fr) auto;column-gap:var(--sp-2)}
.rows li[data-act]{cursor:pointer;min-height:32px}
/* F57: the date is the same size as the event's own title text on that
   line (c-t carries no font-size of its own, F36) -- no override here. */
.c-d{color:var(--text-dim);font-variant-numeric:tabular-nums;white-space:nowrap}
.c-i{font-size:15px;line-height:1;white-space:nowrap;letter-spacing:2px}
/* F36: matches Spoon's "Worth watching" list-item text size -- .opp-name
   there carries no font-size of its own, reading at the plain body size;
   same here, no override (was --fs-meta, reading too small). */
.c-t{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}
.grey .c-i,.ic.grey{filter:grayscale(1);opacity:.45}
.grey .c-t{color:var(--text-dim)}
/* Agenda keeps a cancelled event, title struck through only (Grid never
   draws one -- hideCancelled in cal-model.js). */
.cancelled .c-t{text-decoration:line-through}
.idea .c-i,.ic.idea{opacity:.45}
.flag{display:inline-block;border-radius:var(--r-pill);padding:1px var(--sp-2);font-size:var(--fs-meta);font-weight:var(--fw-medium);max-width:100%;overflow:hidden;text-overflow:ellipsis;vertical-align:middle}
.flag.acc{background:var(--accent);color:var(--accent-text)}
.flag.soft{background:var(--accent-soft);color:var(--text)}
/* Agenda's card model: no week wrapper -- one card per day, straight in a
   run (Grid, below, draws its own separate month-grid card model). Black
   (var(--panel)), same as Grid's own square; a weekend gets the accent's
   own pale tint (--accent-soft, the accent fade) instead, always, unless a stronger state
   (Clear/Open, today) applies -- those are declared after .weekend below,
   so they still win on a weekend day exactly as they do on a weekday. */
.month{margin:var(--sp-3) 0 0;font-size:var(--fs-title-lg);font-weight:var(--fw-strong);letter-spacing:var(--tracking-heading);line-height:var(--lh-title)}
.daycard{background:var(--panel);border-radius:var(--r-card);padding:6px var(--sp-2);cursor:pointer}
/* .content is a flex column with its own gap (sp-3) between every child,
   so it's never the whole story: a bare margin-bottom just adds to that
   gap, and a small difference between two already-large numbers barely
   reads. Both rules below fight the gap directly instead. A week's first
   day (Monday) restores the original between-weeks distance (gap + sp-2,
   what every daycard used before any of this); every other day in the
   week pulls in well past it, with a negative margin-top, down to Grid's
   own intra-month row gap (.monthgrid, 4px) total. */
.dayrow{display:flex;gap:var(--sp-2);align-items:stretch}
.dayrow.week-start{margin-top:var(--sp-2)}
.dayrow:not(.week-start){margin-top:calc(4px - var(--sp-3))}
/* the weekday sits outside the card, on the left; today's takes the accent */
.wdl{flex:none;width:28px;padding-top:6px;font-size:var(--fs-micro);font-weight:500;color:var(--text-dim)}
.wdl.today{color:var(--accent-ink)}
.dayrow > .daycard{flex:1;min-width:0}
/* Weekday top-left, day+month top-right, plain empty space between them
   (no rule, no dots) -- flex justify-content does the work. */
.daycard > .cd{display:flex;justify-content:flex-start;align-items:baseline;gap:var(--sp-2);font-size:var(--fs-micro);font-weight:500;color:var(--text-dim);margin-bottom:var(--sp-2)}
.daycard.weekend,.daycard.holiday-border{background:var(--accent-soft)}
.daycard.today{background:var(--accent);color:var(--accent-text)}
.daycard.today > .cd{color:var(--accent-text)}
/* Text on a solid card (today, Clear) takes that card's own ink, never the page's --text:
   chartreuse and amber are light fills, and --text is near-white in dark mode. The to-do icon sets --text-dim itself, so it inherits the ink back here. */
.daycard.today .todo-ic{color:inherit;opacity:.75}
/* "Check in" / "Check out" after a stay's title, quieter than it. A long title
   ellipsises on its own; the tag never shrinks, so it is always readable. */
.c-t.has-tag{display:flex;min-width:0}
.c-name{min-width:0;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}
.c-tag{flex:none;white-space:nowrap;color:var(--text-dim)}
.daycard.today .c-tag{color:inherit;opacity:.75}
/* a dimmed (other person's) event keeps the card's full ink on a solid card: any dimming drops chartreuse, amber and cobalt below 4.5:1; its icon is still greyed */
.daycard.today .grey .c-t{color:inherit}

/* A weekday bank holiday (never Sat/Sun) is shaded like a weekend: its
   class (holiday-border, a leftover name) shares the .weekend rule above,
   declared before Clear/Open/today so they still win. */
/* the holiday's name in the header: the middle of three slots, shrinking and ellipsising before it can push the date */
.cd-hol{flex:1;min-width:0;text-align:left;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}
/* grid: a real Monday-first month grid, blank pad cells outside the month.
   No card: just the squares, month to month, with no boxed container or
   border around the group. */
.gridCard{margin-bottom:var(--sp-3)}
.wdhead{display:grid;grid-template-columns:repeat(7,minmax(0,1fr));margin-bottom:2px}
.wdhead span{text-align:center;font-size:var(--fs-micro);font-weight:var(--fw-medium);color:var(--text-dim)}
.monthgrid{display:flex;flex-direction:column;gap:4px}
.grid7{display:grid;grid-template-columns:repeat(7,minmax(0,1fr));gap:4px}
/* var(--panel), not a literal black -- a hardcoded #000 here was the bug:
   Grid's squares stayed black in light mode (the comment above has always
   said var(--panel), the rule just never matched it). */
.dsq{aspect-ratio:5/6;border-radius:8px;background:var(--panel);position:relative;cursor:pointer}
.dsq.pad{background:transparent;cursor:default}
.dsq .num{position:absolute;top:4px;left:5px;font-size:var(--fs-micro);font-weight:var(--fw-medium);color:var(--text-dim)}
/* the top-right info, level with the day number: the event dots (one per
   extra event, a "+" past three). */
.dsq .dinfo{position:absolute;top:4px;right:6px;height:calc(var(--fs-micro) * var(--lh-base));display:flex;align-items:center;gap:2px}
.dsq .ddots{display:flex;align-items:center;gap:2px;color:var(--text-dim)}
.dsq .ddots i{display:block;width:4px;height:4px;border-radius:var(--r-round);background:currentColor}
.dsq .ddots b{font-size:8px;font-weight:var(--fw-medium);line-height:4px}
/* the day's single emoji, centred in the bottom two thirds -- no border
   ever says whose day it is; a day that's only the other person's uses
   the app's existing "grey" convention (same filter as .c-i.grey in the
   event rows) instead. */
.dsq .emo{position:absolute;top:67%;left:50%;transform:translate(-50%,-50%);font-size:21px;line-height:1}
.dsq .emo.grey{filter:grayscale(1);opacity:.45}
/* weekend square: the accent fade (--accent-soft), same as Agenda's weekend
   day cards -- unconditional, but Clear/Open/today (declared after) still
   win, same priority as everywhere else this app colours a square. */
.dsq.weekend,.dsq.holiday-border{background:var(--accent-soft)}
.dsq.today{background:var(--accent)}
.dsq.today .num{color:var(--accent-text)}
.dsq.today .ddots{color:var(--accent-text);opacity:.75}
/* search */
.hint{margin:0;color:var(--text-dim);font-size:var(--fs-meta)}
.card{background:var(--panel);border-radius:var(--r-card);padding:var(--sp-3)}
/* the sheet: header taps and swipes close; each level looks different */
/* The backdrop starts where the sheet does (top: --header-h, the header's
   measured height from wire.js), so the page header stays undarkened. */
.shade{position:absolute;left:0;right:0;bottom:0;top:var(--header-h,56px);background:var(--bg);opacity:.6;z-index:7}
.sbar{flex:none;background:var(--accent-soft);border-radius:var(--r-sheet);padding:var(--sp-4);position:relative;touch-action:none;cursor:pointer}
.grab{position:absolute;top:7px;left:50%;transform:translateX(-50%);width:34px;height:4px;border-radius:var(--r-pill);background:var(--text-dim);opacity:.5}
.stitle{margin:0;font-size:var(--fs-title-lg);font-weight:var(--fw-strong);letter-spacing:var(--tracking-heading);line-height:1.2}
.stitle-wrap{flex:1;min-width:0}
.stags{display:flex;flex-wrap:wrap;gap:var(--sp-2)}
.stags:not(:empty){margin-top:var(--sp-2)}
/* week level: a roomy row per day, "Monday 21" in Title Case */
.lrow{background:var(--panel);border-radius:var(--r-card);padding:var(--sp-3);display:flex;flex-direction:column;gap:var(--sp-2);cursor:pointer}
.lrow.today{outline:2px solid var(--accent);outline-offset:-2px}
.lday{font-size:var(--fs-body);font-weight:var(--fw-strong)}
.greyw .wicons,.greyw .eicons{filter:grayscale(1);opacity:.45}
.todo-l{margin:0;display:flex;align-items:center;gap:var(--sp-2)}
.box{width:14px;height:14px;border:2px solid var(--text-dim);border-radius:4px;flex:none}
.ticket{margin:0;align-self:flex-start;background:var(--surface-2);border-radius:var(--r-pill);padding:4px var(--sp-3);font-size:var(--fs-meta)}
.hol{align-self:flex-start}
/* event level: no cards, a recipe-style page on the sheet itself */
.sheet.lv-event .sbody{padding:0;gap:0}
.epage{display:flex;flex-direction:column}
.ehero{padding:var(--sp-5) var(--sp-4) var(--sp-4);display:flex;flex-direction:column;gap:var(--sp-2)}
.eicons{font-size:48px;line-height:1;display:flex;gap:var(--sp-1)}
.esub{margin:0;color:var(--text-dim)}
.esec{padding:var(--sp-4);border-top:1px solid var(--rule);display:flex;flex-direction:column;gap:var(--sp-2)}
.esec h3{margin:0;font-size:var(--fs-title);font-weight:var(--fw-strong);letter-spacing:var(--tracking-heading)}
.esec p{margin:0}
.epage > .hint{padding:var(--sp-4)}
/* wide window: a week is one row of seven; controls in two lines, left-aligned */
@media (min-width: 900px){
  .app-header{padding-inline:var(--sp-5)}
  .mn{padding:var(--sp-5) var(--sp-5) calc(var(--sp-7) * 2)}
  /* F65: below this breakpoint .ctl spans the full phone width (width:100%,
     set unconditionally); above it, per the approved round-6 mock-up, it
     stops stretching and settles to the left instead -- reusing this
     existing wide-screen breakpoint (already used just below for .segment's
     own fixed width), not a second invented one. */
  /* Still wraps to two lines at 518px of content, but the sticky bar itself spans the
     full width (so nothing shows beside it) and .mn pads by --sp-5 here, not --sp-4. */
  .ctl{flex-wrap:wrap;justify-content:flex-start;width:auto;top:calc(-1 * var(--sp-5));margin-top:calc(-1 * var(--sp-5));padding:var(--sp-5) max(0px, calc(100% - 518px)) var(--sp-5) 0}
  /* Was 380px, sized for the three-option segment (F59); two options with
     the wider per-button padding above need less. */
  .ctl .segment{flex:none;width:260px}
  .ctl.searching .ctl2{width:260px}
  .fab.add{right:var(--sp-6)}
  .fab.up,.fab.down{right:var(--sp-6)}
}
/* day level (P2 feedback): no cards, sections on the sheet like a recipe */
.sheet.lv-day .sbody{padding:0;gap:0}
.dpage{display:flex;flex-direction:column}
.dhol{margin:0;padding:var(--sp-3) var(--sp-4);font-weight:var(--fw-medium);color:var(--text-dim)}
.dpage > .hint{padding:var(--sp-4)}
/* day strips with room, a closing rule (layout A until Task 9c). F13: the
   icons are a sibling of the title block, in the same row as the chevron,
   so .dsec's own align-items:center keeps all three vertically centred on
   one another regardless of how many lines the title block wraps to. */
.dpage{padding-bottom:var(--sp-7)}
.dsec{display:flex;flex-direction:row;align-items:center;gap:var(--sp-3);padding:var(--sp-5) var(--sp-4);border-top:1px solid var(--rule)}
.dpage > .dsec:first-child{border-top:0}
.dpage > .dsec:last-of-type{border-bottom:1px solid var(--rule)}
.dmain{flex:1;min-width:0;display:flex;flex-direction:column;gap:var(--sp-2)}
.dmain > h3{margin:0;font-size:var(--fs-title);font-weight:var(--fw-strong);letter-spacing:var(--tracking-heading)}
.dicons{flex:none;font-size:24px;line-height:1;display:flex;gap:2px}
.dline{margin:0}
.dline + .dline{color:var(--text-dim)}
.dchev{flex:none;display:grid;place-items:center;color:var(--text-dim)}
.dchev .chev{width:20px;height:20px;margin:0}
.day.empty,.lrow.empty,.wcard.empty{cursor:default}
/* F70: a jump lands the target week at the top of Agenda, but the month heading sits just above that week in the flow
   and was landing flush against, or even partly behind, the header (measured
   live: heading top 22px above the header's own bottom edge, i.e. hidden
   under it). scroll-margin-top only pads the scrolled-to element itself, so
   it has to clear the header by enough to also clear the heading above it --
   measured live, the heading sits ~38px above its week row, so sp-4 (16px)
   plus that plus a comfortable visible gap lands here; not a spacing-scale
   step, a one-off scroll offset. */
[data-week],[data-month],#today{scroll-margin-top:60px}

/* ---- F10: Grid's big per-month heading (the "2026" treatment, reused for
   every month name -- "September", then "January 2027" once the year turns
   over); no border on the heading itself (Isa's correction). ---- */
.year-big{font-size:var(--fs-display);font-weight:var(--fw-strong);letter-spacing:var(--tracking-heading);margin:var(--sp-3) 0 0;display:block}

/* ---- a small inline SVG checkbox glyph marks an event with open to-dos
   (never an emoji) ---- */
.todo-ic{display:inline-flex;color:var(--text-dim);vertical-align:-2px}
.todo-ic svg{width:14px;height:14px;stroke-width:2}

/* ================= The event page and form (round 2) =================
   After Google Calendar: a group per kind of information, a line icon on
   the left instead of a label, one text column, a thin full-width rule
   between groups. To do and Costs are titled sections. */
.sbar{display:flex;align-items:center;gap:var(--sp-3)}
.bar-acts{display:flex;gap:var(--sp-2);flex:none}
.bar-acts:empty{display:none}
.bar-acts .sbtn{min-height:40px;min-width:40px;padding:8px;border-radius:var(--r-round);background:none;display:grid;place-items:center}
.bar-acts .sbtn svg{width:22px;height:22px}
.bar-acts .act-btn{min-height:40px;padding:8px var(--sp-3);border-radius:var(--r-control);background:var(--surface);font-weight:500}
.bar-acts .act-btn.primary,#sheetRoot button.primary{background:var(--accent);color:var(--accent-text)}
.sheet.lv-event .sbody,.sheet.lv-edit .sbody,.sheet.lv-new .sbody{padding:0 0 var(--sp-7);gap:0}
/* align-items:start keeps the icon at the top of its column; the icon
   centres in a box one text line tall, so it lines up with the first line. */
.grp{display:grid;grid-template-columns:24px minmax(0,1fr);column-gap:var(--sp-4);align-items:start;padding:var(--sp-4);border-top:1px solid var(--rule)}
.grp:first-child{border-top:0}
.gic{color:var(--text-dim);display:flex;align-items:center;height:calc(var(--fs-body) * var(--lh-base));padding-top:0}
.gic svg{width:22px;height:22px;stroke-width:1.8}
/* F-alignment: in the edit form the first line of a group is a real control
   (an input, the "Add an activity" button, or the activity chip row), not a
   line of text -- each is taller than one text line, so the icon's fixed
   text-line height leaves it sitting near the top instead of centred on
   that control. Match the icon's box to whichever control actually opens
   the group. */
.grp:has(> .gbody > input:first-child) > .gic,
.grp:has(> .gbody > button.add:first-child) > .gic,
.grp:has(> .gbody > .choices:first-child) > .gic{height:var(--touch-min)}
.grp:has(> .gbody > .acts:first-child) > .gic{height:calc(var(--fs-ui) * var(--lh-base) + var(--sp-2))}
/* the title field's larger font makes its box taller than --touch-min */
.grp:has(> .gbody > input.titlein:first-child) > .gic{height:calc(var(--fs-title-lg) * var(--lh-base) + 20px)}
.gbody{display:flex;flex-direction:column;align-items:flex-start;gap:var(--sp-2);min-width:0}
.gbody p{margin:0;font-size:var(--fs-body)}
.gbody .big{font-size:var(--fs-lede);font-weight:500}
.dim{color:var(--text-dim)}
.pad{padding:var(--sp-4)}
.grp.sec{grid-template-columns:minmax(0,1fr);row-gap:var(--sp-2)}
/* F68: the status pill now lives in the sheet header's .stags row (see
   .stitle-wrap), Spoon's .detail-tag under the recipe name, not the page body. */
/* F45: one "to" label between the day/time columns, vertically centred. */
.dt-row{display:grid;grid-template-columns:1fr auto 1fr;align-items:center;gap:var(--sp-2);width:100%}
.dt-col{display:flex;flex-direction:column;gap:var(--sp-2);min-width:0}
.dt-to{align-self:center}
/* F46: the bar collapses to Save plus a small reveal arrow; Cancel and
   Delete stay hidden (see [hidden]) until it opens. */
.bar-acts .sbtn.reveal svg{transition:transform var(--motion-base) var(--ease-standard)}
.bar-acts .sbtn.reveal.on svg{transform:rotate(90deg)}
.bar-more{display:flex;gap:var(--sp-2)}
.sh{margin:0;font-size:var(--fs-lede);font-weight:600;letter-spacing:var(--tracking-heading);line-height:var(--lh-title)}
.maps{color:var(--text);font-size:var(--fs-ui)}
.ticket{display:inline-flex;align-items:center;gap:var(--sp-1);background:var(--surface-2);color:var(--text);text-decoration:none;border-radius:var(--r-pill);padding:6px var(--sp-3);font-size:var(--fs-ui)}
.ticket svg{width:14px;height:14px}
.ref{display:flex;align-items:center;gap:var(--sp-2);flex-wrap:wrap}
.refv{font-variant-numeric:tabular-nums}
#sheetRoot .copy{min-height:32px;padding:4px var(--sp-2);font-size:var(--fs-meta);color:var(--text-dim);background:none;display:inline-flex;align-items:center;gap:var(--sp-1)}
#sheetRoot .copy svg{width:16px;height:16px}
/* to-dos tick on the page; the list ends with a line to write a task */
#sheetRoot .todo{background:none;padding:var(--sp-1) 0;width:100%;text-align:left;display:flex;align-items:center;gap:var(--sp-3)}
.box{width:22px;height:22px;border-radius:6px;border:2px solid var(--rule-strong);display:grid;place-items:center;flex:none}
.box svg{width:14px;height:14px;stroke-width:3}
.box.empty{border-style:dashed}
.todo.done .box{background:var(--accent);border-color:var(--accent);color:var(--accent-text)}
.todo.done .tt{text-decoration:line-through;color:var(--text-dim)}
.tt{flex:1}
.who{font-size:var(--fs-meta);color:var(--text-dim)}
.newtodo,.newline{display:flex;align-items:center;gap:var(--sp-3);flex-wrap:wrap;width:100%}
#sheetRoot input.bare{background:none;padding-left:0;flex:1;min-width:160px;width:auto}
.plus{width:22px;height:22px;border-radius:6px;border:2px dashed var(--rule-strong);display:grid;place-items:center;color:var(--text-dim);flex:none}
.plus svg{width:14px;height:14px}
/* costs: name and details left; price and its rung right; rules only between */
.cost{display:flex;align-items:flex-start;gap:var(--sp-3);width:100%;padding:var(--sp-2) 0}
.cost + .cost,.cost + .newcost{border-top:1px solid var(--rule)}
.cost + .newcost{padding-top:var(--sp-3)}
.cleft{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}
.cright{display:flex;flex-direction:column;align-items:flex-end;gap:2px;text-align:right}
.cname{margin:0;font-size:var(--fs-body);font-weight:500}
.camt{margin:0;font-size:var(--fs-body);font-weight:600;font-variant-numeric:tabular-nums}
.cmeta{margin:0;font-size:var(--fs-meta);color:var(--text-dim)}
.rung{margin:0;display:inline-flex;align-items:center;gap:3px;font-size:var(--fs-meta);color:var(--text-dim)}
.rung svg{width:14px;height:14px}
.cost.fixed .rung{color:var(--text)}
.newcost{display:flex;flex-direction:column;gap:var(--sp-2);width:100%}
/* the form */
.line{display:flex;gap:var(--sp-2);width:100%;flex-wrap:wrap;align-items:center}
.line input{flex:1;min-width:120px;width:auto}
.line input.amt{flex:0 1 140px;min-width:100px;font-variant-numeric:tabular-nums}
#sheetRoot select,#sheetRoot textarea{font:inherit;font-size:var(--fs-body);color:var(--text);background:var(--surface-2);border:none;border-radius:var(--r-control);padding:10px 12px;min-height:var(--touch-min)}
#sheetRoot textarea{width:100%;resize:vertical}
#sheetRoot input[type=date],#sheetRoot input[type=time]{flex:1;width:auto}
#sheetRoot input.titlein{font-size:var(--fs-title-lg);font-weight:600;background:none;padding-left:0}
.need{outline:2px solid var(--text);outline-offset:1px}
.sub{margin:var(--sp-1) 0 0;font-size:var(--fs-ui);font-weight:500;color:var(--text-dim)}
#sheetRoot button.add{background:none;padding-left:0;display:inline-flex;align-items:center;gap:var(--sp-2)}
#sheetRoot button.add svg{width:16px;height:16px}
#sheetRoot .iconbtn{min-height:0;padding:6px;background:none;color:var(--text-dim)}
#sheetRoot .iconbtn svg{width:16px;height:16px}
.acts{display:flex;flex-wrap:wrap;align-items:center;gap:var(--sp-2)}
.act{display:inline-flex;align-items:center;gap:var(--sp-1);background:var(--surface-2);border-radius:var(--r-pill);padding:4px 4px 4px var(--sp-3);font-size:var(--fs-ui)}
.then{color:var(--text-dim);font-size:var(--fs-ui)}
.catgroup{font-size:var(--fs-micro);font-weight:500;letter-spacing:var(--tracking-label);color:var(--text-dim);text-transform:uppercase;margin:var(--sp-3) 0 var(--sp-1)}
.catgroup:first-child{margin-top:0}
.catgrid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--sp-2);width:100%}
#sheetRoot .catgrid button{justify-content:flex-start;text-align:left;font-size:var(--fs-ui);display:flex;align-items:center;gap:var(--sp-2)}
.ci{font-size:20px;line-height:1}
#sheetRoot .choices button.big{font-size:22px;min-width:52px}
/* the undo banner */
.banner.undo{display:flex;align-items:center;justify-content:space-between;gap:var(--sp-3)}
.banner.undo button{background:none;color:var(--bg);font-weight:600;min-height:36px}
@media (min-width:900px){.catgrid{grid-template-columns:repeat(3,minmax(0,1fr))}}
/* Day popup row (design review, 2026-10-11): emoji left, status top right, a
   coloured edge for Booked only, then the best tier of links. */
.dst{align-items:flex-start}
.dem{flex:none;font-size:24px;line-height:1.2;display:flex;gap:2px}
.dst .dline{color:var(--text-dim);font-size:var(--fs-ui)}
.dsep{display:inline-block;margin:0 var(--sp-2)}
/* the title block is a grid so the status (row 1) and the to-do count (row 2,
   level with the time) stay right-aligned under each other, even when a long
   title wraps */
.dst .dmain{display:grid;grid-template-columns:minmax(0,1fr) auto;column-gap:var(--sp-3);row-gap:var(--sp-2)}
.dst .dmain > h3{grid-column:1;grid-row:1}
.dst .dmain > .dstat{grid-column:2;grid-row:1}
.dst .dmain > .dline{grid-column:1;grid-row:2}
.dst .dmain > .dcount{grid-column:2;grid-row:2}
.dst .dmain > .dlinks{grid-column:1 / -1;grid-row:3}
.dstat{display:flex;align-items:center;height:calc(var(--fs-title) * var(--lh-base));font-size:var(--fs-meta);font-weight:var(--fw-medium);color:var(--text-dim)}
.dst.st-b .dstat{color:var(--accent-ink)}
.dst.st-c h3{text-decoration:line-through;color:var(--text-dim)}
.dlinks{margin-top:var(--sp-2);display:flex;flex-direction:column}
.dlink{display:flex;align-items:center;gap:var(--sp-2);padding:var(--sp-2) 0;border-top:1px solid var(--rule);color:var(--text);text-decoration:none;font-size:var(--fs-ui)}
.dlink .dlt{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.dlink .chev{width:18px;height:18px;margin:0;color:var(--text-dim)}
.dmore{margin:0;padding:var(--sp-2) 0 0;border-top:1px solid var(--rule);font-size:var(--fs-meta);color:var(--text-dim)}
/* the open-to-do count and box, right-aligned on the time's line */
.dcount{display:inline-flex;align-items:center;gap:var(--sp-1);justify-self:end;font-size:var(--fs-ui);color:var(--text-dim)}
.dcount svg{width:14px;height:14px;stroke-width:2}
/* Today: a thin calendar outline like the search and "+" icons, the date inside
   as plain text (no stroke), slightly larger so two digits stay readable */
.ib .tdy{width:20px;height:20px}
.ib .tdy text{fill:currentColor;stroke:none;font-family:inherit;font-weight:var(--fw-medium);text-anchor:middle}
