/* =====================================================================================
   web-v2/styles.css — Sol Passeio (App v3 rebuild: fonts, tokens, the shell, every surface)

   Order: the four font faces → tokens (App v3's lines, verbatim) → decision-11 text aliases →
   globals → the 38 App v3 keyframes → one class family per surface (page- demo- hdr-
   acct- sw- gal- ov-/sheet-/how- hist- dp- rec- home- share- mng- acs- ntf- store- wel- qlog- deck- focus-
   cb- bd-/bd-pill/bd-ctx/bd-menu tg- sm- sel- mv- rn- tk-/nt-/ts- way- fd- ftr- fb- toast- dlg- lp-/auth-).
   Step 9 emptied the old LEGACY BAND: every pre-App-v3 rule is gone.

   Visual authority: design/app-v3/App v3.dc.html (every px below is one of its inline
   style numbers; every style-hover is one :hover rule — and every :hover sits inside
   @media (hover: hover), so a phone never keeps a hover look after a tap: phone ruling 2). Dark mode = body[data-mode="dark"],
   palette = body[data-theme], both set before first paint by /theme-boot.js. Nothing in
   this file reads the <html> `dark` class (theme.js / theme-boot.js still toggle it — a plain hook, read by no stylesheet).
   ===================================================================================== */

/* ---------- 1. Fonts — self-hosted (web-v2/fonts/, OFL texts beside them); Google's own
   latin + latin-ext subsets and unicode-ranges. Only the two latin files are preloaded
   by index.html; the latin-ext files load on demand through unicode-range. ---------- */
/* Lora latin-ext */
@font-face {
  font-family: 'Lora';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url('fonts/lora-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* Lora latin */
@font-face {
  font-family: 'Lora';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url('fonts/lora-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* Nunito latin-ext */
@font-face {
  font-family: 'Nunito';
  font-style: normal;
  font-weight: 400 900;
  font-display: swap;
  src: url('fonts/nunito-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* Nunito latin */
@font-face {
  font-family: 'Nunito';
  font-style: normal;
  font-weight: 400 900;
  font-display: swap;
  src: url('fonts/nunito-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* ---------- 2. Tokens — App v3 lines 21–25, VERBATIM (byte-for-byte; nothing between them).
   body[data-theme] and body[data-mode] have equal specificity: the dark line is LAST, so dark
   overrides every palette (App v3's dark look is palette-independent). ---------- */
:root, body[data-theme="warm"]{ --bg:#e9e6dd; --panel:#f6f4ee; --surface:#faf9f4; --soft:#f4f2ea; --chip:#efece2; --chip2:#eceae0; --switchbg:#e6e2d6; --border:#e4e0d5; --border2:#ece8dd; --border3:#e8e4d8; --hair:#f0eee6; --divider:#dcd8cc; --bordersoft:#d8d3c5; --muted:#8b8577; --muted2:#a7a293; --muted3:#b0ab9c; --ink2:#5a564b; --ink3:#6b665a; --card:#fff; --ink:#3c3830; --accent:#b5642a; --danger:#c0392b; --go:#2f7d51; --go-soft:#8fd6a8; --go-ink:#1e3f2b; --solid:#3c3830; --on-solid:#ffffff; }
body[data-theme="neutral"]{ --bg:#e9e7e2; --panel:#f4f3f0; --surface:#f8f7f4; --soft:#f2f1ec; --chip:#ecebe6; --chip2:#e9e8e3; --switchbg:#e6e4de; --border:#e2e0d9; --border2:#ebe9e3; --border3:#e7e5df; --hair:#efeeea; --divider:#d9d7d0; --bordersoft:#d6d4cd; --muted:#86837c; --muted2:#a4a19a; --muted3:#b0ada6; --ink2:#57554f; --ink3:#64625c; }
body[data-theme="natural"]{ --bg:#e7e8dd; --panel:#f2f3ea; --surface:#f6f7ef; --soft:#f0f1e8; --chip:#eaece0; --chip2:#e7e9dd; --switchbg:#e4e6d8; --border:#dfe1d3; --border2:#e9ebdf; --border3:#e5e7db; --hair:#eef0e7; --divider:#d6d8c9; --bordersoft:#d3d5c6; --muted:#82857a; --muted2:#a1a497; --muted3:#adb0a3; --ink2:#545650; --ink3:#61635b; }
body[data-theme="slate"]{ --bg:#e5e7ea; --panel:#f0f2f4; --surface:#f5f6f8; --soft:#eef0f3; --chip:#e8eaed; --chip2:#e5e7ea; --switchbg:#e2e5e9; --border:#dde0e4; --border2:#e7eaed; --border3:#e3e6ea; --hair:#edeff2; --divider:#d4d7db; --bordersoft:#d1d4d9; --muted:#7f838a; --muted2:#9ea2a9; --muted3:#abaeb5; --ink2:#52555b; --ink3:#5f6268; }
  body[data-mode="dark"]{ --bg:#1e1c19; --panel:#26231f; --surface:#2b2823; --soft:#302c27; --chip:#302c27; --chip2:#38332c; --switchbg:#2b2823; --border:#4a443b; --border2:#413b33; --border3:#38332c; --hair:#302c27; --divider:#443e35; --bordersoft:#4a4339; --muted:#9c968a; --muted2:#847f74; --muted3:#726d63; --ink2:#ddd8cc; --ink3:#c7c2b6; --card:#26231f; --ink:#f0eadd;  --accent:#d68a52; --danger:#e57a68; --go:#5aa87a; --go-soft:#8fd6a8; --go-ink:#1e3f2b; --solid:#f0eadd; --on-solid:#26231f;}

/* The site's extra tokens (mode-independent). App v3 writes these as literals; named here so no rule repeats one. */
:root {
  --scrim: rgba(30,28,24,.45);        /* t5.scrimStyle (4157) + confirmScrimStyle (4159): every sheet scrim + cmDialog */
  --scrim-modal: rgba(30,28,24,.5);   /* the Send feedback modal (L294) */
  --scrim-menu: rgba(30,28,24,.42);   /* t5.menuScrimStyle (4156): narrow NON-anchored menu sheets (none in step 2) */
  --gold: #e3990d;                    /* wordmark gold (README) — same in dark mode */
  --gold-hi: #ffd873;                 /* the sun disc highlight (L264) */
  /* Z scale = App v3 this.Z (3255) minus canvas, plus confirm (4159: nested + 5). overlay.js / popover.js hold the same numbers. */
  --z-base: 1; --z-raised: 10; --z-menu: 40; --z-scrim-low: 90; --z-sticky: 100;
  --z-scrim: 900; --z-overlay: 1000; --z-nested: 1010; --z-confirm: 1015; --z-toast: 1100;
  --scrim-share: rgba(30,28,24,.55);  /* homeShareScrimStyle (2646): the share card's scrim */
  --scrim-nested: rgba(30,28,24,.4);  /* t5.scrimNestedStyle (4158): the Account sheet's nested dialogs */
  --heat-empty: rgba(61,54,45,.05);   /* App v3's rgba('#3d362d', .05) (calendar-grids HEAT_EMPTY_HEX): level-0 heat cells + legends */
}
/* Site deviation (owner, 2026-09-29): App v3 keeps the light value in dark mode, where the empty cells
   vanish on the dark panel. Dark mode uses the dark ink (--ink #f0eadd) at 8% instead. */
body[data-mode="dark"] { --heat-empty: rgba(240,234,221,.08); }

/* Decision 11 (owner, 2026-09-29): darker TEXT-ONLY aliases for the muted tokens. The verbatim
   --muted/--muted2/--muted3 stay for surfaces, borders, icons, disabled controls and aria-hidden
   decoration; every muted TEXT colour uses these. Method: the token in OKLCH, hue + chroma kept,
   lightness stepped toward darker (light) / lighter (dark); the FIRST hex reaching >= 4.5:1 on ALL
   of --bg / --panel / --surface / --card. The number after each value = its measured MINIMUM
   contrast over those four (WCAG 2.x). --switch-text-off also meets 4.5:1 on --switchbg (the
   unselected Counter | Gallery tab sits there). Same selector order as the token lines (dark last). */
:root, body[data-theme="warm"]{ --muted-text:#6d675a; /* 4.50 (bg 4.50 · panel 5.11 · surface 5.33 · card 5.62) */ --muted2-text:#6c6759; /* 4.52 */ --muted3-text:#6c675a; /* 4.52 */ --switch-text-off:#6a6457; /* 4.54 on --switchbg */ --accent-text:#a15213; /* 4.51 (bg 4.51 · panel 5.12 · surface 5.34 · card 5.63 · 8 % wash 5.10) */ --go-text:#26754a; /* 4.52 (12 % wash 4.82) */ }
body[data-theme="neutral"]{ --muted-text:#6a6761; /* 4.56 */ --muted2-text:#6a6861; /* 4.51 */ --muted3-text:#6a6861; /* 4.51 */ --switch-text-off:#696660; /* 4.50 on --switchbg */ --accent-text:#a15213; /* 4.55 */ --go-text:#26754a; /* 4.56 */ }
body[data-theme="natural"]{ --muted-text:#67695f; /* 4.51 */ --muted2-text:#67695d; /* 4.52 */ --muted3-text:#67695d; /* 4.52 */ --switch-text-off:#65675d; /* 4.55 on --switchbg */ --accent-text:#a15213; /* 4.55 */ --go-text:#26754a; /* 4.56 */ }
body[data-theme="slate"]{ --muted-text:#65686f; /* 4.50 */ --muted2-text:#65686f; /* 4.50 */ --muted3-text:#65686f; /* 4.50 */ --switch-text-off:#63676d; /* 4.50 on --switchbg */ --accent-text:#a15213; /* 4.54 */ --go-text:#26754a; /* 4.55 */ }
body[data-mode="dark"]{ --muted-text:#9c968a; /* = --muted, 4.99 (surface) */ --muted2-text:#938e83; /* 4.50 (surface) */ --muted3-text:#938e83; /* 4.50 (surface) */ --switch-text-off:#9c968a; /* 4.99 on --switchbg */ --accent-text:#d68a52; /* = --accent, 5.01 (the wash) */ --go-text:#5aa87a; /* = --go, 4.53 (the wash) */ }
/* Light mode before/after (min over the four surfaces): --muted 2.94–3.07 → 4.50–4.56; --muted2 2.04–2.09 → 4.50–4.52;
   --muted3 1.78–1.84 → 4.50–4.52. Dark: --muted 4.99 (already passes, kept); --muted2 3.68 → 4.50; --muted3 2.85 → 4.50.
   Not in the target set: dark --muted2-text on --chip/--soft 4.25, on --chip2 3.84 — no step-2 text sits there.
   Text on a coloured FILL (--go/--accent/--danger) uses var(--on-solid): = #fff in every light palette (App v3's literal),
   #26231f in dark (#fff on the dark fills measures 2.76–2.87; #26231f 5.45–5.67).
   --accent-text / --go-text: App v3 step 6 — the Account sheet's accent text (Danger zone, the pending banner, Sign out of
   all other devices) and the ✓ Verified badge. App v3 writes var(--accent) / var(--go) for that small text (4.36:1 / 4.30:1 on
   the light surfaces); same method (OKLCH hue + chroma kept, lightness stepped), also >= 4.5:1 on the 8 % accent wash /
   12 % go wash the sheet puts text on. Surfaces, borders and fills keep the verbatim --accent / --go. */

/* ---------- 3. Globals ---------- */
/* Reset — the SITE's (the legacy surfaces depend on zero default margins/padding); App v3 has only box-sizing (L27). */
* { margin: 0; padding: 0; box-sizing: border-box; }
*, *::before, *::after { box-sizing: border-box; }

/* Page base (L16, L87). color: var(--ink) is a site addition — the legacy surfaces inherit body text. */
html, body { overflow-x: clip; }
body { margin: 0; background: var(--bg); color: var(--ink); font-family: 'Nunito', system-ui, sans-serif; -webkit-font-smoothing: antialiased; }
button, input, select, textarea { font-family: inherit; }   /* App v3 writes font-family:inherit inline on every control */
/* No global heading reset: every NEW heading class sets its own font-size / weight / line-height. */

/* Zoom steps (L17–18) — App v3's first two, verbatim. LABELLED DEVIATION (owner, 2026-10-03 — big screens): App v3's
   two bigger steps (1.26 from 1650 px, 1.34 from 1950 px) are GONE — on a 27-inch monitor everything looked really
   big. Every window from 1380 px up stays at 1.14 and a wide one takes more columns instead (the big- section).
   What changed where: a window under 1650 px is exactly as before; from 1650 px (a full-width window on a 15-inch
   laptop — the owner's is 1710 px wide — and every bigger screen) the page is 9.5 % smaller than it was (1.26 → 1.14),
   from 1950 px 15 % smaller (1.34 → 1.14). Every rect maths divides by the body zoom (measure.js zf(); its ZOOM_STEPS mirrors these two rules).
   --zf mirrors the zoom for CSS: `zoom` scales viewport units too, so a sheet capped at plain 82dvh would render at
   82dvh × zoom (93% of the screen at 1.14; a 100dvh panel 114%) and run past the top and bottom. Every vh/dvh
   height below is written as calc(Ndvh / var(--zf, 1)) — a no-op under 1180 px (zf 1). LABELLED
   DEVIATION: App v3 caps its sheets at plain 82dvh under the same zoom. */
body { --zf: 1; }
@media (min-width:1180px){ body{ zoom:1.07; --zf:1.07; } }
@media (min-width:1380px){ body{ zoom:1.14; --zf:1.14; } }

/* Links (L26) — verbatim (the mix measures 4.94:1+ light, 7.77:1+ dark). */
a { color:color-mix(in oklab, var(--accent) 65%, var(--ink)); text-decoration:none; } @media (hover: hover) { a:hover { color:var(--ink); text-decoration:underline; text-underline-offset:2px; } }

/* Transitions — BOTH App v3 rules in App v3's order (L28, then L110): a <button> ends with the second
   (transform .1s / filter .12s / background .12s); links, summary, [data-seg], [role=slider] keep
   the .15s cubic-bezier(.2,0,0,1) rule. */
button, summary, a, [data-seg], [role="slider"] { transition: background-color .15s cubic-bezier(.2,0,0,1), color .15s cubic-bezier(.2,0,0,1), border-color .15s cubic-bezier(.2,0,0,1), box-shadow .15s cubic-bezier(.2,0,0,1); }
button{ transition: transform .1s ease, filter .12s ease, background .12s ease; }
button:active{ transform:scale(.94); }
@media (hover: hover) { button:hover { filter:brightness(.97); } }
button[data-still]{ transition:background-color .15s ease, color .15s ease, border-color .15s ease; }
button[data-still]:active{ transform:none; }

/* Reduced motion — ONE rule (App v3 has it twice, L29 + L79); scroll-behavior kept from the site's old rule. */
@media (prefers-reduced-motion: reduce){ *, *::before, *::after { animation-duration:.01ms !important; animation-iteration-count:1 !important; transition-duration:.01ms !important; scroll-behavior:auto !important; } }

/* Focus + tap (L75–76). LABELLED DEVIATION (owner, 2026-10-01): the ring is the text ink (--ink: dark in light mode,
   light in dark mode) — App v3 L75 uses the accent, which read as an error. Same 2 px / 2 px offset; :focus-visible only
   (keyboard users). On a coloured or solid surface the ring takes that surface's own text colour (the rules below).
   The ring- section (LAST in this file) finishes the story: a text field never draws it (its focus shows inside the
   field), and nothing draws it while the last input was a pointer (html[data-input="pointer"], js/input-modality.js). */
:focus-visible{ outline:2px solid var(--ink); outline-offset:2px; }
*{ -webkit-tap-highlight-color:transparent; }
/* Every dialog PANEL that takes the initial focus (polish ruling 1) shows no ring — it is not a control; the ring stays
   for keyboard users on the controls (the first Tab reaches the first one). */
[role="dialog"][tabindex="-1"]:focus, [role="alertdialog"][tabindex="-1"]:focus { outline: none; }
/* LABELLED (a11y — WCAG 2.4.7): where the ring is drawn ON a coloured or solid surface, the ink would vanish (ink on ink)
   or read under 3:1 — there it takes that surface's own text colour (the idea of the dealt card's kept #fff inside-ring,
   .deck-card-btn below). White on a category / pack colour and on the share card's dark scrim; --on-solid on the
   --solid surfaces (the Select bar, the toast's Undo, the store's lead card) and inside a PRESSED chip filled with the
   ink / --solid (an inside ring); --go-ink on the demo banner. Width / offset stay each rule's own. */
.bd-head :focus-visible, .deck-card-swap:focus-visible, .store-band :focus-visible, .share-controls :focus-visible { outline-color: #fff; }
.sel-bar :focus-visible, .toast :focus-visible, .store-lead-card :focus-visible,
.hist-chip[aria-pressed="true"]:focus-visible { outline-color: var(--on-solid); }
/* The demo banner keeps its light green strip in dark mode too (App v3 literals, the demo- section): dark mode's cream
   ink would vanish on it (1.05:1) — its ring is the strip's own text colour, --go-ink, in both modes (10.2:1). */
.demo-banner :focus-visible { outline-color: var(--go-ink); }

/* The hidden attribute always wins over a class's display (tab panels, the menu catcher). */
[hidden] { display: none !important; }

/* Visually hidden, still read by assistive tech (the History search label, the pill tips, the editor's note label). */
.vh { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0; }

/* 44-px touch targets on coarse pointers WITHOUT changing the look: an invisible 44×44 hit area centred
   on every isolated control smaller than 44 px (class .hit in the markup). Placed before the surfaces on
   purpose: a later class that sets position (e.g. .auth-x absolute) wins over .hit's relative. */
@media (pointer: coarse) {
  .hit { position: relative; }
  .hit::after { content: ""; position: absolute; left: 50%; top: 50%; width: 100%; height: 100%; min-width: 44px; min-height: 44px; transform: translate(-50%, -50%); }
}

/* Bottom sheets on NARROW (L71–72). One boundary everywhere: max-width 639.98px = JS innerWidth < 640
   (App v3's CSS says 640px, a 1-px disagreement with its own JS — LABELLED DEVIATION). */
@media (max-width:639.98px){ [data-sheet]::before{ content:''; display:block; width:38px; height:4px; border-radius:999px; background:var(--border); margin:2px auto 10px; flex:none; } }
/* … and the PANEL is the scroller on a phone (its backdrop root is not — tidy round 2, the dim- section at the end), so
   the panel itself keeps a swipe that reaches either end from scrolling the page behind it. */
@media (max-width:639.98px){ [data-scrim] > *{ max-height:calc(88dvh / var(--zf, 1)) !important; overflow:auto !important; overscroll-behavior:contain; } }

/* ---------- 4. Keyframes — all 38 of App v3 (L58–109), VERBATIM except sheetUp (mobile pass ruling 4: no
   opacity — Safari samples the sheet on its first frame), in source order. Used in step 2: popup,
   ovfade, menuIn, sheetUp; the rest wait for steps 3–10 (cardTapA/B and hlbeat/hlbeat2 are intentional
   A/B restart twins). plantClose reads --lw/--lpl/--lpr, set inline by App v3's cart float — never built
   (the cart was removed, 2026-09-30); kept verbatim with the rest. ---------- */
@keyframes numswap { from { opacity:0; transform:translateY(5px); } to { opacity:1; transform:none; } }
@keyframes settleIn { from { opacity:.28; } to { opacity:1; } }
@keyframes sparkDraw { from { stroke-dashoffset:1; } to { stroke-dashoffset:0; } }
@keyframes plantIn { 0% { opacity:0; transform:scale(.94); } 100% { opacity:1; transform:scale(1); } }
@keyframes plantBarOut { from { opacity:1; } to { opacity:0; } }
@keyframes cardSwap { 0% { opacity:.25; transform:scale(.9); } 60% { opacity:1; } 100% { opacity:1; transform:none; } }
@keyframes plantClose { from { max-width:var(--lw); padding-left:var(--lpl); padding-right:var(--lpr); } to { max-width:0px; padding-left:0px; padding-right:0px; } }
@keyframes plantWordOut { to { opacity:0; } }
@keyframes plantDoneIn { from { opacity:0; } to { opacity:1; } }
@keyframes popup { from { opacity:0; } to { opacity:1; } }
@keyframes revUnfold { from { opacity:0; transform:translateY(12px) scale(.94); } to { opacity:1; transform:none; } }
@keyframes menuIn { from { opacity:0; } to { opacity:1; } }
@keyframes calIn { from { opacity:0; } to { opacity:1; } }   /* menuIn again under a second name: the Period dialog's calendar page fades in as a menu does (a new name restarts the animation on a panel that is already open) */
@keyframes menuOut { from { opacity:1; } to { opacity:0; } }  /* …while a copy of the rows it replaces fades out under it (.cb-ghost): a cross-fade, not a blink */
@keyframes sheetUp { from { transform:translateY(16px); } to { transform:none; } }
@keyframes trayUnfold { from { opacity:0; transform:scaleY(.5) translateY(-6px); } to { opacity:1; transform:none; } }
@keyframes pulse { 0%{transform:scale(1)} 40%{transform:scale(1.16)} 100%{transform:scale(1)} }
@keyframes ovfade { from{opacity:0} to{opacity:1} }
@keyframes tabin { from{opacity:0; transform:translateY(3px)} to{opacity:1; transform:none} }
@keyframes barup { from { transform:scaleY(0) } to { transform:scaleY(1) } }
@keyframes yearwipe { from { clip-path:inset(-6px 100% -6px -6px) } to { clip-path:inset(-6px -6px -6px -6px) } }
@keyframes dcspin { to { transform:rotate(360deg) } }
@keyframes floatup { from{opacity:1;transform:translate(-50%,2px)} to{opacity:0;transform:translate(-50%,-24px)} }
@keyframes nubIn { from{opacity:0;transform:scale(.4)} to{opacity:1;transform:none} }
@keyframes nubInY { from{opacity:0;transform:translateY(-50%) scale(.4)} to{opacity:1;transform:translateY(-50%)} }
@keyframes pipFade { from{opacity:0} to{opacity:1} }
@keyframes chipPop { from{ opacity:0; transform:scale(.92); } to{ opacity:1; transform:none; } }
@keyframes gridFade { from{opacity:0;transform:translateY(7px)} to{opacity:1;transform:none} }
@keyframes dealIn { from{opacity:0;transform:translateY(16px) rotate(-1.6deg) scale(.93)} to{opacity:1;transform:none} }
@keyframes deckReveal { from{opacity:0} to{opacity:1} }
@keyframes cardTapA { 0%{transform:scale(1)} 30%{transform:scale(.955)} 65%{transform:scale(1.02)} 100%{transform:scale(1)} }
@keyframes deckPop { from{opacity:0;transform:translateY(-7px) scale(.96)} to{opacity:1;transform:none} }
@keyframes cardTapB { 0%{transform:scale(1)} 30%{transform:scale(.955)} 65%{transform:scale(1.02)} 100%{transform:scale(1)} }
@keyframes rippleGo { from{transform:scale(0);opacity:.5} to{transform:scale(2.7);opacity:0} }
@keyframes flashGo { from{opacity:.45} to{opacity:0} }
@keyframes hlbeat { 0%{transform:scale(1)} 40%{transform:scale(1.25)} 100%{transform:scale(1)} }
@keyframes hlbeat2 { 0%{transform:scale(1)} 40%{transform:scale(1.25)} 100%{transform:scale(1)} }
@keyframes hlfade { from{opacity:0} to{opacity:1} }
@keyframes focusDockIn { from{ opacity:0; transform:translateY(10px); } to{ opacity:1; transform:none; } }
@keyframes focusMenuRise { from{ opacity:0; transform:translateY(10px) scale(.97); } to{ opacity:1; transform:none; } }

/* ===================================== NEW SURFACES ===================================== */

/* ---------- page- : the page column (App v3 L130–131). position: relative = the containing block of the page's dims
   (.page-dim boxes, the dim- section — tidy rounds 2 + 3). It must never become a stacking context (no z-index,
   transform, opacity, filter, isolation, contain, will-change): each dim's z sits between the layers' in the root
   context. ---------- */
.page { position: relative; background: var(--bg); min-height: calc(100vh / var(--zf, 1)); padding: 40px clamp(12px, 2.6vw, 34px) 20px; display: flex; flex-direction: column; gap: 22px; }
.page-col { width: 100%; max-width: 1240px; margin: 0 auto; }
.page-main { display: block; }

/* ---------- demo- : the demo banner (L132–140). #demoNotice keeps the .visible mechanism. The greens are
   App v3 LITERALS on purpose: the strip stays light green in dark mode too (--go-ink on #e7f3ea = 10.2:1). ---------- */
.demo-banner { display: none; align-items: center; justify-content: center; gap: 14px; flex-wrap: wrap; background: #e7f3ea; border: 1px solid #b5d9c2; border-radius: 14px; padding: 10px 16px; margin-bottom: 14px; }
.demo-banner.visible { display: flex; }
.demo-msg { font-size: 14px; font-weight: 800; color: var(--go-ink); }
.demo-actions { display: inline-flex; gap: 8px; align-items: center; }
.demo-fresh { background: transparent; border: 1px solid #9cc7ab; border-radius: 999px; padding: 7px 14px; font-size: 13px; font-weight: 800; color: var(--go-ink); cursor: pointer; white-space: nowrap; }
.demo-signup { background: var(--go); color: var(--on-solid); /* App v3 #fff — fills rule */ border: none; border-radius: 999px; padding: 8px 15px; font-size: 13px; font-weight: 900; white-space: nowrap; cursor: pointer; }

/* ---------- hdr- : the header (top wrap t5.topWrapStyle 4068; brand row 4069–4077; wordmark L263–266) ---------- */
.hdr { position: relative; display: flex; flex-direction: column; gap: 14px; margin-bottom: 18px; z-index: 100; /* --z-sticky */ transition: opacity .2s ease; }
@media (min-width: 1100px) { .hdr { gap: 11px; margin-bottom: 15px; } }
/* NARROW with the account menu open: the menu is a fixed bottom sheet INSIDE the header, so drop the header's
   stacking context and let the sheet (z 1000) rise over the fixed chrome (the Select bar, the rail, the focus dock — 100).
   App v3: zIndex 'auto' when _narrow() && _anyMenuOpen(). shell.js toggles .hdr--menu-open; the :has()
   twin is a separate rule so an old browser that cannot parse :has() still keeps the class rule. */
@media (max-width: 639.98px) { .hdr.hdr--menu-open { z-index: auto; } }
@media (max-width: 639.98px) { .hdr:has(.acct-menu.visible) { z-index: auto; } }

.hdr-row { display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 14px; }
.hdr-greet { justify-self: start; }
.hdr-greet-inner { text-align: left; line-height: 1.2; }
.hdr-greeting { font-size: 16px; font-weight: 800; color: var(--ink2); }
.hdr-date { font-size: 12px; font-weight: 800; letter-spacing: .08em; text-transform: uppercase; color: var(--muted2-text); /* d11 */ margin-top: 3px; white-space: nowrap; }
.hdr-utils { display: flex; align-items: center; gap: 10px; justify-self: end; }
@media (max-width: 639.98px) {
  .hdr-row { display: flex; flex-direction: column; align-items: center; gap: 12px; }
  .hdr-greet { display: none; }
}

.hdr-brand { min-width: 0; text-align: center; }
.hdr-h1 { font: inherit; margin: 0; }            /* = App v3's plain <div>: Nunito 16px / normal line box */
.hdr-wordmark { display: inline-flex; align-items: center; gap: 7px; font-family: 'Lora', serif; font-weight: 700; font-size: 38px; letter-spacing: -.015em; color: var(--ink); line-height: 1.05; text-decoration: none; }
.hdr-wordmark:visited { color: var(--ink); text-decoration: none; } @media (hover: hover) { .hdr-wordmark:hover { color: var(--ink); text-decoration: none; } }   /* App v3's inline style beats the global a:hover */
.hdr-sun { width: 42px; height: 42px; border-radius: 50%; background: radial-gradient(circle at 50% 40%, var(--gold-hi), var(--gold)); box-shadow: 0 6px 18px rgba(227,153,13,.34); flex: none; }
.hdr-name { display: inline-flex; align-items: baseline; }
.hdr-sol { color: var(--gold); }                 /* a logotype — WCAG 1.4.3 exempts logo text */
.hdr-sub { font-size: 13.5px; font-weight: 800; letter-spacing: .14em; color: var(--muted2-text); /* d11 */ text-transform: uppercase; margin-top: 8px; }

/* round utility buttons (L268–273; t5.howBtnStyle 4076, howQStyle 4077) */
.hdr-btn { background: var(--card); border: 1px solid var(--border); border-radius: 999px; width: 40px; height: 40px; padding: 0; cursor: pointer; color: var(--ink2); display: grid; place-items: center; flex: none; }
.hdr-q { color: var(--ink2); font-size: 17px; font-weight: 800; line-height: 1; }
/* the mode toggle's two icons swap on body[data-mode] — right from first paint (theme-boot sets it) */
.hdr-ico-sun { display: none; }
body[data-mode="dark"] .hdr-ico-sun { display: block; }
body[data-mode="dark"] .hdr-ico-moon { display: none; }

/* ---------- acct- : the account menu (L272–291; acctMenuStyle 4153 = _menuCss 3257–3264, the numbers
   popover.js menuGeometry pins). >= 640: an anchored popover; NARROW: a bottom sheet with a drag handle. ---------- */
.acct-wrap { position: relative; }
/* _menuCss({ align:'right', top:'46px', fixedW:250, anchored:true }) → overflow visible, no max-height */
.acct-menu { display: none; position: absolute; top: 46px; right: 0; width: 250px; z-index: 40; /* --z-menu */ background: var(--card); border: 1px solid var(--border2); border-radius: 14px; padding: 8px; overflow: visible; box-shadow: 0 12px 30px rgba(0,0,0,.18); animation: menuIn .16s ease; text-align: left; }
.acct-menu.visible { display: block; }
/* NARROW: _menuCss({ fixedW:250, sheet:true }) (fixedW ignored in the sheet branch). The handle is the global [data-sheet]::before. */
@media (max-width: 639.98px) {
  .acct-menu { position: fixed; left: 0; right: 0; bottom: 0; top: auto; transform: none; z-index: 1000; /* --z-overlay */ width: 100%; max-width: none; max-height: calc(72dvh / var(--zf, 1)); overflow: auto; overscroll-behavior: contain; padding: 8px 8px calc(8px + env(safe-area-inset-bottom, 0px)); border-radius: 18px 18px 0 0; border-bottom: none; animation: sheetUp .22s ease; box-shadow: 0 -18px 50px rgba(0,0,0,.34); }
}

/* head (L276–282) */
.acct-head { display: flex; align-items: center; gap: 11px; padding: 8px 8px 12px; border-bottom: 1px solid var(--hair); margin-bottom: 6px; }
.acct-avatar { width: 38px; height: 38px; border-radius: 999px; background: var(--chip); flex: none; display: grid; place-items: center; color: var(--ink2); }
.acct-who { min-width: 0; padding-right: 6px; }
.acct-signed { font-size: 12px; font-weight: 800; letter-spacing: .09em; text-transform: uppercase; color: var(--muted2-text); /* d11 */ margin-bottom: 3px; }
.acct-email { font-size: 13px; font-weight: 700; color: var(--ink); line-height: 1.3; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* items (L283–288; style-hover="background:var(--chip);") */
.acct-item { display: flex; align-items: center; gap: 11px; width: 100%; text-align: left; background: none; border: none; cursor: pointer; color: var(--ink); font-size: 14px; font-weight: 700; padding: 10px 8px; border-radius: 10px; }
@media (hover: hover) { .acct-item:hover { background: var(--chip); } }
.acct-item--strong { font-weight: 800; }
.acct-ico { width: 16px; height: 16px; flex: none; color: var(--ink2); }
.acct-divider { border-top: 1px solid var(--hair); margin: 6px 0; }
@media (pointer: coarse) { .acct-item { min-height: 44px; } }   /* 39-px rows → 44 on touch (a11y — LABELLED) */

/* the menu's outside-press catcher (popover.js #popCatcher, a <body> child): TRANSPARENT at every width and in every
   form (z 35 = menu − 5, under the header's 100 — App v3 L141 / 4156). The --dim form (a narrow NON-anchored menu
   sheet: the focus tray, the dock menu) only NAMES its dim (--layer-dim = App v3's .42): js/page-dim.js paints it on
   the page (a .page-dim box, z 89 — the dim- section, tidy round 2), so iPhone Safari finds no tinted fixed box at the top
   edge. No fade (mobile pass ruling 4 — LABELLED: App v3 faded it in): the dim is at full strength from its first frame. */
.ov-menu-catcher { position: fixed; inset: 0; z-index: 35; background: transparent; }
.ov-menu-catcher--dim { z-index: 90; /* --z-scrim-low */ --layer-dim: var(--scrim-menu); }

/* ---------- sw- : the Counter | Gallery switch (L311–316; navOn / navOff 3873–3874) ---------- */
.sw-row { display: flex; justify-content: center; }
.sw-track { display: flex; gap: 6px; background: var(--switchbg); border-radius: 999px; padding: 6px; box-shadow: inset 0 0 0 1px color-mix(in oklab, var(--ink) 8%, transparent); }
.sw-tab { display: inline-flex; align-items: center; justify-content: center; gap: 7px; padding: 11px 24px; border-radius: 999px; cursor: pointer; font-weight: 800; font-size: 14.5px; border: none; background: transparent; color: var(--switch-text-off); /* d11 — App v3 var(--muted) */ }
.sw-tab[aria-selected="true"] { background: var(--solid); color: var(--on-solid); box-shadow: 0 3px 10px rgba(60,56,48,.22); }
.sw-tab svg { flex: none; }

/* ---------- gal- : the Gallery placeholder until step 10 — App v3's calm card (the Patterns placeholder:
   radius 18, --card, 1px --border, min-height 360, Lora 26/700 title, Lora 16/500 body, 36ch) ---------- */
.gal { padding-top: 4px; }
.gal-card { background: var(--card); border: 1px solid var(--border); border-radius: 18px; min-height: 360px; display: grid; place-items: center; padding: 44px 24px; text-align: center; animation: ovfade .4s ease; /* artWrapStyle: ovfade .4s when the Gallery shows */ }
.gal-inner { max-width: 36ch; display: flex; flex-direction: column; gap: 14px; align-items: center; }
.gal-title { font-family: 'Lora', serif; font-size: 26px; font-weight: 700; line-height: 1.2; color: var(--ink); }
.gal-lead { font-family: 'Lora', serif; font-size: 16px; font-weight: 500; line-height: 1.55; color: var(--ink3); text-wrap: pretty; margin: 0; }
.gal-soon { font-size: 13px; font-weight: 700; color: var(--muted-text); /* d11 */ }

/* ---------- ov- / sheet- : the generic sheet chrome every overlay.js SHEET uses (scrim t5.scrimStyle 4157,
   sheetFix 4160). The scrim goes display:none → flex, so the panel's popup (sheetUp on a phone) replays on every
   open. Every backdrop ROOT (.ov-scrim and its .home- / .rec- / .acs-dlg- forms, .dlg-scrim, .share-scrim, .fb-scrim,
   the dim catcher) is TRANSPARENT and only names its dim (--layer-dim: var(--scrim…)) — tidy round 2, the owner's
   iPhone lab E, round 3: js/page-dim.js paints every open layer's dim on the page (.page-dim boxes, each one z below
   its layer, so a covering layer's dim lies over the covered one) — the dim- section at the end; there too, no root is
   a scroll container on a phone (its panel scrolls itself). The dim does NOT fade (mobile pass ruling 4 — LABELLED:
   App v3 ovfade .18s): it is at full strength from its first frame — iPhone Safari 26 colours its status strip and
   bottom bar from what it finds at each edge when a layer is added and skips a box under opacity .1, so a fading dim
   left the strips the page colour and they changed late. The auth modal (.auth-scrim) keeps its own tint (see there).
   scripts/mobile-css.test.mjs pins it. ---------- */
.ov-scrim { --layer-dim: var(--scrim); display: none; position: fixed; inset: 0; z-index: 900; /* --z-scrim */ background: transparent; justify-content: center; align-items: center; padding: 64px 20px; overflow: auto; overscroll-behavior: contain; }
.ov-scrim.visible { display: flex; }
@media (max-width: 639.98px) { .ov-scrim { align-items: flex-end; padding: 0 0 env(safe-area-inset-bottom, 0px); } }

.sheet { background: var(--panel); border-radius: 18px; box-shadow: 0 24px 60px rgba(0,0,0,.3); animation: popup .24s cubic-bezier(.22,1,.36,1); overflow: hidden; max-width: 100%; }
@media (max-width: 639.98px) { .sheet { width: 100%; max-width: none; max-height: calc(88vh / var(--zf, 1)); max-height: calc(88dvh / var(--zf, 1)); border-radius: 18px 18px 0 0; } }

/* header row: eyebrow + Lora title + round × (the 12-px gap is a site addition so a long title never touches the ×) */
.sheet-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 18px 20px 12px; }
.sheet-headtext { min-width: 0; }
.sheet-eyebrow { font-size: 10.5px; font-weight: 800; letter-spacing: .1em; text-transform: uppercase; color: var(--muted2-text); /* d11 */ line-height: normal; }
.sheet-title { font-family: 'Lora', serif; font-size: 20px; font-weight: 700; color: var(--ink); line-height: normal; }
.sheet-x { background: var(--chip2); border: none; border-radius: 999px; width: 30px; height: 30px; padding: 0; cursor: pointer; color: var(--ink2); font-size: 17px; font-weight: 800; display: grid; place-items: center; flex: none; }
.sheet-body { flex: 1; overflow: auto; padding: 0 22px 24px; }

/* ---------- how- : How it works (L1451–1497) ---------- */
.how-sheet { width: 560px; max-height: calc(82dvh / var(--zf, 1)); display: flex; flex-direction: column; }
.how-head { padding: 18px 22px 12px; }
@media (max-width: 639.98px) {
  /* width restated: .how-sheet comes after .sheet's NARROW rule; padding-top = room for the handle */
  .how-sheet { width: 100%; max-height: calc(88dvh / var(--zf, 1)); padding-top: 8px; }
  .how-head { padding-top: 0; }
}
.how-p { font-size: 14px; font-weight: 600; color: var(--ink2); line-height: 1.55; }
.how-list { margin: 0; padding-left: 20px; list-style: disc; display: flex; flex-direction: column; gap: 6px; }   /* the owner's How it works text (2026-10-03): two short bullet lists */
.how-list > li::marker { color: var(--muted2); }
.how-mb16 { margin-bottom: 16px; }
.how-mb14 { margin-bottom: 14px; }
.how-label { font-size: 12px; font-weight: 800; letter-spacing: .1em; color: var(--muted2-text); /* d11 */ text-transform: uppercase; line-height: normal; margin-bottom: 8px; }
.how-ex { background: var(--surface); border-radius: 14px; padding: 16px 18px; margin-bottom: 16px; }
.how-ex-eyebrow { font-size: 10.5px; font-weight: 800; letter-spacing: .09em; text-transform: uppercase; color: var(--muted2-text); /* d11 */ margin-bottom: 12px; }
.how-ex-rows { display: flex; flex-direction: column; gap: 10px; }
.how-ex-row { display: flex; align-items: center; gap: 12px; }
.how-ex-time { flex: none; font-size: 11.5px; font-weight: 800; color: var(--muted-text); /* d11 */ width: 64px; font-variant-numeric: tabular-nums; }
.how-ex-text { flex: 1; min-width: 0; font-size: 13.5px; font-weight: 700; color: var(--ink2); line-height: 1.4; }
.how-ex-badge { flex: none; font-size: 11px; font-weight: 900; color: var(--on-solid); /* App v3 #fff — fills rule */ background: var(--go); border-radius: 999px; padding: 2px 9px; }
.how-ex-total { display: flex; align-items: center; justify-content: flex-end; gap: 8px; margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--hair); }
.how-ex-total-label { font-size: 12px; font-weight: 700; color: var(--muted-text); /* d11 */ }
.how-ex-total-val { font-size: 13px; font-weight: 900; color: var(--go); }

/* ---------- hist- : the History sheet (App v3 L921–1019; histFiltersBtnStyle 3972, histTimeChips 3962,
   histSortChips 3969, _histCatData 2959, _histDaysRv 3601, _tickCss). The panel rides overlay.js as a
   [data-sheet] (step 3 adds the handle + drag App v3's History lacks). In-sheet popovers (Filters, Move to…)
   are App v3's pattern: a transparent fixed click-away at z 40 + the panel at z 41, both inside the scrim's
   stacking context — NOT popover.js. ---------- */
/* panel: App v3 width 620, max-height 82 dvh (divided by the zoom — see the zoom steps), flex column (the body scrolls) */
.hist-sheet { width: 620px; max-height: calc(82dvh / var(--zf, 1)); display: flex; flex-direction: column; }
.hist-head { padding: 18px 20px 14px; }                        /* App v3 924 (the generic head has 12 px below) */
@media (max-width: 639.98px) {
  /* width restated: .hist-sheet comes after .sheet's NARROW rule; padding-top = room for the handle (= .how-sheet) */
  .hist-sheet { width: 100%; max-height: calc(88dvh / var(--zf, 1)); padding-top: 8px; }
  .hist-head { padding-top: 0; }
}
/* LABELLED DEVIATION (site): App v3's panel clips an in-sheet popover at its own bottom edge (overflow:hidden),
   and a filter stays open after a pick — so on a short list (a When pick that matches nothing) the Filters
   panel's Category / Hide archived / Clear all rows, or the Move to… calendar, were cut off. While either
   is open the sheet keeps room for it; closed, the sheet sizes to its list exactly as App v3. */
.hist-sheet:has(.hist-pop:not([hidden])),
.hist-sheet:has(.dp-pop:not([hidden])) { min-height: min(520px, calc(82dvh / var(--zf, 1))); }
@media (max-width: 639.98px) {
  .hist-sheet:has(.hist-pop:not([hidden])),
  .hist-sheet:has(.dp-pop:not([hidden])) { min-height: min(640px, calc(88dvh / var(--zf, 1))); }   /* the taller touch targets + the wrapped Select bar */
}

/* search (928–930) */
.hist-search { padding: 0 20px 12px; }
/* LABELLED DEVIATION: 16 px (App v3 14.5) — iOS Safari zooms the page on focus of any field under 16 px (the auth-input rule).
   Its focus: the field rule (the ring- section — no outside ring, an ink border inside). */
.hist-search-input { display: block; width: 100%; border: 1px solid var(--border); border-radius: 10px; padding: 9px 13px; /* 10 → 9 keeps App v3's box height with the larger type */ font-size: 16px; font-weight: 600; color: var(--ink); background: var(--card); -webkit-appearance: none; appearance: none; }
.hist-search-input::placeholder { color: var(--muted-text); /* d11 — App v3 leaves the UA placeholder colour */ opacity: 1; }
.hist-search-input::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; }   /* App v3's field has no ×; the UA one would add a second control */

/* toolbar (931–948) */
.hist-toolbar { padding: 0 20px 10px; display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.hist-filters-wrap { position: relative; display: inline-flex; }
.hist-filters-btn { display: inline-flex; align-items: center; gap: 7px; background: var(--card); border: 1px solid var(--border); border-radius: 999px; padding: 6px 13px; font-size: 13px; font-weight: 800; color: var(--ink2); cursor: pointer; }
/* hot = the popover is open OR any filter is active (histFiltersBtnStyle 3972) */
.hist-filters-btn.is-hot, .hist-filters-btn[aria-expanded="true"] { background: var(--chip); border-color: var(--ink2); }
.hist-badge { background: var(--ink2); color: var(--on-solid); border-radius: 999px; min-width: 18px; height: 18px; padding: 0 5px; font-size: 11px; font-weight: 900; display: inline-grid; place-items: center; }
.hist-chev { opacity: .7; flex: none; }
.hist-select-btn { margin-left: auto; background: var(--card); border: 1px solid var(--border); border-radius: 999px; padding: 6px 13px; font-size: 13px; font-weight: 800; color: var(--ink2); cursor: pointer; }

/* the Filters popover (935–936) */
.hist-away { position: fixed; inset: 0; z-index: 40; background: transparent; }
.hist-pop { position: absolute; top: calc(100% + 8px); left: 0; z-index: 41; width: min(440px, calc(100vw - 56px)); background: var(--panel); border: 1px solid var(--border2); border-radius: 16px; box-shadow: 0 16px 42px rgba(60,56,48,.22); padding: 14px 15px; text-align: left; }
.hist-pop-label { font-size: 11px; font-weight: 800; letter-spacing: .08em; color: var(--muted2-text); /* d11 */ text-transform: uppercase; margin: 0 0 7px; line-height: normal; }
.hist-seg-wrap { margin-bottom: 13px; }
.hist-seg { display: inline-flex; max-width: 100%; overflow-x: auto; background: var(--chip); border-radius: 999px; padding: 3px; scrollbar-width: none; }
.hist-seg::-webkit-scrollbar { display: none; }               /* the When track scrolls at 375 — no bar (App v3's [data-tagscroll]) */
/* The week range (?week= from the weekly email — copy handoff 2026-10-10, E2): its button makes SIX in the When track,
   more than the 440-px popover holds. With a mouse the track wraps to a second row (the scrolling track has no bar,
   and a wheel cannot reach "This month"); touch keeps the one row it scrolls with a finger. */
@media (pointer: fine) { .hist-seg:has(> #recentEntriesWhenRange) { flex-wrap: wrap; border-radius: 20px; } }
.hist-seg-btn { flex: none; padding: 6px 13px; border-radius: 999px; cursor: pointer; font-weight: 800; font-size: 13px; white-space: nowrap; border: none; background: transparent; color: var(--muted-text); /* d11 */ }
.hist-seg-btn[aria-pressed="true"] { background: var(--card); color: var(--ink); box-shadow: 0 1px 3px rgba(0,0,0,.14); }
.hist-seg-btn--sort { padding: 5px 12px; }
.hist-seg-btn--sort[aria-pressed="true"] { box-shadow: 0 1px 3px rgba(0,0,0,.08); }
/* category chips (942, _histCatData 2959) — the strip masks its scrolled edge (tagFadeRef 4097; history.js sets is-scrolled-l/r) */
.hist-cats { display: flex; gap: 6px; overflow-x: auto; padding-bottom: 2px; margin-bottom: 13px; scrollbar-width: none; }
.hist-cats::-webkit-scrollbar { display: none; }
.hist-cats.is-scrolled-l { -webkit-mask-image: linear-gradient(to right, transparent 0, #000 18px, #000 100%); mask-image: linear-gradient(to right, transparent 0, #000 18px, #000 100%); }
.hist-cats.is-scrolled-r { -webkit-mask-image: linear-gradient(to right, #000 0, #000 calc(100% - 18px), transparent 100%); mask-image: linear-gradient(to right, #000 0, #000 calc(100% - 18px), transparent 100%); }
.hist-cats.is-scrolled-l.is-scrolled-r { -webkit-mask-image: linear-gradient(to right, transparent 0, #000 18px, #000 calc(100% - 18px), transparent 100%); mask-image: linear-gradient(to right, transparent 0, #000 18px, #000 calc(100% - 18px), transparent 100%); }
.hist-chip { display: inline-flex; align-items: center; gap: 6px; padding: 5px 12px; border-radius: 999px; cursor: pointer; font-weight: 800; font-size: 13px; white-space: nowrap; border: 1px solid var(--border); background: var(--card); color: var(--ink2); flex: none; }
.hist-chip-dot { width: 8px; height: 8px; border-radius: 999px; flex: none; background: var(--muted3); }   /* history.js sets the category hex inline */
/* active: "All" = the ink fill; a category chip = its hex (history.js sets background / border / text colour inline) */
.hist-chip[aria-pressed="true"] { border-color: var(--ink); background: var(--ink); color: var(--on-solid); }
/* App v3 turns the dot #fff on an active chip → the chip's own text colour; !important beats the dot's inline hex */
.hist-chip[aria-pressed="true"] .hist-chip-dot { background: currentColor !important; }
/* the segment tracks and the chip strip clip overflow (they scroll): the focus ring goes inside so it is never cut */
.hist-seg-btn:focus-visible, .hist-chip:focus-visible { outline-offset: -2px; }
/* Hide archived — the site's session-only toggle (no App v3 twin; App v3's small-caps label + chip type) */
.hist-check { display: inline-flex; align-items: center; gap: 8px; font-size: 13px; font-weight: 800; color: var(--ink2); cursor: pointer; }
/* Hide archived: App v3 has no native checkbox — its one check control is the round _tickCss tick (the
   .hist-tick recipe), so the input is drawn as that tick: a ring on the card, the ink fill + ✓ when checked
   (a native box would paint a white square on the dark popover). Still a real checkbox (label, Space, :checked). */
.hist-check input { -webkit-appearance: none; appearance: none; flex: none; width: 20px; height: 20px; margin: 0; box-sizing: border-box; border-radius: 999px; border: 1.5px solid var(--border2); background: var(--card); display: inline-grid; place-items: center; cursor: pointer; transition: background .12s ease, border-color .12s ease; }
.hist-check input::before { content: "\2713"; font-size: 11px; font-weight: 900; line-height: 1; color: transparent; }
.hist-check input:checked { background: var(--ink); border-color: var(--ink); }
.hist-check input:checked::before { color: var(--card); }
.hist-clear { display: block; margin-top: 14px; background: none; border: none; color: var(--danger); font-size: 13px; font-weight: 800; cursor: pointer; padding: 2px; }

/* the Select bar (956–982) — a direct child of the panel, OUTSIDE #recentEntriesList */
.hist-selbar { margin: 0 20px 10px; display: flex; align-items: center; gap: 9px; flex-wrap: wrap; background: var(--card); border: 1px solid var(--border2); border-radius: 14px; padding: 9px 12px; box-shadow: 0 6px 18px rgba(60,56,48,.07); }
.hist-sel-count { font-size: 13.5px; font-weight: 900; color: var(--ink); }
.hist-pill-btn { background: var(--card); border: 1px solid var(--border); border-radius: 999px; padding: 6px 12px; font-size: 13px; font-weight: 800; color: var(--ink2); cursor: pointer; }
.hist-mv { position: relative; display: inline-flex; align-items: center; }
.hist-mv-btn { display: inline-flex; align-items: center; gap: 6px; }
.hist-danger-btn { background: var(--card); border: 1px solid var(--danger); border-radius: 999px; padding: 7px 14px; font-size: 13px; font-weight: 800; color: var(--danger); cursor: pointer; }
.hist-cancel-btn { margin-left: auto; background: none; border: none; padding: 1px 6px; /* App v3 sets none → the UA's */ font-size: 13px; font-weight: 800; color: var(--muted-text); /* d11 */ cursor: pointer; }
/* LABELLED (site): Move to… / Delete wait for a tick (App v3 keeps them live and toasts "Select some entries first") */
.hist-pill-btn:disabled, .hist-danger-btn:disabled { opacity: .45; cursor: default; transform: none; filter: none; }

/* body + day groups (983–990) */
.hist-body { flex: 1; overflow: auto; overscroll-behavior: contain; padding: 0 20px 20px; }  /* overrides .sheet-body's 0 22px 24px */
.hist-note { text-align: center; color: var(--muted2-text); /* d11 */ font-weight: 700; padding: 40px 0; }
.hist-day { margin-bottom: 16px; }
.hist-day-head { display: flex; align-items: baseline; gap: 9px; margin: 0 2px 7px; }
.hist-day-label { font-size: 13.5px; font-weight: 800; color: var(--ink); }
.hist-day-count { font-size: 11.5px; font-weight: 700; color: var(--muted2-text); /* d11 */ }
.hist-card { background: var(--surface); border: 1px solid var(--border2); border-radius: 14px; overflow: hidden; }
.hist-hair { height: 1px; background: var(--hair); margin: 0 14px; }

/* rows (992–1009 + App v3's globals [data-hrow] / [data-hrow] button, L78–79) */
.hist-row { display: flex; align-items: center; gap: 10px; padding: 0 14px 0 12px; border-radius: 10px; }
@media (hover: hover) { .hist-row:hover { background: var(--soft); } }
.hist-row button { border-radius: 9px; }
/* the Select tick = _tickCss(on, 'var(--ink)') */
.hist-row .hist-tick { flex: none; width: 20px; height: 20px; border-radius: 999px; box-sizing: border-box; display: grid; place-items: center; font-size: 11px; font-weight: 900; line-height: 1; padding: 0; cursor: pointer; background: transparent; color: transparent; border: 1.5px solid var(--border2); transition: background .12s ease, border-color .12s ease, color .12s ease; }
.hist-row .hist-tick[aria-checked="true"] { background: var(--ink); color: var(--card); border-color: var(--ink); }
.hist-row-btn { flex: 1; min-width: 0; display: flex; align-items: center; gap: 12px; padding: 11px 0; background: none; border: none; cursor: pointer; text-align: left; color: inherit; }
.hist-row-btn:focus-visible { outline-offset: -2px; }          /* the card clips overflow: the ring goes inside so the first / last row keep all four sides */
.hist-time { flex: none; min-width: 60px; text-align: right; font-size: 13px; font-weight: 700; color: var(--muted-text); /* d11 */ font-variant-numeric: tabular-nums; white-space: nowrap; }
.hist-dot { width: 9px; height: 9px; border-radius: 999px; flex: none; background: var(--muted3); }   /* history.js sets the category hex inline; none = no live category */
.hist-col { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.hist-name-line { display: flex; align-items: center; min-width: 0; gap: 6px; }
.hist-name { min-width: 0; font-size: 13px; font-weight: 700; color: var(--ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* the ×N fold — a SITE feature (App v3 lists one row per start); the class name stays for the e2e tests */
.hist-row .entry-count { flex: none; font-size: 10.5px; font-weight: 900; letter-spacing: .02em; color: var(--ink2); background: var(--chip2); border-radius: 999px; padding: 1px 7px; line-height: 1.5; }
.hist-meta { display: flex; align-items: baseline; min-width: 0; overflow: hidden; }
.hist-cat { flex: none; max-width: 62%; font-size: 11.5px; font-weight: 700; color: var(--muted2-text); /* d11 */ white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.hist-pill { margin-left: 7px; flex: none; font-size: 9.5px; font-weight: 900; letter-spacing: .05em; text-transform: uppercase; border-radius: 999px; padding: 1px 7px; white-space: nowrap; border: 1px solid var(--border); background: var(--chip); }
.hist-cat:empty { display: none; }                               /* an orphan row whose snapshot has no category */
.hist-cat:empty + .hist-pill, .hist-meta > .hist-pill:first-child { margin-left: 0; }
/* unlinked: App v3's literals #8a6a2a / #f1ecdd / #e2dcc9 tokenised (G4 §1.6) — 5.47:1 light, 7.18:1 dark on --chip.
   archived: the site's second pill (App v3 has none), the same chip in the muted text. */
.hist-row .entry-unlinked { color: color-mix(in oklab, var(--accent) 60%, var(--ink)); }
.hist-row .entry-archived { color: var(--muted-text); /* d11 */ }
.hist-note-text { flex: 1 1 auto; min-width: 0; font-size: 12px; font-weight: 600; color: var(--muted-text); /* d11 */ white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* the row's › door to the activity home (App v3 1007, its CSS L115–117 [data-hrow] [data-histchev]); history.js renders it
   only when the row's activity is on the board, never in Select mode. Opacity .4, .85 on row hover, .55 on touch. */
.hist-row .hist-door { flex: none; display: grid; place-items: center; width: 34px; height: 34px; border-radius: 999px; background: none; border: none; cursor: pointer; color: var(--muted2); /* glyph — verbatim token */ font-size: 16px; line-height: 1; padding: 0; opacity: .4; transition: opacity .15s ease, background-color .12s ease, color .12s ease; }
@media (hover: hover) { .hist-row:hover .hist-door { opacity: .85; } }
@media (hover: hover) { .hist-row .hist-door:hover { background: var(--chip2); color: var(--ink2); } }
.hist-row .hist-door:focus-visible { opacity: 1; }
@media (hover: none) { .hist-row .hist-door { opacity: .55; } }

/* show more (1015) */
.hist-more-wrap { display: flex; justify-content: center; padding: 4px 0 10px; }
.hist-more { background: var(--card); border: 1px solid var(--border); border-radius: 999px; padding: 10px 20px; font-size: 13.5px; font-weight: 800; color: var(--ink2); cursor: pointer; }
@media (hover: hover) { .hist-more:hover { background: var(--chip); } }

/* 44-px targets on touch (G4 §1, contract ruling 10 — LABELLED: the look is unchanged on fine pointers) */
@media (pointer: coarse) {
  .hist-row-btn { min-height: 44px; }
  .hist-row .hist-tick { position: relative; }
  .hist-row .hist-tick::after { content: ""; position: absolute; inset: -12px; }
  .hist-filters-btn, .hist-select-btn, .hist-seg-btn, .hist-chip, .hist-pill-btn, .hist-danger-btn, .hist-cancel-btn, .hist-clear, .hist-check, .hist-more { min-height: 44px; }
}

/* ---------- dp- : the day picker (App v3 962–977, _dpDays 2972) — ONE calendar popover for History's Move to…
   and the record editor's Date row (js/day-picker.js). Same click-away pattern as the Filters popover. ---------- */
.dp-away { position: fixed; inset: 0; z-index: 40; background: transparent; }
.dp-pop { position: absolute; top: calc(100% + 7px); left: 0; z-index: 41; width: 252px; background: var(--panel); border: 1px solid var(--border2); border-radius: 14px; box-shadow: 0 16px 42px rgba(60,56,48,.22); padding: 13px; text-align: left; }
/* LABELLED DEVIATION: at 375 App v3's calendar runs off the right edge (measured x 201 + 252 > 375). On NARROW it
   hangs from the Select bar's right edge instead of the button, so it stays inside the viewport whichever line
   the wrapping bar puts Move to… on (the button's own right edge would push it off the LEFT edge at 320). */
@media (max-width: 639.98px) {
  .hist-selbar { position: relative; }
  .hist-mv { position: static; }
  .hist-mv .dp-pop { left: auto; right: 12px; }
}
.dp-nav { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; }
.dp-nav-btn { width: 26px; height: 26px; border: 1px solid var(--border); background: var(--surface); border-radius: 10px; cursor: pointer; color: var(--ink2); font-size: 15px; line-height: 1; display: grid; place-items: center; padding: 0; flex: none; }
@media (hover: hover) { .dp-nav-btn:hover { background: var(--chip); } }                 /* App v3 style-hover */
.dp-title { font-size: 14px; font-weight: 800; color: var(--ink); }
.dp-dows { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; margin-bottom: 3px; }
.dp-dow { text-align: center; font-size: 12px; font-weight: 800; letter-spacing: .02em; color: var(--muted2-text); /* d11 */ padding: 2px 0; }
.dp-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; }
.dp-blank { height: 30px; }
.dp-day { height: 30px; min-width: 0; border: 1.5px solid transparent; background: transparent; color: var(--ink); border-radius: 10px; font-size: 13.5px; font-weight: 600; cursor: pointer; display: grid; place-items: center; padding: 0; }
.dp-day.is-today, .dp-day[aria-current="date"] { border-color: var(--muted2); }   /* decorative ring — verbatim token */
.dp-day.is-sel, .dp-day[aria-pressed="true"] { background: var(--solid); color: var(--on-solid); font-weight: 800; border-color: transparent; }
/* LABELLED DEVIATION: a future day is disabled (contract ruling 3); App v3 draws it live and clamps the pick to today */
.dp-day.is-future, .dp-day:disabled { opacity: .35; cursor: default; }
.dp-day:disabled { transform: none; filter: none; }
@media (pointer: coarse) {
  .dp-blank, .dp-day { height: 36px; }                           /* 30 → 36: the 252-px grid can't take 44 (LABELLED) */
  .dp-nav-btn { width: 36px; height: 36px; position: relative; }
  .dp-nav-btn::after { content: ""; position: absolute; inset: -4px; }   /* 44-px hit area */
}

/* ---------- rec- : the record editor, "Edit start" (App v3 2241–2277; _recRv 2633 recScrim / recSheet /
   recSelStyle / recSegBtn). A centred 340-px card on wide, a bottom sheet with the drag handle on NARROW.
   The scrim is .ov-scrim (display, centring, overflow, transparent — no fade, mobile pass ruling 4) raised, naming its
   own dim (painted on the page by page-dim.js, over History's panel too — the dim- section). ---------- */
.rec-scrim { z-index: 1010; /* --z-nested: above the History sheet */ --layer-dim: var(--scrim-modal); /* App v3 recScrim rgba(30,28,24,.5) */ padding: 24px 20px; }
@media (max-width: 639.98px) { .rec-scrim { align-items: flex-end; padding: 0 0 env(safe-area-inset-bottom, 0px); } }   /* = .ov-scrim's NARROW rule (restated: .rec-scrim's padding comes later) */
.rec-sheet { width: 340px; max-width: 100%; background: var(--panel); border-radius: 20px; box-shadow: 0 24px 60px rgba(0,0,0,.34); padding: 18px; animation: popup .24s cubic-bezier(.22,1,.36,1); text-align: left; }
@media (max-width: 639.98px) { .rec-sheet { width: 100%; border-radius: 18px 18px 0 0; } }   /* App v3 keeps the 18-px padding; the handle ([data-sheet]::before) sits inside it */
.rec-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 12px; }
.rec-head .sheet-x { font-size: 16px; }                        /* App v3's editor × is 16 px (the sheets' is 17) */
.rec-headtext { min-width: 0; }
.rec-eyebrow { font-size: 10.5px; font-weight: 800; letter-spacing: .1em; text-transform: uppercase; color: var(--muted2-text); /* d11 */ line-height: normal; }
.rec-title { font-family: 'Lora', serif; font-size: 17px; font-weight: 700; color: var(--ink); line-height: normal; }
/* the unlinked / archived explanation on such a row (a site feature — App v3 has none) */
.rec-flag { font-size: 12px; font-weight: 700; color: var(--muted-text); /* d11 */ line-height: 1.4; margin: -4px 0 12px; }
.rec-label { font-size: 10px; font-weight: 800; letter-spacing: .09em; text-transform: uppercase; color: var(--muted2-text); /* d11 */ margin: 0 0 6px; line-height: normal; }
/* the Date row — the site's re-date (no App v3 twin), in the hour select's chrome */
.rec-date-wrap { position: relative; display: block; margin-bottom: 14px; }
.rec-date-btn { width: 100%; display: flex; align-items: center; justify-content: space-between; gap: 8px; background: var(--surface); border: 1px solid var(--border2); border-radius: 10px; padding: 9px 12px; font-size: 15px; font-weight: 800; color: var(--ink); cursor: pointer; text-align: left; }
.rec-date-btn:active { transform: none; }                      /* a full-width field, not a pill: no press-scale */
/* time: hour : minute + AM / PM (2249–2256) */
.rec-time { display: flex; align-items: center; gap: 7px; margin-bottom: 14px; }
.rec-sel { flex: 1 1 0; min-width: 0; -webkit-appearance: none; -moz-appearance: none; appearance: none; text-align: center; text-align-last: center; background: var(--surface); border: 1px solid var(--border2); border-radius: 10px; padding: 9px 10px; font-size: 15px; font-weight: 800; color: var(--ink); cursor: pointer; }
.rec-colon { font-size: 16px; font-weight: 900; color: var(--muted2); line-height: 1; }   /* decorative glyph (aria-hidden) — verbatim token */
.rec-ampm { display: flex; gap: 3px; background: var(--soft); border-radius: 11px; padding: 3px; flex: none; }
.rec-ampm-btn { min-width: 44px; padding: 8px 14px; border-radius: 8px; border: 1px solid transparent; background: transparent; color: var(--muted-text); /* d11 */ font-size: 13px; font-weight: 800; letter-spacing: .03em; cursor: pointer; }
.rec-ampm-btn[aria-pressed="true"] { border-color: var(--border); background: var(--surface); color: var(--ink); }
.rec-ampm-btn:disabled, .rec-sel:disabled { opacity: .45; cursor: default; }   /* the "—" (no time) state */
/* count stepper (2258–2265) */
.rec-count { display: flex; align-items: center; gap: 12px; margin-bottom: 13px; }
.rec-step { flex: none; width: 30px; height: 30px; border-radius: 8px; border: 1px solid var(--border2); background: var(--surface); cursor: pointer; font-size: 16px; font-weight: 800; color: var(--ink); display: grid; place-items: center; line-height: 1; padding: 0; }
.rec-step:disabled { opacity: .35; cursor: default; }
.rec-qty { font-size: 16px; font-weight: 900; color: var(--ink); font-variant-numeric: tabular-nums; min-width: 22px; text-align: center; }
/* note (2266–2267) */
.rec-note-btn { width: 100%; display: inline-flex; align-items: center; justify-content: center; gap: 7px; background: var(--soft); border: 1px dashed var(--border); border-radius: 12px; padding: 12px; font-size: 13.5px; font-weight: 800; color: color-mix(in oklab, var(--accent) 65%, var(--ink)); cursor: pointer; margin-bottom: 12px; }
/* LABELLED DEVIATION: 16 px (App v3 14) — the iOS zoom rule. Its focus: the field rule (the ring- section) */
.rec-note { display: block; width: 100%; min-height: 76px; font-size: 16px; font-weight: 600; color: var(--ink); background: var(--surface); border: 1px solid var(--border2); border-radius: 12px; padding: 11px 12px; resize: vertical; margin-bottom: 12px; }
.rec-note::placeholder { color: var(--muted-text); /* d11 */ opacity: 1; }
/* actions (2269–2273) */
.rec-actions { display: flex; gap: 8px; }
.rec-save { flex: 1; background: var(--accent); border: none; border-radius: 12px; padding: 12px; font-size: 14px; font-weight: 800; color: var(--on-solid); /* App v3 #fff — fills rule */ cursor: pointer; }
/* App v3 literals #d8b3a6 / #b5573c → tokens (G4 §1.6) */
.rec-delete { flex: none; background: none; border: 1px solid color-mix(in oklab, var(--danger) 35%, var(--border)); border-radius: 12px; padding: 12px 16px; font-size: 14px; font-weight: 800; color: var(--danger); cursor: pointer; }
.rec-cancel { display: block; width: 100%; background: none; border: none; padding: 9px; margin-top: 4px; font-size: 13.5px; font-weight: 800; color: var(--muted-text); /* d11 */ cursor: pointer; }
@media (pointer: coarse) {
  .rec-date-btn, .rec-sel, .rec-ampm-btn, .rec-note-btn, .rec-save, .rec-delete, .rec-cancel { min-height: 44px; }
  .rec-step { width: 36px; height: 36px; position: relative; }
  .rec-step::after { content: ""; position: absolute; inset: -4px; }   /* 44-px hit area */
  .rec-sel { font-size: 16px; }   /* phone ruling 1 (LABELLED): 15 → 16 on touch — iOS Safari zooms the page on focus of a field under 16 px */
}

/* ---------- home- : the activity / category HOME sheet (App v3 1886–2198; homeScrimStyle / homeSheetStyle / tabStyle
   2646, _homeRv / _homeOv2 2646–2707; js/home.js + js/home-settings.js). The WHOLE sheet scrolls (header and tabs
   scroll with the content — App v3). --hc = the subject's stored category hex and --hc-on = palette.onHex(--hc), both
   written on #homeSheet by home.js; every heat / bar / line colour derives from --hc (color-mix N% = App v3's
   rgba(col, N/100)). In-sheet popovers (category menu, colour popover) are App v3's pattern: a transparent fixed
   click-away .home-away at z 19 + the panel at z 20, inside the scrim's stacking context — NOT popover.js. ---------- */
/* scrim: .ov-scrim (display, fixed, centring, overflow, transparent — no fade, mobile pass ruling 4) naming its own dim — App v3 rgba(30,28,24,.42), padding 40 20 */
.home-scrim { --layer-dim: var(--scrim-menu); padding: 40px 20px; }
@media (max-width: 639.98px) { .home-scrim { align-items: flex-end; padding: 0; } }   /* the sheet's own padding carries the safe area */
/* the sheet IS the scroller (App v3: overflow auto on the panel). --hc / --hc-on defaults = App v3's fallback colour
   (#8a8578) until home.js writes the subject's — never seen once the home has rendered. */
.home-sheet { --hc: #8a8578; --hc-on: #ffffff; position: relative; width: 420px; max-width: 100%; max-height: calc(84dvh / var(--zf, 1)); height: min(calc(84dvh / var(--zf, 1)), 680px); display: flex; flex-direction: column; overflow: auto; overscroll-behavior: contain; background: var(--panel); border-radius: 20px; box-shadow: 0 24px 60px rgba(0,0,0,.3); padding: 16px 16px calc(20px + env(safe-area-inset-bottom, 0px)); animation: popup .24s cubic-bezier(.22,1,.36,1); text-align: left; }
@media (max-width: 639.98px) { .home-sheet { width: 100%; max-width: none; max-height: calc(90dvh / var(--zf, 1)); border-radius: 18px 18px 0 0; } }   /* the global [data-scrim] > * rule caps it at 88dvh (App v3 too — measured) */
/* Site deviation (owner, 2026-09-30): App v3 sizes the home to its content, so it jumped between tabs and an
   empty tab shrank it to a sliver. The home keeps ONE height (above: 84 dvh, at most 680 px — the tallest tabs fit;
   longer content scrolls inside it as before), the visible panel fills it, and an empty-state message sits centred. */
.home-sheet > * { flex-shrink: 0; }
.home-panel:not([hidden]) { flex: 1 0 auto; }
.home-panel:not([hidden]):has(> .home-muted-note:only-child, > .home-note:only-child, > .home-empty:only-child) { display: flex; flex-direction: column; justify-content: center; }
.home-head { display: flex; align-items: center; gap: 10px; margin-bottom: 12px; }
.home-dot { width: 26px; height: 26px; border-radius: 999px; background: var(--hc, var(--muted3)); flex: none; box-shadow: 0 1px 3px rgba(0,0,0,.16); }
.home-headtext { flex: 1 1 auto; min-width: 0; }
.home-kind { font-size: 10.5px; font-weight: 800; letter-spacing: .1em; text-transform: uppercase; color: var(--muted2-text); /* d11 */ line-height: normal; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.home-title { font-family: 'Lora', serif; font-size: 20px; font-weight: 700; color: var(--ink); line-height: 1.4; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.home-hbtn { flex: none; background: var(--chip2); border: none; border-radius: 999px; width: 30px; height: 30px; padding: 0; cursor: pointer; color: var(--ink2); display: grid; place-items: center; }
.home-x { font-size: 16px; font-weight: 800; }

/* tabs + panels (App v3 1899–1901, tabStyle 2646) */
.home-tabs { display: flex; gap: 4px; flex-wrap: wrap; border-bottom: 1px solid var(--hair); margin: 0 -2px 14px; padding: 0 2px 10px; }
.home-tab { padding: 7px 12px; border-radius: 999px; border: none; cursor: pointer; font-size: 12.5px; font-weight: 700; background: transparent; color: var(--muted-text); /* d11 (App v3 var(--muted)) */ }
/* LABELLED: App v3 writes #fff on the colour — onHex (--hc-on) is #fff for every swatch / palette colour (checked) */
.home-tab[aria-selected="true"] { font-weight: 800; background: var(--hc); color: var(--hc-on); }
.home-panel { animation: tabin .16s ease; }                   /* replays each time a panel is un-hidden (App v3 per-tab tabin) */
.home-panel:focus-visible { outline-offset: 4px; border-radius: 6px; }
.home-note, .home-muted-note { text-align: center; color: var(--muted2-text); /* d11 */ font-weight: 700; padding: 36px 12px; font-size: 13.5px; line-height: 1.5; }
.home-muted-note--small { padding: 14px 8px; font-size: 13px; }

/* Overview (App v3 1902–1982; _homeRv / _homeOv2). The dead 28d/12m/All switcher, runs grid and month bars are not built. */
.home-empty { text-align: center; padding: 24px 16px 26px; }
.home-empty-lead { font-family: 'Lora', serif; font-size: 16px; font-weight: 700; color: var(--ink); margin-bottom: 6px; }
.home-empty-msg { font-size: 13px; line-height: 1.55; color: var(--muted-text); /* d11 */ max-width: 290px; margin: 0 auto; }
.home-stats { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 10px 8px; margin-bottom: 14px; }
.home-stat { min-width: 0; }
.home-stat-k { font-size: 10px; font-weight: 900; letter-spacing: .06em; text-transform: uppercase; color: var(--muted2-text); /* d11 */ margin-bottom: 2px; line-height: normal; }
.home-stat-v { font-family: 'Lora', serif; font-size: 19px; font-weight: 700; color: var(--ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; line-height: normal; }
.home-ovtags { display: flex; flex-wrap: wrap; gap: 7px; margin-bottom: 14px; }
.home-ovtag { display: inline-flex; align-items: center; padding: 5px 11px; border-radius: 999px; background: var(--chip); border: 1px solid var(--border2); color: var(--ink2); font-size: 12px; font-weight: 700; white-space: nowrap; }
.home-winrow { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; margin: 0 0 4px; }
.home-label { display: block; font-size: 10px; font-weight: 800; letter-spacing: .06em; text-transform: uppercase; color: var(--muted2-text); /* d11 */ line-height: normal; }
.home-winrow .home-label { display: inline; }
.home-read { font-size: 12px; font-weight: 700; color: var(--muted-text); /* d11 */ white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 62%; }
/* the last-28-days spark (viewBox 286 × 34; the path geometry is home-model's) */
.home-spark { position: relative; touch-action: pan-y; border-radius: 4px; }
.home-spark:focus-visible, .home-year:focus-visible, .home-bars:focus-visible { outline-offset: 4px; }
/* Mobile pass ruling 2: a press on a chart never starts a text selection or the iOS callout (the charts only — never the
   read lines, which a person may copy). A tap reads a point (home.js). */
.home-spark, .home-year, .home-bars { -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; }
.home-spark-svg { width: 100%; height: auto; display: block; overflow: visible; }
.home-spark-area { fill: color-mix(in srgb, var(--hc) 12%, transparent); }   /* App v3 rgba(col,.12) */
.home-spark-line { fill: none; stroke: var(--hc); stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; stroke-dasharray: 1; }   /* pathLength="1" in the markup */
.home-spark-end { fill: var(--hc); }
/* hover / keyboard dot (homeSparkDotStyle): left / top in % set inline */
.home-spark-dot { position: absolute; width: 9px; height: 9px; border-radius: 999px; background: var(--hc); transform: translate(-50%, -50%); pointer-events: none; transition: left .12s cubic-bezier(.2,0,0,1), top .12s cubic-bezier(.2,0,0,1); box-shadow: 0 1px 3px rgba(0,0,0,.22); }
/* reveal: once per page load, the first Overview render with data (App v3 _ovSeen / hoAnim*) */
.home-ov.is-reveal .home-spark-area { animation: ovfade .5s ease both; }
.home-ov.is-reveal .home-spark-line { animation: sparkDraw .55s ease-out both; }
.home-ov.is-reveal .home-spark-end { animation: ovfade .3s ease both; }
.home-ov.is-reveal .home-year { animation: yearwipe .5s ease both; }
/* the 371-cell year heatmap (53 columns × 7 rows, week start from prefs) */
.home-label--year { margin: 15px 0 8px; }
.home-year { display: grid; grid-auto-flow: column; grid-template-rows: repeat(7, 1fr); grid-auto-columns: 1fr; gap: 1px; border-radius: 2px; touch-action: pan-y; }   /* phone ruling 7: a sideways finger scrubs the days (home.js), a vertical one scrolls the sheet — the .home-spark rule */
.home-yc, .share-wc { width: 100%; aspect-ratio: 1; border-radius: 1.5px; min-width: 4px; position: relative; background: var(--heat-empty); }
.home-yc { transition: transform .16s cubic-bezier(.2,.7,.2,1), box-shadow .16s ease, background-color .3s ease; }
/* YEAR_ALPHA [.05 .24 .42 .63 .85] — the heatmap, the share card's 13 weeks and both legends (level 0 = --heat-empty) */
.home-yc.l1, .share-wc.l1, .home-lg.l1 { background: color-mix(in srgb, var(--hc) 24%, transparent); }
.home-yc.l2, .share-wc.l2, .home-lg.l2 { background: color-mix(in srgb, var(--hc) 42%, transparent); }
.home-yc.l3, .share-wc.l3, .home-lg.l3 { background: color-mix(in srgb, var(--hc) 63%, transparent); }
.home-yc.l4, .share-wc.l4, .home-lg.l4 { background: color-mix(in srgb, var(--hc) 85%, transparent); }
.home-yc.is-future { background: transparent; }
/* App v3 style-hover on a cell; .is-cur = the keyboard cursor (site addition, same look) */
.home-yc.is-cur { transform: translateY(-2px) scale(1.45); z-index: 3; box-shadow: inset 0 0 0 1.5px var(--muted2), 0 2px 6px rgba(61,54,45,.16); border-radius: 2px; } @media (hover: hover) { .home-yc:hover { transform: translateY(-2px) scale(1.45); z-index: 3; box-shadow: inset 0 0 0 1.5px var(--muted2), 0 2px 6px rgba(61,54,45,.16); border-radius: 2px; } }
.home-yearfoot { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-top: 9px; font-size: 11px; font-weight: 700; color: var(--muted2-text); /* d11 */ }
.home-yread { color: var(--muted-text); /* d11 */ white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.home-legend { display: inline-flex; align-items: center; gap: 6px; flex: none; }
.home-lg { width: 10px; height: 10px; border-radius: 2px; display: inline-block; background: var(--heat-empty); }
/* weekday + time-of-day bars (_homeOv2 mkBar: 34-px box, bar height inline max(2, v/max·34) px) */
.home-bars2 { display: grid; grid-template-columns: 1fr 1fr; gap: 0 16px; margin-top: 15px; }
.home-barcol { min-width: 0; }
.home-barhead { font-size: 10px; font-weight: 800; letter-spacing: .06em; text-transform: uppercase; color: var(--muted2-text); /* d11 */ margin-bottom: 6px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; line-height: normal; }
.home-bars { display: flex; gap: 4px; }
.home-bars--tod { gap: 5px; }
.home-bcol { flex: 1 1 0; min-width: 0; position: relative; display: flex; flex-direction: column; }
.home-bbox { display: flex; align-items: flex-end; height: 34px; }
.home-bar { display: block; width: 100%; border-radius: 3px 3px 0 0; background: var(--hc); opacity: .8; transition: height .25s ease, filter .2s ease; }
.home-bcol.is-cur .home-bar { opacity: 1; filter: brightness(.9) saturate(1.12); } @media (hover: hover) { .home-bcol:hover .home-bar { opacity: 1; filter: brightness(.9) saturate(1.12); } }   /* App v3 [data-ovcol]:hover [data-ovbar]; .is-cur = the key / tap cursor (mobile pass ruling 2, the hover look) */
.home-blbl { display: block; margin-top: 4px; font-size: 9px; font-weight: 800; color: var(--muted2-text); /* d11 */ text-align: center; white-space: nowrap; overflow: hidden; line-height: normal; }
/* Activities (category home — every live activity, fix-v3-door ruling 2; App v3 listed the top five): a counted row =
   name · bar (width inline max(4, n/max·100) %) · count · ›; a quiet row (.is-quiet — no start in 28 days) is muted with
   its note in the bar's place. Both texts use --muted-text (AA on the panel AND the hover chip in both modes —
   light 5.11 / 4.75, dark 5.32 / 4.71; --muted2-text is 4.25 on the dark chip). The name column is
   clamp(112px, 46%, 172px) — a LABELLED deviation from App v3's fixed 112 px: this list is now the way into every
   activity home, and 112 px cut "Spend time with family" and "… friends" to the same "Spend time with …" (the column
   holds every one of the starter board's 141 names at 375 and on desktop; the bars still start in one line). A quiet row's
   name may grow past the column into the room its short note leaves, then ellipses; the note never shrinks. */
.home-label--top { margin: 15px 0 6px; }
.home-empty + .home-acts > .home-label--top { margin-top: 0; }   /* under the empty state: the box's own 26-px foot is the gap */
.home-toprow { --top-name-w: clamp(112px, 46%, 172px); display: flex; align-items: center; gap: 9px; width: 100%; border: none; background: transparent; border-radius: 8px; padding: 5px 6px; cursor: pointer; text-align: left; color: inherit; }
@media (hover: hover) { button.home-toprow:hover { background: var(--chip); } }
.home-top-name { flex: none; width: var(--top-name-w); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 12.5px; font-weight: 700; color: var(--ink); text-align: left; }
.home-toprow.is-quiet .home-top-name { flex: 0 1 auto; width: auto; min-width: var(--top-name-w); color: var(--muted-text); }
.home-top-note { flex: 1 0 auto; font-size: 12px; font-weight: 600; color: var(--muted-text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.home-top-track { flex: 1; min-width: 20px; display: block; }
.home-top-bar { display: block; height: 7px; border-radius: 4px; background: var(--hc); opacity: .8; }
.home-top-n { flex: none; min-width: 28px; text-align: right; font-size: 12px; font-weight: 900; color: var(--ink); font-variant-numeric: tabular-nums; }
.home-top-chev { flex: none; font-size: 12px; font-weight: 800; color: var(--muted2); }   /* decorative (aria-hidden) — verbatim token */

/* History tab, day-panel rows, Notes (App v3 2080–2107, 2158–2170, 2177–2192; its CSS L77–78, L115–117).
   The card (.hist-card), hairline (.hist-hair), time column (.hist-time), name (.hist-name), pills and
   "Show N older" (.hist-more) are step 3's classes, unchanged. */
.home-days { display: flex; flex-direction: column; gap: 16px; }
.home-day-head { display: flex; align-items: center; gap: 9px; margin-bottom: 7px; padding: 0 2px; }
.home-day-dot { width: 10px; height: 10px; border-radius: 999px; background: var(--hc); flex: none; }
.home-day-label { font-size: 13.5px; font-weight: 800; color: var(--ink); }
.home-day-count { font-size: 11.5px; font-weight: 700; color: var(--muted2-text); /* d11 */ }
.home-hrow { display: flex; align-items: center; gap: 12px; padding: 11px 14px; width: 100%; text-align: left; background: none; border: none; border-radius: 10px; cursor: pointer; color: inherit; }
@media (hover: hover) { .home-hrow:hover { background: var(--soft); } }
.home-hrow:focus-visible, .home-nrow:focus-visible { outline-offset: -2px; }   /* the card clips overflow: the ring goes inside */
.home-hcol { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.home-hcol .hist-name { display: flex; align-items: baseline; }
.home-hcol .hist-pill { margin-left: 7px; }
/* the archived pill (category home) — step 3's .hist-row rule scoped to these rows too */
.home-hrow .entry-archived { color: var(--muted-text); /* d11 */ }
.home-hnote { min-width: 0; font-size: 12px; font-weight: 600; color: var(--muted-text); /* d11 */ white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.home-qty { flex: none; font-size: 11.5px; font-weight: 800; color: var(--muted2-text); /* d11 */ font-variant-numeric: tabular-nums; }
.home-chev { flex: none; font-size: 14px; color: var(--muted2); line-height: 1; opacity: .4; transition: opacity .15s ease; }   /* App v3 [data-hrow] [data-histchev] — decorative, verbatim token */
@media (hover: hover) { .home-hrow:hover .home-chev, .home-nrow:hover .home-nchev { opacity: .85; } }
.home-chev--day { font-size: 17px; width: 16px; display: grid; place-items: center; opacity: 1; }   /* App v3 2167: the day panel's › is not a histchev */
@media (hover: hover) { .home-hrow:hover .home-chev--day { opacity: 1; } }
@media (hover: none) { .home-chev, .home-nchev { opacity: .55; } .home-chev--day { opacity: 1; } }
.home-notes { background: var(--surface); border: 1px solid var(--border2); border-radius: 14px; overflow: hidden; }
.home-nhair { height: 1px; background: var(--hair); margin: 0 16px; }
.home-nrow { display: flex; align-items: flex-start; gap: 11px; padding: 15px 16px; width: 100%; text-align: left; background: none; border: none; border-radius: 10px; cursor: pointer; color: inherit; }
@media (hover: hover) { .home-nrow:hover { background: var(--soft); } }
.home-ndot { width: 7px; height: 7px; border-radius: 999px; background: var(--hc); flex: none; margin-top: 7px; }
.home-nbody { flex: 1 1 auto; min-width: 0; display: block; }
.home-ntext { display: block; font-size: 14px; font-weight: 600; color: var(--ink); line-height: 1.55; overflow-wrap: anywhere; }
.home-nmeta { display: block; font-size: 11.5px; font-weight: 600; color: var(--muted-text); /* d11 */ margin-top: 6px; }
.home-nchev { flex: none; align-self: center; font-size: 15px; color: var(--muted2); line-height: 1; opacity: .4; transition: opacity .15s ease; }

/* Calendar + day panel (App v3 2108–2174, homeCal* styles 2646). Always 6 rows (42 cells). */
.home-calnav { position: relative; display: flex; align-items: center; justify-content: center; min-height: 34px; margin-bottom: 8px; }
.home-calstep { position: absolute; top: 2px; width: 30px; height: 30px; border-radius: 9px; border: 1px solid var(--border2); background: var(--surface); cursor: pointer; font-size: 15px; color: var(--muted); /* glyph — verbatim token */ line-height: 1; padding: 0; }
.home-calstep--prev { left: 0; }
.home-calstep--next { right: 0; }
.home-calmonth { display: inline-flex; align-items: center; gap: 5px; background: none; border: none; cursor: pointer; padding: 4px 6px; border-radius: 8px; font-family: 'Lora', serif; font-size: 16px; font-weight: 700; color: var(--ink); line-height: 1; white-space: nowrap; }
@media (hover: hover) { .home-calmonth:hover { background: var(--chip2); } }
.home-calcaret { font-size: 9px; line-height: 1; color: var(--muted2); display: inline-block; transition: transform .15s ease; }
.home-calcaret svg { display: block; }
.home-calmonth[aria-expanded="true"] .home-calcaret { transform: rotate(180deg); }
.home-caltoday { position: absolute; right: 38px; top: 5px; background: var(--chip2); border: none; border-radius: 999px; padding: 5px 11px; font-size: 11.5px; font-weight: 800; letter-spacing: .02em; color: var(--ink2); cursor: pointer; }
/* the inline month / year picker (pushes the grid down — App v3) */
.home-calpick { border: 1px solid var(--border2); background: var(--surface); border-radius: 14px; padding: 12px; margin-bottom: 12px; }
.home-calpick-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 10px; }
.home-calpick-step { flex: none; width: 28px; height: 28px; border-radius: 8px; border: 1px solid var(--border2); background: var(--panel); cursor: pointer; font-size: 15px; color: var(--muted); /* glyph — verbatim token */ line-height: 1; padding: 0; }
.home-calpick-step:disabled { opacity: .35; cursor: default; transform: none; filter: none; }   /* App v3 homeCalPickNextStyle */
.home-calpick-year { font-family: 'Lora', serif; font-size: 17px; font-weight: 700; color: var(--ink); font-variant-numeric: tabular-nums; }
.home-calpick-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; }
.home-calpick-m { padding: 9px 4px; border-radius: 10px; border: 1px solid var(--border2); background: var(--panel); color: var(--ink); font-size: 12.5px; font-weight: 800; cursor: pointer; }
.home-calpick-m[aria-current="true"] { border-color: transparent; background: var(--accent); color: var(--on-solid); /* App v3 #fff — fills rule */ }
.home-calpick-m:disabled { color: var(--muted2); cursor: default; opacity: .4; transform: none; filter: none; }
.home-caldows { display: grid; grid-template-columns: repeat(7, 1fr); gap: 3px; margin-bottom: 3px; }
.home-caldow { text-align: center; font-size: 10.5px; font-weight: 800; color: var(--muted2-text); /* d11 */ }
.home-calgrid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 3px; }
.home-calblank { aspect-ratio: 1; }
.home-calday { position: relative; aspect-ratio: 1; display: flex; align-items: center; justify-content: center; border-radius: 9px; font-size: 12.5px; font-weight: 700; border: 1.5px solid transparent; background: var(--heat-empty); color: var(--ink); cursor: pointer; padding: 0; min-width: 0; }
/* MONTH_ALPHA [.05 .26 .44 .64 .85] — deliberately not the year's (App v3; T8 odd 4). Levels 3–4 carry --hc-on text (App v3 #fff). */
.home-calday.l1 { background: color-mix(in srgb, var(--hc) 26%, transparent); }
.home-calday.l2 { background: color-mix(in srgb, var(--hc) 44%, transparent); }
.home-calday.l3 { background: color-mix(in srgb, var(--hc) 64%, transparent); color: var(--hc-on); }
.home-calday.l4 { background: color-mix(in srgb, var(--hc) 85%, transparent); color: var(--hc-on); }
.home-calday.is-today, .home-calday[aria-current="date"] { border-color: var(--hc); }
.home-calday[aria-pressed="true"] { border: 2px solid var(--hc); }
/* a future day: App v3 inert (transparent, --muted2, opacity .4) → a real disabled button */
.home-calday.is-future, .home-calday:disabled { background: transparent; color: var(--muted2); cursor: default; opacity: .4; transform: none; filter: none; }
.home-calnote { position: absolute; left: 50%; bottom: 3px; transform: translateX(-50%); width: 4px; height: 4px; border-radius: 999px; background: var(--hc); }
.home-calday.l3 .home-calnote, .home-calday.l4 .home-calnote { background: rgba(255,255,255,.92); }
.home-calcap { text-align: center; color: var(--muted2-text); /* d11 */ font-size: 11.5px; font-weight: 600; line-height: 1.4; margin-top: 8px; }
.home-callegend { display: flex; align-items: center; gap: 6px; justify-content: flex-end; margin-top: 6px; font-size: 11px; font-weight: 700; color: var(--muted2-text); /* d11 */ }
/* the day panel (App v3 2147–2174). App v3's panel stays mounted while a day is open and animates only when it
   first appears; home.js rebuilds the Calendar on every render, so the entry animation rides on .is-new — set only
   when the panel was not on screen before (a day opened), never when another day is picked or the tab re-renders. */
.home-daypanel { margin-top: 14px; border: 1px solid var(--border2); border-radius: 14px; overflow: hidden; }
.home-daypanel.is-new { animation: numswap .22s ease; }
.home-dayhead { display: flex; align-items: center; gap: 9px; padding: 11px 13px; background: var(--surface); border-bottom: 1px solid var(--hair); }
.home-daytitle { flex: none; font-size: 13.5px; font-weight: 800; color: var(--ink); white-space: nowrap; line-height: normal; }
.home-daycount { flex: 1 1 auto; min-width: 0; font-size: 12px; font-weight: 700; color: var(--muted-text); /* d11 */ white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.home-dayadd { flex: none; display: inline-flex; align-items: center; gap: 5px; background: none; border: 1px dashed var(--border2); border-radius: 999px; padding: 5px 12px 5px 9px; font-size: 12px; font-weight: 800; color: var(--ink2); cursor: pointer; }
@media (hover: hover) { .home-dayadd:hover { border-color: var(--muted2); color: var(--ink); } }
.home-dayx { flex: none; width: 26px; height: 26px; border-radius: 999px; border: none; background: none; cursor: pointer; color: var(--muted); /* icon — verbatim token */ display: grid; place-items: center; padding: 0; }
.home-dayempty { text-align: center; color: var(--muted2-text); /* d11 */ font-weight: 700; padding: 20px 0 6px; font-size: 13px; }
.home-dayrows { background: var(--surface); }

/* Settings (App v3 1987–2079; its CSS L54–56). Built by js/home-settings.js. */
.home-set { display: flex; flex-direction: column; gap: 20px; }
.home-field { display: block; margin: 0; }
.home-set-label { display: block; font-size: 11px; font-weight: 800; letter-spacing: .09em; text-transform: uppercase; color: var(--muted2-text); /* d11 */ margin-bottom: 8px; line-height: normal; }
.home-name-row { display: flex; gap: 8px; align-items: stretch; }
.home-namefield { position: relative; flex: 1; min-width: 0; }
/* LABELLED DEVIATION: 16 px (App v3 14) — the iOS zoom rule; padding 10 → 8.5 keeps App v3's box (40.5 measured on the
   served design at 1280). Its focus border: the field rule (the ring- section); App v3's focus background stays here. */
.home-name-input { display: block; width: 100%; font-size: 16px; font-weight: 700; color: var(--ink); background: var(--surface); border: 1px solid var(--border); border-radius: 11px; padding: 8.5px 38px 8.5px 12px; -webkit-appearance: none; appearance: none; }
.home-name-input:focus { background: var(--panel); }
.home-name-input::placeholder { color: var(--muted-text); /* d11 */ opacity: 1; }
.home-name-clear { position: absolute; right: 8px; top: 50%; transform: translateY(-50%); width: 20px; height: 20px; border-radius: 6px; border: none; background: transparent; color: var(--muted2); display: grid; place-items: center; cursor: pointer; padding: 0; opacity: 0; pointer-events: none; transition: opacity .15s ease; }
.home-namefield:focus-within .home-name-clear { opacity: 1; pointer-events: auto; }   /* App v3 [data-namefield]:focus-within button */
.home-name-clear:active { transform: translateY(-50%) scale(.94); }                  /* keep the centring under the global press scale */
/* LABELLED: max-width + ellipsis — App v3 lets "Save as “<a very long name> (1)”" squeeze the field to nothing */
.home-name-save { flex: none; align-self: stretch; background: var(--solid); color: var(--on-solid); border: none; border-radius: 11px; padding: 0 18px; font-size: 13.5px; font-weight: 800; cursor: pointer; white-space: nowrap; max-width: 64%; overflow: hidden; text-overflow: ellipsis; }
.home-name-save:disabled { opacity: .42; cursor: default; transform: none; filter: none; }   /* App v3 button[data-namesave]:disabled */
/* the category / colour select buttons */
.home-select-wrap, .home-taginput-wrap { position: relative; }
.home-select { width: 100%; display: flex; align-items: center; gap: 9px; background: var(--surface); border: 1px solid var(--border); border-radius: 11px; padding: 11px 13px; cursor: pointer; text-align: left; color: var(--ink); }
@media (hover: hover) { .home-select:hover { border-color: var(--muted2); } }
.home-select:active { transform: none; }                        /* a full-width field, not a pill (rec-date-btn precedent) */
.home-select-dot { width: 12px; height: 12px; border-radius: 999px; flex: none; }   /* background inline: the category hex */
.home-select-swatch { width: 20px; height: 20px; border-radius: 999px; flex: none; background: var(--hc, var(--muted2)); }
.home-select-val { flex: 1; min-width: 0; text-align: left; font-size: 14.5px; font-weight: 700; color: var(--ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.home-select-chev { flex: none; stroke: var(--muted2); stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round; }
.home-away { position: fixed; inset: 0; z-index: 19; background: transparent; }
/* the category menu (uHomeCatMenuToggle; App v3 z 6 → 20 over the click-away) */
.home-menu { position: absolute; top: calc(100% + 5px); left: 0; right: 0; z-index: 20; max-height: 214px; overflow-y: auto; overscroll-behavior: contain; background: var(--panel); border: 1px solid var(--border); border-radius: 12px; box-shadow: 0 14px 34px rgba(0,0,0,.16); padding: 5px; display: flex; flex-direction: column; gap: 2px; }
.home-menu-row { display: flex; align-items: center; gap: 9px; width: 100%; text-align: left; border: none; background: transparent; border-radius: 9px; padding: 9px 10px; font-size: 14px; font-weight: 700; color: var(--ink); cursor: pointer; flex: none; }
.home-menu-row[aria-current="true"] { background: var(--soft); } @media (hover: hover) { .home-menu-row:hover { background: var(--soft); } }
.home-menu-dot { width: 11px; height: 11px; border-radius: 999px; flex: none; }   /* background inline */
.home-menu-name { flex: 1; min-width: 0; text-align: left; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.home-menu-tick { flex: none; width: 20px; height: 20px; border-radius: 999px; background: var(--ink); display: grid; place-items: center; }
.home-menu-tick svg { stroke: var(--panel); stroke-width: 3; stroke-linecap: round; stroke-linejoin: round; }
/* tags: the chip strip (App v3 [data-tagscroll]) + the combobox and its listbox */
.home-tagchips { display: flex; flex-wrap: nowrap; gap: 7px; align-items: center; margin-bottom: 8px; overflow-x: auto; scrollbar-width: none; }
.home-tagchips::-webkit-scrollbar { display: none; }
.home-tagchip { display: inline-flex; align-items: center; gap: 5px; padding: 5px 6px 5px 11px; border-radius: 999px; background: var(--chip); border: 1px solid var(--border2); color: var(--ink2); font-size: 12.5px; font-weight: 700; white-space: nowrap; flex: none; }
.home-tagchip-x { display: grid; place-items: center; width: 16px; height: 16px; border-radius: 999px; background: var(--chip2); border: none; cursor: pointer; color: var(--muted); /* glyph — verbatim token */ font-size: 11px; line-height: 1; padding: 0; }
/* LABELLED DEVIATION: 16 px (App v3 13.5) — the iOS zoom rule; padding 10 → 8.5 keeps App v3's box (40.5 measured) */
.home-taginput { display: block; width: 100%; font-size: 16px; font-weight: 600; color: var(--ink); background: var(--surface); border: 1px solid var(--border2); border-radius: 11px; padding: 8.5px 12px; -webkit-appearance: none; appearance: none; }
.home-taginput::placeholder { color: var(--muted-text); /* d11 */ opacity: 1; }
.home-tagmenu { position: absolute; left: 0; right: 0; top: calc(100% + 6px); z-index: 20; background: var(--panel); border: 1px solid var(--border2); border-radius: 12px; box-shadow: 0 16px 40px rgba(0,0,0,.18); padding: 6px; max-height: 216px; overflow-y: auto; overscroll-behavior: contain; }
.home-tagopt { display: flex; align-items: center; gap: 8px; width: 100%; text-align: left; cursor: pointer; padding: 9px 11px; border-radius: 8px; color: var(--ink); }
.home-tagopt[aria-selected="true"] { background: var(--chip); } @media (hover: hover) { .home-tagopt:hover { background: var(--chip); } }
.home-tagopt-plus { flex: none; display: grid; place-items: center; width: 20px; height: 20px; border-radius: 999px; background: var(--chip2); color: var(--muted); /* glyph — verbatim token */ font-size: 14px; line-height: 0; }
.home-tagopt-text { font-size: 13.5px; font-weight: 700; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.home-tagopt-text b { font-weight: 800; }
.home-tagopt-name { flex: 1; min-width: 0; font-size: 13.5px; font-weight: 700; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.home-tagopt-count { flex: none; font-size: 11.5px; font-weight: 700; color: var(--muted2-text); /* d11 */ }
.home-tagmenu-empty { padding: 12px 11px; font-size: 12.5px; font-weight: 600; color: var(--muted2-text); /* d11 */ text-align: center; }
.home-set-note { font-size: 11.5px; color: var(--muted2-text); /* d11 */ margin-top: 8px; line-height: 1.5; }
/* Duplicate / Archive / Delete… */
.home-actions { border-top: 1px solid var(--hair); padding-top: 16px; display: flex; gap: 9px; flex-wrap: wrap; align-items: center; }
.home-act-btn { background: var(--soft); border: 1px solid var(--border); border-radius: 10px; padding: 9px 15px; font-size: 13.5px; font-weight: 800; color: var(--ink); cursor: pointer; }
/* App v3 literals #d8b3a6 / #b5573c → tokens (G4 §1.6, the .rec-delete precedent) */
.home-act-btn--danger { background: none; border-color: color-mix(in oklab, var(--danger) 35%, var(--border)); color: var(--danger); }
/* the colour popover (SWATCHES 20 + the current colour when it is not one of them) */
.home-swpop { position: absolute; left: 0; right: 0; top: calc(100% + 6px); z-index: 20; background: var(--panel); border: 1px solid var(--border2); border-radius: 13px; box-shadow: 0 16px 40px rgba(0,0,0,.18); padding: 11px; }
.home-swgrid { display: grid; grid-template-columns: repeat(10, 1fr); gap: 9px; }
.home-sw { display: grid; place-items: center; width: 100%; aspect-ratio: 1; max-width: 34px; height: auto; border-radius: 999px; border: none; padding: 0; cursor: pointer; transition: none; box-shadow: 0 0 0 1px rgba(0,0,0,.08); }   /* --sw + background inline */
.home-sw[aria-pressed="true"] { box-shadow: inset 0 0 0 3px var(--panel), 0 0 0 2px var(--sw); }
.home-sw-dot { width: 6px; height: 6px; border-radius: 999px; background: rgba(255,255,255,.5); }   /* "used by another category" */
/* Reorder activities (↑ / ↓; App v3 _arrowBtn) */
.home-reorder { display: flex; flex-direction: column; gap: 6px; max-height: 220px; overflow-y: auto; overscroll-behavior: contain; }
.home-rrow { display: flex; align-items: center; gap: 8px; background: var(--surface); border: 1px solid var(--border2); border-radius: 11px; padding: 8px 10px 8px 13px; flex: none; }
.home-rname { flex: 1; min-width: 0; font-size: 13.5px; font-weight: 700; color: var(--ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.home-rbtn { flex: none; width: 34px; height: 34px; border-radius: 10px; border: 1px solid var(--border); background: var(--soft); cursor: pointer; font-size: 15px; font-weight: 800; color: var(--ink); display: grid; place-items: center; padding: 0; }
.home-rbtn:disabled { opacity: .35; cursor: default; transform: none; filter: none; }   /* App v3 opacity .35 + pointer-events none → a real disabled */

/* 44-px targets on touch (G4 §1, contract ruling 11 — LABELLED: the look is unchanged on fine pointers). .hit already
   covers the header buttons, the calendar / year steps, the day-panel ×, the tag chip × and History's door.
   Swatches stay 28 (ten to a row can't take 44 — LABELLED, like the day picker's cells); calendar cells are ≥ 46 at 375. */
@media (pointer: coarse) {
  .home-tab, .home-hrow, .home-nrow, .home-toprow, .home-act-btn, .home-select, .home-menu-row, .home-tagopt, .home-calpick-m, .home-dayadd, .share-go, .share-close { min-height: 44px; }
  /* the Today chip is absolutely placed in the 34-px nav row: a 44-px min-height would overlap the weekday row, so it
     gets .hit's invisible centred 44 × 44 area instead (it is already positioned) */
  .home-caltoday::after { content: ""; position: absolute; left: 50%; top: 50%; width: 100%; height: 100%; min-width: 44px; min-height: 44px; transform: translate(-50%, -50%); }
  .home-rbtn { position: relative; }
  .home-rbtn::after { content: ""; position: absolute; inset: -5px; }            /* 34 → 44 */
  .home-name-clear::after { content: ""; position: absolute; inset: -12px; }      /* 20 → 44 */
}

/* Show on board: the card ring lives with the card (.bd-card.home-flash, the bd- family). */

/* ---------- share- : the share card (App v3 2200–2239, homeShare* styles 2646; js/share-card.js). A centred stage at
   every width (no handle): the 340-px card is scaled to fit by share-card.js (wrap width / height + the card's
   scale(sk) inline). The footer is the site's wordmark — App v3's hard-coded domain is not ported (LABELLED). ---------- */
.share-scrim { --layer-dim: var(--scrim-share); display: none; position: fixed; inset: 0; z-index: 1010; /* --z-nested */ background: transparent; /* its dim is painted on the page / over the home (the dim- section); no fade: mobile pass ruling 4 (.ov-scrim) */ align-items: center; justify-content: center; padding: 18px; overflow: hidden; overscroll-behavior: contain; }
.share-scrim.visible { display: flex; }
.share-stage { display: flex; flex-direction: column; align-items: center; gap: 14px; max-height: 100%; max-width: 100%; animation: popup .24s cubic-bezier(.22,1,.36,1); }
.share-wrap { position: relative; flex: none; }                    /* width / height inline: 340·sk × natH·sk */
.share-card { --hc: #8a8578; --hc-on: #ffffff; position: absolute; top: 0; left: 0; width: 340px; transform-origin: top left; background: var(--panel); border: 1px solid var(--border); border-radius: 22px; overflow: hidden; box-shadow: 0 10px 30px rgba(60,56,48,.16); text-align: left; }   /* transform inline: scale(sk); --hc / --hc-on inline */
.share-band { background: var(--hc); padding: 20px; color: var(--hc-on); /* App v3 #fff */ }
.share-kind { font-size: 11px; font-weight: 800; letter-spacing: .14em; text-transform: uppercase; opacity: .85; line-height: normal; }
.share-name { font-family: 'Lora', serif; font-size: 24px; font-weight: 700; line-height: 1.12; margin-top: 3px; overflow-wrap: anywhere; }
.share-body { padding: 20px; }
.share-stats { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 10px 8px; margin-bottom: 14px; }
.share-stat { min-width: 0; }
.share-stat-v { font-family: 'Lora', serif; font-size: 30px; font-weight: 700; color: var(--ink); line-height: 1; }
.share-stat-k { font-size: 10px; font-weight: 800; letter-spacing: .06em; text-transform: uppercase; color: var(--muted2-text); /* d11 */ margin-top: 4px; }
.share-label { font-size: 10px; font-weight: 800; letter-spacing: .06em; text-transform: uppercase; color: var(--muted2-text); /* d11 */ line-height: normal; }
.share-label--r { text-align: right; margin: 0 0 4px; }
.share-label--weeks { margin: 16px 0 8px; }
.share-spark { width: 100%; height: auto; display: block; overflow: visible; }
.share-spark-area { fill: color-mix(in srgb, var(--hc) 12%, transparent); }
.share-spark-line { fill: none; stroke: var(--hc); stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.share-spark-end { fill: var(--hc); }
/* the last 13 weeks (91 cells; .share-wc shares the heatmap cell + YEAR_ALPHA rules above) */
.share-weeks { display: grid; grid-auto-flow: column; grid-template-rows: repeat(7, 1fr); grid-auto-columns: 1fr; gap: 1.5px; }
.share-foot { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-top: 16px; padding-top: 13px; border-top: 1px solid var(--hair); }
.share-brand { display: inline-flex; align-items: center; gap: 5px; flex: none; font-family: 'Lora', serif; font-size: 15px; font-weight: 700; color: var(--ink); }   /* line-height normal = App v3's footer row (18.7 measured) */
.share-sun { width: 16px; height: 16px; border-radius: 50%; background: radial-gradient(circle at 50% 40%, var(--gold-hi), var(--gold)); flex: none; }
.share-wm { white-space: nowrap; }
.share-sol { color: var(--gold); }                             /* a logotype (the header's rule — WCAG 1.4.3 exempts logo text) */
.share-tag { font-size: 9.5px; font-weight: 800; letter-spacing: .1em; text-transform: uppercase; color: var(--muted2-text); /* d11 */ text-align: right; }
.share-plus { color: var(--accent); }                           /* App v3 #9e4a3c → the accent token */
.share-controls { flex: none; max-width: 100%; }                 /* width inline: min(340, available) px */
.share-row { display: flex; gap: 8px; }
.share-go { flex: 1; display: inline-flex; align-items: center; justify-content: center; gap: 8px; background: var(--accent); border: none; border-radius: 12px; padding: 12px; font-size: 14px; font-weight: 800; color: var(--on-solid); /* App v3 #fff — fills rule */ cursor: pointer; transition: filter .12s ease; }
@media (hover: hover) { .share-go:hover { filter: brightness(1.07); } }
.share-close { display: block; margin: 0 auto; background: none; border: none; padding: 9px 18px 4px; font-size: 13px; font-weight: 800; color: #fff; cursor: pointer; }
/* LABELLED DEVIATION (a11y — secondary text meets AA): Close sits on the .55 scrim, not on a surface. App v3's var(--muted)
   reads 1.1:1 there over the home sheet in light mode and the d11 alias 1.4:1 (the aliases are tuned for surfaces), so
   light mode uses #fff (4.1:1 over the dimmed sheet, 8.0:1 over the dimmed page); dark keeps the d11 alias (5.0:1). */
body[data-mode="dark"] .share-close { color: var(--muted-text); /* d11 */ }

/* ---------- mng- : the Manage sheet (App v3 1024–1144; t5.scrimStyle 4157, sheetFix 4160, dcOn/dcOff 3851/3856;
   js/manage.js + the tab renderers js/organise.js · archived.js · recently-deleted.js · export.js · backups.js).
   Scrim = .ov-scrim, panel base = .sheet, header = .sheet-head / .sheet-eyebrow / .sheet-title / .sheet-x. ---------- */
/* Site deviation (owner, 2026-09-30): App v3 sizes Manage to its tab (738 / 408 / 371 / 661 px at 1280×900), so it
   jumped between tabs. The sheet keeps ONE height — App v3's 82 dvh (divided by the zoom), at most 720 px (Data with one
   backup fits) — the visible panel fills it, longer content scrolls inside the body, an empty state sits centred. */
.mng-sheet { width: 640px; height: min(calc(82dvh / var(--zf, 1)), 720px); display: flex; flex-direction: column; }
@media (max-width: 639.98px) {
  /* width restated (.mng-sheet comes after .sheet's NARROW rule); App v3 sheetFix 88 dvh; padding-top = room for the
     handle (LABELLED: App v3's Manage has no handle — every site bottom sheet has one, as History since step 3) */
  .mng-sheet { width: 100%; height: calc(88dvh / var(--zf, 1)); padding-top: 8px; }
  .mng-head { padding-top: 0; }
}
.mng-head, .mng-tabs { flex: none; }   /* only the body shrinks / scrolls */
/* tab row (1031–1036): wraps to two lines at 375 (measured: Organise · Archived / Recently deleted · Data) */
.mng-tabs { display: flex; flex-wrap: wrap; gap: 7px; padding: 0 20px 14px; }
.mng-tab { padding: 9px 15px; border-radius: 999px; border: 1px solid var(--border); background: var(--soft); color: var(--ink2); font-size: 14px; font-weight: 800; line-height: normal; cursor: pointer; white-space: nowrap; }
.mng-tab > span { white-space: nowrap; }
/* dcOn = var(--solid) / var(--on-solid), border none — LABELLED: a same-colour border keeps every tab the same
   height on whichever line it wraps to */
.mng-tab[aria-selected="true"] { background: var(--solid); color: var(--on-solid); border-color: var(--solid); }
body[data-mode="dark"] .mng-tab[aria-selected="false"] { border-color: rgba(240,234,221,.22); }   /* dcOff _dkOpt literal (3856), verbatim */
/* body (1037): the scroller */
.mng-body { flex: 1 1 auto; min-height: 0; overflow: auto; overscroll-behavior: contain; padding: 0 20px 20px; display: flex; flex-direction: column; }
.mng-panel:not([hidden]) { flex: 1 0 auto; display: flex; flex-direction: column; }
.mng-panel:focus-visible { outline-offset: -2px; border-radius: 6px; }   /* the body scrolls (clips) and the panel starts flush with its top: the ring goes inside so all four sides show */
.mng-list { display: flex; flex-direction: column; }
.mng-list:has(> .mng-empty) { flex: 1 0 auto; }
/* "Nothing archived." / "Nothing recently deleted." (1062 / 1088): text-align center, --muted2, 700, padding 36px 0 */
.mng-empty { margin: auto 0; text-align: center; color: var(--muted2-text); /* d11 */ font-weight: 700; padding: 36px 0; }

/* rows — the card App v3 repeats at 1040 / 1056 / 1081 */
.mng-row { display: flex; align-items: center; gap: 11px; background: var(--card); border: 1px solid var(--border2); border-radius: 14px; padding: 11px 13px; margin-bottom: 8px; }
.mng-row-text { flex: 1; min-width: 0; }
/* Archived / Recently deleted: label 14/800 ink + "· Kind" 12.5/800 muted2 (1057 / 1083) */
.mng-row-title { line-height: normal; overflow-wrap: anywhere; }
.mng-row-name { font-size: 14px; font-weight: 800; color: var(--ink); }
.mng-row-kind { font-size: 12.5px; font-weight: 800; color: var(--muted2-text); /* d11 */ white-space: nowrap; }
/* LABELLED (site): the meta line — dates, counts, until / leaving soon; App v3's rows carry label + kind only */
.mng-row-meta { font-size: 12.5px; font-weight: 700; color: var(--muted2-text); /* d11 */ line-height: 1.35; margin-top: 1px; overflow-wrap: anywhere; }
/* green Restore (1058 / 1084): App v3 rgba(47,125,81,.12/.3) = --go light, tokenised so dark takes its own --go.
   LABELLED: the text is --go + 10% ink — App v3's --go on its own 12% tint is 4.29:1 in light (below AA);
   the mix measures 4.68:1 light / 5.0:1 dark */
.mng-restore-btn { flex: none; background: color-mix(in srgb, var(--go) 12%, transparent); border: 1px solid color-mix(in srgb, var(--go) 30%, transparent); border-radius: 10px; padding: 7px 13px; font-size: 13.5px; font-weight: 800; color: color-mix(in srgb, var(--go) 90%, var(--ink)); line-height: normal; cursor: pointer; }
/* text buttons: Delete (1059 / 1085 — App v3 sets no padding → the UA's 1px 6px, measured), Restore all / Empty */
.mng-text-btn { flex: none; background: none; border: none; padding: 1px 6px; font-size: 13.5px; font-weight: 800; color: var(--muted-text); /* d11 */ line-height: normal; cursor: pointer; }
.mng-text-btn--danger { color: var(--danger); }
.mng-text-btn--go { color: color-mix(in srgb, var(--go) 80%, var(--ink)); }   /* Restore all, on the panel: the green pill's mix (LABELLED — plain --go reads 4.48:1 on the slate panel) */
/* the interlock (rulings 6 / 7): every button of a busy tab is aria-disabled (it keeps its focus) */
.mng-panel [aria-disabled="true"] { opacity: .45; cursor: default; }
.mng-panel button[aria-disabled="true"]:active { transform: none; }
@media (hover: hover) { .mng-panel button[aria-disabled="true"]:hover { filter: none; } }

/* Organise (1038–1053) */
.mng-dot { width: 11px; height: 11px; border-radius: 999px; flex: none; }   /* background = the stored colour, inline */
.mng-org-name { font-size: 14.5px; font-weight: 800; color: var(--ink); line-height: normal; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mng-org-count { font-size: 12.5px; font-weight: 700; color: var(--muted2-text); /* d11 */ line-height: normal; white-space: nowrap; }
/* ↑ ↓ (1046–1047): 30×30, --soft, 1px --border, radius 10, 14/800 --ink2; App v3 sets no padding → the UA's 1px 6px.
   The 44×44 touch area comes from the global .hit class in the markup. */
.mng-arrow { flex: none; width: 30px; height: 30px; padding: 1px 6px; background: var(--soft); border: 1px solid var(--border); border-radius: 10px; font-size: 14px; font-weight: 800; color: var(--ink2); line-height: normal; cursor: pointer; }
/* LABELLED: App v3 computes canUp/canDown but never binds them — the site disables the ends (dcDis idiom, opacity .32) */
.mng-arrow:disabled { opacity: .32; cursor: not-allowed; transform: none; filter: none; }
.mng-org-row .mng-text-btn { padding: 4px; }   /* Organise's Archive / Delete (1048–1049) set padding 4px */
/* footer (1052): border-top 1px --hair, margin-top 16 (App v3's collapses with the last row's 8-px margin — in this
   flex list it cannot collapse, so 8 + the row's 8 = 16), padding-top 14 */
.mng-foot { border-top: 1px solid var(--hair); margin-top: 8px; padding-top: 14px; }
.mng-soft-btn { background: var(--soft); border: 1px solid var(--border); border-radius: 10px; padding: 9px 14px; font-size: 14px; font-weight: 800; color: var(--ink2); line-height: normal; cursor: pointer; }

/* Recently deleted (1065–1088; delFilterChips 4369, _tickCss 3267) */
.mng-intro { font-size: 13px; font-weight: 600; color: var(--muted2-text); /* d11 */ line-height: normal; margin-bottom: 16px; }   /* Data 1092 */
.mng-intro--bin { font-weight: 700; margin-bottom: 12px; }                                                                       /* 1065 */
/* chip row (1067): chips + Select (margin-left auto); the chips sit in a role=group wrapper. App v3's row stretches its
   items, so one line of chips takes Select's 33.6-px height (31.6 in Select mode, Select hidden); the wrapper stretches
   and its single line with it. Select itself stays top-aligned, so a two-line chip wrap (375 px) never stretches it. */
.mng-chiprow { display: flex; align-items: stretch; gap: 7px; margin-bottom: 14px; }
.mng-chips { display: flex; flex-wrap: wrap; gap: 7px; min-width: 0; }
.mng-chip { display: inline-flex; align-items: center; padding: 6px 12px; border-radius: 999px; border: 1px solid var(--border); background: transparent; color: var(--muted-text); /* d11 */ font-size: 13px; font-weight: 800; line-height: normal; cursor: pointer; }
/* active: App v3 border/bg var(--ink) + color #fff — LABELLED: #fff vanishes on dark mode's light --ink; the fills rule's
   --on-solid (#fff light, the dark ground in dark — as History's .hist-chip) reads 11.7:1 / 13.1:1 */
.mng-chip[aria-pressed="true"] { border-color: var(--ink); background: var(--ink); color: var(--on-solid); }
.mng-select-btn { margin-left: auto; flex: none; align-self: flex-start; background: var(--card); border: 1px solid var(--border); border-radius: 999px; padding: 7px 14px; font-size: 13px; font-weight: 800; color: var(--ink2); line-height: normal; cursor: pointer; }
/* select bar (1071–1078): a plain row — no card, unlike History's */
.mng-selbar { display: flex; align-items: center; gap: 9px; flex-wrap: wrap; margin-bottom: 12px; }
.mng-sel-count { font-size: 13.5px; font-weight: 900; color: var(--ink); }
/* the green Restore pill (1075) sits on the panel, not a card: its --go + ink mix is 80 % (LABELLED — 90 % reads 4.28:1
   there in light; 80 % measures 4.58–4.67:1 light across the four palettes, 5.46:1 dark) */
.mng-go-pill { background: color-mix(in srgb, var(--go) 12%, transparent); border: 1px solid color-mix(in srgb, var(--go) 30%, transparent); border-radius: 999px; padding: 7px 14px; font-size: 13px; font-weight: 800; color: color-mix(in srgb, var(--go) 80%, var(--ink)); line-height: normal; cursor: pointer; }
.mng-danger-pill { background: var(--card); border: 1px solid var(--danger); border-radius: 999px; padding: 7px 14px; font-size: 13px; font-weight: 800; color: var(--danger); line-height: normal; cursor: pointer; }
.mng-go-pill:disabled, .mng-danger-pill:disabled { opacity: .45; cursor: default; transform: none; filter: none; }   /* the History precedent */
.mng-cancel-btn { margin-left: auto; background: none; border: none; padding: 1px 6px; font-size: 13px; font-weight: 800; color: var(--muted-text); /* d11 */ line-height: normal; cursor: pointer; }
/* LABELLED (site): Restore all · Empty Recently Deleted — "the header of the list", right-aligned quiet text buttons */
.mng-binall { display: flex; justify-content: flex-end; align-items: center; flex-wrap: wrap; gap: 12px; margin: -4px 0 10px; }
/* the Select tick = _tickCss(on, 'var(--ink)') (3267) — History's .hist-tick recipe */
.mng-tick { flex: none; width: 20px; height: 20px; border-radius: 999px; box-sizing: border-box; display: grid; place-items: center; font-size: 11px; font-weight: 900; line-height: 1; padding: 0; cursor: pointer; background: transparent; color: transparent; border: 1.5px solid var(--border2); transition: background .12s ease, border-color .12s ease, color .12s ease; }
.mng-tick[aria-checked="true"] { background: var(--ink); color: var(--card); border-color: var(--ink); }

/* Data (1090–1140) */
.mng-data-lead { font-size: 13.5px; font-weight: 700; color: var(--muted-text); /* d11 */ line-height: normal; margin-bottom: 2px; }   /* 1091 */
/* CSV card (1093–1100) */
.mng-csv { border: 1px solid var(--border); background: var(--card); border-radius: 14px; padding: 2px 16px; margin-bottom: 12px; }
.mng-csv-row { display: flex; align-items: center; gap: 10px; padding: 12px 0; border-bottom: 1px solid var(--hair); }   /* the last row keeps its hairline (App v3) */
.mng-csv-text { flex: 1; min-width: 0; }
.mng-csv-label { font-size: 14.5px; font-weight: 800; color: var(--ink); line-height: normal; }
.mng-csv-count { font-size: 12.5px; font-weight: 700; color: var(--muted2-text); /* d11 */ line-height: normal; min-height: 17px; }
.mng-csv-btn { flex: none; display: inline-flex; align-items: center; gap: 7px; background: var(--soft); border: 1px solid var(--border); border-radius: 999px; padding: 8px 15px; font-size: 13.5px; font-weight: 800; color: var(--ink2); line-height: normal; cursor: pointer; }
.mng-csv-btn svg, .mng-solid-btn svg { flex: none; }
/* Backup & restore card (1101–1139) */
.mng-bk { border: 1px solid var(--border); background: transparent; border-radius: 14px; padding: 16px; }
.mng-bk-title { font-size: 14.5px; font-weight: 900; color: var(--ink); line-height: normal; margin-bottom: 5px; }
.mng-bk-body { font-size: 13.5px; font-weight: 600; color: var(--muted-text); /* d11 */ line-height: 1.5; margin-bottom: 14px; }
.mng-bk-actions { display: flex; flex-wrap: wrap; gap: 9px; align-items: center; margin-bottom: 18px; }
.mng-solid-btn { display: inline-flex; align-items: center; gap: 8px; background: var(--solid); color: var(--on-solid); border: none; border-radius: 999px; padding: 10px 18px; font-size: 14px; font-weight: 800; line-height: normal; cursor: pointer; }
.mng-solid-btn--sm { padding: 9px 17px; font-size: 13.5px; }                        /* "Restore this backup" (1130) */
.mng-solid-btn:disabled { opacity: .45; cursor: default; transform: none; filter: none; }
.mng-bk-label { font-size: 12px; font-weight: 800; letter-spacing: .06em; text-transform: uppercase; color: var(--muted2-text); /* d11 */ line-height: normal; margin-bottom: 8px; }
.mng-bk-empty { font-size: 13.5px; font-weight: 700; color: var(--muted2-text); /* d11 */ padding: 6px 0 2px; }
.mng-bk-list { display: flex; flex-direction: column; gap: 8px; }
.mng-bk-row { border: 1px solid var(--border); background: var(--card); border-radius: 12px; padding: 12px 13px; }
.mng-bk-top { display: flex; align-items: center; gap: 10px; }
.mng-bk-text { flex: 1; min-width: 0; }
.mng-bk-when { font-size: 14px; font-weight: 800; color: var(--ink); line-height: normal; overflow-wrap: anywhere; }
.mng-bk-sum { font-size: 12.5px; font-weight: 700; color: var(--muted2-text); /* d11 */ line-height: normal; }
.mng-bk-hint { font-size: 12px; font-weight: 700; color: var(--muted2-text); /* d11 */ line-height: normal; margin-top: 2px; }   /* LABELLED (site): the automatic row's hint */
.mng-bk-restore { flex: none; background: var(--soft); border: 1px solid var(--border); border-radius: 999px; padding: 8px 15px; font-size: 13.5px; font-weight: 800; color: var(--ink2); line-height: normal; cursor: pointer; }
.mng-bk-delete { flex: none; background: none; border: none; color: var(--danger); padding: 6px 4px; font-size: 13px; font-weight: 800; line-height: normal; cursor: pointer; }
.mng-bk-row.is-asking .mng-bk-restore, .mng-bk-row.is-asking .mng-bk-delete { display: none; }   /* App v3 notAsk */
/* the inline typed-RESTORE confirm (1127–1137, the site's typed keyword + count line inside it) */
.mng-bk-ask { margin-top: 11px; border-top: 1px solid var(--hair); padding-top: 11px; }
/* App v3 literal #a5382a → var(--danger) (LABELLED: tokenised, 5.4:1 on --card light / 5.5:1 dark) */
.mng-bk-warn { font-size: 12.5px; font-weight: 800; color: var(--danger); line-height: 1.45; margin-bottom: 10px; }
.mng-bk-type { display: block; font-size: 12.5px; font-weight: 700; color: var(--ink2); margin-bottom: 6px; }   /* site: the typed-keyword label */
/* 16 px: iOS Safari zooms the page on focus of any field under 16 px (the auth-input rule) */
.mng-bk-input { display: block; width: 100%; box-sizing: border-box; padding: 10px 12px; border: 1px solid var(--border); border-radius: 10px; background: var(--surface); color: var(--ink); font-size: 16px; font-weight: 700; margin-bottom: 10px; }
.mng-bk-askbtns { display: flex; gap: 9px; align-items: center; }
.mng-bk-askbtns .mng-cancel-btn { margin-left: 0; font-size: 13.5px; }                /* App v3 1131: 13.5, no auto margin */
.mng-bk-msg { font-size: 12.5px; font-weight: 700; color: var(--danger); margin-top: 8px; }
.mng-bk-msg:empty { display: none; }
.mng-bk-note { font-size: 12px; font-weight: 700; color: var(--muted2-text); /* d11 */ margin-top: 10px; }
/* LABELLED (site): the pointer to Clear history / Erase everything (plan-decided: they live in Account settings) */
.mng-pointer { font-size: 13px; font-weight: 600; color: var(--muted2-text); /* d11 */ line-height: 1.5; margin-top: 14px; }
.mng-link { background: none; border: none; padding: 0; font: inherit; font-weight: 800; color: color-mix(in oklab, var(--accent) 65%, var(--ink)); text-decoration: underline; text-underline-offset: 2px; cursor: pointer; }   /* the site's link colour (L26) */
@media (hover: hover) { .mng-link:hover { color: var(--ink); filter: none; } }
.mng-link:active { transform: none; }

/* 44-px targets on touch (ruling 11, G4 §1 — LABELLED: the look is unchanged on fine pointers) */
@media (pointer: coarse) {
  .mng-tab, .mng-chip, .mng-select-btn, .mng-go-pill, .mng-danger-pill, .mng-cancel-btn, .mng-text-btn, .mng-restore-btn,
  .mng-soft-btn, .mng-csv-btn, .mng-solid-btn, .mng-bk-restore, .mng-bk-delete { min-height: 44px; }
  .mng-tick { position: relative; }
  /* 20 → 44: the global .hit recipe, sized from the centre — an inset would be measured from the padding box, which
     the 1.5-px border shrinks (18 + 24 = 42 measured) */
  .mng-tick::after { content: ""; position: absolute; left: 50%; top: 50%; width: 100%; height: 100%; min-width: 44px; min-height: 44px; transform: translate(-50%, -50%); }
  .mng-link { position: relative; }
  .mng-link::after { content: ""; position: absolute; left: -4px; right: -4px; top: 50%; height: 44px; transform: translateY(-50%); }
}

/* ---------- acs- : the Account sheet + its two nested dialogs (App v3 1499–1709; t5.scrimStyle 4157,
   scrimNestedStyle 4158, sheetFix 4160, modeOn/modeOff 3848–3849, dangerBtn 3851, googleBtnStyle 4414–4416,
   themes 4378; js/account.js). Scrim = .ov-scrim, panel base = .sheet, header = .sheet-head / .sheet-eyebrow /
   .sheet-title / .sheet-x, body = .sheet-body. NO [data-sheet]: App v3's Account panel has no handle and no
   drag-to-dismiss (contract ruling 2) — ≤ 640 px it is a plain bottom sheet (.sheet's NARROW rule). ---------- */
.acs-sheet { width: 520px; max-height: calc(82dvh / var(--zf, 1)); display: flex; flex-direction: column; }
@media (max-width: 639.98px) {
  /* width restated: .acs-sheet comes after .sheet's NARROW rule; App v3 sheetFix 88 dvh; no handle → no padding-top */
  .acs-sheet { width: 100%; max-height: calc(88dvh / var(--zf, 1)); }
}
.acs-head, .ntf-head { flex: none; padding: 18px 22px 12px; }   /* App v3 1502 / 1714: 22 px sides (.sheet-head is 20) */
.acs-body, .ntf-body { min-height: 0; overscroll-behavior: contain; }   /* .sheet-body = flex 1, overflow auto, 0 22 24 */

/* section label (1507 …): 12 / 800 / .06em / uppercase / muted2 — Connected accounts .08em (1589), Danger zone accent (1642) */
.acs-label { font-size: 12px; font-weight: 800; letter-spacing: .06em; text-transform: uppercase; color: var(--muted2-text); /* d11 */ line-height: normal; margin-bottom: 8px; }
.acs-label--wide { letter-spacing: .08em; }
.acs-label--danger { color: var(--accent-text); /* d11 accent alias (App v3 var(--accent) — 4.36:1 on --card) */ }

/* the card (1508, 1580, 1590, 1601, 1620): 1px border, radius 14, --card, mb 24 */
.acs-card { border: 1px solid var(--border); border-radius: 14px; background: var(--card); margin-bottom: 24px; }
.acs-card--tight { margin-bottom: 6px; }                         /* Connected (1590) / Preferences (1620) — a note follows */
.acs-card--dev { margin-bottom: 8px; }                           /* Signed-in devices (1601) */
.acs-card--pad { padding: 14px 15px; }                           /* Appearance (1580) */
.acs-card--row { display: flex; align-items: center; gap: 12px; padding: 13px 15px; }   /* Google (1590) */
.acs-card--pref { display: flex; align-items: center; justify-content: space-between; gap: 14px; padding: 13px 15px; }   /* 1620 */
.acs-row { display: flex; align-items: center; gap: 12px; padding: 13px 15px; }
.acs-row--rule { border-top: 1px solid var(--hair); }            /* the Password row (1528) */
.acs-row-main { flex: 1; min-width: 0; }
.acs-row-title { display: block; font-size: 14px; font-weight: 800; color: var(--ink); line-height: normal; }
.acs-row-sub { display: block; font-size: 13px; font-weight: 600; color: var(--muted-text); /* d11 */ line-height: normal; margin-top: 2px; }
.acs-card--pref .acs-row-sub { line-height: 1.45; }             /* 1623 */
.acs-card--row .acs-row-sub { overflow-wrap: anywhere; }          /* LABELLED: the Google row's address wraps in its column (App v3 1595 runs it under the pill at 375) */
/* the site's loading / demo / error line in an account-dependent card (no App v3 twin — the design has sample data) */
.acs-sect-msg { padding: 13px 15px; font-size: 13px; font-weight: 600; color: var(--muted-text); /* d11 */ line-height: 1.45; }

/* Sign-in details (1507–1535) */
.acs-mini { font-size: 12px; font-weight: 800; letter-spacing: .06em; text-transform: uppercase; color: var(--muted2-text); /* d11 */ line-height: normal; margin-bottom: 4px; }
.acs-email-line { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.acs-email { font-size: 14px; font-weight: 700; color: var(--ink); line-height: normal; overflow-wrap: anywhere; min-width: 0; }
.acs-verified { display: inline-flex; align-items: center; gap: 4px; background: color-mix(in srgb, var(--go) 12%, transparent); color: var(--go-text); /* d11 go alias */ border-radius: 999px; padding: 2px 9px; font-size: 12px; font-weight: 800; line-height: normal; flex: none; white-space: nowrap; }
.acs-pill-btn { flex: none; background: var(--chip); border: none; border-radius: 999px; padding: 8px 15px; font-size: 13.5px; font-weight: 800; color: var(--ink2); line-height: normal; cursor: pointer; }
.acs-dots { font-size: 14px; font-weight: 800; color: var(--ink); letter-spacing: .15em; line-height: normal; }
.acs-dots--unset { letter-spacing: normal; font-weight: 700; color: var(--muted-text); }   /* "Not set" (site) */
/* the pending banner (1519–1527): accent 8 % wash, hairline above */
.acs-pending { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; padding: 10px 15px; background: color-mix(in srgb, var(--accent) 8%, transparent); border-top: 1px solid var(--hair); }
.acs-pending-text { flex: 1; min-width: 180px; font-size: 13.5px; font-weight: 700; color: var(--accent-text); line-height: 1.45; overflow-wrap: anywhere; }
.acs-pending-text b { font-weight: 900; }
.acs-resend { flex: none; background: none; border: 1px solid color-mix(in srgb, var(--accent) 40%, transparent); border-radius: 999px; padding: 5px 12px; font-size: 13px; font-weight: 800; color: var(--accent-text); line-height: normal; cursor: pointer; }
.acs-resend:disabled { opacity: .45; cursor: default; transform: none; filter: none; }
@media (max-width: 639.98px) {
  /* App v3's Resend + Cancel group is too wide to sit beside the text at phone width, so it drops below
     and the text takes the whole line (measured 299 px at 375). The site has no Cancel — Resend alone
     would fit beside a squeezed text column; the text keeps the whole line instead, as in App v3. */
  .acs-pending-text { flex-basis: 100%; }
}

/* Appearance (1579–1588) + the palette row (LABELLED addition — App v3 computes `themes` 4378 but renders no picker) */
.acs-sub-title { font-size: 13.5px; font-weight: 800; color: var(--ink); line-height: normal; margin-bottom: 3px; }
.acs-sub-title--gap { margin-top: 16px; }
.acs-sub-desc { font-size: 12.5px; font-weight: 600; color: var(--muted2-text); /* d11 */ line-height: 1.45; margin-bottom: 11px; }
.acs-seg { display: flex; gap: 6px; }
.acs-seg button { flex: 1; text-align: center; padding: 8px 0; border-radius: 999px; font-size: 14px; font-weight: 800; line-height: normal; background: var(--soft); color: var(--ink2); border: 1px solid var(--border); cursor: pointer; }
/* modeOn: --solid / --on-solid; border:none in App v3 — a same-colour border keeps the three the same height (the old menu segment's rule) */
.acs-seg button[aria-pressed="true"] { background: var(--solid); color: var(--on-solid); border-color: var(--solid); }
.acs-pal { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 6px; }
/* App v3's `themes` row (4378: gap 10, padding 8px 10px, radius 10, --chip when chosen) stacked chip-over-name so four fit a 375-px row */
.acs-pal-btn { display: flex; flex-direction: column; align-items: center; gap: 6px; min-width: 0; padding: 8px 4px; border-radius: 10px; border: 1px solid transparent; background: transparent; color: var(--ink2); font-size: 12.5px; font-weight: 800; line-height: normal; cursor: pointer; }
.acs-pal-btn[aria-pressed="true"] { background: var(--chip); border-color: var(--border); color: var(--ink); }
.acs-pal-chip { width: 40px; height: 26px; border-radius: 6px; border: 1px solid; flex: none; }
.acs-pal-name { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* App v3 4378's four previews — each palette's own light paper / tone / border (data, not tokens: they depict the palettes) */
.acs-pal-btn[data-palette="warm"] .acs-pal-chip { background: linear-gradient(120deg, #eee9de 48%, #b5814a 48%); border-color: #cdc3ac; }
.acs-pal-btn[data-palette="neutral"] .acs-pal-chip { background: linear-gradient(120deg, #eceae4 48%, #8f8b80 48%); border-color: #cbc8bf; }
.acs-pal-btn[data-palette="natural"] .acs-pal-chip { background: linear-gradient(120deg, #e9ebdf 48%, #7f9550 48%); border-color: #c6c9b6; }
.acs-pal-btn[data-palette="slate"] .acs-pal-chip { background: linear-gradient(120deg, #e6e9ee 48%, #6d7d9c 48%); border-color: #c4c8ce; }
/* the autosave line ("Changes save automatically." — App v3 1630 under Preferences; LABELLED: also under Appearance) */
.acs-status { font-size: 13px; font-weight: 600; color: var(--muted2-text); /* d11 */ line-height: normal; margin-bottom: 24px; }

/* Connected accounts (1589–1598) */
.acs-google-g { flex: none; }
.acs-google-btn { flex: none; background: none; border: 1px solid var(--border); border-radius: 999px; padding: 7px 14px; font-size: 13.5px; font-weight: 800; color: var(--ink2); line-height: normal; cursor: pointer; }   /* Disconnect */
.acs-google-btn--connect { background: var(--solid); border: none; padding: 7px 15px; color: var(--on-solid); }                                                                                            /* Connect */
.acs-google-btn:disabled { opacity: .6; cursor: default; transform: none; filter: none; }
.acs-after { margin-bottom: 24px; }
.acs-note { font-size: 13px; font-weight: 600; color: var(--muted2-text); /* d11 */ line-height: normal; }
.acs-msg { font-size: 13px; font-weight: 700; color: var(--danger); line-height: 1.45; margin-bottom: 6px; }
.acs-msg:empty { display: none; }

/* Signed-in devices (1600–1617): ONE row (no client API lists sessions) */
.acs-dev-line { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.acs-chip { background: var(--chip); color: var(--ink2); border-radius: 999px; padding: 2px 9px; font-size: 12px; font-weight: 800; line-height: normal; white-space: nowrap; }
.acs-text-btn { display: inline-block; background: none; border: none; padding: 2px 0; font-size: 14px; font-weight: 800; color: var(--accent-text); line-height: normal; cursor: pointer; }
.acs-text-btn:disabled { opacity: .45; cursor: default; transform: none; filter: none; }
.acs-after .acs-text-btn + .acs-msg { margin: 6px 0 0; }

/* Preferences (1619–1630) — LABELLED: 16 px (App v3 14.5) — the iOS zoom rule; padding 8 → 7 keeps App v3's 39.3-px box */
.acs-select { flex: none; border: 1px solid var(--border); border-radius: 10px; padding: 7px 10px; font-size: 16px; font-weight: 700; color: var(--ink); background: var(--surface); cursor: pointer; }

/* Data & privacy (1632–1640) — one full-width button */
.acs-data { width: 100%; display: flex; align-items: center; gap: 12px; border: 1px solid var(--border); border-radius: 14px; background: var(--card); padding: 13px 15px; margin-bottom: 24px; cursor: pointer; text-align: left; color: var(--ink); }
.acs-data-ico { flex: none; display: grid; color: var(--ink2); }
.acs-data-chev { flex: none; display: grid; color: var(--muted2); }   /* a glyph — verbatim token */

/* Danger zone (1642–1705) — App v3's literals as token mixes (they follow dark mode) */
.acs-danger { border: 1px solid color-mix(in srgb, var(--accent) 32%, transparent); border-radius: 14px; background: var(--card); overflow: hidden; }
.acs-dz { padding: 15px 16px; }
.acs-dz + .acs-dz { border-top: 1px solid color-mix(in srgb, var(--accent) 22%, transparent); }
.acs-dz-title { font-size: 14px; font-weight: 900; color: var(--accent-text); line-height: normal; margin-bottom: 4px; }
.acs-dz-title--danger { color: var(--danger); }
.acs-dz-desc { font-size: 13.5px; font-weight: 600; color: var(--muted-text); /* d11 */ line-height: 1.5; margin-bottom: 12px; }
.acs-dz-arm { background: none; border: 1.5px solid var(--accent); border-radius: 999px; padding: 7px 15px; font-size: 13.5px; font-weight: 800; color: var(--accent-text); line-height: normal; cursor: pointer; }
.acs-dz-arm--danger { border-color: var(--danger); color: var(--danger); }
.acs-arm-line { font-size: 14px; font-weight: 700; color: var(--accent-text); line-height: normal; margin-bottom: 10px; }   /* the Erase count line (App v3's Reset line 1668) */
.acs-arm-prompt { font-size: 14px; font-weight: 700; color: var(--accent-text); line-height: normal; margin-bottom: 8px; }
.acs-arm-prompt--danger { color: var(--danger); }
.acs-arm-row { display: flex; gap: 8px; align-items: center; }
/* LABELLED: 16 px (App v3 14) — the iOS zoom rule; padding 9 → 7.6 keeps App v3's 38.6-px box.
   #d9a88f / #d98f83 → accent 55 % / danger 60 % over --card (≈ the literals in light, follow dark) */
.acs-arm-input { flex: 1; min-width: 0; border: 1px solid color-mix(in oklab, var(--accent) 55%, var(--card)); border-radius: 10px; padding: 7.6px 12px; font-size: 16px; font-weight: 800; letter-spacing: .05em; color: var(--ink); background: var(--card); }
.acs-arm-input--danger { border-color: color-mix(in oklab, var(--danger) 60%, var(--card)); }
.acs-arm-input::placeholder { color: var(--muted-text); /* d11 — App v3 leaves the UA placeholder colour */ opacity: 1; }
/* dangerBtn(ok, var(--danger)) (3851): enabled = --danger; blocked = #e6cabf .75 not-allowed (→ accent 33 % over --card).
   Text on the fill = --on-solid (#fff light = App v3; #26231f dark — #fff on the dark --danger is 2.87:1) */
.acs-arm-go { flex: none; background: var(--danger); color: var(--on-solid); border: none; border-radius: 10px; padding: 10px 15px; font-size: 14px; font-weight: 800; line-height: normal; white-space: nowrap; cursor: pointer; }
.acs-arm-go:disabled { background: color-mix(in oklab, var(--accent) 33%, var(--card)); opacity: .75; cursor: not-allowed; transform: none; filter: none; }
.acs-arm-cancel { flex: none; background: none; border: none; padding: 1px 6px; /* the UA padding App v3 leaves (measured) */ font-size: 14px; font-weight: 800; color: var(--muted-text); /* d11 */ line-height: normal; cursor: pointer; }
.acs-arm-msg { font-size: 13px; font-weight: 700; color: var(--danger); line-height: 1.45; margin-top: 8px; }
.acs-arm-msg:empty { display: none; }
.acs-arm-foot { font-size: 13px; font-weight: 600; color: var(--muted2-text); /* d11 */ line-height: normal; margin-top: 12px; }
@media (max-width: 639.98px) {
  /* LABELLED: App v3 squeezes the input to 64 px at 375 (measured — "DELETE" does not fit): the input takes the first line */
  .acs-arm-row { flex-wrap: wrap; }
  .acs-arm-input { flex: 1 0 100%; }
}

/* the nested dialogs (1537–1577; scrimNestedStyle 4158 z 1010 rgba(30,28,24,.4)) */
.acs-dlg-scrim { z-index: 1010; /* --z-nested */ --layer-dim: var(--scrim-nested); }   /* .ov-scrim: transparent; its dim over Account is page-dim.js's box on the page (the dim- section) */
.acs-dlg { width: 400px; max-width: 100%; background: var(--panel); border-radius: 18px; box-shadow: 0 24px 60px rgba(0,0,0,.35); animation: popup .24s cubic-bezier(.22,1,.36,1); padding: 22px; text-align: left; }
@media (max-width: 639.98px) { .acs-dlg { width: 100%; border-radius: 18px 18px 0 0; max-height: calc(88dvh / var(--zf, 1)); overflow: auto; overscroll-behavior: contain; } }   /* sheetFix */
.acs-dlg-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 4px; }
.acs-dlg-title { font-family: 'Lora', serif; font-size: 18px; font-weight: 700; color: var(--ink); line-height: normal; }
.acs-dlg-x { width: 28px; height: 28px; font-size: 16px; }       /* App v3's dialog × (the sheets' is 30 / 17) */
.acs-dlg-help { font-size: 14px; font-weight: 600; color: var(--muted-text); /* d11 */ line-height: 1.5; margin-bottom: 16px; }
.acs-dlg-help b { font-weight: 900; color: var(--ink); }
.acs-fields { display: flex; flex-direction: column; gap: 8px; margin-bottom: 12px; }
.acs-fields--gap16 { margin-bottom: 16px; }
/* LABELLED: 16 px (App v3 14) — the iOS zoom rule; padding 11 → 9.6 keeps App v3's 42.6-px box */
.acs-input { display: block; width: 100%; border: 1px solid var(--border); border-radius: 10px; padding: 9.6px 12px; font-size: 16px; color: var(--ink); background: var(--card); }
.acs-input::placeholder { color: var(--muted-text); /* d11 — App v3 leaves the UA placeholder colour (3.39:1 on the dark card) */ opacity: 1; }
.acs-dlg-msg { font-size: 13px; font-weight: 700; color: var(--danger); line-height: 1.45; margin: -4px 0 12px; }
.acs-dlg-msg:empty { display: none; }
.acs-link { display: inline-block; background: none; border: none; padding: 0; text-align: left; font-size: 13.5px; font-weight: 800; color: var(--ink2); text-decoration: underline; line-height: normal; cursor: pointer; margin-bottom: 16px; }
.acs-link:disabled { opacity: .5; cursor: default; transform: none; filter: none; }
.acs-dlg-foot { display: flex; gap: 8px; justify-content: flex-end; }
.acs-dlg-cancel { background: none; border: none; padding: 11px 10px; font-size: 14.5px; font-weight: 800; color: var(--muted-text); /* d11 */ line-height: normal; cursor: pointer; }
.acs-dlg-go { background: var(--solid); color: var(--on-solid); border: none; border-radius: 10px; padding: 11px 18px; font-size: 14.5px; font-weight: 800; line-height: normal; cursor: pointer; }
.acs-dlg-go:disabled { opacity: .6; cursor: default; transform: none; filter: none; }

/* ---------- ntf- : the Notifications sheet (App v3 1711–1772; switchStyle 3854; js/notifications.js) ---------- */
.ntf-sheet { width: 480px; max-height: calc(82dvh / var(--zf, 1)); display: flex; flex-direction: column; }
@media (max-width: 639.98px) { .ntf-sheet { width: 100%; max-height: calc(88dvh / var(--zf, 1)); } }   /* width restated (after .sheet's NARROW rule) */
.ntf-intro { font-size: 14.5px; font-weight: 600; color: var(--ink2); line-height: 1.55; margin-bottom: 20px; }
.ntf-row { display: flex; align-items: flex-start; justify-content: space-between; gap: 14px; padding: 14px 0; border-top: 1px solid var(--divider); }
.ntf-row-text { min-width: 0; }
.ntf-row-title { font-size: 14.5px; font-weight: 800; color: var(--ink); line-height: normal; }
.ntf-row-desc { font-size: 13.5px; font-weight: 600; color: var(--muted-text); /* d11 */ line-height: 1.45; margin-top: 2px; }
/* switchStyle (3854): 44 × 25, pad 2, knob 19; on = --go; off #d8d3c6 → --bordersoft (#d8d3c5 light) */
.ntf-switch { flex: none; width: 44px; height: 25px; border-radius: 999px; border: none; padding: 2px; display: flex; align-items: center; justify-content: flex-start; background: var(--bordersoft); cursor: pointer; transition: background .15s, transform .1s ease, filter .12s ease; }
.ntf-switch[aria-checked="true"] { justify-content: flex-end; background: var(--go); }
/* LABELLED: App v3 keeps the light literal in dark mode; --bordersoft dark hides the knob — --muted3 (3.1:1 vs the knob) */
body[data-mode="dark"] .ntf-switch[aria-checked="false"] { background: var(--muted3); }
.ntf-switch:disabled { opacity: .5; cursor: default; transform: none; filter: none; }
.ntf-thumb { display: block; width: 19px; height: 19px; border-radius: 999px; background: var(--card); }
.ntf-panel { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 12px 14px; background: var(--chip); border-radius: 14px; margin: 4px 0 10px; }
.ntf-panel-label { font-size: 14.5px; font-weight: 700; color: var(--ink2); line-height: normal; }
.ntf-slot, .ntf-pair { display: inline-flex; gap: 8px; }
/* LABELLED: 16 px (App v3 14.5) — the iOS zoom rule; padding 8 → 7 keeps App v3's 39.3-px box */
.ntf-select { border: 1px solid var(--border); border-radius: 10px; padding: 7px 10px; font-size: 16px; font-weight: 700; color: var(--ink); background: var(--card); cursor: pointer; }
.ntf-select:disabled { opacity: .5; cursor: default; }
.ntf-foot { font-size: 13px; font-weight: 600; color: var(--muted2-text); /* d11 */ line-height: normal; margin-top: 6px; }

/* 44-px targets on touch (the look is unchanged on fine pointers; .sheet-x / .ntf-switch carry .hit) */
@media (pointer: coarse) {
  .acs-pill-btn, .acs-resend, .acs-seg button, .acs-pal-btn, .acs-google-btn, .acs-text-btn, .acs-select, .acs-data,
  .acs-dz-arm, .acs-arm-input, .acs-arm-go, .acs-arm-cancel, .acs-input, .acs-link, .acs-dlg-cancel, .acs-dlg-go, .ntf-select { min-height: 44px; }
}

/* ---------- store- : App v3's "Add to your board" sheet (App v3 1146–1328; _storeVals 3123–3216; js/store.js).
   Scrim = .ov-scrim, panel base = .sheet, header = .sheet-head / .sheet-eyebrow / .sheet-title / .sheet-x.
   NO [data-sheet]: App v3's store has no handle and no drag-to-dismiss (the Account precedent). ---------- */
/* Panel (1148): 460 px in Create, 720 px in every other view (3195); App v3's max-height 86dvh, written calc(86dvh / var(--zf, 1)) — the zoom rule. */
.store-sheet { width: 460px; max-height: calc(86dvh / var(--zf, 1)); display: flex; flex-direction: column; }
.store-sheet:not([data-view="create"]) { width: 720px; }
/* LABELLED DEVIATION (site): the Starter board keeps ONE height while its search filters (the owner's one-height
   rule for sheets). App v3 sizes the sheet to the filtered list, so each narrowing keystroke shrank the sheet
   and moved the search field under the typing (1280×900: y 175 → 432; a phone: toward the keyboard). The
   unfiltered library is always taller than the cap, so this is the height it opens at anyway. */
.store-sheet[data-view="starter"] { height: calc(86dvh / var(--zf, 1)); }
@media (max-width: 639.98px) {
  /* sheetFix (4160): full width, calc(88dvh / var(--zf, 1)) — restated here (these rules come after .sheet's NARROW rule) */
  .store-sheet, .store-sheet:not([data-view="create"]) { width: 100%; max-height: calc(88dvh / var(--zf, 1)); }
  .store-sheet[data-view="starter"] { height: calc(88dvh / var(--zf, 1)); }
}
/* header (1149): Back · title stack (flex 1) · Discover | Create · ×, gap 10 */
.store-head { justify-content: flex-start; gap: 10px; flex: none; }
.store-headtext { flex: 1; }
.store-title { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.store-hbtn { flex: none; display: inline-flex; align-items: center; gap: 6px; background: var(--chip); border: none; border-radius: 999px; padding: 7px 14px; font-size: 13.5px; font-weight: 800; color: var(--ink2); line-height: normal; cursor: pointer; white-space: nowrap; }
@media (hover: hover) { .store-hbtn--mode:hover { background: var(--soft); } }
.store-hbtn svg { flex: none; }
/* body (1156): the scroller */
.store-body { flex: 1 1 auto; min-height: 0; overflow: auto; overscroll-behavior: contain; padding: 2px 20px 16px; }
.store-view { animation: popup .24s cubic-bezier(.22,1,.36,1); }

/* ---- Create (1157–1195) ---- */
.store-seg { display: flex; gap: 3px; background: var(--chip); border-radius: 999px; padding: 3px; margin-bottom: 15px; }
.store-seg-btn { flex: 1; display: inline-flex; align-items: center; justify-content: center; gap: 7px; border: none; border-radius: 999px; padding: 9px 14px; font-size: 13.5px; font-weight: 800; line-height: normal; cursor: pointer; color: var(--muted-text); /* d11 */ background: transparent; box-shadow: none; }
.store-seg-btn[aria-pressed="true"] { color: var(--on-solid); background: var(--solid); box-shadow: 0 1px 3px rgba(60,56,48,.2); }
/* LABELLED (site, the owner's one-height rule): both forms share ONE grid cell, so the view keeps the Activity form's
   height when Category is chosen; the form not shown is visibility:hidden + inert (never focusable, never announced). */
.store-forms { display: grid; }
.store-form { grid-area: 1 / 1; min-width: 0; }
.store-form--off { visibility: hidden; }
/* The form a segment shows must be focusable AT ONCE: under prefers-reduced-motion the global rule (top of this file)
   gives EVERY element a .01ms transition of `all` — visibility included — so the name field was still
   visibility:hidden when setSegment focused it and the focus stayed on the segment button. Nothing in the forms
   transitions on purpose (buttons keep their own listed transitions), so the switch is instant in every mode. */
.store-form, .store-form :not(button) { transition-property: none; }
.store-lead { font-size: 13.5px; font-weight: 700; color: var(--muted-text); /* d11 */ line-height: 1.5; margin-bottom: 14px; }
.store-lead--starter { margin-bottom: 12px; }   /* App v3 1280: the Starter board's lead sits 12 above its search */
.store-fields { display: flex; flex-direction: column; gap: 14px; margin-bottom: 16px; }
.store-field { width: 100%; min-width: 0; }
.store-form--cat .store-field { margin-bottom: 16px; }
.store-label { display: block; font-size: 10.5px; font-weight: 800; letter-spacing: .08em; text-transform: uppercase; color: var(--muted2-text); /* d11 */ margin-bottom: 7px; line-height: normal; }
/* LABELLED DEVIATION: 16 px (App v3 15) — iOS zooms on focus of any field under 16 px (the hist-search / auth-input rule);
   padding 12 → 11.5 keeps App v3's 46-px box. Its focus: the field rule (the ring- section). */
.store-input { display: block; width: 100%; border: 1px solid var(--border); border-radius: 11px; padding: 11.5px 14px; font-size: 16px; font-weight: 600; color: var(--ink); background: var(--card); line-height: normal; }
.store-input::placeholder { color: var(--muted-text); /* d11 — App v3 leaves the UA placeholder colour */ opacity: 1; }
/* the category picker (1169–1177): a select-only combobox (button) + listbox */
.store-pick { position: relative; }
.store-pick-btn { width: 100%; display: flex; align-items: center; gap: 9px; background: var(--card); border: 1px solid var(--border); border-radius: 11px; padding: 12px 13px; cursor: pointer; text-align: left; line-height: normal; }
@media (hover: hover) { .store-pick-btn:hover { border-color: var(--muted2); } }
.store-pick-btn:active { transform: none; }            /* a full-width field, not a pill (the home-select precedent) */
.store-pick-btn:disabled { cursor: default; }
@media (hover: hover) { .store-pick-btn:disabled:hover { border-color: var(--border); filter: none; } }
.store-pick-dot { width: 12px; height: 12px; border-radius: 999px; flex: none; background: var(--muted2); }   /* inline background: the chosen category's colour */
.store-pick-val { flex: 1; min-width: 0; font-size: 15px; font-weight: 700; color: var(--ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.store-pick-chev { flex: none; stroke: var(--muted2); stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round; }
.store-pick-away { position: fixed; inset: 0; z-index: 5; background: transparent; }
/* the list opens UPWARD (App v3: bottom calc(100% + 6px)), 190 px max, scrolls */
.store-pick-list { list-style: none; position: absolute; bottom: calc(100% + 6px); right: 0; width: 100%; z-index: 6; max-height: 190px; overflow-y: auto; overscroll-behavior: contain; background: var(--panel); border: 1px solid var(--border); border-radius: 12px; box-shadow: 0 14px 34px rgba(0,0,0,.16); padding: 5px; display: flex; flex-direction: column; gap: 2px; }
.store-opt { flex: none; display: flex; align-items: center; gap: 9px; width: 100%; padding: 9px 10px; border-radius: 9px; cursor: pointer; font-size: 14px; font-weight: 700; color: var(--ink); line-height: normal; }
.store-opt[aria-selected="true"] { background: var(--soft); } @media (hover: hover) { .store-opt:hover { background: var(--soft); } }
/* LABELLED (a11y): the keyboard's active option (aria-activedescendant) carries a visible ring — App v3 has no keyboard
   path. Keyboard mode only: the trigger keeps the focus while the list is open, and it matches :focus-visible once a
   key is used (a mouse-opened list shows App v3's look — the --soft row and the tick, no ring). */
.store-pick:has(.store-pick-btn:focus-visible) .store-opt.is-active { outline: 2px solid var(--ink); outline-offset: -2px; }
.store-opt-dot { width: 11px; height: 11px; border-radius: 999px; flex: none; }
.store-opt-name { flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.store-opt-tick { flex: none; width: 20px; height: 20px; border-radius: 999px; background: var(--ink); display: grid; place-items: center; }
.store-opt-tick svg { stroke: var(--panel); stroke-width: 3; stroke-linecap: round; stroke-linejoin: round; fill: none; }
/* the Add / Create button (1180, 1188; storeCreateBtnStyle 3188) — LABELLED: var(--on-solid), not App v3's literal #fff
   (white on the dark mode's cream --solid is unreadable) */
.store-go { display: block; width: 100%; background: var(--solid); color: var(--on-solid); border: none; border-radius: 13px; padding: 14px; font-size: 15px; font-weight: 900; line-height: normal; cursor: pointer; }
.store-go:disabled { background: var(--chip2); color: var(--muted); cursor: default; }
@media (hover: hover) { .store-go:disabled:hover { filter: none; } }
/* footer (1190–1193, 1255–1260) */
.store-foot { display: flex; align-items: center; justify-content: center; gap: 8px; flex-wrap: wrap; margin-top: 18px; padding-top: 14px; border-top: 1px solid var(--hair); }
.store-foot-q { font-size: 12.5px; font-weight: 700; color: var(--muted2-text); /* d11 */ line-height: normal; }
.store-foot-link { background: none; border: none; padding: 2px 4px; color: var(--accent-text); /* d11 */ font-size: 12.5px; font-weight: 800; line-height: normal; cursor: pointer; }
.store-foot-dot { color: var(--muted2); line-height: normal; }

/* ---- Discover (1196–1262) — the lead and the Packs shelf. LABELLED (copy handoff, 2026-10-10): Discover labels are
   gone, and with them App v3's label strip, its chips, Clear and the label results (their rules were removed). ---- */
/* the starter-board browser's "no match" line */
.store-empty { text-align: center; color: var(--muted-text); /* d11 */ font-size: 14px; font-weight: 700; padding: 24px 12px; line-height: 1.5; }
/* pack-row cards (1268–1275) */
.store-cards { list-style: none; display: grid; grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); gap: 9px; }
.store-cards--pack { grid-template-columns: repeat(auto-fill, minmax(min(100%, 260px), 1fr)); }
.store-card { display: flex; align-items: center; gap: 10px; background: var(--card); border: 1px solid var(--border2); border-radius: 12px; padding: 11px 13px; }
.store-card-text { flex: 1; min-width: 0; }
.store-card-name { font-size: 14px; font-weight: 700; color: var(--ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.store-card-sub { display: inline-flex; align-items: center; gap: 6px; margin-top: 2px; }
.store-dot { width: 8px; height: 8px; border-radius: 999px; flex: none; background: var(--muted2); }   /* inline background: where it lands; the neutral default = a new category whose colour the data layer picks (store-model destination) */
.store-card-dest { font-size: 12px; font-weight: 700; color: var(--muted2-text); /* d11 */ }
.store-new { font-size: 10px; font-weight: 900; letter-spacing: .08em; color: var(--accent-text); /* d11 */ border: 1px solid var(--accent); border-radius: 999px; padding: 1px 6px; }
.store-plus { flex: none; width: 26px; height: 26px; border-radius: 999px; border: none; background: var(--chip2); color: var(--ink2); font-size: 16px; font-weight: 800; line-height: 0; display: grid; place-items: center; padding: 0; cursor: pointer; }
@media (hover: hover) { .store-plus:hover { background: var(--solid); color: var(--on-solid); } }
.store-tick { flex: none; font-size: 15px; font-weight: 800; color: var(--go-text); /* d11 */ }
/* the Packs header (1224) */
.store-packs-head { display: flex; align-items: center; gap: 9px; border-top: 1px solid var(--hair); margin-top: 6px; padding: 14px 2px 11px; }
.store-packs-head svg { flex: none; }
.store-packs-label { font-size: 12px; font-weight: 800; letter-spacing: .09em; text-transform: uppercase; color: var(--muted2-text); /* d11 */ line-height: normal; }
/* the default-board lead card (1225–1236) — LABELLED: margin-bottom 10 (App v3's card touches the first row of tiles) */
.store-lead-card { background: var(--solid); color: var(--on-solid); border-radius: 16px; padding: 18px 20px; margin-bottom: 10px; }
.store-lead-title { font-size: 17px; font-weight: 900; line-height: normal; }
.store-lead-line { font-size: 13px; font-weight: 700; opacity: .85; line-height: 1.5; margin-top: 3px; }
.store-lead-row { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; margin-top: 13px; }
.store-lead-add { flex: none; border: none; background: var(--card); color: var(--ink); border-radius: 999px; padding: 9px 16px; font-size: 13px; font-weight: 900; line-height: normal; cursor: pointer; }
.store-lead-browse { flex: none; background: transparent; color: var(--on-solid); border: 1px solid color-mix(in oklab, var(--on-solid) 40%, transparent); border-radius: 999px; padding: 9px 15px; font-size: 13px; font-weight: 800; line-height: normal; cursor: pointer; }
/* pack tiles (1237–1248): the band is the tile's real button; its ::after stretches over the tile, so the whole tile
   opens the pack (App v3's div role=button — which had no keyboard path); Add all sits above it */
.store-packs { list-style: none; display: grid; grid-template-columns: repeat(auto-fill, minmax(215px, 1fr)); gap: 10px; }
.store-pack { position: relative; display: flex; flex-direction: column; text-align: left; background: var(--card); border: 1px solid var(--border2); border-radius: 14px; overflow: hidden; min-height: 124px; transition: box-shadow .15s ease; }
@media (hover: hover) { .store-pack:hover { box-shadow: 0 6px 18px rgba(60,56,48,.14); } }
.store-pack:has(.store-pack-open:focus-visible) { outline: 2px solid var(--ink); outline-offset: 2px; }
.store-pack-open { flex: none; display: flex; align-items: center; justify-content: space-between; gap: 8px; width: 100%; background: var(--pk, #8a6a55); border: none; padding: 9px 13px; text-align: left; cursor: pointer; line-height: normal; }
.store-pack-open::after { content: ''; position: absolute; inset: 0; }
.store-pack-open:focus-visible { outline: none; }   /* the tile draws the ring */
.store-pack-open:active { transform: none; }        /* the tile is one surface (App v3's div never scaled) */
@media (hover: hover) { .store-pack-open:hover { filter: none; } }
.store-pack-name { min-width: 0; font-size: 14.5px; font-weight: 800; color: #fff; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.store-pack-n { flex: none; background: rgba(255,255,255,.24); color: #fff; border-radius: 999px; padding: 2px 9px; font-size: 11.5px; font-weight: 900; font-variant-numeric: tabular-nums; }
.store-pack-blurb { flex: 1; margin: 10px 13px 0; font-size: 12.5px; font-weight: 600; color: var(--muted-text); /* d11 */ line-height: 1.45; }
.store-pack-foot { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; margin: 11px 13px 12px; }
.store-pack-foottext { flex: 1; min-width: 0; font-size: 11.5px; font-weight: 600; color: var(--muted2-text); /* d11 */ white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.store-pack-add { position: relative; z-index: 1; flex: none; border: 1px solid var(--border); background: var(--card); color: var(--ink2); border-radius: 999px; padding: 7px 13px; font-size: 12.5px; font-weight: 800; line-height: normal; white-space: nowrap; cursor: pointer; }
/* the tuck button (1249–1251) */
.store-tuck { display: block; width: 100%; margin-top: 16px; background: transparent; border: 1.5px dashed var(--border2); border-radius: 14px; padding: 14px 16px; font-size: 13.5px; font-weight: 800; color: var(--ink2); line-height: normal; cursor: pointer; }

/* ---- Pack detail (1263–1278) ---- */
.store-band { display: flex; align-items: center; gap: 12px; background: var(--pk, #8a6a55); border-radius: 14px; padding: 13px 15px; margin: 2px 0 10px; }
.store-band-blurb { flex: 1; min-width: 0; font-size: 13px; font-weight: 700; color: #fff; line-height: 1.5; }
.store-band-n { flex: none; background: rgba(255,255,255,.24); color: #fff; border-radius: 999px; padding: 3px 10px; font-size: 11.5px; font-weight: 900; white-space: nowrap; line-height: normal; }
/* LABELLED: #3c3830 (the light --ink) — App v3's var(--ink) on its #fff pill vanishes in dark mode */
.store-band-add { flex: none; background: #fff; color: #3c3830; border: none; border-radius: 999px; padding: 8px 16px; font-size: 12.5px; font-weight: 800; white-space: nowrap; line-height: normal; cursor: pointer; }
.store-note { font-size: 12.5px; font-weight: 800; color: var(--accent-text); /* d11 */ margin: 2px 0 8px; line-height: normal; }

/* ---- Starter board (1279–1308) ---- */
.store-search { position: relative; margin-bottom: 12px; }
.store-search-ico { position: absolute; left: 13px; top: 50%; transform: translateY(-50%); color: var(--muted2); display: inline-flex; pointer-events: none; }
/* LABELLED DEVIATION: 16 px (App v3 14.5), padding 10 → 9 (the hist-search rule) */
.store-search-input { display: block; width: 100%; padding: 9px 13px 9px 34px; border: 1px solid var(--border); border-radius: 10px; font-size: 16px; font-weight: 600; color: var(--ink); background: var(--card); line-height: normal; -webkit-appearance: none; appearance: none; }
.store-search-input::placeholder { color: var(--muted-text); /* d11 */ opacity: 1; }
.store-search-input::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; }
.store-groups { list-style: none; }
.store-group { border: 1px solid var(--border2); border-radius: 14px; margin-bottom: 8px; overflow: hidden; }
.store-group-head { display: flex; align-items: center; gap: 10px; padding: 11px 12px; }
.store-group-dot { width: 11px; height: 11px; border-radius: 999px; flex: none; background: var(--muted2); }   /* inline background as .store-dot */
.store-group-toggle { flex: 1; min-width: 0; display: flex; align-items: center; justify-content: space-between; gap: 8px; background: none; border: none; padding: 0; cursor: pointer; text-align: left; line-height: normal; }
.store-group-toggle:active { transform: none; }
.store-group-name { min-width: 0; font-size: 14px; font-weight: 800; color: var(--ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.store-group-side { display: flex; align-items: center; gap: 8px; flex: none; }
.store-group-count { font-size: 12px; font-weight: 700; color: var(--muted2-text); /* d11 */ white-space: nowrap; }
.store-group-chev { flex: none; display: grid; place-items: center; color: var(--muted2); transform: rotate(-90deg); transition: transform .15s ease; }
.store-group-toggle[aria-expanded="true"] .store-group-chev { transform: none; }
.store-group-add { flex: none; background: var(--chip2); border: none; color: var(--ink2); font-size: 12.5px; font-weight: 800; border-radius: 999px; padding: 6px 12px; white-space: nowrap; line-height: normal; cursor: pointer; }
.store-group-add:disabled { background: none; cursor: default; color: var(--muted2-text); /* d11 */ font-size: 12px; padding: 6px 4px; }
@media (hover: hover) { .store-group-add:disabled:hover { filter: none; } }
.store-group-body { list-style: none; padding: 0 10px 8px; }
.store-row { display: flex; align-items: center; gap: 10px; padding: 8px 6px 8px 23px; border-radius: 9px; }
/* LABELLED (a11y — decision 11): App v3 dims an owned row to opacity .5 (its text then reads 2.0–2.2:1); the site keeps
   full opacity and writes the name in the d11 muted text colour instead (>= 4.5:1) — the same "already there" read. */
.store-row--owned .store-row-name { color: var(--muted-text); /* d11 */ }
.store-row-name { flex: 0 1 auto; min-width: 0; font-size: 14px; font-weight: 700; color: var(--ink2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; line-height: normal; }
.store-row > .store-plus, .store-row-own { margin-left: auto; }
.store-row-own { flex: none; font-size: 12px; font-weight: 800; color: var(--muted2-text); /* d11 */ text-transform: uppercase; letter-spacing: .06em; line-height: normal; }
/* LABELLED (readability): on a phone the row's name WRAPS instead of App v3's ellipsis — beside "On your board" a
   name was cut to a few letters ("Get some …"), which says nothing about what it adds. */
@media (max-width: 639.98px) { .store-row-name { white-space: normal; overflow-wrap: anywhere; } }

/* 44-px targets on touch (contract ruling 7, G4 §1 — LABELLED: the look is unchanged on fine pointers). The .hit class in
   the markup gives ＋, Add all, Back / Discover / Create / × and the per-card + a centred 44 × 44 area;
   the controls it does not cover grow to 44 here (the mng- / hist- rule) or take the same centred area. */
@media (pointer: coarse) {
  .store-seg-btn, .store-opt, .store-search-input, .store-lead-add, .store-lead-browse, .store-band-add { min-height: 44px; }
  /* text on a taller row (the group head is 52.7) / a text link: the .hit recipe, sized from the centre */
  .store-group-toggle, .store-foot-link { position: relative; }
  .store-group-toggle::after, .store-foot-link::after { content: ""; position: absolute; left: 50%; top: 50%; width: 100%; height: 100%; min-width: 44px; min-height: 44px; transform: translate(-50%, -50%); }
}

/* ---------- wel- : App v3's first-run Welcome (App v3 2303–2344; uWelcome* 3221–3247, the render values 4351–4356;
   js/welcome.js). Scrim = .ov-scrim, panel base = .sheet. NOT dismissable (no ×, no backdrop, no Esc) — App v3's has
   none; "Start blank" is the no-thanks door. No [data-sheet]: no handle. ---------- */
.wel-sheet { width: 460px; max-height: calc(86dvh / var(--zf, 1)); overflow: auto; overscroll-behavior: contain; padding: 34px 30px 26px; text-align: center; }
@media (max-width: 639.98px) { .wel-sheet { width: 100%; max-height: calc(88dvh / var(--zf, 1)); } }
.wel-eyebrow { font-size: 12px; font-weight: 800; letter-spacing: .16em; text-transform: uppercase; color: var(--muted2-text); /* d11 */ margin-bottom: 14px; line-height: normal; }
.wel-title { font-family: 'Lora', serif; font-weight: 700; font-size: 26px; color: var(--ink); line-height: 1.14; margin-bottom: 10px; }
.wel-title--choose { font-size: 24px; line-height: 1.16; margin-bottom: 18px; }
.wel-title--anchor { margin-bottom: 12px; }
/* The focus moves to the title of the screen that shows (welcome.js — a focus change a screen reader announces);
   a heading is not a control: no ring, like the dialog panels (polish ruling 1). */
.wel-title[tabindex="-1"]:focus { outline: none; }
.wel-sub { font-size: 14.5px; font-weight: 600; color: var(--ink2); line-height: 1.55; margin-bottom: 22px; }
.wel-primary { display: block; width: 100%; text-align: left; background: var(--solid); color: var(--on-solid); border: none; border-radius: 16px; padding: 16px 18px; margin-bottom: 12px; cursor: pointer; }
.wel-second { display: block; width: 100%; text-align: left; background: var(--card); border: 1px solid var(--border); border-radius: 16px; padding: 15px 18px; margin-bottom: 14px; cursor: pointer; }   /* 18 → 14: the smaller door follows (owner, 2026-10-01) */
@media (hover: hover) { .wel-second:hover { background: var(--chip); } }
.wel-btn-title { display: block; font-size: 15.5px; font-weight: 900; margin-bottom: 4px; line-height: normal; }
.wel-btn-sub { display: block; font-size: 13px; font-weight: 700; opacity: .85; line-height: 1.4; }
.wel-second .wel-btn-title { font-size: 15px; color: var(--ink); margin-bottom: 3px; }
.wel-second .wel-btn-sub { opacity: 1; color: var(--muted-text); /* d11 */ line-height: normal; }
/* Screen 1's ONE smaller door, "Start blank" (copy handoff, 2026-10-10: the second small door went with the
   starter tier — LABELLED: App v3 has a text link here, the site keeps the owner's small button, 2026-10-01). Alone in
   its row it is CENTRED at its own width (a 150-px floor), so it never reads as half of a pair or as a third full-width
   door; 44 px tall by min-height (no .hit needed). */
.wel-minor { display: flex; justify-content: center; }
.wel-small { flex: none; min-width: 150px; min-height: 44px; background: var(--card); border: 1px solid var(--border); border-radius: 12px; padding: 10px 22px; font-size: 13px; font-weight: 800; line-height: 1.3; color: var(--ink2); text-align: center; cursor: pointer; }
@media (hover: hover) { .wel-small:hover { background: var(--chip); } }
/* The category list scrolls inside its own cap (owner, 2026-10-11 — round 2, P3; App v3's list has no cap and no hint):
   the cap is 46dvh (it was 38: 7–9 of the 20 categories sat out of view on a phone and "Music" was cut on a 1280 × 800
   laptop) — but never more than the sheet can hold beside the rest of this screen (about 270 px: on a short screen the
   SHEET would start to scroll and push the Add button away), and never under the old 38dvh. While rows remain BELOW,
   welcome.js sets .has-more and the list's bottom edge fades (--wel-fade); at the end of the list, and whenever
   everything fits, there is no fade. scroll-padding keeps a chip the keyboard reaches 4 px above the fade: its ring whole.
   Under 360 px the title takes THREE lines (measured: from 342 px down), so the rest of the screen is about 297 px:
   the narrow rule reserves 300. On a 320 × 568 screen the list is then the old 38dvh and the sheet scrolls by the 12 px
   it always did there (Add and Back on screen); without the rule it was 24. */
.wel-areas { --wel-fade: 32px; display: flex; flex-wrap: wrap; gap: 8px; justify-content: center; margin-bottom: 20px; max-height: max(calc(38dvh / var(--zf, 1)), min(calc(46dvh / var(--zf, 1)), calc(86dvh / var(--zf, 1) - 272px))); overflow-y: auto; overscroll-behavior: contain; scroll-padding-bottom: calc(var(--wel-fade) + 4px); }
@media (max-width: 639.98px) { .wel-areas { max-height: max(calc(38dvh / var(--zf, 1)), min(calc(46dvh / var(--zf, 1)), calc(88dvh / var(--zf, 1) - 272px))); } }   /* the phone sheet's own cap is 88dvh */
@media (max-width: 359.98px) { .wel-areas { max-height: max(calc(38dvh / var(--zf, 1)), min(calc(46dvh / var(--zf, 1)), calc(88dvh / var(--zf, 1) - 300px))); } }   /* a three-line title */
.wel-areas.has-more { -webkit-mask-image: linear-gradient(180deg, #000 calc(100% - var(--wel-fade)), transparent 100%); mask-image: linear-gradient(180deg, #000 calc(100% - var(--wel-fade)), transparent 100%); }
.wel-area { display: inline-flex; align-items: center; gap: 6px; border: 1.5px solid var(--border); background: var(--card); color: var(--ink2); border-radius: 999px; padding: 8px 13px; font-size: 13px; font-weight: 800; line-height: normal; white-space: nowrap; cursor: pointer; }
.wel-area[aria-pressed="true"] { border-color: var(--wc); background: color-mix(in srgb, var(--wc) 14%, transparent); color: var(--ink); }
.wel-area-n { opacity: .55; }
.wel-area:focus-visible { outline-offset: -2px; }   /* the list scrolls (clips) and its chips touch its edges: the ring goes inside so all four sides show */
@media (pointer: coarse) { .wel-area { min-height: 44px; } }   /* 44-px targets on touch (ruling 7 — LABELLED; Back carries .hit, .wel-small its own min-height) */
.wel-go { display: block; width: 100%; background: var(--solid); color: var(--on-solid); border: none; border-radius: 14px; padding: 15px; font-size: 15px; font-weight: 900; line-height: normal; cursor: pointer; }
.wel-go:disabled { background: var(--chip2); color: var(--muted); cursor: default; }
@media (hover: hover) { .wel-go:disabled:hover { filter: none; } }
.wel-back { background: none; border: none; padding: 1px 6px; margin-top: 14px; color: var(--muted-text); /* d11 */ font-size: 14px; font-weight: 800; line-height: normal; cursor: pointer; }
.wel-body { font-size: 14.5px; font-weight: 600; color: var(--ink2); line-height: 1.58; margin-bottom: 18px; text-wrap: pretty; }
/* The anchor ("Before you begin" — the owner's words, 2026-10-11): the heading, the text, then How it works' own
   example (.how-ex — ONE component, the same look; left-aligned in the centred sheet) and, under it, the closing line:
   a quiet takeaway — the heading's face, much smaller, centred, with its own space above so it does not read as part
   of the example. ONE line at every screen size (the owner, the same day): on a phone the sheet is as wide as the
   screen, so the line's size follows the width — (100vw − the room it may not use) / 25, never over 16 px; 25 = the
   line's width at 1 px (22.2, measured) plus 12 % for a rasterizer that sets the same fonts wider (Linux, Android).
   It may reach 8 px into the sheet's side padding before it would wrap. Its two halves never break inside (nowrap):
   should a line ever not fit after all, it breaks after its comma, nowhere else. A current iPhone: about 14.5 px. */
.wel-ex { text-align: left; margin-bottom: 18px; }
.wel-takeaway { font-family: 'Lora', serif; font-size: 16px; font-weight: 600; line-height: 1.35; color: var(--ink2); margin-bottom: 20px; }
.wel-takeaway > span { white-space: nowrap; }
@media (max-width: 639.98px) {
  .wel-sheet:has(#welAnchor:not([hidden])) { padding-left: 22px; padding-right: 22px; }   /* 30 → 22: the lines wrap later */
  .wel-takeaway { margin-left: -8px; margin-right: -8px; font-size: min(16px, calc((100vw - 28px) / 25)); }
}
@media (max-width: 359.98px) {
  .wel-sheet:has(#welAnchor:not([hidden])) { padding-left: 20px; padding-right: 20px; }
  .wel-takeaway { font-size: calc((100vw - 24px) / 25); }
  #welAnchor .how-ex-time { width: 54px; }
}
/* Small phones: the anchor is the tallest Welcome screen. Its SPACING tightens so the whole screen shows without
   scrolling — never its words (owner, 2026-10-11). Small = up to 700 px tall: an iPhone SE (375 x 553 in Safari,
   375 x 667 on the home screen), a current iPhone in Safari (390 x 664), a small Android (360 x 560 in its browser,
   360 x 640 on the home screen). The room is sized for WIDER text than a Mac draws: Linux and Android set the same
   fonts a little wider, so the text, an example row and the Undo line each wrap a line sooner there (CI, 2026-10-11:
   it scrolled by 4 px at 360 x 560). */
@media (max-width: 639.98px) and (max-height: 700px) {
  .wel-sheet:has(#welAnchor:not([hidden])) { padding-top: 20px; padding-bottom: 14px; }
  #welAnchor .wel-eyebrow { margin-bottom: 8px; }
  #welAnchor .wel-title--anchor { margin-bottom: 8px; }
  #welAnchor .wel-body { margin-bottom: 12px; line-height: 1.5; }
  #welAnchor .wel-ex { padding: 12px; margin-bottom: 12px; }
  #welAnchor .how-ex-eyebrow { margin-bottom: 8px; }
  #welAnchor .how-ex-rows { gap: 8px; }
  #welAnchor .how-ex-row { gap: 10px; }
  #welAnchor .how-ex-time { width: 54px; }
  #welAnchor .how-ex-total { margin-top: 8px; padding-top: 8px; }
  #welAnchor .wel-takeaway { margin-bottom: 12px; }
  #welAnchor .wel-begin { padding: 13px; }
  #welAnchor .wel-undo-row { margin-top: 8px; }
}
/* An old 320 x 568 phone: everything takes a line more. */
@media (max-width: 359.98px) and (max-height: 700px) {
  .wel-sheet:has(#welAnchor:not([hidden])) { padding-top: 16px; padding-bottom: 12px; }
  #welAnchor .wel-title--anchor { font-size: 24px; }
  #welAnchor .wel-body { margin-bottom: 10px; }
  #welAnchor .wel-ex { padding: 10px 12px; margin-bottom: 10px; }
  #welAnchor .wel-takeaway { margin-bottom: 10px; }
  #welAnchor .wel-begin { padding: 12px; }
}
.wel-begin { display: block; width: 100%; background: var(--accent); color: var(--on-solid); border: none; border-radius: 14px; padding: 14px; font-size: 15px; font-weight: 900; line-height: normal; cursor: pointer; }
/* The anchor's Undo row (tidy ruling 3): the store's words in a quiet line under "Let’s begin"; the Undo a text button
   (its 44-px touch area is the markup's .hit). */
.wel-undo-row { margin-top: 14px; font-size: 13px; font-weight: 700; line-height: 1.4; color: var(--muted-text); /* d11 */ text-wrap: balance; }
.wel-undo { background: none; border: none; padding: 1px 4px; font: inherit; font-weight: 900; color: var(--ink); text-decoration: underline; text-underline-offset: 3px; cursor: pointer; }
.wel-undo:disabled { color: var(--muted-text); cursor: default; }
/* LABELLED (site): the seed's status line — App v3's Welcome cannot fail (a mock); the site's write can */
.wel-status { margin-top: 14px; font-size: 12.5px; font-weight: 700; color: var(--muted-text); /* d11 */ line-height: 1.4; }
.wel-status:empty { display: none; }
.wel-status[data-error] { color: var(--danger); }

/* ---------- qlog- : direct logging (App v3 step 8; js/quick-log.js + js/old-cart.js): the "+1" pop (popStyle 3717,
   720 ms — uInc 2801) on a board pill (.bd-pill is its anchor) and the old-cart banner. The pill's count badge is
   .bd-pill-count (the bd-pill family); a deck card keeps its own badge (.deck-card-count). ---------- */
.qlog-pop { position: absolute; top: -8px; left: 50%; z-index: 6; background: color-mix(in oklab, var(--cat, #3c3830) 86%, #fff); color: #fff; font-size: 12px; font-weight: 900; line-height: normal; border-radius: 999px; padding: 1px 7px; white-space: nowrap; pointer-events: none; animation: floatup .6s ease forwards; }
body[data-mode="dark"] .qlog-pop { background: color-mix(in oklab, var(--cat-acc, #e8e0d2) 86%, #fff); color: #26231f; }
/* Reduced motion: the pop stays still for its 720 ms (never a zero-length flash). */
@media (prefers-reduced-motion: reduce) { .qlog-pop, .deck-pop { animation: none !important; transform: translateX(-50%); } }

/* the board's own banners (the old cart, the picked past day, Add to Home Screen — none is in App v3): the demo
   strip's layout (L132–140) on the board's QUIET TRAY — the Smart tags tray's surface (.sm-card: --soft, the
   --border2 hairline, 14-px corners). Owner, 2026-10-12: the earlier accent wash with an accent border, borrowed from
   Account's "waiting on verification" row, matched nothing else on the board; a white card was "too loud". */
.qlog-banner { display: flex; align-items: center; justify-content: center; gap: 14px; flex-wrap: wrap; background: var(--soft); border: 1px solid var(--border2); border-radius: 14px; padding: 10px 16px; margin-bottom: 14px; }
.qlog-banner[hidden] { display: none; }
.qlog-banner-msg { font-size: 14px; font-weight: 800; color: var(--ink); }
.qlog-banner-acts { display: inline-flex; gap: 8px; align-items: center; }
.qlog-banner-log { background: var(--solid); color: var(--on-solid); border: none; border-radius: 999px; padding: 8px 15px; font-size: 13px; font-weight: 900; white-space: nowrap; cursor: pointer; }
.qlog-banner-discard { background: none; border: none; border-radius: 999px; padding: 5px 8px; font-size: 13px; font-weight: 800; color: var(--muted-text); white-space: nowrap; cursor: pointer; }
.qlog-banner-log:disabled, .qlog-banner-discard:disabled { opacity: .45; cursor: default; transform: none; filter: none; }

/* ---------- deck- : App v3's deck (L320–428; deckBar* / deckToggleBtnStyle 4240, deckCtrlWrapStyle 4026, the spacers
   4012–4013, the Deal split 334–337 + dealSepStyle 4235 + deckCaretStyle 4236, dealMenuStyle 4155 = _menuCss,
   the deck message L391, deckLayoutStyle 4242 = js/deal.js deckLayout, the card _deckRv 3756–3794; js/deck.js). ---------- */
.deck[hidden] { display: none; }
/* the bar */
.deck-bar { display: flex; align-items: center; gap: 10px; width: 100%; padding: 2px 6px 10px; margin-bottom: 14px; border-bottom: 1px solid var(--hair); }
.deck.is-collapsed .deck-bar { margin-bottom: 26px; border-bottom: 2px dashed var(--bordersoft); }
.deck-bar-lead { flex: 1; display: flex; align-items: center; gap: 10px; color: var(--muted); min-width: 0; }
.deck-bar-ico { flex: none; opacity: .9; }
.deck-bar-label { font-size: 12px; font-weight: 800; letter-spacing: .14em; text-transform: uppercase; line-height: normal; color: var(--muted-text); /* d11 — App v3 var(--muted) */ }
.deck-toggle { display: inline-flex; align-items: center; gap: 6px; flex: none; white-space: nowrap; cursor: pointer; background: var(--card); color: var(--ink2); border: 1px solid var(--border); border-radius: 999px; padding: 9px 18px; font-size: 14px; font-weight: 800; }
.deck.is-collapsed .deck-toggle { background: var(--solid); color: var(--on-solid); border: none; padding: 9px 20px; }
.deck-toggle-down, .deck.is-collapsed .deck-toggle-up { display: none; }
.deck.is-collapsed .deck-toggle-down { display: block; }
.deck-body[hidden] { display: none; }
/* the controls row + the Deal split button */
.deck-ctrl { position: relative; z-index: 30; display: flex; justify-content: center; align-items: center; gap: 8px; margin-bottom: 14px; flex-wrap: wrap; animation: deckReveal .3s ease both; }
.deck-ctrl.is-open { z-index: 60; }   /* App v3 _hostZ(open, 30) */
.deck-ctrl-spacer { flex: 1; min-width: 0; }
.deck-ctrl-right { flex: 1; min-width: 0; display: flex; justify-content: flex-end; }
.deck-anchor { position: relative; }
.deck-split { display: inline-flex; align-items: stretch; border-radius: 999px; box-shadow: 0 3px 10px rgba(60,56,48,.22); }
.deck-deal { display: inline-flex; align-items: center; gap: 9px; height: 46px; background: var(--solid); color: var(--on-solid); border: none; border-radius: 999px 0 0 999px; padding: 0 10px 0 22px; font-weight: 800; font-size: 14.5px; white-space: nowrap; cursor: pointer; }
.deck-deal-ico { flex: none; }
.deck-deal-ico rect { fill: var(--solid); }   /* App v3 fill="var(--solid)": the front card hides the back one's lines */
.deck-deal-sep { width: 1px; height: 15px; background: color-mix(in oklab, currentColor 30%, transparent); margin: 0 3px 0 5px; flex: none; }
.deck-deal-src { font-weight: 800; font-size: 12px; letter-spacing: .09em; text-transform: uppercase; opacity: .62; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
body[data-mode="dark"] .deck-deal-src { opacity: .7; }   /* LABELLED: App v3's .62 reads 4.19:1 on the light dark-mode --solid; .7 reads ≥ 4.5 */
.deck-deal-n { font-weight: 800; font-size: 12px; opacity: .72; font-variant-numeric: tabular-nums; }
.deck-caret { display: inline-flex; align-items: center; justify-content: center; height: 46px; background: var(--solid); color: var(--on-solid); border: none; border-left: 1px solid color-mix(in oklab, currentColor 26%, transparent); border-radius: 0 999px 999px 0; padding: 0 15px; font-size: 15px; cursor: pointer; }
.deck-caret-chev { display: inline-block; transition: transform .2s cubic-bezier(.2,.85,.3,1.12); }
.deck-caret-chev svg { display: block; }
.deck-caret[aria-expanded="true"] .deck-caret-chev { transform: rotate(180deg); }
/* the Deal menu — _menuCss({ align:'center', top:'52px', w:240, fixedW:240, anchored:true, maxH:'min(46dvh, 360px)' }) — dvh ÷ var(--zf, 1) here
   + { display:flex; flex-direction:column; overflow:hidden }; NARROW: _menuCss({ sheet:true }) (no handle: not data-sheet) */
.deck-menu { display: none; position: absolute; top: 52px; left: 50%; transform: translateX(-50%); z-index: 40; /* --z-menu */ width: 240px; max-height: min(calc(46dvh / var(--zf, 1)), 360px); flex-direction: column; overflow: hidden; background: var(--card); border: 1px solid var(--border2); border-radius: 14px; padding: 8px; box-shadow: 0 12px 30px rgba(0,0,0,.18); animation: menuIn .16s ease; text-align: left; }
.deck-menu.visible { display: flex; }
.deck-menu-scroll { flex: 1 1 auto; min-height: 0; overflow: auto; overscroll-behavior: contain; }
.deck-pane[hidden] { display: none; }
.deck-now { padding: 10px 12px 9px; }
.deck-now-row { display: flex; align-items: baseline; gap: 7px; margin-bottom: 7px; }
.deck-now-label { flex: none; font-size: 12px; font-weight: 800; letter-spacing: .09em; text-transform: uppercase; color: var(--muted2-text); }
.deck-now-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 13.5px; font-weight: 900; color: var(--ink); }
.deck-now-kind-row { display: flex; }
.deck-now-kind { font-size: 11px; font-weight: 800; letter-spacing: .06em; text-transform: uppercase; color: var(--muted-text); /* LABELLED d11: --muted2-text reads 4.25:1 on dark --chip */ background: var(--chip); border-radius: 999px; padding: 2px 8px; }
.deck-menu-hr { height: 1px; background: var(--hair); margin: 0 4px 5px; }
.deck-menu-sep { height: 1px; background: var(--border2); margin: 6px 4px; }
.deck-menu-head { font-size: 12px; font-weight: 800; letter-spacing: .09em; text-transform: uppercase; color: var(--muted2-text); padding: 4px 11px 3px; }
.deck-menu-head--board { padding: 2px 11px 3px; }
.deck-src { display: block; width: 100%; text-align: left; background: none; border: none; cursor: pointer; padding: 8px 11px; border-radius: 10px; }
.deck-src-title { display: block; font-size: 14.5px; font-weight: 700; color: var(--ink); }
.deck-src-sub { display: block; font-size: 12px; font-weight: 600; color: var(--muted-text); line-height: 1.35; margin-top: 1px; }
.deck-nav { display: flex; align-items: center; gap: 7px; width: 100%; text-align: left; background: none; border: none; cursor: pointer; color: var(--ink); font-size: 14.5px; font-weight: 700; padding: 9px 11px; border-radius: 10px; }
.deck-nav[hidden] { display: none; }
.deck-nav svg { flex: none; color: var(--muted2); }
.deck-nav-name { flex: 1; min-width: 0; }
.deck-count { flex: none; font-size: 12px; font-weight: 800; color: var(--muted2-text); }
.deck-back { position: sticky; top: 0; z-index: 2; display: flex; align-items: center; gap: 6px; width: 100%; text-align: left; background: var(--card); border: none; border-bottom: 1px solid var(--hair); cursor: pointer; color: var(--ink2); padding: 9px 11px 10px; margin: 0 0 4px; border-radius: 10px; }
@media (hover: hover) { .deck-back:hover { color: var(--ink); } }
.deck-back-label { font-size: 12px; font-weight: 800; letter-spacing: .08em; text-transform: uppercase; }
.deck-pick { display: flex; align-items: center; gap: 8px; width: 100%; text-align: left; background: none; border: none; cursor: pointer; color: var(--ink); font-size: 14px; font-weight: 700; padding: 10px 11px; border-radius: 10px; }
.deck-pick-dot { flex: none; width: 8px; height: 8px; border-radius: 999px; }
.deck-pick-name { flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
@media (hover: hover) { .deck-src:hover, .deck-nav:hover, .deck-pick:hover { background: var(--chip); } }
.deck-foot { flex: none; display: flex; align-items: center; gap: 12px; border-top: 1px solid var(--hair); margin: 6px 0 0; padding: 10px 11px 4px; }
.deck-foot-label { font-size: 12px; font-weight: 800; letter-spacing: .06em; text-transform: uppercase; white-space: nowrap; color: var(--muted2-text); }
.deck-step { display: inline-flex; align-items: center; gap: 5px; }
.deck-step-btn { width: 27px; height: 27px; border: none; border-radius: 999px; background: var(--chip); color: var(--ink); font-size: 17px; font-weight: 900; line-height: 1; display: grid; place-items: center; padding: 0; cursor: pointer; }
.deck-step-btn--more { font-size: 16px; }
.deck-step-btn:disabled { opacity: .4; cursor: default; transform: none; filter: none; }
.deck-step-n { min-width: 18px; text-align: center; font-size: 14px; font-weight: 900; color: var(--ink); }
@media (max-width: 639.98px) {
  .deck-ctrl.is-open { z-index: 1010; }   /* _hostZ narrow → Z.nested: the sheet rises over every page layer */
  .deck-ctrl-spacer { display: none; }
  .deck-ctrl-right { flex: 1 0 100%; justify-content: center; }
  .deck-menu { position: fixed; left: 0; right: 0; bottom: 0; top: auto; transform: none; z-index: 1000; /* --z-overlay */ width: 100%; max-width: none; max-height: calc(72dvh / var(--zf, 1)); overscroll-behavior: contain; padding: 8px 8px calc(8px + env(safe-area-inset-bottom, 0px)); border-radius: 18px 18px 0 0; border-bottom: none; animation: sheetUp .22s ease; box-shadow: 0 -18px 50px rgba(0,0,0,.34); }
}
/* the deck message (L391): a 0-height holder, the pill hangs over the top of the strip for 2200 ms */
.deck-msg-holder { position: relative; height: 0; }
.deck-msg { position: absolute; left: 50%; top: 1px; transform: translateX(-50%); z-index: 40; pointer-events: none; white-space: nowrap; background: var(--card); border: 1px solid var(--border2); border-radius: 999px; padding: 5px 14px; font-size: 13.5px; font-weight: 700; color: var(--muted-text); box-shadow: 0 6px 18px rgba(0,0,0,.12); }
.deck-msg[hidden] { display: none; }
/* the strip — deal.js deckLayout(n, innerWidth) → --deck-gap / --deck-max / --deck-basis + .is-compact */
.deck-strip-wrap { position: relative; margin-bottom: 24px; animation: deckReveal .34s ease both; }
.deck-strip { display: flex; flex-wrap: wrap; justify-content: center; align-content: flex-start; gap: var(--deck-gap, 13px); padding: 2px 0 6px; max-width: var(--deck-max, 100%); margin: 0 auto; width: 100%; }
.deck-empty { flex: 1 0 100%; width: 100%; border: 2px dashed var(--border2); border-radius: 18px; padding: 30px 20px; text-align: center; display: flex; flex-direction: column; align-items: center; justify-content: center; }
.deck-empty[hidden] { display: none; }
.deck-empty-title { font-size: 14.5px; font-weight: 900; color: var(--ink2); margin-bottom: 5px; }
.deck-empty-sub { font-size: 13.5px; font-weight: 700; color: var(--muted-text); line-height: 1.5; }
.deck-empty-sub b { color: var(--ink2); }
/* a card: the visual box (the dealt colour mixHex(color, '#f5f2e9', .15) set inline); the + is the WHOLE card
   (.deck-card-btn fills it); the swap button sits on top, bottom-left. */
.deck-card { position: relative; display: flex; flex: 0 1 var(--deck-basis, 100%); max-width: 100%; min-width: 0; color: #fff; border-radius: 18px; overflow: hidden; box-shadow: 0 4px 14px rgba(0,0,0,.10); transition: box-shadow .2s; user-select: none; -webkit-user-select: none; -webkit-touch-callout: none; animation: dealIn .42s cubic-bezier(.22,1,.36,1) both; animation-delay: var(--deal-delay, 0s); }
.deck-card.is-swapped { animation: cardSwap .24s ease both; animation-delay: 0s; }
.deck-card.is-tap-a { animation: dealIn .42s cubic-bezier(.22,1,.36,1) both, cardTapA .34s cubic-bezier(.34,1.56,.64,1); animation-delay: var(--deal-delay, 0s), 0s; }
.deck-card.is-tap-b { animation: dealIn .42s cubic-bezier(.22,1,.36,1) both, cardTapB .34s cubic-bezier(.34,1.56,.64,1); animation-delay: var(--deal-delay, 0s), 0s; }
.deck-card.is-swapped.is-tap-a { animation: cardSwap .24s ease both, cardTapA .34s cubic-bezier(.34,1.56,.64,1); animation-delay: 0s, 0s; }
.deck-card.is-swapped.is-tap-b { animation: cardSwap .24s ease both, cardTapB .34s cubic-bezier(.34,1.56,.64,1); animation-delay: 0s, 0s; }
.deck-card-btn { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 12px; min-height: 180px; padding: 14px 15px 13px; background: none; border: none; border-radius: inherit; color: inherit; text-align: center; cursor: pointer; transition: none; }
@media (hover: hover) { .deck-card-btn:hover { filter: none; } }
.deck-card-btn:active { transform: none; }
.deck-card-btn:focus-visible { outline: 2px solid #fff; outline-offset: -4px; }   /* LABELLED a11y: the card clips an outside ring */
.deck-card-head { display: flex; align-items: center; justify-content: flex-end; gap: 8px; min-height: 22px; }
.deck-card-name { flex: 1; display: flex; align-items: center; justify-content: center; text-align: center; padding: 8px 6px; font-size: 19px; font-weight: 800; line-height: 1.2; overflow-wrap: anywhere; }
.deck-card-foot { min-height: 30px; }
/* the count: App v3's OWN deck-card badge (template 405–424, logic 3785–3791) — a soft white pill (rgba(255,255,255,.26)),
   #fff 13 / 900, 26 px tall, top 11 / right 11, replaying `pulse` .3s on a change — showing TODAY's total, hidden at 0.
   (The board's pills keep the Lora MAIN badge; the owner, 2026-09-30, asked for the deck's own look back.) */
.deck-card-count { position: absolute; top: 11px; right: 11px; z-index: 5; min-width: 26px; height: 26px; padding: 0 8px; border-radius: 999px; display: grid; place-items: center; background: rgba(255,255,255,.26); color: #fff; font-size: 13px; font-weight: 900; line-height: 1; font-variant-numeric: tabular-nums; pointer-events: none; box-sizing: border-box; }
.deck-card-count[hidden] { display: none; }
.deck-card-count.is-settle { animation: pulse .3s ease; }
/* LABELLED (owner, 2026-09-30): the swap sits TOP-left — the corner App v3's − pip used (the − is gone) — across from the
   count (top-right); App v3 put it bottom-left. It slides DOWN into place on hover / focus. */
.deck-card-swap { position: absolute; top: 11px; left: 11px; z-index: 5; width: 26px; height: 26px; padding: 0; border: none; border-radius: 999px; display: grid; place-items: center; background: rgba(255,255,255,.26); color: #fff; font-size: 14px; font-weight: 800; cursor: pointer; opacity: 0; pointer-events: none; transform: translateY(-4px); transition: opacity .18s ease, transform .2s ease; }
.deck-card:focus-within .deck-card-swap { opacity: 1; pointer-events: auto; transform: none; } @media (hover: hover) { .deck-card:hover .deck-card-swap { opacity: 1; pointer-events: auto; transform: none; } }
@media (hover: none) { .deck-card-swap { opacity: 1; pointer-events: auto; transform: none; } }   /* always visible on touch (App v3 never set uDeckEdit — its swap never showed on touch) */
/* Select mode (App v3 407 manageCheckStyle = _tickCss(selected, base, true) at top / left 11, z 4; notEdit hides the
   swap): a tap selects the card (deck.js → bulk.js). LABELLED: the ticked ✓ is App v3's var(--ink) as the light-mode
   literal — the dark --ink would vanish on the white disc. */
.deck-card-tick { display: none; position: absolute; top: 11px; left: 11px; z-index: 4; width: 20px; height: 20px; box-sizing: border-box; border-radius: 999px; place-items: center; background: rgba(255,255,255,.22); border: 1.5px solid #fff; color: transparent; font-size: 11px; font-weight: 900; line-height: 1; pointer-events: none; transition: background .12s ease, border-color .12s ease, color .12s ease; }
.deck[data-mode="select"] .deck-card-tick { display: grid; }
.deck[data-mode="select"] .deck-card.is-selected .deck-card-tick { background: #fff; color: #3c3830; }
.deck[data-mode="select"] .deck-card-swap { display: none; }
.deck-pop { position: absolute; top: 8px; left: 50%; z-index: 6; background: var(--cat, #3c3830); color: #fff; font-size: 14px; font-weight: 900; line-height: normal; border-radius: 999px; padding: 2px 11px; white-space: nowrap; pointer-events: none; box-shadow: 0 3px 10px rgba(0,0,0,.2); animation: floatup .6s ease forwards; }
.deck-strip.is-compact .deck-card-btn { gap: 6px; min-height: 126px; padding: 11px 12px 10px; }
.deck-strip.is-compact .deck-card-name { padding: 4px; font-size: 15.5px; }

/* Step 9: the Deal menu's Smart decks + Focus rows (App v3 353–369; deck.js renderSmartRows). A smart row: the name and
   the rule stacked, the count top-right (grid: the markup may wrap name + count in .deck-smart-top — it is `contents`). */
.deck-menu-head--smart { display: flex; align-items: center; gap: 6px; padding: 9px 11px 3px; }
.deck-menu-head--smart svg { flex: none; fill: var(--accent); }
.deck-smart { display: grid; grid-template-columns: minmax(0, 1fr) auto; column-gap: 8px; align-items: start; width: 100%; padding: 8px 11px; background: none; border: none; border-radius: 10px; text-align: left; color: var(--ink); cursor: pointer; }
@media (hover: hover) { .deck-smart:hover { background: var(--chip); } }
.deck-smart-top { display: contents; }
.deck-smart-name { grid-column: 1; grid-row: 1; min-width: 0; font-size: 14.5px; font-weight: 700; color: var(--ink); }
.deck-smart .deck-count { grid-column: 2; grid-row: 1; margin-top: 2px; }
.deck-smart-rule { grid-column: 1; grid-row: 2; margin-top: 1px; font-size: 12px; font-weight: 600; line-height: 1.35; color: var(--muted-text); /* d11 */ }

/* ---------- focus- : Focus (App v3 L437–482; focusShellStyle 4047–4052, focusFadeRef 4054, focusTrayStyle 4055,
   focusListStyle 4056, hlRows 4057–4062, hlxStyle 4063, segWrapStyle 4229, _hlSeg 2813, _tickCss 3267, _catTagCss /
   _catDotCss 3268–3269; js/focus.js). Step 9 adds the eye, the choosing line, Choose / Edit and "Add from the board…";
   the floating dock is the fd- family. ---------- */
.focus-shell { display: flex; flex-wrap: nowrap; align-items: center; justify-content: center; gap: 8px; width: fit-content; max-width: 100%; margin: -6px auto 16px; padding: 7px 10px; background: var(--card); border: 1px solid var(--border); border-radius: 999px; }
.focus-shell[hidden] { display: none; }
.focus-label-wrap { position: relative; flex: none; }   /* identity ruling 5 (LABELLED deviation from App v3's flex: 0 1 auto): never shrinks — shown whole, or hidden by design below */
.focus-label { display: inline-flex; align-items: center; gap: 6px; max-width: 100%; background: transparent; border: none; cursor: pointer; padding: 6px 6px 6px 2px; border-radius: 999px; font-size: 12.5px; font-weight: 900; letter-spacing: .08em; text-transform: uppercase; color: var(--ink2); white-space: nowrap; }
@media (hover: hover) { .focus-label:hover { color: var(--ink); } }
.focus-label-text { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.focus-caret { flex: none; color: var(--muted2); transition: transform .18s ease; }   /* App v3 focusCaretStyle 4218: --muted2 (an icon — the verbatim token), never the label's ink */
.focus-label[aria-expanded="true"] .focus-caret { transform: rotate(180deg); }
.focus-seg { flex: none; display: inline-flex; align-items: center; background: var(--chip); border-radius: 999px; padding: 3px; gap: 1px; }
.focus-seg-ico { display: grid; place-items: center; color: var(--muted2); padding: 0 3px 0 6px; }
.focus-seg-btn { display: inline-flex; align-items: center; justify-content: center; min-width: 28px; padding: 6px 11px; border-radius: 999px; border: none; cursor: pointer; font-size: 13px; font-weight: 800; background: transparent; color: var(--muted-text); /* LABELLED d11: App v3 --muted2 — --muted2-text reads 4.25:1 on dark --chip */ box-shadow: none; transition: background .15s ease, color .15s ease, transform .1s ease, box-shadow .15s ease; }
.focus-seg-btn:active { transform: scale(.92); }
.focus-seg-btn[aria-pressed="true"] { background: var(--card); color: var(--ink); box-shadow: 0 1px 3px rgba(0,0,0,.14); }
.focus-acts { display: inline-flex; align-items: center; gap: 6px; }
.focus-acts[hidden] { display: none; }
.focus-log { display: inline-flex; align-items: center; gap: 5px; background: var(--go-soft); border: none; color: var(--go-ink); border-radius: 999px; padding: 8px 16px; font-weight: 900; font-size: 13.5px; white-space: nowrap; cursor: pointer; }
.focus-clear { flex: none; background: var(--card); border: 1px solid var(--border); border-radius: 999px; padding: 8px 15px; font-size: 13px; font-weight: 800; color: var(--danger); white-space: nowrap; cursor: pointer; }
/* the tray — _menuCss({ align:'left', w:344, fixedW:344, maxH:'min(58dvh, 470px)' }) — dvh ÷ var(--zf, 1) here
   + { display:flex; column; overflow:hidden } */
.focus-tray { display: none; position: absolute; top: calc(100% + 8px); left: 0; z-index: 40; /* --z-menu */ width: 344px; max-height: min(calc(58dvh / var(--zf, 1)), 470px); flex-direction: column; overflow: hidden; background: var(--card); border: 1px solid var(--border2); border-radius: 14px; padding: 8px; box-shadow: 0 12px 30px rgba(0,0,0,.18); animation: menuIn .16s ease; text-align: left; }
.focus-tray.visible { display: flex; }
.focus-tray-head { flex: none; display: flex; align-items: center; gap: 8px; padding: 2px 4px 10px; }
.focus-tray-title { font-size: 15px; font-weight: 900; color: var(--ink); white-space: nowrap; }
.focus-tray-count { background: var(--chip); border-radius: 999px; padding: 3px 9px; font-size: 12px; font-weight: 900; color: var(--ink2); }
.focus-tray-clear { margin-left: auto; background: var(--card); border: 1px solid var(--border); border-radius: 999px; padding: 6px 12px; font-size: 12.5px; font-weight: 800; color: var(--danger); white-space: nowrap; cursor: pointer; }
.focus-tray-clear[hidden] { display: none; }
.focus-tray-list { flex: 1 1 auto; min-height: 0; overflow-y: auto; overflow-x: hidden; overscroll-behavior: contain; padding: 2px 0 0; }
.focus-tray-list:empty { display: none; }
.focus-row { display: flex; align-items: center; gap: 9px; width: 100%; padding: 7px 8px 7px 14px; border-radius: 10px; background: transparent; border: none; cursor: pointer; }
@media (hover: hover) { .focus-row:hover { background: var(--chip); } }
.focus-tick { flex: none; width: 20px; height: 20px; border-radius: 999px; display: grid; place-items: center; font-size: 11px; font-weight: 900; line-height: 1; background: transparent; color: transparent; border: 1.5px solid var(--border2); transition: background .12s ease, border-color .12s ease, color .12s ease; }
.focus-row[aria-pressed="true"] .focus-tick { background: #2f6f62; color: var(--card); border-color: #2f6f62; }   /* App v3 literal teal (_tickCss(on, '#2f6f62')) */
.focus-row-name { flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; text-align: left; font-size: 13.5px; font-weight: 700; color: var(--muted-text); }
.focus-row[aria-pressed="true"] .focus-row-name { color: var(--ink); }
.focus-row-cat { flex: none; display: inline-flex; align-items: center; gap: 5px; font-size: 11.5px; font-weight: 800; color: var(--muted2-text); white-space: nowrap; }
.focus-row-dot { flex: none; width: 7px; height: 7px; border-radius: 999px; }
.focus-row-x { flex: none; width: 18px; height: 18px; border-radius: 999px; background: var(--chip2); color: var(--muted-text); display: grid; place-items: center; font-size: 11px; font-weight: 900; line-height: 1; }
.focus-row[aria-pressed="false"] .focus-row-x { display: none; }
.focus-tray-empty { font-size: 13px; font-weight: 700; color: var(--muted-text); padding: 2px 4px 10px; line-height: 1.5; }
.focus-tray-empty[hidden] { display: none; }
.focus-tray-foot { flex: none; display: flex; align-items: center; justify-content: flex-end; gap: 8px; margin-top: 8px; padding-top: 10px; border-top: 1px solid var(--hair); }
.focus-done { flex: none; background: var(--solid); color: var(--on-solid); border: none; border-radius: 999px; padding: 11px 20px; font-size: 13.5px; font-weight: 900; cursor: pointer; }
/* Step 9: the eye (the focus light — decision 5), the choosing line, Choose / Edit / Done, the tray's "Add from the
   board…" (App v3 440–472; glowIconStyle 4215, focusEditBtnStyle 4222, focusShellStyle's float 4050). The dock's eye
   (.fd-eye) shares these rules; App v3 draws it without the glow shadow. */
.focus-eye { flex: none; width: 34px; min-width: 34px; height: 34px; padding: 0; border: none; border-radius: 999px; display: inline-flex; align-items: center; justify-content: center; background: var(--chip); color: var(--muted3); cursor: pointer; transition: color .2s ease, background .2s ease, box-shadow .2s ease; }
.focus-eye[aria-pressed="true"] { background: #3f9960; color: #fff; box-shadow: 0 1px 5px rgba(63,153,96,.38); }   /* App v3 literals */
.fd-eye[aria-pressed="true"] { box-shadow: none; }
.focus-eye:disabled { opacity: .55; cursor: default; transform: none; filter: none; }
.focus-eye .focus-eye-closed, .focus-eye.is-closed .focus-eye-open { display: none; }
.focus-eye.is-closed .focus-eye-closed { display: block; }
@media (pointer: coarse) { .focus-eye { position: relative; } .focus-eye::after { content: ""; position: absolute; inset: -5px; } }
.focus-choosing { display: inline-flex; align-items: center; gap: 6px; padding: 0 2px; font-size: 13px; font-weight: 800; color: var(--muted-text); /* d11 */ white-space: nowrap; }
.focus-choosing b { color: var(--ink); font-weight: 900; }   /* <b> = bolder than the 800 line */
.focus-edit { flex: none; display: inline-flex; align-items: center; gap: 6px; padding: 8px 15px; background: var(--card); border: 1px solid var(--border); border-radius: 999px; font-size: 13px; font-weight: 800; color: var(--ink2); white-space: nowrap; cursor: pointer; }
.focus-edit[aria-pressed="true"] { background: var(--solid); color: var(--on-solid); border-color: var(--solid); }
/* choosing (the board's focus mode): the pill floats (sticky) so its Done stays reachable; the label, 3·5·10, the acts
   and the eye step aside (App v3 focusLblShown / segWrapStyle / focusActsInline / glowIconStyle in focus mode) */
.focus-shell.is-choosing { position: sticky; top: 8px; z-index: 100; /* --z-sticky */ box-shadow: 0 12px 28px rgba(60,56,48,.22); }
.focus-shell.is-choosing .focus-label-wrap, .focus-shell.is-choosing .focus-seg, .focus-shell.is-choosing .focus-acts, .focus-shell.is-choosing .focus-eye { display: none; }
.focus-add-board { flex: 1 1 auto; padding: 11px 16px; background: var(--card); border: 1px solid var(--border); border-radius: 999px; font-size: 13.5px; font-weight: 800; color: var(--ink); white-space: nowrap; text-align: center; cursor: pointer; }
@media (pointer: coarse) { .focus-edit, .focus-add-board { min-height: 44px; } }
@media (max-width: 679.98px) {
  /* vw < 680 (App v3): the shell scrolls sideways with 18-px edge fades (focus.js paints the mask), Clear lives in the
     tray, and the tray is a bottom sheet (_menuCss sheet branch: 72dvh ÷ var(--zf, 1), fixedW ignored) with the drag handle. */
  /* (no -webkit-overflow-scrolling: on iOS it makes the shell a z-0 stacking context that traps the tray sheet under
     the board — mobile pass ruling 3; momentum is native since iOS 13) */
  .focus-shell { justify-content: flex-start; overflow-x: auto; scrollbar-width: none; }
  .focus-shell::-webkit-scrollbar { display: none; }
  .focus-clear { display: none; }
  .focus-tray { position: fixed; left: 0; right: 0; bottom: 0; top: auto; z-index: 1000; /* --z-overlay */ width: 100%; max-width: none; max-height: calc(72dvh / var(--zf, 1)); overscroll-behavior: contain; padding: 8px 8px calc(8px + env(safe-area-inset-bottom, 0px)); border-radius: 18px 18px 0 0; border-bottom: none; animation: sheetUp .22s ease; box-shadow: 0 -18px 50px rgba(0,0,0,.34); }
}
@media (max-width: 639.98px) { .focus-seg-btn { min-width: 34px; padding: 10px 13px; } }
/* Identity ruling 5: the label is shown WHOLE or deliberately hidden, never clipped (App v3's squeeze showed "F" at
   375 px). Below 460 px the word is visually hidden — the .vh rule: the button keeps its accessible name "Focus" /
   "Focus · N" and its caret, the tray's door; below 400 px the decorative shuffle glyph steps aside (the group keeps
   its aria-label) and the gap tightens, so the pill fits from 340 px up. Only a 320–339 px touch screen still scrolls
   the pill sideways (App v3's own narrow rule, with its fades). */
@media (max-width: 459.98px) {
  .focus-label-text { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0; }
  .focus-label { gap: 0; padding: 6px 5px; }
  /* With the word hidden the caret IS the button's visible sign: it takes the label's ink (≥ 4.5:1 on --card in
     every palette and mode — WCAG 1.4.11 asks 3:1), not App v3's decorative --muted2 (2.55:1 on white). */
  .focus-caret { color: inherit; }
}
@media (max-width: 399.98px) {
  .focus-seg-ico { display: none; }
  .focus-shell { gap: 6px; }
}
/* Touch, the narrowest phones (320–339 px): the pill's padding and gaps tighten (never the 44-px segments) so it
   fits without scrolling sideways — identity ruling 5's "nothing overflows at 320–430 px". */
@media (pointer: coarse) and (max-width: 339.98px) {
  .focus-shell { gap: 4px; padding: 7px 4px; }
  .focus-label { padding: 6px 3px; }
  .focus-edit { padding: 8px 12px; }
}
/* 44-px rows on touch (LABELLED a11y — the .acct-item precedent); isolated controls carry .hit in the markup. The
   3 · 5 · 10 segments are adjacent (a centred .hit area would steal taps from the neighbour), so they grow to 44 × 44
   themselves on touch — contract ruling 10; the pill scrolls sideways below 680 px, so nothing pans. */
@media (pointer: coarse) {
  .deck-nav, .deck-pick, .deck-back, .focus-row { min-height: 44px; }
  .focus-seg-btn { min-height: 44px; min-width: 44px; }
  /* The label's centred 44-px .hit area is wider than the word-less label below 460 px: the VISIBLE neighbours win
     their own pixels — a tap on the eye's edge toggles the light, one on 3 picks three, never the tray. */
  .focus-eye { z-index: 1; }
  .focus-seg { position: relative; z-index: 1; }
}
/* Phone ruling 5 (LABELLED — the look is unchanged): below 460 px the word-less Focus label (22 px, the tray's ▾ door)
   is the pill's smallest target and its .hit area ends at the visible neighbours. The inline eye's 44-px area moves
   into the shell's 10-px left padding instead of the gap it shared with the label (still 44 × 44), so the label's area
   takes the whole gap on both sides: ≈ 34 px wide at 340–399, ≈ 38 at 400–459 (was 28 / 32), 45 tall. 44 wide would take
   the eye's or the 3 · 5 · 10 group's pixels. The narrowest phones (≤ 339 px: a 4-px shell padding) keep the old split;
   the floating dock's eye (.fd-eye) is not touched. */
@media (pointer: coarse) and (min-width: 340px) and (max-width: 459.98px) { .focus-shell .focus-eye::after { inset: -5px 0 -5px -10px; } }

/* ---------- cb- : the control bar (App v3 485–659; its container rules L30–41 as `@container ctrlbar`, selector for
   selector; _menuCss 3257 for the three menus; js/control-bar.js). #cbZone is App v3's [data-colzone] size container.
   Every [hidden] on these parts is the global `[hidden] { display: none !important }` rule — none is restated. ---------- */
.cb-zone { container: ctrlbar / inline-size; margin: 0 0 16px; padding-right: 14px; }
@media (min-width: 900px) { .cb-zone { padding-right: 22px; } }   /* App v3 colzonePad 4169 */
.cb-bar { position: relative; display: flex; flex-wrap: wrap; align-items: flex-end; column-gap: 8px; row-gap: 8px; padding: 0 2px; border-bottom: 1px solid var(--border2); }
.cb-util { display: inline-flex; align-items: center; gap: 8px; flex: 0 1 auto; min-width: 0; margin-bottom: 7px; }
.cb-sp { flex: 1 1 0; }
.cb-tabs { display: flex; align-items: flex-end; gap: 8px; }
.cb-viewc { display: flex; align-items: center; gap: 8px; margin-bottom: 7px; transition: opacity .15s; }
.cb-viewc.is-dim { opacity: .45; pointer-events: none; }        /* while a search runs (App v3 viewc .45) */
/* On Analytics the view controls keep their box (their 44-px buttons set the narrow tab row's height — the tab bar must
   not move: pastday ruling 6) but are gone. control-bar.js toggles it. */
.cb-viewc.is-away { visibility: hidden; pointer-events: none; }
/* the search (App v3 488–494) */
.cb-search { position: relative; display: flex; align-items: center; flex: 0 1 400px; min-width: 210px; margin: 0; background: var(--card); border: 1px solid var(--border); border-radius: 999px; box-shadow: inset 0 1px 2px rgba(0,0,0,.05); padding-left: 15px; }
.cb-search-ico { flex: none; display: grid; place-items: center; color: var(--muted2); pointer-events: none; }
/* LABELLED DEVIATION: 16 px (App v3 14) — iOS Safari zooms on focus of any field under 16 px; the vertical padding
   12 → 10.6 keeps App v3's box height (Nunito's normal line box grows 2.7 px). App v3 sizes the pill from the input's
   default 20-character width at 14 px (184 px with its padding — the util group is content-sized); the 16-px font
   would widen it by 16 / 14 (22 px at 1280, pushing + New and ⋯ right), so the width pins App v3's 184 (border-box).
   flex: 1 1 0 = App v3's flex: 1 — it still fills or shrinks with its row. */
.cb-search-input { flex: 1 1 0; width: 184px; min-width: 0; border: none; background: none; color: var(--ink); font: inherit; font-size: 16px; font-weight: 700; padding: 10.6px 15px 10.6px 9px; border-radius: 999px; -webkit-appearance: none; appearance: none; }
.cb-search-input::placeholder { color: var(--muted2-text); opacity: 1; }   /* d11 */
.cb-search-input:focus { box-shadow: none; }   /* the field rule's halo is the WRAPPER's (.cb-search:focus-within, the ring- section): this input has no box of its own */
.cb-search-input::-webkit-search-cancel-button, .cb-search-input::-webkit-search-decoration { -webkit-appearance: none; appearance: none; }
.cb-search-x { flex: none; width: 24px; height: 24px; margin-right: 10px; padding: 0; border: none; border-radius: 999px; background: var(--chip); color: var(--muted-text); font-size: 14px; font-weight: 800; line-height: 1; display: grid; place-items: center; cursor: pointer; }
@media (pointer: coarse) { .cb-search-x { position: relative; } .cb-search-x::after { content: ""; position: absolute; inset: -10px; } }
/* + New and ⋯ (App v3 496–512) */
.cb-toolbox, .cb-more { position: relative; display: inline-flex; align-items: center; gap: 8px; flex: none; }
.cb-new { display: inline-flex; align-items: center; gap: 7px; flex: none; height: 38px; padding: 0 15px; background: var(--card); color: var(--ink2); border: 1px solid var(--border); border-radius: 999px; font-size: 13px; font-weight: 800; white-space: nowrap; cursor: pointer; }
.cb-plus { display: inline-flex; line-height: 0; }
.cb-more-btn { width: 38px; height: 38px; padding: 0; display: grid; place-items: center; background: var(--card); color: var(--ink2); border: 1px solid var(--border); border-radius: 999px; font-size: 15px; font-weight: 800; cursor: pointer; }
@media (hover: hover) { .cb-new:hover, .cb-more-btn:hover, .cb-btn:hover { background: var(--chip); } }
/* Board | Analytics (App v3 455–470; tabOn / tabOff) */
.cb-tabtrack { display: flex; gap: 14px; }
.cb-tab { display: inline-flex; align-items: center; gap: 7px; background: none; border: none; border-bottom: 2.5px solid transparent; border-radius: 0; padding: 6px 3px 11px; font-size: 15px; font-weight: 900; color: var(--muted-text); /* d11 */ white-space: nowrap; cursor: pointer; }
@media (hover: hover) { .cb-tab:hover { color: var(--ink2); } }
.cb-tab[aria-selected="true"] { color: var(--ink); border-bottom-color: var(--ink); }
.cb-tab svg { flex: none; }
/* Period ▾ and View ▾ (App v3 530–617) */
.cb-pop { position: relative; display: inline-flex; align-items: stretch; }
.cb-btn { display: inline-flex; align-items: center; gap: 7px; height: 38px; padding: 0 13px; background: var(--card); color: var(--ink2); border: 1px solid var(--border); border-radius: 999px; font-size: 13px; font-weight: 800; white-space: nowrap; cursor: pointer; }
.cb-period-btn { gap: 0; }
/* The Period's short label (fixes ruling 3): "Week" / "Month" / "Year" / "All" replace the long label in a ≤ 430-px
   control bar (the rule in the container block below) — the long labels wrapped the row on a phone. Both spans are
   control-bar.js's; the short one is aria-hidden (the button's aria-label names the long label). */
.cb-period-short { display: none; }
.cb-eyebrow { font-size: 10.5px; font-weight: 900; letter-spacing: .09em; text-transform: uppercase; color: var(--muted2-text); /* d11 */ margin-right: 7px; line-height: 1; position: relative; top: 1px; }
.cb-chev { flex: none; opacity: .7; }
.cb-period-btn .cb-chev { margin-left: 6px; }
/* the sliders icon always shows: App v3's container rule hides [data-ico-flt], but the span's inline display wins */
.cb-ico-flt { display: inline-flex; line-height: 0; }
.cb-flt-badge { background: var(--chip); color: var(--muted-text); /* d11 — App v3 var(--muted) */ border-radius: 999px; padding: 2px 8px; font-size: 12px; font-weight: 800; }
.cb-flt-dot { display: none; flex: none; width: 7px; height: 7px; border-radius: 999px; background: var(--accent); }
/* the three menus — _menuCss({ anchored: true }): absolute, z --z-menu, the 14-px card with the 12/30 shadow */
.cb-menu { display: none; position: absolute; top: calc(100% + 8px); right: 0; z-index: 40; /* --z-menu */ background: var(--card); border: 1px solid var(--border2); border-radius: 14px; padding: 8px; overflow: visible; box-shadow: 0 12px 30px rgba(0,0,0,.18); animation: menuIn .16s ease; text-align: left; }
.cb-menu.visible { display: block; }
.cb-more-menu { top: 38px; min-width: 216px; max-width: min(296px, calc(100vw - 32px)); }                    /* moreMenuStyle 4154 */
.cb-view-menu { width: 250px; max-height: min(calc(60dvh / var(--zf, 1)), 480px); overflow: hidden; overscroll-behavior: contain; }   /* catsMenuStyle 4142 */
.cb-view-menu.visible { display: flex; flex-direction: column; }
.cb-item { display: flex; align-items: center; width: 100%; text-align: left; background: none; border: none; border-radius: 10px; padding: 10px 12px; font-size: 14.5px; font-weight: 700; color: var(--ink); cursor: pointer; }
.cb-sep { height: 1px; background: var(--hair); margin: 5px 6px; }
/* (.cb-prow — the Period menu's Yesterday and Choose a day… — are two more rows: the same look, their chosen state is
   aria-pressed.) */
.cb-row, .cb-prow { display: flex; align-items: center; gap: 10px; width: 100%; text-align: left; background: none; border: none; border-radius: 10px; padding: 9px 11px; font-size: 14.5px; font-weight: 700; color: var(--ink2); cursor: pointer; }
.cb-row[aria-checked="true"], .cb-prow[aria-pressed="true"] { background: var(--chip); font-weight: 800; color: var(--ink); }
.cb-row-text { flex: 1 1 0; white-space: nowrap; }
.cb-tick { flex: none; display: none; color: var(--muted); }   /* showRows 4151: the tick shows on the chosen row only */
.cb-row[aria-checked="true"] .cb-tick, .cb-prow[aria-pressed="true"] .cb-tick { display: block; }
@media (hover: hover) { .cb-item:hover, .cb-row:hover, .cb-prow:hover, .cb-cat:hover { background: var(--chip); } }
/* the View pane (App v3 619–631): Columns, then Show categories, Show all, Reset colours by order */
.cb-viewpane { flex: none; display: flex; flex-direction: column; gap: 13px; padding: 2px 2px 12px; }
.cb-vlabel { font-size: 11px; font-weight: 900; letter-spacing: .08em; text-transform: uppercase; color: var(--muted-text); /* d11 */ margin: 0 2px 7px; }
.cb-vlabel--cats { flex: none; margin: 0 4px 7px; }
.cb-seg { display: flex; flex-wrap: wrap; gap: 6px; }
/* dcOn / dcOff / dcDis (App v3 3851–3858) under the [data-viewpane] button override (L37) */
.cb-segbtn { padding: 6px 11px; border-radius: 999px; background: var(--soft); color: var(--ink2); border: 1px solid var(--border); font-size: 12.5px; font-weight: 800; cursor: pointer; }
body[data-mode="dark"] .cb-segbtn { border-color: rgba(240,234,221,.22); }
.cb-segbtn[aria-pressed="true"] { background: var(--solid); color: var(--on-solid); border-color: transparent; }
.cb-segbtn:disabled { opacity: .32; cursor: not-allowed; transform: none; filter: none; }
.cb-vhr { flex: none; height: 1px; background: var(--border2); margin: 0 2px 8px; }
.cb-cats { flex: 1 1 auto; min-height: 0; overflow: auto; overscroll-behavior: contain; }
/* a category row — --cat (the stored hex) is set inline by control-bar.js */
.cb-cat { display: flex; align-items: center; gap: 8px; width: 100%; min-height: 34px; padding: 7px 9px; border: none; background: none; border-radius: 10px; text-align: left; font-size: 14px; font-weight: 700; color: var(--ink); cursor: pointer; }
.cb-cat[aria-checked="false"] { color: var(--muted2-text); }   /* d11 */
.cb-cat-box { flex: none; width: 20px; height: 20px; border-radius: 999px; display: grid; place-items: center; background: var(--cat, var(--muted2)); border: 1.5px solid var(--cat, var(--muted2)); color: #fff; font-size: 11px; font-weight: 900; line-height: 1; }   /* catsMenuOptions boxStyle 4162 */
.cb-cat[aria-checked="false"] .cb-cat-box { background: transparent; opacity: .55; color: transparent; }
.cb-cat-name { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cb-showall { flex: none; display: block; width: 100%; text-align: left; background: none; border: none; border-top: 1px solid var(--hair); margin-top: 6px; padding: 11px 9px; font-size: 14px; font-weight: 800; color: var(--ink2); cursor: pointer; }
.cb-reset { flex: none; display: block; width: 100%; text-align: left; background: none; border: none; border-top: 1px solid var(--hair); margin: 6px 0 0; padding: 11px 9px 5px; font-size: 13px; font-weight: 800; color: var(--muted-text); /* d11 */ cursor: pointer; }
@media (hover: hover) { .cb-reset:hover { color: var(--ink); } }
/* 44-px rows on touch (LABELLED a11y — the .acct-item precedent) */
@media (pointer: coarse) { .cb-item, .cb-row, .cb-prow, .cb-cat, .cb-showall, .cb-reset { min-height: 44px; } .cb-segbtn { min-width: 44px; min-height: 44px; } }
/* App v3 L30–41, in App v3's order (its [data-cb=…] / [data-…] hooks → these classes; its !importants dropped where
   nothing competes; the lens / display / tips-i / overview hooks are DEAD — not built) */
@container ctrlbar (min-width: 0px) { .cb-tabs { order: 1; margin-bottom: -1px; } .cb-util { order: 2; margin-left: 28px; } .cb-sp { order: 3; } .cb-viewc { order: 4; } }
@container ctrlbar (max-width: 1100px) { .cb-util { order: 0; flex: 1 1 100%; margin-bottom: 2px; margin-left: 0; } .cb-util .cb-search { flex: 1 1 auto; } }
/* LABELLED: the search's 24-px × is left out of the 44-px rule (App v3 stretches it into a 24 × 44 oval); its touch area
   is the ::after above. */
@container ctrlbar (max-width: 680px) { .cb-util button:not(.cb-search-x), .cb-util input, .cb-tabs button, .cb-viewc .cb-btn { min-height: 44px; } }
/* …and the 44-px Period / View pills keep their WORDS on the tabs' line (owner, 2026-10-12: on a phone "Today" sat
   4.5 px above "Board | Patterns" — the pills grew from 38 to 44 px over the same 7-px foot, which lifted their
   middle). 3 px puts the two middles within half a pixel again, as on a wide bar. */
@container ctrlbar (max-width: 680px) { .cb-viewc { margin-bottom: 3px; } }
@container ctrlbar (max-width: 700px) { .cb-util .cb-search { width: 110px; flex: 1 1 auto; min-width: 0; } .cb-new, .cb-more-btn { width: 44px; height: 44px; padding: 0; justify-content: center; } .cb-plus svg { width: 15px; height: 15px; } .cb-new-lbl { display: none; } }
@container ctrlbar (max-width: 560px) { .cb-lbl-flt { display: none; } .cb-flt-badge { display: none; } .cb-flt-dot { display: inline-block; } }
@container ctrlbar (max-width: 430px) { .cb-bar { column-gap: 6px; } .cb-viewc .cb-btn { padding-left: 10px; padding-right: 10px; gap: 6px; } .cb-tabtrack { gap: 9px; } .cb-tab { gap: 5px; padding: 6px 1px 11px; } }
@container ctrlbar (max-width: 430px) { .cb-period-val { display: none; } .cb-period-short { display: inline; } .cb-period-btn .cb-chev { margin-left: 4px; } .cb-viewc .cb-period-btn { padding-right: 9px; } }   /* fixes ruling 3: "Month" fits one row at 360 px */
@container ctrlbar (max-width: 600px) { .cb-eyebrow { display: none; } }
@container ctrlbar (max-width: 380px) { .cb-tab { font-size: 14px; } }
/* fixes ruling 3, measured: at a 360-px phone the tabs + Period ("Month", the widest short label) + View left ~2 px, and
   CI's Chrome renders the row a few px wider — it wrapped and the board jumped 51 px. These trims free ~27 px so the
   row keeps one line on every Period label with room to spare (the 44-px heights are untouched). */
@container ctrlbar (max-width: 380px) { .cb-bar { column-gap: 4px; } .cb-tabtrack { gap: 4px; } .cb-tab { gap: 4px; } .cb-viewc { gap: 5px; } .cb-viewc .cb-btn { padding-left: 7px; padding-right: 7px; } .cb-viewc .cb-period-btn { padding-right: 7px; } .cb-period-btn .cb-chev { margin-left: 2px; } }
/* Without its "Period" eyebrow (a bar of 600 px and less) the pill BEGINS with its word, and the narrow rules above
   left that word 8 px from a 22-px round end — crowded against the left edge beside the light chevron's 11 px
   (owner, 2026-10-12). The word gets a button's own inset again (.cb-btn's 13 px); the chevron side keeps the narrow
   value. After the three rules above on purpose (same weight, later). The row has the room: 33 px to spare at 360 px
   with the longest label. */
@container ctrlbar (max-width: 600px) { .cb-viewc .cb-period-btn { padding-left: 13px; } }
/* NARROW: the View menu is a bottom sheet (_menuCss sheet branch — App v3 catsMenuStyle: _narrow() → { sheet: true });
   ⋯ stays anchored at every width (anchored: true). No handle (not data-sheet). The Period menu is a sheet too
   (pastday ruling 2 — the block below). */
@media (max-width: 639.98px) {
  .cb-view-menu { position: fixed; left: 0; right: 0; bottom: 0; top: auto; transform: none; z-index: 1000; /* --z-overlay */ width: 100%; max-width: none; max-height: calc(72dvh / var(--zf, 1)); padding: 8px 8px calc(8px + env(safe-area-inset-bottom, 0px)); border-radius: 18px 18px 0 0; border-bottom: none; animation: sheetUp .22s ease; box-shadow: 0 -18px 50px rgba(0,0,0,.34); }
}

/* ---------- the past day (pastday ruling 2, 2026-10-02): Period ▾ → Log for a past day — the View menu's divider and
   small-caps label, a full-width Yesterday in the segment-button style, the inline calendar (day-picker.js
   { inline: true }); the dark Period button while a past day is picked; the banner under the control bar (the
   old-cart banner's look). js/control-bar.js drives all three; js/view-state.js owns the picked day. ---------- */
/* The Period menu is a role=dialog in TWO parts, each under its small-caps heading as in the View menu (owner,
   2026-10-12): "Show counts for" — the five rows (their inner role=menu) — a hairline, then "Log for a past day" —
   Yesterday and Choose a day…, two more rows (.cb-prow, the rule beside .cb-row). The whole calendar that used to hang
   under the rows (and the full-width tinted Yesterday pill above it) is gone from this page: the menu is an ordinary
   short menu until a day is asked for. control-bar.js scrolls the page so the open dialog is whole (block:
   'nearest'); it is never taller than the screen (less 16 px) and scrolls INSIDE on a short wide screen (a landscape
   phone, a low window) — a press outside closes it, so the page itself cannot be dragged to reach its last row. */
.cb-period-menu { width: 268px; min-width: 0; max-width: calc(100vw - 32px); max-height: calc(100dvh / var(--zf, 1) - 16px); overflow: auto; overscroll-behavior: contain; }
.cb-period-menu .cb-vlabel { margin: 5px 4px 6px; }
.cb-period-menu .cb-vhr { margin: 6px 4px 9px; }
.cb-past { padding: 0; }
/* Choose a day… turns the dialog to its CALENDAR PAGE (.is-cal, set by control-bar.js): it becomes the site's pop-up
   calendar — the SAME panel as the entry editor's Date calendar (.dp-pop: the owner's reference, 2026-10-12): 252 px,
   --panel, the --border2 hairline, 14-px corners, its shadow and padding — hanging from the Period button, and it
   holds only the calendar. The day picker inside is drawn INLINE (no click-away, never hidden) and brings nothing of
   its own but the cells: the arrows, the day cells, the today ring and the picked day are the pop-up's, untouched.
   The month takes its own four to six week rows, as the pop-up's does; control-bar.js places the panel by the
   pop-up calendars' own rule (day-picker.js dayPickerTop, for the tallest month): under the button when six weeks
   fit there, else above it, else inside the screen — so ‹ › never push the last row off the screen and the page
   never scrolls under the opening panel. */
.cb-period-menu.is-cal { width: 252px; background: var(--panel); border-radius: 14px; box-shadow: 0 16px 42px rgba(60,56,48,.22); padding: 13px; animation: calIn .16s ease; }   /* it arrives as every menu does (owner, 2026-10-12: the swap from the rows was a static cut) */
/* …and the rows it replaces leave the same way: control-bar.js leaves a throwaway copy of the dialog as it stood
   (.cb-ghost — a picture only: no ids, inert, takes no press) fading out for the same 160 ms, so the two CROSS-FADE.
   Fading the one panel alone made it vanish for a frame before its own fade began — a blink. */
.cb-menu.cb-ghost { animation: menuOut .16s ease forwards; pointer-events: none; }
.dp-pop--inline { position: static; z-index: auto; width: auto; border: none; border-radius: 0; box-shadow: none; padding: 0; background: transparent; }
/* NARROW: the ROWS are a bottom sheet, exactly as the View menu (anchored: no dim, no lock, no handle) — far shorter
   than the old rows + calendar (seven rows and two headings ~ 390 px with the 44-px rows); the 96-dvh cap and the
   inner scroll stay for a landscape phone. The CALENDAR page is no sheet: the same small panel as on a wide screen,
   hanging from the Period button (the entry editor's calendar is a small panel on a phone too); control-bar.js
   places it (above the button when there is no room below) and slides it sideways when its left edge would leave
   a very narrow screen. */
@media (max-width: 639.98px) {
  .cb-period-menu { position: fixed; left: 0; right: 0; bottom: 0; top: auto; transform: none; z-index: 1000; /* --z-overlay */ width: 100%; max-width: none; max-height: calc(96dvh / var(--zf, 1)); overflow: auto; overscroll-behavior: contain; padding: 8px 8px calc(8px + env(safe-area-inset-bottom, 0px)); border-radius: 18px 18px 0 0; border-bottom: none; animation: sheetUp .22s ease; box-shadow: 0 -18px 50px rgba(0,0,0,.34); }
  .cb-period-menu.is-cal { position: absolute; left: auto; right: 0; bottom: auto; top: calc(100% + 8px); z-index: 40; /* --z-menu */ width: 252px; max-width: calc(100vw - 16px); max-height: none; overflow: visible; padding: 13px; border-radius: 14px; border-bottom: 1px solid var(--border2); animation: calIn .16s ease; box-shadow: 0 16px 42px rgba(60,56,48,.22); }
}
/* the Period button while a past day is picked: the solid pair, as a pressed .cb-segbtn */
.cb-period-btn.is-past { background: var(--solid); color: var(--on-solid); border-color: transparent; } @media (hover: hover) { .cb-period-btn.is-past:hover { background: var(--solid); color: var(--on-solid); border-color: transparent; } }
.cb-period-btn.is-past .cb-eyebrow { color: color-mix(in srgb, var(--on-solid) 72%, var(--solid)); }
.cb-period-btn.is-past .cb-chev { opacity: .85; }
/* the banner: .qlog-banner (the quiet tray, the bold title, the solid button) + ONE muted line */
/* its right edge meets the control bar's line (the .cb-zone padding-right: 14 px, 22 px from 900 px), as the board
   under it does — the old-cart banner above the deck spans the page */
.pd-banner { justify-content: space-between; gap: 10px 16px; padding: 12px 12px 12px 18px; margin: -4px 14px 16px 0; text-align: left; }
@media (min-width: 900px) { .pd-banner { margin-right: 22px; } }
.pd-text { display: flex; flex-direction: column; gap: 3px; flex: 1 1 260px; min-width: 0; }
/* balanced lines: on a phone the title breaks as "Logging for yesterday, / Thursday 1 October", never with one word
   left on its own line (a one-line banner is unchanged) */
.pd-title { font-size: 15px; font-weight: 900; color: var(--ink); line-height: 1.3; text-wrap: balance; }
.pd-line { font-size: 13.5px; font-weight: 600; color: var(--ink3); line-height: 1.4; text-wrap: balance; }
.pd-banner .qlog-banner-log { padding: 10px 18px; font-size: 13.5px; }
/* 44-px target on touch: Back to today (Yesterday and Choose a day… are rows — the .cb-row coarse rule's height) */
@media (pointer: coarse) { .pd-banner .qlog-banner-log { min-height: 44px; } }

/* ---------- bd- : the board region (App v3 664–837; gridStyle 4083, the card wrapStyle / headerStyle 3618–3630,
   tileGridStyle 4085; js/board.js). Each card sets its colour variables inline (board-model.js catVars(hex)):
   --cat (the stored header hex = App v3 `base`), --cat-acc (the dark-mode accent), --cat-ink / --cat-ink-d (the pill
   name), --cat-dim (the pill border), --cat-wash / --cat-wash-d / --cat-line-d (the pill fill + dark border), --cat-glow*
   (the focus ring), --cat-sel / --cat-sel-line (a selected pill); pills inherit them. ---------- */
.bd-noresults { text-align: center; padding: 26px 0 10px; font-size: 14.5px; font-weight: 700; color: var(--muted-text); /* d11 */ }
.bd-allhidden { border: 2px dashed var(--border2); border-radius: 18px; padding: 26px 20px; margin: 0 0 14px; text-align: center; }
.bd-allhidden-title { font-size: 14.5px; font-weight: 800; color: var(--ink2); margin-bottom: 5px; }
.bd-allhidden-btn { background: none; border: none; padding: 0; font-size: 13.5px; font-weight: 800; color: var(--ink2); text-decoration: underline; text-underline-offset: 2px; cursor: pointer; }
@media (pointer: coarse) { .bd-allhidden-btn { min-height: 44px; padding: 0 8px; } }
/* the grid — board.js sets data-cols (1–5, capped by the width as App v3 gridStyle does — 4 and 5: the big- section below) and data-mode (count / select / focus) */
.bd-grid { --bd-cols: 3; display: grid; grid-template-columns: repeat(var(--bd-cols), minmax(0, 1fr)); gap: 16px; align-items: stretch; padding-right: 24px; animation: gridFade .22s ease; }
.bd-grid[data-cols="1"] { --bd-cols: 1; }
.bd-grid[data-cols="2"] { --bd-cols: 2; }
.bd-grid[data-cols="3"] { --bd-cols: 3; }
/* the width cap, restated as a belt (App v3: < 640 → 1, < 1000 → 2); the right padding is the rail's lane (28 narrow) */
@media (max-width: 999.98px) { .bd-grid[data-cols="3"] { --bd-cols: 2; } }
@media (max-width: 639.98px) { .bd-grid, .bd-grid[data-cols] { --bd-cols: 1; padding-right: 28px; } }
/* ---------- big- : big screens (owner, 2026-10-03; LABELLED deviations from App v3, whose columns stop at 3). The
   page zoom stops at 1.14 (the zoom steps, top of the file), so a wide window no longer blows everything up; it takes
   MORE COLUMNS instead. View → Columns lists 4 from 1800 px and 5 from 2200 px (view-model.js COL_BREAKS — the same
   numbers as the belts below), and the page column grows by ONE CARD + ONE GAP per extra column, so a card keeps its
   3-column width: 3 columns = the 1240-px column (.page-col) less the rail's 24-px lane = 1216 = 3 cards of 1184/3
   (394.67) + 2 gaps of 16; 4 columns = 1240 + 394.67 + 16 = 1650.67; 5 = 2061.33. Everything in the column — the
   header, the deck, the control bar, the tag row — follows it; the jump rail's dock measures the column (way-rail.js).
   board.js writes the EFFECTIVE count on #grid AND on #appPage (data-cols). The @media rules are the belt, as for
   1–3: a count the window cannot fit falls back (5 → 4 → 3 → 2 → 1) before JS re-caps it.
   BEFORE the board is built #appPage carries no count yet: the loading shell takes the count this device last chose
   — /theme-boot.js puts the 'cm-cols' cache (4 or 5) on <html data-cols> before the first paint — through each
   rule's `html[data-cols] #appPage:not([data-cols])` twin (same widths, same belts), so the header does not jump
   sideways when the board lands. Once board.js has written #appPage's own count the twins stop matching. ---------- */
.bd-grid[data-cols="4"] { --bd-cols: 4; }
.bd-grid[data-cols="5"] { --bd-cols: 5; }
.page[data-cols="4"] .page-col, html[data-cols="4"] #appPage:not([data-cols]) .page-col { max-width: calc(1240px + (1184px / 3 + 16px)); }
.page[data-cols="5"] .page-col, html[data-cols="5"] #appPage:not([data-cols]) .page-col { max-width: calc(1240px + 2 * (1184px / 3 + 16px)); }
@media (max-width: 2199.98px) {
  .bd-grid[data-cols="5"] { --bd-cols: 4; }
  .page[data-cols="5"] .page-col, html[data-cols="5"] #appPage:not([data-cols]) .page-col { max-width: calc(1240px + (1184px / 3 + 16px)); }
}
@media (max-width: 1799.98px) {
  .bd-grid[data-cols="4"], .bd-grid[data-cols="5"] { --bd-cols: 3; }
  .page[data-cols="4"] .page-col, .page[data-cols="5"] .page-col,
  html[data-cols="4"] #appPage:not([data-cols]) .page-col, html[data-cols="5"] #appPage:not([data-cols]) .page-col { max-width: 1240px; }
}
@media (max-width: 999.98px) { .bd-grid[data-cols="4"], .bd-grid[data-cols="5"] { --bd-cols: 2; } }
@media (max-width: 639.98px) { .bd-grid[data-cols="4"], .bd-grid[data-cols="5"] { --bd-cols: 1; } }
.bd-loading { grid-column: 1 / -1; text-align: center; padding: 26px 0; font-size: 14.5px; font-weight: 700; color: var(--muted-text); /* d11 — the boot "Loading…" line (was .muted-note) */ }
/* the card (App v3 717–827) — z 1 at rest, 35 with its ⋮ / colour popover open (_hostZ(open, 5); Z.nested when narrow) */
.bd-card { position: relative; z-index: 1; display: flex; flex-direction: column; min-width: 0; background: var(--card); border-radius: 18px; box-shadow: 0 1px 4px rgba(0,0,0,.07); overflow: hidden; transition: opacity .12s, box-shadow .3s, outline-color .2s; }
.bd-card.is-menu { overflow: visible; z-index: 35; }
@media (max-width: 639.98px) { .bd-card.is-menu { z-index: 1010; /* --z-nested */ } }
.bd-card.is-dragging { opacity: .4; outline: 2px dashed var(--cat); outline-offset: 0; }
/* Show on board (App v3 3618 `jumped`): the card ring rgba(col,.6) — home.js sets --home-flash on the card — + a lift
   shadow, held 1700 ms (the card's box-shadow .3s transition fades it). */
.bd-card.home-flash { box-shadow: 0 0 0 3px var(--home-flash, rgba(0,0,0,.18)), 0 8px 22px rgba(0,0,0,.16); }
.bd-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 12px 15px; background: var(--cat); color: #fff; border-radius: 18px 18px 0 0; }
.bd-head-l { display: flex; align-items: center; gap: 6px; min-width: 0; flex: 1 1 auto; }
.bd-handle { flex: none; width: 24px; height: 24px; padding: 0; border: none; border-radius: 6px; background: rgba(255,255,255,.18); color: #fff; font-size: 14px; line-height: 1; display: grid; place-items: center; cursor: grab; touch-action: none; user-select: none; -webkit-user-select: none; }
.bd-handle:active { cursor: grabbing; transform: none; }
.bd-title { display: flex; align-items: center; gap: 7px; min-width: 0; flex: 1 1 auto; background: none; border: none; color: #fff; text-align: left; padding: 3px 3px 3px 2px; border-radius: 8px; cursor: pointer; }
@media (hover: hover) { .bd-title:hover { background: rgba(255,255,255,.13); } }
.bd-num { flex: none; font-size: 13px; font-weight: 800; opacity: .55; }
.bd-name { min-width: 0; font-size: 16px; font-weight: 900; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bd-chev { flex: none; font-size: 15px; opacity: .6; line-height: 1; }
.bd-head-r { display: flex; align-items: center; gap: 6px; flex: none; }
.bd-hbtn { flex: none; width: 29px; height: 29px; padding: 0; border: none; border-radius: 999px; background: rgba(255,255,255,.15); color: #fff; display: grid; place-items: center; cursor: pointer; }
.bd-hbtn--more { background: rgba(255,255,255,.2); font-size: 16px; line-height: 1; }
/* the header's buttons by mode (board.js also sets `hidden`; these agree): count = + and shuffle; select = ⋮;
   focus (Choose) = none — LABELLED deviation from App v3 (owner, 2026-10-03): + leaves the choosing flow and the
   shuffle replaces the card's picks, so Choose hides both and the shuffle's ← → pill, as Select does */
.bd-grid:not([data-mode="select"]) .bd-more { display: none; }
.bd-grid[data-mode="select"] .bd-add, .bd-grid[data-mode="select"] .bd-shuffle, .bd-grid[data-mode="select"] .bd-cyc,
.bd-grid[data-mode="focus"] .bd-add, .bd-grid[data-mode="focus"] .bd-shuffle, .bd-grid[data-mode="focus"] .bd-cyc { display: none; }
/* touch (a11y rule 9): 44-px hit areas at App v3's sizes, grown into the header's padding and gaps — never over a
   visible neighbour: the handle takes the 15-px padding to the card's edge and 5 of its 6-px gap; + the 10-px gap
   before it and 5 of the 6 after; the last button (the shuffle, or ⋮ in Select mode) 1 px and 14 of the 15-px
   padding; the title 8 px up and down inside the header's 12-px padding; the footer 4 px up into the pills' 18-px
   bottom padding (an ::after spans the PADDING box — a bordered button's inset adds its border back). LABELLED exception: the per-card focus pill's 26-px ← → ⟲ (App v3 729–735, 3-px gaps) keep their
   size, and + then takes only 3 px on its left. */
@media (pointer: coarse) {
  .bd-hbtn, .bd-handle, .bd-title, .bd-glance { position: relative; }
  .bd-hbtn::after, .bd-handle::after, .bd-title::after, .bd-glance::after { content: ""; position: absolute; }
  .bd-handle::after { inset: -10px -5px -10px -15px; }
  .bd-add::after { inset: -8px -5px -8px -10px; }
  .bd-cyc:not([hidden]) ~ .bd-add::after { left: -3px; }
  .bd-shuffle::after, .bd-more::after { inset: -8px -14px -8px -1px; }
  .bd-title::after { inset: -8px 0; }
  .bd-glance::after { inset: -5px 0 0; }
}
/* the per-card focus pill ← / → / clear (App v3 729–735) */
.bd-cyc { flex: none; display: inline-flex; align-items: center; gap: 3px; padding: 3px; border-radius: 999px; background: rgba(0,0,0,.13); animation: menuIn .16s ease; }
/* LABELLED: App v3 inks these near-white discs with var(--ink2), which turns light in dark mode (unreadable on
   rgba(255,255,255,.92)) — the light-mode --ink2 is kept as a literal so the arrows read in both modes. */
.bd-cyc-btn { flex: none; width: 26px; height: 26px; padding: 0; border: none; border-radius: 999px; background: rgba(255,255,255,.92); color: #5a564b; font-size: 14px; display: grid; place-items: center; cursor: pointer; }
/* the pills area (tileGridStyle 4085) */
.bd-pills { display: flex; flex-wrap: wrap; align-items: flex-start; gap: 8px; padding: 12px 12px 18px; }
.bd-pills:empty { display: none; }
/* the glance footer (App v3 816–823): "N this month · +N today" + the 28-day sparkline + Insights › */
.bd-glance { display: flex; align-items: center; gap: 11px; width: 100%; margin-top: auto; padding: 9px 15px 11px; background: none; border: none; border-top: 1px solid color-mix(in oklab, var(--ink) 8%, transparent); border-radius: 0 0 18px 18px; text-align: left; cursor: pointer; }
.bd-glance:active { transform: none; }
.bd-glance-text { min-width: 0; font-size: 12.5px; font-weight: 700; color: var(--muted-text); /* d11 */ white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.bd-glance-sp { flex: 1 1 auto; }
@media (max-width: 400px) { .bd-glance { gap: 8px; } }   /* phone fix 6: "Nothing this month" keeps 7+ px of room at 375 px on every font renderer (CI's Linux Chrome drew it 2 px wider) */
.bd-spark { flex: none; display: block; width: 92px; height: 19px; overflow: visible; opacity: .9; }
.bd-spark.is-quiet { opacity: .55; }
.bd-spark path { fill: none; stroke: var(--cat); stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.bd-spark circle { fill: var(--cat); }
.bd-insights { flex: none; display: inline-flex; align-items: center; gap: 3px; font-size: 12px; font-weight: 800; color: var(--accent-text); /* d11 — App v3 var(--accent) */ }
.bd-insights span { line-height: 1; }
/* the empty-category CTA (App v3 825) */
.bd-first { margin: auto 13px 13px; min-height: 44px; padding: 12px; background: none; border: 1.5px dashed var(--border2); border-radius: 12px; font-size: 13.5px; font-weight: 800; color: var(--muted-text); /* d11 */ cursor: pointer; }
.bd-grid[data-mode="select"] .bd-first, .bd-grid[data-mode="focus"] .bd-first { display: none; }   /* Choose too (tidy round 5): the same store door as + */
/* the New category / Discover tile (App v3 830–835) — the plain count view only */
.bd-tile { break-inside: avoid; margin-bottom: 16px; }
.bd-tile-btn { display: block; width: 100%; background: transparent; border: 2px dashed #cfc9ba; border-radius: 18px; padding: 20px 18px; font-size: 14px; font-weight: 800; line-height: 1.4; color: var(--muted2-text); /* d11 */ cursor: pointer; }
.bd-tile-btn + .bd-tile-btn { margin-top: 10px; }
body[data-mode="dark"] .bd-tile-btn { border-color: var(--bordersoft); }   /* LABELLED: App v3's #cfc9ba literal glares on the dark board */
.bd-grid[data-mode="select"] .bd-tile, .bd-grid[data-mode="focus"] .bd-tile { display: none; }
/* the board's empty state (#gridEmpty — the SITE's; App v3 has none): the deck-empty dashed box, a Lora title */
.bd-empty { text-align: center; padding: 34px 20px 30px; margin-right: 24px; border: 2px dashed var(--border2); border-radius: 18px; }
@media (max-width: 639.98px) { .bd-empty { margin-right: 28px; } }   /* = the grid's right padding (the rail's lane) */
.bd-empty-title { font-family: 'Lora', serif; font-size: 20px; font-weight: 700; color: var(--ink); margin-bottom: 6px; }
.bd-empty-sub { max-width: 40ch; margin: 0 auto 16px; font-size: 14px; font-weight: 600; line-height: 1.5; color: var(--muted-text); /* d11 */ }
.bd-empty-acts { display: flex; flex-wrap: wrap; justify-content: center; gap: 10px; }
.bd-empty-primary { min-height: 44px; padding: 11px 20px; background: var(--solid); color: var(--on-solid); border: none; border-radius: 999px; font-size: 14px; font-weight: 900; cursor: pointer; }
.bd-empty-secondary { min-height: 44px; padding: 11px 20px; background: var(--card); color: var(--ink2); border: 1px solid var(--border); border-radius: 999px; font-size: 14px; font-weight: 800; cursor: pointer; }
/* a board with no category at all: the chrome that has nothing to act on steps aside (board.js toggles body.cm-grid-empty) */
body.cm-grid-empty .tg-row, body.cm-grid-empty .sm-wrap, body.cm-grid-empty .way-dock, body.cm-grid-empty .fd-dock, body.cm-grid-empty .cb-viewc { display: none !important; }
/* Analytics — the Patterns placeholder (README decision 3): the gal- card (no link — the legacy dashboard page was removed, 2026-10-03) */
/* Board ↔ Analytics keeps your place (pastday ruling 6): the panel is at least a screen tall, so the scroll the tab
   bar sits at is still reachable on Analytics (the zoom rule: dvh ÷ --zf); its words sit at the top. */
.pt-card { margin-right: 24px; min-height: calc(100dvh / var(--zf, 1)); align-content: start; }
@media (max-width: 639.98px) { .pt-card { margin-right: 0; } }

/* ---------- bd-pill : an activity (App v3 739–775; tileStyle / badgeStyle 3656–3730 at the default "comfortable" size,
   the Wrap layout — Grid / List are tabled). A container holding ONE button, .bd-pill-main (tap = +1; the tick, the
   name, the count) — the whole pill is the +, its padding symmetric (12, or 15 >= 1100). LABELLED deviation (owner,
   2026-10-02): App v3's › door (doorWrapStyle) is removed; the activity home opens from the context menu's Open (and
   History, a deck card, the category Overview). ---------- */
.bd-pill { position: relative; display: inline-flex; align-items: stretch; max-width: 100%; min-height: 34px; border-radius: 999px; background: var(--cat-wash); border: 1.5px solid var(--cat-dim); box-shadow: none; opacity: 1; user-select: none; -webkit-user-select: none; -webkit-touch-callout: none; transition: opacity .12s, box-shadow .3s, background .25s, border-color .25s; }
body[data-mode="dark"] .bd-pill { background: var(--cat-wash-d); border-color: var(--cat-line-d); }
/* App v3's tile is a div (no button hover / press); the main button keeps that */
.bd-pill-main { display: inline-flex; align-items: center; gap: 6px; flex: 1 1 auto; min-width: 0; padding: 6px 12px; background: none; border: none; border-radius: 999px; color: var(--cat-ink); font: inherit; text-align: left; cursor: pointer; touch-action: manipulation; }
@media (hover: hover) { .bd-pill-main:hover { filter: none; } }
.bd-pill-main:active { transform: none; }
.bd-pill-name { min-width: 0; font-size: 14px; font-weight: 700; line-height: 1.25; color: var(--cat-ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
body[data-mode="dark"] .bd-pill-main, body[data-mode="dark"] .bd-pill-name { color: var(--cat-ink-d); }
/* The pill's count badge — SOLID (owner, 2026-10-02; replaces App v3's Lora MAIN badge on board pills only — a deck
   card keeps .deck-card-count): the category colour mixed exactly 10% toward white for EVERY colour, a white number,
   Nunito 800 12.5 px in a 20-px pill; hidden at 0 (quick-log.js paintBadge). Dark mode: the category's light accent
   (--cat-acc) with a dark number. LABELLED owner deviation: white on the 10%-lighter orange / green sits under WCAG AA
   (≈ 3.7 / 4.2 : 1) — the owner's choice, kept on purpose. settleIn on a first show / a change; numswap on a Period
   switch (uTotals changed). */
.bd-pill-count { flex: none; display: inline-flex; align-items: center; justify-content: center; box-sizing: border-box; height: 20px; min-width: 20px; padding: 0 6px; border-radius: 999px; background: color-mix(in srgb, var(--cat) 90%, #fff); color: #fff; font-family: 'Nunito', system-ui, sans-serif; font-weight: 800; font-size: 12.5px; line-height: 1; letter-spacing: 0; font-variant-numeric: tabular-nums; }
.bd-pill-count[hidden] { display: none; }
body[data-mode="dark"] .bd-pill-count { background: var(--cat-acc); color: #26231f; }
.bd-pill-count.is-settle { animation: settleIn .5s ease; }
.bd-pill-count.is-swap { animation: numswap .36s cubic-bezier(.22,1,.36,1); }
/* >= 1100 px (App v3 _B): pad 8 × 15, gap 7, name 14.5, min-height 39 */
@media (min-width: 1100px) {
  .bd-pill { min-height: 39px; }
  .bd-pill-main { padding: 8px 15px; gap: 7px; }
  .bd-pill-name { font-size: 14.5px; }
}
/* coarse pointer OR < 640 px (App v3 _CO): 44-px pills */
@media (pointer: coarse), (max-width: 639.98px) { .bd-pill { min-height: 44px; } }
/* the focus light (decision 5): .is-glow = in the set with the light on (App v3 glowShadow); .is-dim = App v3 `dimmed` */
.bd-pill.is-glow { box-shadow: 0 0 0 2px var(--cat-glow), 0 5px 14px var(--cat-glow2); }
body[data-mode="dark"] .bd-pill.is-glow { box-shadow: 0 0 0 2px var(--cat-glow-d), 0 5px 14px var(--cat-glow2-d); }
.bd-pill.is-dim { opacity: .42; }
/* Choosing a focus (data-mode focus): a pick glows (App v3 toggleOneHL turns the light on) and the rest dim once anything
   is picked; .is-in (in the set) glows here even before board-model paints .is-glow. No tick while
   choosing (App v3 772 draws the ✓ only when act.manage — Select mode); aria-pressed on the main button names a pick. */
.bd-grid[data-mode="focus"] .bd-pill.is-in { box-shadow: 0 0 0 2px var(--cat-glow), 0 5px 14px var(--cat-glow2); }
body[data-mode="dark"] .bd-grid[data-mode="focus"] .bd-pill.is-in { box-shadow: 0 0 0 2px var(--cat-glow-d), 0 5px 14px var(--cat-glow2-d); }
/* Select mode (App v3 manage tileStyle + pillCheckStyle = _tickCss(selected, base) + margin-right 2) */
.bd-pill-tick { display: none; flex: none; width: 20px; height: 20px; margin-right: 2px; border-radius: 999px; border: 1.5px solid var(--border2); background: transparent; color: transparent; place-items: center; font-size: 11px; font-weight: 900; line-height: 1; transition: background .12s ease, border-color .12s ease, color .12s ease; }
.bd-grid[data-mode="select"] .bd-pill { background: var(--surface); border: 1.5px solid var(--border3); box-shadow: none; }
.bd-grid[data-mode="select"] .bd-pill.is-selected { background: var(--cat-sel); border: 2px solid var(--cat-sel-line); }
.bd-grid[data-mode="select"] .bd-pill-tick { display: grid; }
.bd-grid[data-mode="select"] .bd-pill.is-selected .bd-pill-tick { background: var(--cat); border-color: var(--cat); color: var(--card); }
.bd-grid[data-mode="select"] .bd-pill-name { color: var(--muted-text); }   /* d11 — App v3 var(--muted) */
.bd-grid[data-mode="select"] .bd-pill.is-selected .bd-pill-name { color: var(--cat-ink); }
body[data-mode="dark"] .bd-grid[data-mode="select"] .bd-pill.is-selected .bd-pill-name { color: var(--cat-ink-d); }
.bd-grid[data-mode="select"] .bd-pill-count { display: none; }
/* App v3 glanceShown needs count mode; the ⠿ handle stays in every mode (App v3 720 draws it unconditionally — a card
   drags in Select and Choose too). */
.bd-grid[data-mode="select"] .bd-glance, .bd-grid[data-mode="focus"] .bd-glance { display: none; }
/* the "+1" pop reuses .qlog-pop (quick-log.js playPop(pillEl)) — .bd-pill is position: relative */
@media (prefers-reduced-motion: reduce) { .bd-pill-count.is-settle, .bd-pill-count.is-swap, .bd-grid { animation: none !important; } }
/* the drag ghost — drag.js clones the card's HEADER bar (App v3 beginDrag 'cat': the category bar), fixed, lifted */
.bd-ghost { position: fixed; z-index: 1100; pointer-events: none; margin: 0; transform: scale(1.02); box-shadow: 0 18px 40px rgba(0,0,0,.3); opacity: .96; border-radius: 18px; background: var(--cat); color: #fff; }

/* ---------- bd-ctx : an activity's context menu (App v3 1804–1808; actCtxStyle 4265, actCtxItems 4280). Fixed at
   --z-confirm (above the Select bar, the rail and the dock, all 100, and an open anchored menu, 40); board.js places it
   (÷ zf). ---------- */
.bd-ctx { position: fixed; z-index: 1015; /* --z-confirm */ width: 214px; max-width: calc(100vw - 20px); padding: 6px; background: var(--card); border: 1px solid var(--border2); border-radius: 14px; box-shadow: 0 14px 40px rgba(0,0,0,.22); animation: menuIn .12s ease; text-align: left; }
.bd-ctx:focus { outline: none; }   /* phone ruling 3: a touch hold / right-click focuses the menu itself (tabindex -1) — not a control, no ring */
.bd-ctx-item { display: flex; align-items: center; width: 100%; min-width: 0; padding: 9px 10px; background: transparent; border: none; border-radius: 8px; font-size: 13.5px; font-weight: 600; color: var(--muted-text); /* d11 — App v3 var(--muted) */ text-align: left; white-space: nowrap; cursor: pointer; }
.bd-ctx-item:focus-visible { background: var(--chip); } @media (hover: hover) { .bd-ctx-item:hover { background: var(--chip); } }
.bd-ctx-item--open { font-weight: 800; color: var(--ink); }
.bd-ctx-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bd-ctx-item--sep { margin-top: 5px; padding: 12px 10px 9px; border-top: 1px solid var(--hair); }
.bd-ctx-item--danger { color: #9e4a3c; }
@media (pointer: coarse) { .bd-ctx-item { min-height: 44px; } }

/* ---------- bd-menu : the card ⋮ in Select mode + the colour popover (App v3 745–765; menuStyle 3621 =
   _menuCss({ align: 'right', top: '44px', w: 196, anchored: true }), itemStyle 3629, swStyle 3616). ---------- */
.bd-menu { position: absolute; top: 44px; right: 0; z-index: 40; /* --z-menu */ min-width: 196px; max-width: min(276px, calc(100vw - 32px)); padding: 8px; overflow: visible; background: var(--card); border: 1px solid var(--border2); border-radius: 14px; box-shadow: 0 12px 30px rgba(0,0,0,.18); animation: menuIn .16s ease; text-align: left; }
.bd-menu-item { display: block; width: 100%; padding: 10px 12px; background: transparent; border: none; border-radius: 10px; font-size: 14.5px; font-weight: 700; color: var(--ink); text-align: left; cursor: pointer; }
@media (hover: hover) { .bd-menu-item:hover { background: var(--chip); } }
.bd-menu-item--sep { margin-top: 5px; padding: 12px 12px 9px; border-top: 1px solid var(--hair); }
.bd-menu-item--danger { color: #9e4a3c; }
@media (pointer: coarse) { .bd-menu-item { min-height: 44px; } }
/* LABELLED: App v3's #9e4a3c danger ink reads 2.6:1 on the dark card — the dark --danger instead */
body[data-mode="dark"] .bd-ctx-item--danger, body[data-mode="dark"] .bd-menu-item--danger { color: var(--danger); }
.bd-colors { width: 276px; }
.bd-colors-head { display: flex; align-items: center; justify-content: space-between; padding: 4px 6px 10px; }
.bd-colors-title { font-size: 13px; font-weight: 800; color: var(--ink); }
.bd-colors-x { background: none; border: none; padding: 0 2px; font-size: 15px; font-weight: 800; color: var(--muted2-text); /* d11 */ cursor: pointer; }
@media (pointer: coarse) { .bd-colors-x { position: relative; } .bd-colors-x::after { content: ""; position: absolute; left: 50%; top: 50%; width: 44px; height: 44px; transform: translate(-50%, -50%); } }
.bd-swatches { display: flex; flex-wrap: wrap; gap: 7px; padding: 0 4px 4px; }
/* data-still in App v3 (no press scale, no transition); --sw = the swatch hex, set inline */
.bd-swatch { flex: none; width: 26px; height: 26px; padding: 0; border: none; border-radius: 999px; background: var(--sw); box-shadow: 0 0 0 1px rgba(0,0,0,.08); cursor: pointer; transition: none; }
.bd-swatch:active { transform: none; }
.bd-swatch[aria-checked="true"] { box-shadow: inset 0 0 0 3px var(--card), 0 0 0 2px var(--sw); }
@media (pointer: coarse) { .bd-swatch { position: relative; } .bd-swatch::after { content: ""; position: absolute; inset: -3px; } }   /* 26 + 2 × 3 = 32 — the half-gaps; neighbours never overlap */

/* ---------- tg- : the tags row (App v3 674–694; tagChips 4101, smartTagsBtnStyle 4104, .tagbtn L51–53; js/tags.js).
   Chips FILTER the board (decision 6). The right padding = colzonePad (App v3 675): 22 >= 900, 14 below. ---------- */
.tg-row { display: flex; align-items: center; gap: 10px; min-width: 0; margin: 0 0 14px; padding-right: 14px; }
@media (min-width: 900px) { .tg-row { padding-right: 22px; } }
.tg-label { flex: none; display: inline-flex; align-items: center; gap: 5px; font-size: 10.5px; font-weight: 800; letter-spacing: .1em; text-transform: uppercase; color: var(--muted2-text); /* d11 */ }
/* the chevrons (fine pointers only; tags.js shows each while there is more to scroll that way) */
.tg-chev { flex: none; width: 24px; height: 26px; padding: 0; border: none; border-radius: 999px; background: var(--chip); color: var(--muted); display: grid; place-items: center; cursor: pointer; transition: opacity .15s ease; }
@media (hover: hover) { .tg-chev:hover { color: var(--ink); } }
.tg-scroll { flex: 1 1 auto; min-width: 0; display: flex; gap: 8px; padding: 2px 0; overflow-x: auto; overflow-y: hidden; scrollbar-width: none; }   /* no -webkit-overflow-scrolling (mobile pass ruling 3: an iOS stacking-context trap) */
.tg-scroll::-webkit-scrollbar { display: none; }
/* the 18-px edge fades (App v3 tagFadeRef): tags.js sets .at-start / .at-end */
.tg-scroll { -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 18px, #000 calc(100% - 18px), transparent 100%); mask-image: linear-gradient(90deg, transparent 0, #000 18px, #000 calc(100% - 18px), transparent 100%); }
.tg-scroll.at-start { -webkit-mask-image: linear-gradient(90deg, #000 calc(100% - 18px), transparent 100%); mask-image: linear-gradient(90deg, #000 calc(100% - 18px), transparent 100%); }
.tg-scroll.at-end { -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 18px); mask-image: linear-gradient(90deg, transparent 0, #000 18px); }
.tg-scroll.at-start.at-end { -webkit-mask-image: none; mask-image: none; }
.tg-chip { flex: none; display: inline-flex; align-items: center; padding: 7px 14px; border-radius: 999px; background: var(--chip); border: 1px solid var(--border2); font-size: 12.5px; font-weight: 700; line-height: 1; color: var(--ink2); white-space: nowrap; cursor: pointer; }
.tg-chip[aria-pressed="true"] { background: var(--solid); border-color: transparent; color: var(--on-solid); font-weight: 800; }
.tg-chip-x { margin: 0 -2px 0 7px; opacity: .7; font-size: 12px; font-weight: 800; line-height: 1; }
.tg-chip:not([aria-pressed="true"]) .tg-chip-x { display: none; }
.tg-div { flex: none; width: 1px; height: 20px; background: var(--border2); }
.tg-smart { flex: none; display: inline-flex; align-items: center; gap: 6px; padding: 6px 12px; border-radius: 999px; background: transparent; border: 1px solid var(--border2); font-size: 12.5px; font-weight: 800; color: var(--muted2-text); /* d11 */ white-space: nowrap; cursor: pointer; }
.tg-smart svg { flex: none; opacity: .85; }
.tg-smart[aria-expanded="true"] { background: color-mix(in oklab, var(--accent) 12%, var(--card)); border-color: color-mix(in oklab, var(--accent) 45%, var(--border2)); color: var(--accent-text); /* d11 */ }
/* Under 480 px Smart tags shows ONLY ITS ICON, a 32 × 32 circle like + New and Manage beside it (LABELLED — a deviation
   from App v3, which keeps the word at every width; owner, 2026-10-11). Why: every new board now has the starter
   board's seven tags, and with the word the chips had a 63-px window on a 375-px phone (8 px at 320) — less than one
   chip. Without it: 141 px at 375, 86 at 320. The words stay for assistive technology (the button's aria-label; its
   title), the label is only not drawn; from 480 px up NOTHING changes. */
@media (max-width: 479.98px) {
  .tg-smart { width: 32px; height: 32px; padding: 0; justify-content: center; }
  .tg-smart-lbl { display: none; }
}
/* + New and Manage (.tagbtn L51–53): icon-only 32 × 32 below 900 px, labelled pills from 900 */
.tg-btn { flex: none; display: inline-flex; align-items: center; justify-content: center; gap: 5px; width: 32px; height: 32px; padding: 0; border-radius: 999px; background: transparent; border: 1px solid var(--border2); color: var(--muted2-text); /* d11 */ cursor: pointer; }
.tg-btn svg { flex: none; }
@media (hover: hover) { .tg-btn:hover { color: var(--ink); } }
.tg-btn-lbl { display: none; font-size: 12.5px; font-weight: 800; white-space: nowrap; }
@media (min-width: 900px) { .tg-btn { width: auto; padding: 0 13px; } .tg-btn-lbl { display: inline; } }
/* touch (a11y rule 9): App v3's sizes stay (chip 28.5, Smart tags 31, the icon buttons 32 — the row 33 tall); 44-px
   hit areas instead. The scroller grows 8 px of padding each way (a negative margin keeps the row's height) so its
   overflow never clips the chips' areas. */
@media (pointer: coarse) {
  .tg-chev { display: none !important; }
  .tg-scroll { padding: 8px 0; margin: -6px 0; }
  .tg-chip, .tg-smart, .tg-btn { position: relative; }
  .tg-chip::after, .tg-smart::after, .tg-btn::after { content: ""; position: absolute; }
  .tg-chip::after { inset: -9px -4px; }      /* 26.5 inside the 1-px border + 18 */
  .tg-smart::after { inset: -7.5px -5px; }
  .tg-btn::after { inset: -7px; }
}
/* the icon-only Smart tags (under 480 px): 30 inside the border + 7 up and down = 44; sideways 9 px into the gap before
   it (the divider's — nothing to tap there) and 5 px after it, where + New's own area begins: 30 + 14 = 44 */
@media (max-width: 479.98px) and (pointer: coarse) {
  .tg-smart::after { inset: -7px -5px -7px -9px; }
}

/* ---------- sm- : the Smart tags panel (App v3 695–711; smartChips 4102). ---------- */
.sm-wrap { margin: 8px 0 14px; padding-right: 14px; }
@media (min-width: 900px) { .sm-wrap { padding-right: 22px; } }
.sm-card { background: var(--soft); border: 1px solid var(--border2); border-radius: 14px; padding: 11px 13px; }
.sm-row { display: flex; align-items: center; flex-wrap: wrap; gap: 9px; }
.sm-label { flex: none; display: inline-flex; align-items: center; gap: 5px; font-size: 10.5px; font-weight: 800; letter-spacing: .1em; text-transform: uppercase; color: var(--accent-text); /* d11 */ }
.sm-chips { display: contents; }
.sm-chip { flex: none; display: inline-flex; align-items: center; gap: 6px; height: 30px; padding: 0 14px; border-radius: 999px; background: color-mix(in oklab, var(--accent) 8%, var(--card)); border: 1px solid color-mix(in oklab, var(--accent) 30%, var(--border2)); font-size: 12.5px; font-weight: 800; line-height: 1; color: var(--accent-text); /* d11 */ white-space: nowrap; cursor: pointer; }
/* text on the accent FILL = var(--on-solid) (the house rule; App v3 #fff) */
.sm-chip[aria-pressed="true"] { background: var(--accent); border-color: transparent; color: var(--on-solid); }
.sm-chip-x { display: inline-flex; align-items: center; justify-content: center; width: 16px; height: 16px; margin-right: -5px; border-radius: 999px; font-size: 13px; line-height: 1; opacity: .85; }
.sm-chip:not([aria-pressed="true"]) .sm-chip-x { display: none; }
.sm-empty { font-size: 13px; font-weight: 700; color: var(--muted-text); /* d11 */ }
.sm-cap { display: flex; align-items: center; flex-wrap: wrap; gap: 10px; margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--border2); }
.sm-cap-text { flex: 1 1 240px; min-width: 0; font-size: 13px; font-weight: 700; line-height: 1.45; color: var(--muted-text); /* d11 */ text-wrap: pretty; }
.sm-cap-text b { color: var(--ink); font-weight: 800; }
.sm-deal { flex: none; display: inline-flex; align-items: center; gap: 6px; padding: 7px 15px; border: none; border-radius: 999px; background: var(--solid); color: var(--on-solid); font-size: 12.5px; font-weight: 800; white-space: nowrap; cursor: pointer; }
.sm-deal svg { flex: none; }
.sm-deal svg rect { fill: var(--solid); }   /* App v3 fill="var(--solid)": the front card hides the back one's lines */
/* touch: 44-px hit areas at App v3's sizes (the chips 30, Deal 29) */
@media (pointer: coarse) { .sm-chip, .sm-deal { position: relative; } .sm-chip::after, .sm-deal::after { content: ""; position: absolute; inset: -8px -4px; } }

/* ---------- sel- : Select mode — the bar and the bulk move panel (App v3 224–257; manageBarStyle 4023,
   selBarLabelStyle 4338; js/bulk.js). Fixed, centred 24 px up; inside #counterView, so the Gallery never shows it. ---------- */
/* LABELLED: max-content (App v3 `auto`): a left-50% fixed box shrinks to the right half of the screen, which squeezed
   the hint onto two lines at 375 px; with a selection the bar takes min(680, 92vw) as in App v3. */
.sel-wrap { position: fixed; left: 50%; bottom: calc(24px + env(safe-area-inset-bottom, 0px)); transform: translateX(-50%); z-index: 100; /* --z-sticky */ width: max-content; max-width: 92vw; }
.sel-wrap.has-sel { width: min(680px, 92vw); }
.sel-bar { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 11px 18px; background: var(--solid); color: var(--on-solid); border-radius: 14px; box-shadow: 0 12px 32px rgba(0,0,0,.28); animation: popup .2s ease; }
.sel-status { display: flex; align-items: baseline; flex-wrap: wrap; gap: 9px; min-width: 0; margin: 0; }
.sel-label { font-size: 18px; font-weight: 900; white-space: nowrap; }
.sel-label.is-hint { font-size: 14px; font-weight: 800; white-space: normal; line-height: 1.3; color: color-mix(in oklab, var(--on-solid) 82%, transparent); }
.sel-msg { font-size: 13.5px; font-weight: 800; color: var(--go-soft); }
.sel-msg:empty { display: none; }
.sel-acts { display: flex; align-items: center; gap: 6px; }
.sel-btn { background: rgba(255,255,255,.16); color: #fff; border: none; border-radius: 999px; padding: 9px 15px; font-size: 14px; font-weight: 800; white-space: nowrap; cursor: pointer; }
.sel-btn--danger { background: var(--danger); color: #fff; }
.sel-cancel { background: none; border: none; border-radius: 999px; padding: 9px 8px; font-size: 14px; font-weight: 800; color: #c9c4b6; white-space: nowrap; cursor: pointer; }
/* LABELLED: App v3 paints the bar's buttons for a DARK bar only; in dark mode --solid is light, so the translucent
   white buttons, #fff ink, the pale green message and the pale Cancel vanish — dark-mode twins that read on it. */
body[data-mode="dark"] .sel-btn { background: rgba(0,0,0,.08); color: var(--on-solid); }
body[data-mode="dark"] .sel-btn--danger { background: #c0392b; color: #fff; }   /* the light --danger: #fff reads 5.4:1 on it */
body[data-mode="dark"] .sel-cancel { color: color-mix(in oklab, var(--on-solid) 78%, var(--solid)); }
body[data-mode="dark"] .sel-msg { color: var(--go-ink); }
@media (pointer: coarse) { .sel-btn, .sel-cancel { min-height: 44px; } }
/* LABELLED: App v3's five buttons run ~145 px past a 375-px screen — with a selection the bar wraps (the count on top,
   the buttons below, wrapping again if they must) */
@media (max-width: 639.98px) {
  .sel-wrap.has-sel .sel-bar { flex-wrap: wrap; padding: 11px 14px; }
  .sel-wrap.has-sel .sel-status { flex: 1 1 100%; }
  .sel-wrap.has-sel .sel-acts { flex: 1 1 100%; flex-wrap: wrap; }
}
/* the bulk move panel above the bar (App v3 movePicker 226–238) */
.sel-move { margin-bottom: 10px; padding: 13px 16px; background: var(--card); color: var(--ink); border: 1px solid var(--border2); border-radius: 14px; box-shadow: 0 8px 22px rgba(0,0,0,.12); animation: popup .2s ease; }
.sel-move-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 10px; }
.sel-move-title { font-size: 14.5px; font-weight: 900; color: var(--ink); }
.sel-move-cancel { background: none; border: none; padding: 4px 2px; font-size: 14px; font-weight: 800; color: var(--muted2-text); /* d11 */ cursor: pointer; }
.sel-move-list { display: flex; flex-direction: column; gap: 3px; max-height: calc(44dvh / var(--zf, 1)); overflow: auto; overscroll-behavior: contain; }
/* the bar never covers the last card: 96 px more room at the page's foot. INSIDE .page (tidy round 3, review), never
   on <body>: the dims (.page-dim, the dim- section) cover .page's box only, so room on <body> stayed bright under a
   dialog — the Select bar too, scrolled to the end. The same layout as the old body padding: + 96 px, at least
   100vh + 96 px. */
body.sel-on .page { padding-bottom: calc(20px + 96px); min-height: calc(100vh / var(--zf, 1) + 96px); }

/* ---------- mv- : a move target row (both move surfaces) + the one-activity "Move to…" dialog (App v3 2279–2286;
   js/move-picker.js). --cat is set inline on each row. ---------- */
.mv-row { display: flex; align-items: center; gap: 10px; width: 100%; padding: 10px 12px; background: none; border: none; border-radius: 10px; color: var(--ink); text-align: left; cursor: pointer; }
@media (hover: hover) { .mv-row:hover { background: var(--chip); } }
.mv-row:disabled { cursor: default; }
@media (hover: hover) { .mv-row:disabled:hover { background: none; filter: none; } }
.mv-dot { flex: none; width: 11px; height: 11px; border-radius: 999px; background: var(--cat, var(--muted2)); }
.mv-name { flex: 1 1 auto; min-width: 0; font-size: 14.5px; font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mv-current { flex: none; display: inline-flex; align-items: center; padding: 4px 11px; background: var(--chip); border: 1px solid var(--border2); border-radius: 999px; font-size: 10.5px; font-weight: 800; letter-spacing: .07em; text-transform: uppercase; color: var(--muted-text); /* d11 */ }
@media (pointer: coarse) { .mv-row { min-height: 44px; } .sel-move-cancel, .mv-cancel { min-height: 44px; } }
.mv-sheet { width: 420px; max-width: 100%; max-height: calc(82dvh / var(--zf, 1)); padding: 22px; display: flex; flex-direction: column; }
.mv-head { flex: none; display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 12px; }
.mv-title { font-size: 16px; font-weight: 900; color: var(--ink); }
.mv-cancel { background: none; border: none; padding: 4px 2px; font-size: 14px; font-weight: 800; color: var(--muted-text); /* d11 */ cursor: pointer; }
.mv-list { display: flex; flex-direction: column; gap: 3px; min-height: 0; max-height: calc(60dvh / var(--zf, 1)); overflow: auto; overscroll-behavior: contain; }
.mv-list .mv-row { padding: 11px 12px; }
@media (max-width: 639.98px) { .mv-sheet { width: 100%; } }   /* .ov-scrim + .sheet's NARROW rules make it the bottom sheet (the scrim holds the safe area) */

/* ---------- rn- : the Rename dialog (App v3 1435–1449; js/rename-dialog.js). A .sheet; its × is .sheet-x. ---------- */
.rn-dlg { width: 400px; max-width: 100%; padding: 20px; }
.rn-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 14px; }
.rn-title { min-width: 0; font-family: 'Lora', serif; font-size: 18px; font-weight: 700; color: var(--ink); }
.rn-field { position: relative; }
/* LABELLED DEVIATION: 16 px (App v3 14) — the iOS zoom rule; padding 11 → 9.6 keeps App v3's box height */
.rn-input { width: 100%; padding: 9.6px 38px 9.6px 13px; background: var(--card); border: 1px solid var(--border); border-radius: 10px; font: inherit; font-size: 16px; font-weight: 600; color: var(--ink); }
.rn-input::placeholder, .tk-input::placeholder, .tk-search-input::placeholder { color: var(--muted2-text); opacity: 1; }   /* d11 */
.rn-clear { position: absolute; right: 8px; top: 50%; transform: translateY(-50%); width: 20px; height: 20px; padding: 0; border: none; border-radius: 6px; background: transparent; color: var(--muted2); display: grid; place-items: center; cursor: pointer; }
.rn-clear:active { transform: translateY(-50%) scale(.94); }   /* keep the centring translate under the global press scale */
@media (pointer: coarse) { .rn-clear::after { content: ""; position: absolute; inset: -12px; } }
.rn-err { margin-top: 8px; font-size: 12.5px; font-weight: 700; color: var(--danger); }
.rn-save { display: block; width: 100%; margin-top: 14px; padding: 13px; background: var(--solid); color: var(--on-solid); border: none; border-radius: 14px; font-size: 15px; font-weight: 900; cursor: pointer; }
.rn-save:disabled { opacity: .42; cursor: default; transform: none; filter: none; }
@media (max-width: 639.98px) { .rn-dlg { width: 100%; } }

/* ---------- nd- : the "+1 with note…" dialog (note addendum 1, owner 2026-10-03 — LABELLED: not in App v3;
   js/note-dialog.js). The Rename dialog's frame (a .sheet: centred, a bottom sheet under 640 px — .ov-scrim + .sheet's
   NARROW rules) and its field / button looks; the eyebrow is .sheet-eyebrow. The note field is 16 px at every width
   (the iOS zoom rule) and never grows past 40 % of the window (÷ the zoom). ---------- */
.nd-dlg { width: 400px; max-width: 100%; padding: 20px; }
.nd-title { margin: 2px 0 14px; font-family: 'Lora', serif; font-size: 18px; font-weight: 700; line-height: 1.3; color: var(--ink); overflow-wrap: anywhere; }
.nd-text { display: block; width: 100%; min-height: 96px; max-height: calc(40dvh / var(--zf, 1)); padding: 10px 13px; background: var(--card); border: 1px solid var(--border); border-radius: 10px; font: inherit; font-size: 16px; font-weight: 600; line-height: 1.45; color: var(--ink); resize: vertical; }
.nd-text::placeholder { color: var(--muted2-text); /* d11 */ opacity: 1; }
.nd-foot { display: flex; gap: 10px; margin-top: 14px; }
.nd-cancel { flex: none; padding: 13px 20px; background: none; border: 1px solid var(--border); border-radius: 14px; font-size: 15px; font-weight: 800; color: var(--ink2); cursor: pointer; }
.nd-log { flex: 1 1 auto; padding: 13px; background: var(--solid); color: var(--on-solid); border: none; border-radius: 14px; font-size: 15px; font-weight: 900; cursor: pointer; }
@media (pointer: coarse) { .nd-cancel, .nd-log { min-height: 44px; } }
@media (max-width: 639.98px) { .nd-dlg { width: 100%; } }

/* ---------- tk- : the shared parts of New tag and the Tags sheet (App v3 1356–1377 + 1407–1420; newTagSections 4119,
   _tickCss 3267). A tick row sets --cat, --cat-half (rgba(hex,.5)) and --cat-tenth (rgba(hex,.1)) inline. ---------- */
.tk-label { display: block; margin: 0 0 8px; font-size: 12px; font-weight: 800; letter-spacing: .08em; text-transform: uppercase; color: var(--muted2-text); /* d11 */ }
.tk-field { position: relative; }
/* LABELLED DEVIATION: 16 px (App v3 14) — the iOS zoom rule; padding 11 → 9.6 keeps App v3's box height */
.tk-input { width: 100%; padding: 9.6px 38px 9.6px 13px; background: var(--card); border: 1px solid var(--border); border-radius: 10px; font: inherit; font-size: 16px; font-weight: 600; color: var(--ink); }
.tk-input[aria-invalid="true"] { border-color: var(--danger); }   /* App v3 newTagNameStyle: the danger border while an error shows (it outranks the field rule's focus border) */
.tk-clear { position: absolute; right: 10px; top: 50%; transform: translateY(-50%); width: 20px; height: 20px; padding: 0; border: none; background: transparent; color: var(--muted2); display: grid; place-items: center; cursor: pointer; }
.tk-clear:active { transform: translateY(-50%) scale(.94); }
@media (pointer: coarse) { .tk-clear::after { content: ""; position: absolute; inset: -12px; } }
.tk-err { margin-top: 7px; font-size: 12px; font-weight: 700; color: var(--danger); }
.tk-note { margin-top: 7px; font-size: 12px; font-weight: 700; color: var(--muted-text); /* d11 */ }
/* the chosen activities (a sideways strip — App v3 1365 / 1417); a chip is a button, a tap un-picks */
.tk-chips { display: flex; flex-wrap: nowrap; gap: 6px; margin: 0 0 10px; padding-bottom: 2px; overflow-x: auto; overflow-y: hidden; }
.tk-chip { flex: none; display: inline-flex; align-items: center; gap: 5px; padding: 5px 6px 5px 11px; white-space: nowrap; border-radius: 999px; background: color-mix(in oklab, var(--accent) 10%, var(--card)); border: 1px solid color-mix(in oklab, var(--accent) 40%, var(--border)); font-size: 12.5px; font-weight: 700; color: var(--ink); cursor: pointer; }
.tk-chip-x { display: grid; place-items: center; width: 16px; height: 16px; border-radius: 999px; background: var(--chip2); color: var(--muted-text); /* d11 */ font-size: 11px; font-weight: 900; line-height: 1; }
.tk-search { position: relative; }
.tk-search-ico { position: absolute; left: 12px; top: 50%; transform: translateY(-50%); display: grid; place-items: center; color: var(--muted2); pointer-events: none; }
/* LABELLED DEVIATION: 16 px (App v3 14) — the iOS zoom rule; padding 10 → 8.6 keeps App v3's box height */
.tk-search-input { width: 100%; padding: 8.6px 13px 8.6px 36px; background: var(--card); border: 1px solid var(--border); border-radius: 10px; font: inherit; font-size: 16px; font-weight: 600; color: var(--ink); -webkit-appearance: none; appearance: none; }
.tk-search-input::-webkit-search-cancel-button, .tk-search-input::-webkit-search-decoration { -webkit-appearance: none; appearance: none; }
.tk-list { flex: 1 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain; }
/* a category section: the dot, the title, Add all / Clear */
.tk-sec-head { display: flex; align-items: center; gap: 7px; margin: 6px 0 8px; }
.tk-sec-dot { flex: none; width: 9px; height: 9px; border-radius: 999px; background: var(--cat, var(--muted2)); }
.tk-sec-title { flex: 1 1 auto; min-width: 0; font-size: 12.5px; font-weight: 900; color: var(--ink2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tk-sec-all { flex: none; margin-left: 3px; padding: 2px; background: none; border: none; font-size: 12px; font-weight: 800; color: var(--accent-text); /* d11 */ cursor: pointer; }
.tk-sec-all.is-clear { color: var(--muted-text); }
.tk-row { display: flex; align-items: center; gap: 9px; width: 100%; margin-bottom: 6px; padding: 9px 11px; text-align: left; background: var(--card); border: 1px solid var(--border2); border-radius: 11px; cursor: pointer; }
.tk-row[aria-checked="true"] { background: var(--cat-tenth, var(--chip)); border-color: var(--cat-half, var(--border)); }
.tk-tick { flex: none; width: 20px; height: 20px; border-radius: 999px; border: 1.5px solid var(--border2); background: transparent; color: transparent; display: grid; place-items: center; font-size: 11px; font-weight: 900; line-height: 1; transition: background .12s ease, border-color .12s ease, color .12s ease; }
.tk-row[aria-checked="true"] .tk-tick { background: var(--cat, var(--ink2)); border-color: var(--cat, var(--ink2)); color: var(--card); }
.tk-row-name { flex: 1 1 auto; min-width: 0; font-size: 13.5px; font-weight: 700; color: var(--ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tk-none { padding: 16px 10px; text-align: center; font-size: 13px; color: var(--muted-text); /* d11 */ }
@media (pointer: coarse) { .tk-row, .tk-chip { min-height: 44px; } .tk-sec-all { min-height: 44px; padding: 2px 8px; } }

/* ---------- nt- : New tag (App v3 1349–1383; newTagApplyStyle 4118). A .sheet: a flex column whose list scrolls. ---------- */
.nt-sheet { width: 460px; max-width: 100%; max-height: calc(84dvh / var(--zf, 1)); display: flex; flex-direction: column; }
.nt-head { flex: none; }
.nt-form { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
.nt-top { flex: none; padding: 0 20px 4px; }
.nt-apply-label { margin: 16px 0 10px; }
.nt-form .tk-list { padding: 0 20px 6px; }
.nt-foot { flex: none; padding: 12px 20px 18px; border-top: 1px solid var(--hair); }
.nt-apply { display: block; width: 100%; padding: 13px; background: var(--solid); color: var(--on-solid); border: none; border-radius: 14px; font-size: 15px; font-weight: 900; cursor: pointer; }
/* never disabled while idle (App v3): a press without a name / a pick says what is missing; .is-idle only styles it */
.nt-apply.is-idle { background: var(--chip2); color: var(--muted-text); /* d11 — App v3 var(--muted) */ cursor: default; }
body[data-mode="dark"] .nt-apply.is-idle { color: var(--ink3); }   /* LABELLED: --muted-text reads 4.2:1 on the dark --chip2 */
.nt-apply:disabled { opacity: .6; cursor: default; transform: none; filter: none; }   /* only while the write runs */

/* ---------- ts- : the Tags sheet — LIST / EDIT (App v3 1385–1433; manageTags 4125). A .sheet, one scrolling body. ---------- */
.ts-sheet { width: 460px; max-width: 100%; max-height: calc(84dvh / var(--zf, 1)); display: flex; flex-direction: column; }
.ts-head { flex: none; }
.ts-back { display: inline-flex; align-items: center; gap: 5px; padding: 2px; background: none; border: none; font-size: 15px; font-weight: 800; color: var(--ink2); cursor: pointer; }
.ts-head-r { display: flex; align-items: center; gap: 8px; }
.ts-new { display: inline-flex; align-items: center; gap: 6px; padding: 7px 13px; background: var(--card); border: 1px solid var(--border); border-radius: 999px; font-size: 13px; font-weight: 800; color: var(--ink2); cursor: pointer; }
.ts-body { flex: 1 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain; padding: 4px 20px 20px; }
/* LIST */
.ts-trow { display: flex; align-items: center; gap: 10px; width: 100%; margin-bottom: 8px; padding: 13px 16px; text-align: left; background: var(--card); border: 1px solid var(--border2); border-radius: 14px; cursor: pointer; }
.ts-trow-name { flex: 0 1 auto; min-width: 0; font-size: 15px; font-weight: 800; color: var(--ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ts-trow-count { flex: none; margin-right: auto; font-size: 12.5px; font-weight: 700; color: var(--muted2-text); /* d11 */ }
.ts-trow-chev { flex: none; display: grid; place-items: center; color: var(--muted2); }   /* App v3 1402: a 16-px SVG chevron */
.ts-hint { margin-top: 8px; text-align: center; font-size: 12px; font-weight: 600; color: var(--muted2-text); /* d11 */ }
/* the empty LIST (App v3 1399): a title, what tags are for, and a solid "New tag" */
.ts-empty { padding: 40px 16px; text-align: center; }
.ts-empty-title { margin: 0 0 6px; font-size: 14.5px; font-weight: 800; color: var(--ink2); }
.ts-empty-body { max-width: 340px; margin: 0 auto; font-size: 13px; font-weight: 600; line-height: 1.5; color: var(--muted-text); /* d11 */ }
.ts-empty-new { margin-top: 16px; padding: 10px 20px; background: var(--solid); color: var(--on-solid); border: none; border-radius: 999px; font-size: 14px; font-weight: 800; cursor: pointer; }
@media (pointer: coarse) { .ts-empty-new { min-height: 44px; } }
/* EDIT */
.ts-rename-label { margin: 2px 0 8px; }
.ts-rename-row { display: flex; align-items: center; gap: 8px; }
.ts-rename-field { flex: 1 1 auto; min-width: 0; }
.ts-rename-input { padding-right: 34px; font-weight: 700; }
.ts-rename-clear { right: 9px; }
.ts-save { flex: none; padding: 11px 18px; background: var(--solid); color: var(--on-solid); border: none; border-radius: 10px; font-size: 14px; font-weight: 800; cursor: pointer; }
.ts-save:disabled { opacity: .42; cursor: default; transform: none; filter: none; }
.ts-applies { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin: 18px 0 10px; }
.ts-applies .tk-label { margin: 0; white-space: nowrap; }
.ts-selcount { font-size: 12px; font-weight: 800; color: var(--muted2-text); /* d11 */ }
.ts-edit .tk-search { margin-bottom: 10px; }
/* the foot: Merge into…, the merge row, Delete tag */
.ts-foot { flex: none; display: flex; flex-direction: column; gap: 10px; padding: 12px 20px 18px; border-top: 1px solid var(--hair); }
.ts-merge { align-self: flex-start; padding: 2px; background: none; border: none; font-size: 13px; font-weight: 800; color: var(--muted-text); /* d11 */ cursor: pointer; }
.ts-merging { display: flex; flex-wrap: wrap; align-items: center; gap: 7px; }
.ts-merging-label { margin-right: 2px; font-size: 12.5px; font-weight: 800; color: var(--ink2); }
.ts-targets { display: contents; }
.ts-target { padding: 6px 12px; background: var(--chip); border: 1px solid var(--border2); border-radius: 999px; font-size: 12.5px; font-weight: 700; color: var(--ink2); cursor: pointer; }
.ts-merge-cancel { padding: 6px 4px; background: none; border: none; font-size: 12.5px; font-weight: 800; color: var(--muted-text); /* d11 */ cursor: pointer; }
.ts-delete { width: 100%; padding: 12px; background: none; border: 1px solid color-mix(in oklab, var(--danger) 45%, var(--border)); border-radius: 12px; font-size: 14px; font-weight: 800; color: var(--danger); cursor: pointer; }
@media (pointer: coarse) { .ts-trow, .ts-target, .ts-merge, .ts-merge-cancel, .ts-back, .ts-new, .ts-save { min-height: 44px; } }
/* NARROW: .ov-scrim + .sheet make both bottom sheets; the widths are restated (these rules come after .sheet's) */
@media (max-width: 639.98px) { .nt-sheet, .ts-sheet { width: 100%; max-height: calc(88dvh / var(--zf, 1)); } }

/* ---------- way- : the jump rail (App v3 866–875; wayDockStyle 3797, wayCats, wayRailStyle 3806, wayPanelStyle 3810,
   wayPanelRows 3812–3815; js/way-rail.js). Fixed at the right edge, centred; >= 900 px way-rail.js sets `right` inline
   (App v3's centred-column maths, ÷ zf). Hidden (fade + visibility) until the board is scrolled into.
   Tidy round 3 (LABELLED DEVIATION — App v3 centres the dock at 50 % and sizes the rail / the list in dvh): the dock's
   centre, the rail's height and the list's cap are in svh — the SMALL viewport, which Safari's toolbar never changes —
   so a toolbar that collapses or expands as the scrub scrolls the page never moves or resizes the rail under a still
   finger (it re-mapped the finger to another row → another scroll → the bar flipped back). Wherever the viewport does
   not change (a desktop, the home-screen app, a Safari bar left open) svh = dvh, so the look is the same; with the bar
   collapsed the rail sits up to ~40 px above the visible centre and up to ~35 px shorter. ---------- */
.way-dock { position: fixed; top: calc(50svh / var(--zf, 1)); right: calc(6px + env(safe-area-inset-right, 0px)); transform: translateY(-50%); z-index: 100; /* --z-sticky */ display: flex; flex-direction: column; align-items: flex-end; gap: 8px; pointer-events: none; opacity: 0; visibility: hidden; transition: opacity .24s ease, visibility 0s .24s; }
.way-dock.is-shown { opacity: 1; visibility: visible; transition: opacity .24s ease, visibility 0s 0s; }
.way-wrap { position: relative; display: flex; align-items: center; pointer-events: auto; }
.way-rail { display: flex; flex-direction: column; justify-content: space-between; align-items: flex-end; height: min(calc(52svh / var(--zf, 1)), 380px, calc(100svh / var(--zf, 1) - 224px)); padding: 8px 4px 8px 8px; background: transparent; border: 1px solid transparent; border-radius: 16px; cursor: ns-resize; touch-action: none; user-select: none; -webkit-user-select: none; }
/* a row's mark: a 2.5-px dash (12 wide, 18 when active; way-rail.js writes the scrub bulge's width / opacity inline),
   or the 13-px house for Top. --cat is set inline. */
.way-tick { flex: none; display: block; width: 12px; height: 2.5px; border-radius: 2px; background: var(--muted2); opacity: .62; pointer-events: none; transition: width .14s cubic-bezier(.2,.7,.3,1), opacity .12s ease; }
.way-tick.is-on { width: 18px; opacity: 1; background: var(--cat, var(--ink2)); }
.way-tick.is-top { width: auto; height: auto; border-radius: 0; background: none; display: grid; place-items: center; color: var(--muted2); opacity: .65; transition: color .15s ease, opacity .15s ease; }
.way-tick.is-top.is-on { width: auto; background: none; color: var(--ink2); opacity: 1; }
/* the panel beside the rail (the jump list): rows are buttons — the name, then the dot / the house at the right */
.way-panel { display: none; position: absolute; right: 34px; top: 50%; transform: translateY(-50%); flex-direction: column; gap: 1px; width: min(178px, 72vw); max-height: calc(86svh / var(--zf, 1)); padding: 7px; overflow: auto; overscroll-behavior: contain; background: var(--panel); border: 1px solid var(--border); border-radius: 16px; box-shadow: 0 12px 32px rgba(30,28,24,.18); animation: menuIn .18s ease; }
.way-panel.is-open { display: flex; }
.way-row { display: flex; align-items: center; justify-content: flex-end; gap: 8px; width: 100%; min-width: 0; padding: 3px 8px; background: transparent; border: none; border-radius: 999px; text-align: right; cursor: pointer; transition: background .12s ease; }
@media (hover: hover) { .way-row:hover { background: var(--chip); } }
.way-row[aria-current="true"] { background: var(--card); box-shadow: 0 3px 10px rgba(60,56,48,.14); }
.way-name { order: 1; min-width: 0; font-size: 12.5px; font-weight: 700; color: var(--muted-text); /* d11 */ white-space: nowrap; overflow: hidden; text-overflow: ellipsis; transition: color .12s ease; }
.way-row[aria-current="true"] .way-name { font-weight: 900; color: var(--ink); }
.way-dot { order: 2; flex: none; width: 9px; height: 9px; border-radius: 999px; background: var(--cat, var(--muted2)); transition: transform .12s ease; }
.way-row[aria-current="true"] .way-dot { transform: scale(1.3); }
.way-house { order: 2; flex: none; display: grid; place-items: center; color: var(--muted2); }
.way-row[aria-current="true"] .way-house { color: var(--ink2); }
/* LABELLED: App v3's 23.7-px panel rows are too small to tap, so on touch they are 40 px — a full board's list is then
   taller than its 86 svh cap on a phone and scrolls (a scrub's lower rows sit below its visible box) */
@media (pointer: coarse) { .way-row { min-height: 40px; } }
/* Phone ruling 5 (LABELLED — the look is unchanged): on touch the rail answers 40 px wide, not 32 — to the screen edge on
   the right (the rail sits 6 px in) and to the cards' edge on the left (their glance footer and Shuffle start there, so
   44 would take their taps). The list's rows stay 40 tall: they sit 1 px apart, so a bigger area would take the next
   row's taps. */
@media (pointer: coarse) { .way-rail { position: relative; } .way-rail::after { content: ""; position: absolute; inset: -1px -7px -1px -2px; } }

/* ---------- fd- : the floating focus dock (App v3 877–919; focusDockStyle 4185, focusDockPillStyle 4186,
   focusDockCaretStyle 4188, focusDockEyeStyle 4189, focusDockMenuStyle 4190, focusDockAddStyle 4191; js/focus.js). Fades
   in WITH the rail (App v3: the dock rides uWayShow), count mode only. ---------- */
.fd-dock { position: fixed; right: calc(6px + env(safe-area-inset-right, 0px)); bottom: calc(14px + env(safe-area-inset-bottom, 0px)); z-index: 100; /* --z-sticky */ display: flex; flex-direction: column; align-items: flex-end; pointer-events: none; opacity: 0; transform: translateY(8px); visibility: hidden; transition: opacity .24s ease, transform .24s ease, visibility 0s .24s; }
/* The home-screen app (owner, 2026-10-03): with no Safari toolbar the dock sat 6 / 14 px from the screen's rounded
   bottom-right corner and was clipped by it. In display-mode standalone it moves in and up, clear of a ~47-pt corner
   radius and the home bar (the toast's dock lift is measured, so it follows). The browser keeps 6 / 14. */
@media (display-mode: standalone) { .fd-dock { right: calc(16px + env(safe-area-inset-right, 0px)); bottom: calc(28px + env(safe-area-inset-bottom, 0px)); } }
.fd-dock.is-shown { opacity: 1; transform: none; visibility: visible; transition: opacity .24s ease, transform .24s ease, visibility 0s 0s; }
/* Mobile pass: the dock, the rail and Select are three z-100 fixed layers whose tie is DOM order (index.html: dock →
   rail → Select, so the rail's list paints over the dock's caret). While the dock's MENU is open the rail steps one
   below the tie — still above the menu's dim (z 90) — so its ticks never sit over the menu's rows (their × at the
   right edge) and never take their taps. */
body:has(.fd-menu.visible) .way-dock { z-index: 99; /* --z-sticky − 1 */ }
/* Phone ruling 8: below 640 px the dock's menu and the focus tray dim the page (popover.js's catcher, z 90) — the rail (z 100)
   would paint its ticks bright on that dim and take its taps: it hides while either is open (at once; it fades back on close). */
@media (max-width: 639.98px) { body:has(.fd-menu.visible) .way-dock, body:has(.focus-tray.visible) .way-dock { opacity: 0; visibility: hidden; transition: none; } }
.fd-hold { position: relative; pointer-events: auto; }
.fd-pill { display: inline-flex; flex-direction: column; align-items: center; gap: 3px; padding: 6px; background: var(--card); border: 1px solid var(--border); border-radius: 999px; box-shadow: 0 8px 24px rgba(30,28,24,.2); animation: focusDockIn .22s cubic-bezier(.2,.7,.3,1) both; }
.fd-caret-btn { width: 34px; height: 14px; padding: 0; border: none; background: transparent; color: var(--muted2); display: inline-flex; align-items: center; justify-content: center; cursor: pointer; transition: transform .18s ease; }
.fd-caret-btn[aria-expanded="true"] { transform: rotate(180deg); }
.fd-caret-btn[aria-expanded="true"]:active { transform: rotate(180deg) scale(.94); }
@media (pointer: coarse) { .fd-caret-btn { position: relative; } .fd-caret-btn::after { content: ""; position: absolute; inset: -27px -5px -3px; } }   /* 44 × 44 — up past the pill's top (nothing of the dock or the rail sits there), never over the eye below */
/* the menu that rises above the pill (focusDockMenuStyle) */
.fd-menu { display: none; position: absolute; right: 0; bottom: calc(100% + 10px); flex-direction: column; width: max-content; min-width: 216px; max-width: calc(100vw - 32px); max-height: min(calc(72dvh / var(--zf, 1)), 520px); overflow: hidden; overscroll-behavior: contain; /* mobile pass: a swipe on the menu never chains to the board */ padding: 14px; background: var(--card); border: 1px solid var(--border); border-radius: 16px; box-shadow: 0 16px 40px rgba(30,28,24,.24); animation: focusMenuRise .18s cubic-bezier(.2,.7,.3,1) both; text-align: left; }
.fd-menu.visible { display: flex; }
.fd-head { flex: none; display: flex; align-items: center; gap: 16px; margin-bottom: 10px; }
.fd-trig { flex: none; display: inline-flex; align-items: center; gap: 4px; padding: 6px 2px; background: transparent; border: none; cursor: pointer; }
.fd-title, .fd-count { font-size: 12.5px; font-weight: 900; color: var(--ink2); white-space: nowrap; }
.fd-title { letter-spacing: .08em; text-transform: uppercase; }
.fd-rcaret { flex: none; display: inline-flex; color: var(--muted2); transform: rotate(180deg); transition: transform .16s ease; }
.fd-trig[aria-expanded="true"] .fd-rcaret { transform: none; }
.fd-seg { flex: none; display: inline-flex; align-items: center; gap: 1px; padding: 3px; background: var(--chip); border-radius: 999px; }
.fd-seg-ico { display: grid; place-items: center; padding: 0 3px 0 6px; color: var(--muted2); }
.fd-seg-btn { display: inline-flex; align-items: center; justify-content: center; min-width: 26px; padding: 6px 9px; border: none; border-radius: 999px; background: transparent; color: var(--muted-text); /* LABELLED d11: App v3 --muted2 — the focus-seg precedent */ font-size: 13px; font-weight: 900; cursor: pointer; }
.fd-seg-btn:active { transform: scale(.92); }
.fd-seg-btn[aria-pressed="true"] { background: var(--surface); color: var(--ink); box-shadow: 0 1px 3px rgba(0,0,0,.13); }
/* the roster (closed by default — App v3 focusRoster) */
.fd-list { display: flex; flex-direction: column; gap: 1px; max-height: min(calc(34dvh / var(--zf, 1)), 150px); overflow-y: auto; overscroll-behavior: contain; margin: 0 0 12px; animation: focusMenuRise .16s ease both; }
.fd-row { display: flex; align-items: center; gap: 9px; padding: 6px 4px; }
.fd-row-dot { flex: none; width: 8px; height: 8px; border-radius: 999px; background: var(--cat, var(--muted2)); }
.fd-row-name { flex: 1 1 auto; min-width: 0; max-width: 172px; font-size: 13.5px; font-weight: 700; color: var(--ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.fd-row-x { flex: none; width: 18px; height: 18px; padding: 0; border: none; border-radius: 999px; background: var(--chip2); color: var(--muted-text); /* d11 */ font-size: 11px; font-weight: 900; line-height: 1; display: grid; place-items: center; cursor: pointer; }
@media (pointer: coarse) { .fd-row-x { position: relative; } .fd-row-x::after { content: ""; position: absolute; inset: -13px; } }
.fd-none { padding: 2px 2px 10px; animation: focusMenuRise .16s ease both; }
.fd-none-a { font-size: 13px; font-weight: 700; line-height: 1.5; color: var(--muted-text); /* d11 */ }
.fd-none-b { margin-top: 2px; font-size: 12px; font-weight: 600; line-height: 1.5; color: var(--muted2-text); /* d11 */ }
.fd-log { flex: none; width: 100%; padding: 8px 16px; background: var(--go-soft); color: var(--go-ink); border: none; border-radius: 999px; font-size: 13.5px; font-weight: 900; cursor: pointer; }
.fd-foot { flex: none; display: flex; gap: 8px; margin-top: 10px; }
.fd-edit { flex: 1 1 auto; padding: 8px 15px; background: var(--card); border: 1px solid var(--border); border-radius: 999px; font-size: 13px; font-weight: 800; color: var(--ink); cursor: pointer; }
.fd-clear { flex: none; padding: 8px 15px; background: var(--card); border: 1px solid var(--border); border-radius: 999px; font-size: 13px; font-weight: 800; color: var(--danger); cursor: pointer; }
@media (pointer: coarse) { .fd-seg-btn, .fd-trig, .fd-log, .fd-edit, .fd-clear { min-height: 44px; } }

/* ---------- ftr- : the footer (App v3 855–863 without Credits — no Credits page exists; footerStyle 3910). ---------- */
.ftr { max-width: 1600px; margin: 10px auto 0; padding: 20px 16px 26px; border-top: 1px solid var(--hair); display: flex; flex-wrap: wrap; justify-content: center; align-items: center; gap: 6px 14px; font-size: 12.5px; font-weight: 700; color: var(--muted2-text); /* d11 */ }
.ftr-brand { font-weight: 900; color: var(--muted-text); /* d11 */ }
.ftr-sep { opacity: .45; }
.ftr a { font-weight: 800; color: var(--muted2-text); /* d11 */ }
@media (hover: hover) { .ftr a:hover { color: var(--ink2); } }
body[data-view="art"] .ftr { border-top: none; }   /* App v3: no rule under the Gallery */

/* ---------- fb- : the Send feedback modal (L293–309, bugSendStyle 4376). A centred card at every width
   (no sheet form, no animation — App v3). ---------- */
.fb-scrim { --layer-dim: var(--scrim-modal); display: none; position: fixed; inset: 0; background: transparent; z-index: 1010; /* --z-nested */ align-items: center; justify-content: center; padding: 18px; overflow: auto; overscroll-behavior: contain; }   /* transparent: its dim is on the page (the dim- section). overflow + overscroll: every other scrim's rule — a swipe never scrolls the page behind (mobile pass); on a phone the root does not scroll at all (the dim- section) and the card contains the swipe ([data-scrim] > *) */
.fb-scrim.visible { display: flex; }
.fb-card { width: min(460px, 100%); background: var(--card); border: 1px solid var(--border); border-radius: 20px; padding: 22px 22px 20px; box-shadow: 0 20px 60px rgba(0,0,0,.28); }
.fb-head { display: flex; align-items: center; gap: 11px; margin-bottom: 6px; }
.fb-disc { width: 34px; height: 34px; border-radius: 999px; background: var(--chip); flex: none; display: grid; place-items: center; color: var(--ink2); }
.fb-titlewrap { flex: 1; min-width: 0; }
.fb-title { font-size: 17px; font-weight: 800; color: var(--ink); font-family: 'Lora', serif; line-height: normal; }   /* 800 on Lora renders as 700 — same as App v3 */
.fb-x { flex: none; background: var(--chip); border: none; border-radius: 999px; width: 30px; height: 30px; cursor: pointer; color: var(--ink2); font-size: 15px; font-weight: 800; display: grid; place-items: center; padding: 0; }
.fb-intro { font-size: 13px; font-weight: 600; color: var(--muted-text); /* d11 */ line-height: 1.5; margin-bottom: 13px; }
/* Its focus: the field rule (the ring- section — App v3's outline:none, plus an ink border inside: visible focus). */
.fb-text { display: block; width: 100%; min-height: 112px; resize: vertical; border: 1px solid var(--border); border-radius: 12px; background: var(--bg); padding: 12px 13px; font-size: 14px; font-weight: 600; color: var(--ink); line-height: 1.5; }
.fb-text::placeholder { color: var(--muted-text); /* d11 — App v3 leaves the UA placeholder colour */ opacity: 1; }
@media (pointer: coarse) { .fb-text { font-size: 16px; } }   /* phone ruling 1 (LABELLED): 14 → 16 on touch — the iOS zoom rule */
.fb-foot { display: flex; align-items: center; gap: 10px; justify-content: flex-end; margin-top: 14px; }
.fb-cancel { background: none; border: 1px solid var(--border); border-radius: 999px; padding: 9px 17px; font-size: 14px; font-weight: 800; color: var(--ink2); cursor: pointer; }
.fb-send { background: var(--ink); color: var(--card); border: none; border-radius: 999px; padding: 9px 18px; font-size: 14px; font-weight: 800; cursor: pointer; }
.fb-send:disabled { background: var(--chip); color: var(--muted2); cursor: default; }   /* a disabled control — contrast-exempt, verbatim token */
/* The address line under the note (note addendum 2, owner 2026-10-03 — LABELLED: not in App v3): "Or email us at" +
   the support address as SELECTABLE text (one tap / click selects the whole address — never a link: Send is the mailto)
   + a small Copy button (.hit: 44 px on touch). It wraps on a narrow card; a long address breaks, never overflows. */
.fb-or { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 6px; margin-top: 11px; font-size: 13px; font-weight: 600; line-height: 1.5; color: var(--muted-text); /* d11 */ }
.fb-addr { min-width: 0; font-weight: 700; color: var(--ink2); overflow-wrap: anywhere; -webkit-user-select: all; user-select: all; }
.fb-copy { flex: none; background: var(--chip); border: none; border-radius: 999px; padding: 3px 11px; font-size: 12.5px; font-weight: 800; color: var(--ink2); cursor: pointer; }

/* ---------- ins- : the Add to Home Screen steps (js/install.js, owner 2026-10-12 — LABELLED: not in App v3). The
   feedback modal's own card (.fb-scrim / .fb-card / .fb-head …) holding three numbered steps; the numbers are drawn
   (a counter in a chip disc), the list keeps role="list". The first step ends with iOS's Share glyph and carries one
   muted line under it. ---------- */
.ins-steps { list-style: none; counter-reset: ins; display: grid; gap: 11px; margin: 2px 0 0; padding: 0; }
.ins-steps > li { counter-increment: ins; display: grid; grid-template-columns: 24px 1fr; column-gap: 11px; align-items: start; }
.ins-steps > li::before { content: counter(ins); grid-row: 1 / span 2; width: 24px; height: 24px; border-radius: 999px; background: var(--chip); color: var(--ink2); font-size: 12.5px; font-weight: 800; display: grid; place-items: center; }
.ins-step { grid-column: 2; padding-top: 2px; font-size: 14px; font-weight: 700; color: var(--ink); line-height: 1.45; }   /* 2 px: one line sits level with its 24-px number */
.ins-hint { grid-column: 2; font-size: 13px; font-weight: 600; color: var(--muted-text); /* d11 */ line-height: 1.5; }
.ins-glyph { vertical-align: -3px; margin-left: 6px; color: var(--ink2); }

/* ---------- toast- : the ONE toast (L430–432, toastStyle 4065). #toastRegion is the persistent aria-live
   region (never display:none); the pill .toast.undo-toast shows with .visible. 24 px from the bottom; 92 px while
   the Select bar shows (toast.js setToastOffset → .toast--raised) or while the toast would reach the floating focus
   dock (toast.js measures it → .toast--dock — tidy ruling 1: a short toast stays low beside the dock; at ≥ 684 px no
   toast can reach it). The sheets' "toast to the top" block below wins over both (body:has(…) .toast-region is the
   higher specificity). ---------- */
.toast-region { position: fixed; left: 50%; bottom: calc(24px + env(safe-area-inset-bottom, 0px)); transform: translateX(-50%); z-index: 1100; /* --z-toast */ pointer-events: none; width: max-content; max-width: calc(100vw - 24px); }
.toast-region.toast--raised, .toast-region.toast--dock { bottom: calc(92px + env(safe-area-inset-bottom, 0px)); }
/* LABELLED DEVIATION (site): on NARROW a confirm (cmDialog) and the account menu are bottom sheets whose
   action row (Cancel / Archive instead / Delete; Sign out) sits exactly where the toast lives — measured at
   375×812: buttons y 728–790 under a two-line Undo toast at y 736–788, so the buttons were unclickable for
   the toast's 5-s life. While such a sheet is open the toast yields to the TOP edge (a 92-px lift would
   still cover the sheet's count-stating sentence). Back to the bottom the moment the sheet closes. The
   record editor ("Edit start") is the same case: its − / + toasts landed on Cancel (y 757–794 under a
   toast at 747–788) and clipped the Save / Delete row. The store ("Add to your board") is the same case: its
   Create button is the sheet's last row (App v3's "＋ New tag" footer below it waits for step 9), so an add's
   Undo toast landed on "Add to …" (y 748–796 under a toast at 747–788) and the next tap there hit Undo. */
@media (max-width: 639.98px) {
  body:has(.dlg-scrim.visible) .toast-region,
  body:has(.acct-menu.visible) .toast-region,
  body:has(.rec-scrim.visible) .toast-region,
  body:has(#storeOverlay.visible) .toast-region { bottom: auto; top: calc(16px + env(safe-area-inset-top, 0px)); }
}
/* LABELLED DEVIATION: App v3 sets white-space:nowrap; the site's longer messages wrap inside the pill instead of running off a phone. */
.toast { display: none; align-items: center; gap: 10px; background: var(--solid); color: var(--on-solid); font-size: 14px; font-weight: 800; border-radius: 999px; padding: 10px 18px; box-shadow: 0 10px 26px rgba(0,0,0,.25); animation: popup .25s ease; pointer-events: none; white-space: normal; max-width: min(560px, calc(100vw - 24px)); }
.toast.visible { display: inline-flex; }
.toast.has-undo { padding: 7px 8px 7px 18px; pointer-events: auto; }
.toast-msg { min-width: 0; }
.toast-undo { flex: none; white-space: nowrap; background: rgba(255,255,255,.16); color: var(--on-solid); border: none; border-radius: 999px; padding: 5px 13px; font-size: 12.5px; font-weight: 900; cursor: pointer; }
/* Dark mode (owner, 2026-10-03: the Undo was almost the toast's own shade): the toast is LIGHT there (--solid), so a
   white tint vanished — it takes a dark tint instead, the Select bar's own dark-mode pattern (.sel-btn). LABELLED: App v3
   used the white tint in both modes. */
body[data-mode="dark"] .toast-undo { background: rgba(30,28,24,.18); }

/* ---------- dlg- : cmDialog as App v3's ask dialog (T7 §4 act-ask L1789–1802; confirmScrimStyle 4159,
   sheetFix 4160). The cm-dialog* classes stay on the elements as e2e hooks only; .visible = open. No drag
   handle: a confirm is answered, not flicked away. ---------- */
.dlg-scrim { --layer-dim: var(--scrim); display: none; position: fixed; inset: 0; z-index: 1015; /* --z-confirm */ background: transparent; /* its dim is painted on the page / over the sheet below (the dim- section); no fade: mobile pass ruling 4 (.ov-scrim) */ justify-content: center; align-items: center; padding: 64px 20px; overflow: auto; overscroll-behavior: contain; }
.dlg-scrim.visible { display: flex; }
.dlg { width: 420px; max-width: 100%; background: var(--panel); border-radius: 18px; box-shadow: 0 24px 60px rgba(0,0,0,.3); animation: popup .24s cubic-bezier(.22,1,.36,1); padding: 22px; }
@media (max-width: 639.98px) {
  .dlg-scrim { align-items: flex-end; padding: 0 0 env(safe-area-inset-bottom, 0px); }
  .dlg { width: 100%; max-width: none; max-height: calc(88vh / var(--zf, 1)); max-height: calc(88dvh / var(--zf, 1)); border-radius: 18px 18px 0 0; }
}
.dlg-title { font-family: 'Lora', serif; font-size: 18px; font-weight: 700; line-height: 1.3; color: var(--ink); margin-bottom: 8px; overflow-wrap: anywhere; }
.dlg-body { font-size: 14.5px; font-weight: 600; color: var(--ink2); line-height: 1.5; margin-bottom: 16px; }
.dlg-body:empty { display: none; }
.dlg-actions { display: flex; flex-wrap: wrap; gap: 8px; }
/* the affirmative: App v3's accent fill (#fff on --accent = 4.36:1 light — App v3 verbatim; dark uses --on-solid) */
.dlg-btn { flex: 1; background: var(--accent); color: var(--on-solid); /* App v3 #fff — fills rule */ border: none; border-radius: 11px; padding: 12px; font-size: 14px; font-weight: 800; cursor: pointer; transition: filter .12s ease; }
@media (hover: hover) { .dlg-btn:hover { filter: brightness(1.07); } }                     /* App v3 style-hover on the affirmative */
.dlg-btn--danger { background: var(--danger); }                  /* App v3 "Delete forever"; its "Delete" literal #9e4a3c → var(--danger) */
.dlg-btn--cancel { flex: none; background: var(--surface); border: 1px solid var(--border); border-radius: 11px; padding: 12px 18px; color: var(--ink); transition: transform .1s ease, filter .12s ease, background .12s ease; }
@media (hover: hover) { .dlg-btn--cancel:hover { filter: brightness(.97); } }              /* App v3's Cancel has no style-hover → the global button hover */

/* ---------- lp- : the landing (#cmLogin) — MINIMAL (pastday ruling 4, 2026-10-02): centred, the sun disc + the
   "Sol Passeio" wordmark large (the page's one h1, #lpTitle), the one line under it (#lpTagline — copy handoff,
   2026-10-10), Create account (solid) and Try the demo (outline), the
   "Already have an account? Sign in" line, and the small footer at the very bottom. App v3's tokens, so it follows
   light / dark and the four palettes; Lora + Nunito self-hosted. auth.js drives #cmLogin's display (with
   html[data-boot], below). .lp-sun / .lp-name / .lp-sol / .lp-btn* / .lp-footer are shared with the auth screens and
   the static pages (privacy / terms / 404). ---------- */
.lp { position: fixed; inset: 0; z-index: 9999; background: var(--bg); overflow-y: auto; flex-direction: column; align-items: center; }
.lp-wrap { width: 100%; max-width: 1040px; min-height: 100%; display: flex; flex-direction: column; padding: 0 24px; }
.lp-sun { width: 26px; height: 26px; border-radius: 50%; background: radial-gradient(circle at 50% 40%, var(--gold-hi), var(--gold)); box-shadow: 0 4px 12px rgba(227,153,13,.34); flex: none; }
.lp-name { display: inline-flex; align-items: baseline; }
.lp-sol { color: var(--gold); }                 /* a logotype — WCAG 1.4.3 exempts logo text (the .hdr-sol rule) */
.lp-btn { display: inline-flex; align-items: center; justify-content: center; border: 1px solid transparent; border-radius: 999px; padding: 9px 18px; font-size: 14px; font-weight: 800; line-height: 1.2; white-space: nowrap; cursor: pointer; text-decoration: none; }
.lp-btn--solid, .lp-btn--solid:visited { background: var(--solid); color: var(--on-solid); text-decoration: none; } @media (hover: hover) { .lp-btn--solid:hover { background: var(--solid); color: var(--on-solid); text-decoration: none; } }
.lp-btn--outline, .lp-btn--outline:visited { background: var(--card); border-color: var(--border); color: var(--ink2); text-decoration: none; } @media (hover: hover) { .lp-btn--outline:hover { background: var(--card); border-color: var(--border); color: var(--ink2); text-decoration: none; } }   /* an <a> (Try the demo) styled as a button beats the global a / a:hover colours */
.lp-btn--lg { min-height: 48px; padding: 12px 24px; font-size: 15px; font-weight: 900; }
/* the hero: one centred column above the footer — the wordmark (the h1: the sun disc + "Sol Passeio"; its space is a
   plain space inside an inline span, so the region's name reads "Sol Passeio"), the line under it, the notice, the two
   doors, the sign-in line */
.lp-hero { flex: 1 0 auto; display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; padding: 48px 0 28px; }
.lp-mark { display: flex; align-items: center; justify-content: center; gap: 14px; margin: 0 0 16px; font-family: 'Lora', serif; font-weight: 700; font-size: 58px; letter-spacing: -.015em; line-height: 1.05; color: var(--ink); }
/* The landing's one line (owner, 2026-10-11): the app header's own strapline, "+1 every time you start", in the
   header's own voice (.hdr-sub above: the body font at 800, 13.5 px, .14em capitals, the muted2 TEXT colour — d11),
   directly under the wordmark — the front door shows the same pairing as the app's header. The capitals are CSS only.
   (The copy handoff of 2026-10-10 first put "Count what you started, not what you finished." here; the owner replaced
   it the next day. That sentence stays in How it works and on the share image.) ONE line on every screen: it is 16.6em
   wide (224 px), inside the 280 px a 320-px phone leaves.
   The space the wordmark used to keep above the doors (34 / 30 / 12) sits under this line. */
.lp-tagline { max-width: 100%; margin: 0 0 34px; font-weight: 800; font-size: 13.5px; line-height: 1.4; letter-spacing: .14em; text-transform: uppercase; white-space: nowrap; color: var(--muted2-text); /* d11 */ }
.lp-mark-sun { width: 62px; height: 62px; border-radius: 50%; background: radial-gradient(circle at 50% 40%, var(--gold-hi), var(--gold)); box-shadow: 0 8px 24px rgba(227,153,13,.34); flex: none; }
.lp-hero .lp-notice { width: 100%; max-width: 340px; margin: 0 0 18px; }
.lp-doors { display: flex; flex-direction: column; align-items: stretch; gap: 12px; width: 100%; max-width: 320px; }
.lp-signin { margin: 22px 0 0; font-size: 14.5px; font-weight: 700; line-height: 1.5; color: var(--muted-text); /* d11 */ }
/* Sign in: a text link (a button — it opens the auth modal); its 44-px touch area is the markup's .hit */
.lp-link { background: none; border: none; padding: 0; font: inherit; font-weight: 900; color: var(--ink); text-decoration: underline; text-underline-offset: 3px; cursor: pointer; }
@media (hover: hover) { .lp-link:hover { color: var(--accent-text); } }
.lp-footer { text-align: center; font-size: 12.5px; font-weight: 700; line-height: 1.6; color: var(--muted-text); /* d11 */ padding: 16px 0 22px; }
.lp-footer a { color: var(--muted-text); font-weight: 800; }
@media (hover: hover) { .lp-footer a:hover { color: var(--ink); } }
/* Touch: a footer that wraps (≈ 320–340 px) keeps its lines 24 px apart, so a link's 44-px .hit area never reaches
   the line above or below it (wrapped inline lines sat 20 px apart — a tap on "Privacy" opened the mail app). The
   middots become flex items; a one-line footer looks exactly as before. Shared by the landing and the static pages. */
@media (pointer: coarse) { .lp-footer { display: flex; flex-wrap: wrap; justify-content: center; align-items: center; column-gap: 4px; row-gap: 24px; } }
@media (max-width: 559.98px) {
  .lp-wrap { padding: 0 20px; }
  /* shared with the static pages and the auth screens — their phone look is unchanged */
  .lp-btn { padding: 8px 14px; }
  .lp-btn--lg { padding: 12px 20px; }
  .lp-footer { padding: 10px 0 18px; }
  .lp-hero { padding: 36px 0 20px; }
  .lp-mark { font-size: 44px; gap: 11px; margin-bottom: 14px; }
  .lp-mark-sun { width: 48px; height: 48px; }
  .lp-tagline { margin-bottom: 30px; }
}
/* a landscape phone (≤ 420 px high): the hero tightens so the landing stays one screen, the footer included (it ran
   7–62 px below the fold at 667 × 375 / 568 × 320) */
@media (max-height: 420px) {
  .lp-hero { padding: 16px 0 12px; }
  .lp-mark { font-size: 44px; gap: 11px; margin-bottom: 6px; }
  .lp-mark-sun { width: 48px; height: 48px; }
  /* the line under the wordmark costs one row: it, the sign-in line and the footer give the room back, so
     568 × 320 is still one screen */
  .lp-tagline { margin-bottom: 12px; }
  .lp-signin { margin-top: 14px; }
  .lp .lp-footer { padding-bottom: 16px; }   /* the landing's own footer only — the static pages share .lp-footer */
}
@media (max-width: 359.98px) {
  .lp-mark { font-size: 38px; gap: 10px; }
  .lp-mark-sun { width: 42px; height: 42px; }
}

/* ---------- boot- : the first screen (fixes ruling 1). /theme-boot.js sets html[data-boot] = out | in before the
   first paint (index.html's rel=expect link holds that paint until the header is parsed), so the tab never paints an
   empty page: out = the landing, in = the calm shell (the header + "Loading your activities…", the un-built controls
   hidden). auth.js keeps it true (a wrong guess, a sign-in, the in-place sign-out) and board.js ends at 'ready' — then
   nothing here applies. No attribute (theme-boot failed) = the page as before: the CSS waits for auth.js. ---------- */
#cmLogin { display: none; }                               /* was style="display:none" — auth.js still writes it inline */
html[data-boot="out"] #cmLogin { display: flex; }         /* signed out: the landing IS the first paint */
.boot-line { display: none; text-align: center; padding: 26px 0; font-size: 14.5px; font-weight: 700; color: var(--muted-text); /* d11 — .bd-loading's look */ }
html[data-boot="in"] .boot-line { display: block; }
/* The un-built controls never show and take no press; the layout is kept (the Gallery-tabled check reads
   #counterView's box). opacity, NOT visibility: a scroller laid out under visibility:hidden (#tagScroll) kept a stale
   hit test in Chrome once shown — the tag chips' 44-px touch areas missed until something relaid it out. */
html[data-boot="in"] .sw-row,
html[data-boot="in"] #counterView { opacity: 0; pointer-events: none; }
/* Programmatic focus targets (auth.js, after an in-place sign-out / delete — a focus change a screen reader announces),
   and the already-exists panel's title (tidy ruling 5); a heading and a status line are not controls: no ring, like
   the dialog panels and .wel-title (polish ruling 1). */
#lpTitle:focus, #lpNotice:focus, #cmAuthExistsTitle:focus { outline: none; }
/* The landing's one notice ("Your account has been deleted.") — App v3's calm banner geometry (the demo strip's
   14-px radius and 10 / 16 padding) in the panel tokens, so it follows light / dark and the palettes. */
.lp-notice { margin: 6px 0 0; padding: 10px 16px; border: 1px solid var(--border); border-radius: 14px; background: var(--panel); color: var(--ink2); font-size: 14px; font-weight: 700; line-height: 1.45; text-align: center; }

/* ---------- auth- : the auth modal, page mode (?signup / ?signin), reset / recovery / backend-down.
   Form parts = App v3's small-caps label (Account sheet "Email" 12/800/.06em) and input (T7 §1c). ---------- */
/* modal scrim — the old modal geometry; App v3 scrim colour (no ovfade: mobile pass ruling 4, see .ov-scrim). overlay.js adds .visible.
   It KEEPS its own tint and names no --layer-dim (tidy round 2, D5): it only ever opens over the landing (inside
   #cmLogin, hidden once signed in), which is itself a fixed opaque box Safari keeps whatever the modal does — moving
   its dim onto the page would buy nothing. On a phone it is not a scroll container (the dim- section at the end): its
   .auth-inner scrolls itself ([data-scrim] > *). */
.auth-scrim { display: none; position: fixed; inset: 0; z-index: 10000; background: var(--scrim); justify-content: center; align-items: flex-start; padding: 24px; overflow-y: auto; }
.auth-scrim.visible { display: flex; }
.auth-scrim.modal-page { background: var(--bg); }                 /* ?signup / ?signin: an opaque page, no ×, a back link */
.auth-inner { width: 100%; max-width: 380px; margin: auto 0; position: relative; }
.auth-x { position: absolute; top: 12px; right: 12px; z-index: 1; background: var(--chip2); border: none; border-radius: 999px; width: 30px; height: 30px; padding: 0; cursor: pointer; color: var(--ink2); font-size: 17px; font-weight: 800; display: grid; place-items: center; }   /* = .sheet-x */
.auth-scrim.modal-page .auth-x { display: none; }
.auth-card { background: var(--card); border: 1px solid var(--border); border-radius: 18px; padding: 24px; box-shadow: 0 24px 60px rgba(0,0,0,.3); animation: popup .24s cubic-bezier(.22,1,.36,1); }
.auth-scrim.modal-page .auth-card, .auth-card--page { box-shadow: 0 2px 14px rgba(0,0,0,.05); animation: none; }   /* on an opaque page the floating-panel shadow is too heavy */
.auth-back { display: none; text-align: center; margin-top: 16px; }
.auth-scrim.modal-page .auth-back { display: block; }
.auth-back a { font-size: 13px; font-weight: 700; color: var(--muted-text); /* d11 */ text-decoration: underline; text-underline-offset: 2px; }
/* Phone ruling 5: "← Back to home" (class .hit) is the last line of the auth panel, which is its own scroller on a phone
   ([data-scrim] > * — overflow: auto): a CENTRED area would be cut at the panel's bottom and give the panel 13 px of
   scroll. On touch its 44-px area grows UP from the link's bottom instead — over the 16-px gap and into the card's empty
   24-px bottom padding (the card's last control sits above it), never over another control. */
@media (pointer: coarse) { .auth-back a.hit::after { top: auto; bottom: 0; transform: translateX(-50%); } }
/* The wordmark above the card on the standalone auth pages (identity ruling 1): page mode (?signup / ?signin),
   reset, recovery, backend-down. The modal over the landing hides it (the landing's top bar is right behind). */
.auth-brand { display: none; justify-content: center; align-items: center; gap: 6px; margin: 0 0 22px; font-family: 'Lora', serif; font-weight: 700; font-size: 22px; letter-spacing: -.015em; line-height: 1.05; color: var(--ink); }
.auth-scrim.modal-page .auth-brand, .auth-screen .auth-brand { display: flex; }
.auth-brand .lp-sun { width: 24px; height: 24px; }

.auth-label { display: block; font-size: 12px; font-weight: 800; letter-spacing: .06em; text-transform: uppercase; color: var(--muted2-text); /* d11 */ margin: 0 0 6px; }
/* LABELLED DEVIATION: 16 px (App v3's inputs are 14) — iOS Safari zooms the page on focus of any field under 16 px. */
.auth-input { display: block; width: 100%; border: 1px solid var(--border); border-radius: 10px; padding: 11px 12px; font-size: 16px; font-weight: 600; color: var(--ink); background: var(--card); margin-bottom: 14px; }
.auth-input::placeholder { color: var(--muted-text); opacity: 1; }   /* d11 */
.auth-submit { display: block; width: 100%; background: var(--solid); color: var(--on-solid); border: none; border-radius: 14px; padding: 13px; font-size: 15px; font-weight: 900; cursor: pointer; }   /* App v3's full-width primary */
.auth-submit:disabled { opacity: .6; cursor: default; }
.auth-row { text-align: center; margin-top: 12px; }
.auth-row--16 { margin-top: 16px; }
.auth-link { background: none; border: none; padding: 0; font-size: 13px; font-weight: 700; color: var(--muted-text); /* d11 */ text-decoration: underline; text-underline-offset: 2px; cursor: pointer; }
@media (hover: hover) { a.auth-link:hover { color: var(--ink); } }
.auth-link--strong { color: var(--ink); font-weight: 800; }
@media (pointer: coarse) { .auth-link--strong { position: relative; } .auth-link--strong::after { content: ""; position: absolute; left: 50%; top: 50%; width: 100%; height: 100%; min-width: 44px; min-height: 44px; transform: translate(-50%, -50%); } }   /* phone ruling 5: the .hit recipe — auth.js re-renders this button on every mode switch */
.auth-or { display: flex; align-items: center; gap: 10px; margin: 16px 0; color: var(--muted-text); font-size: 12px; font-weight: 700; }
.auth-or::before, .auth-or::after { content: ""; flex: 1; height: 1px; background: var(--border); }
.auth-google { width: 100%; display: flex; align-items: center; justify-content: center; gap: 9px; background: var(--card); border: 1px solid var(--border); border-radius: 14px; padding: 12px; font-size: 15px; font-weight: 800; color: var(--ink); cursor: pointer; }
.auth-toggle-row { text-align: center; font-size: 13px; font-weight: 600; color: var(--muted-text); /* d11 */ margin-top: 18px; }
.auth-msg { font-size: 13px; font-weight: 700; line-height: 1.5; margin-top: 14px; color: var(--ink2); }
.auth-msg:empty { margin-top: 0; }
.auth-msg.is-ok { color: var(--go); }       /* was #3b6d2d inline — 5.03 light / 5.45 dark on --card */
.auth-msg.is-err { color: var(--danger); }  /* was #a03028 inline — 5.44 / 5.45 */
.auth-sent { display: none; text-align: center; padding: 8px 0 4px; }   /* display:block from auth.js */
.auth-sent-title { font-family: 'Lora', serif; font-weight: 600; font-size: 22px; line-height: 1.2; color: var(--ink); margin: 0 0 10px; }
.auth-sent-p { font-size: 13.5px; font-weight: 600; line-height: 1.6; color: var(--ink2); margin: 0 0 4px; }
.auth-sent-email { font-size: 14px; font-weight: 800; color: var(--ink); margin: 0 0 12px; overflow-wrap: anywhere; }
.auth-sent-hint { font-size: 13px; font-weight: 600; line-height: 1.6; color: var(--muted-text); /* d11 */ margin: 0 0 18px; }
/* The already-exists panel's title (tidy ruling 5) is two lines on a phone: kept clear of the modal's × (top right, 12 px
   in, 30 px — it reaches 18 px into the card's content box; measured: the title's first line ran under it at 320 and
   390) by an equal inset on both sides, so it stays centred; balanced lines. */
#cmAuthExistsTitle { padding: 0 26px; text-wrap: balance; }

/* full-screen auth states — display:flex from auth.js / board.js */
.auth-screen { position: fixed; inset: 0; z-index: 9999; background: var(--bg); display: none; align-items: center; justify-content: center; padding: 24px; overflow-y: auto; }
.auth-screen--down { z-index: 9998; text-align: center; }
.auth-screen-inner { width: 100%; max-width: 380px; }
.auth-screen-inner--down { max-width: 360px; }
.auth-screen-title { font-family: 'Lora', serif; font-weight: 600; font-size: 28px; line-height: 1.2; letter-spacing: -.01em; text-align: center; color: var(--ink); margin: 0 0 6px; }
.auth-screen--down .auth-screen-title { font-size: 26px; margin-bottom: 10px; }
/* a title with NO line under it (the new-password screen — copy handoff, 2026-10-10: its sub line said what the
   heading now says): the card keeps the 24 px the sub line used to give it */
.auth-screen-title--solo { margin-bottom: 24px; }
.auth-screen-sub { text-align: center; font-size: 13.5px; font-weight: 600; line-height: 1.5; color: var(--muted-text); /* d11 */ margin: 0 0 24px; }
.auth-down-p { font-size: 15px; font-weight: 600; line-height: 1.6; color: var(--ink2); margin: 0 0 22px; }
.auth-legal { text-align: center; font-size: 12px; font-weight: 700; color: var(--muted-text); margin: 18px 0 0; }
.auth-legal a { color: var(--muted-text); }

/* ---------- sp- : the static pages — privacy.html, terms.html, 404.html (identity ruling 3). They link this sheet
   for App v3's tokens, the four palettes and dark mode (body[data-mode] / body[data-theme] from /theme-boot.js) and
   the self-hosted Lora / Nunito; their prose is their own (the HTML is the content source — the legal wording is the
   owner's). The wordmark and the footer are the landing's (.lp-sun / .lp-name / .lp-sol / .lp-footer). ---------- */
.sp-wrap { display: flex; flex-direction: column; width: 100%; max-width: 760px; min-height: calc(100dvh / var(--zf, 1)); margin: 0 auto; padding: 0 24px; }
.sp-top { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 18px 0 6px; }
.sp-brand { display: inline-flex; align-items: center; gap: 6px; font-family: 'Lora', serif; font-weight: 700; font-size: 22px; letter-spacing: -.015em; line-height: 1.05; color: var(--ink); text-decoration: none; }
.sp-brand:visited { color: var(--ink); text-decoration: none; } @media (hover: hover) { .sp-brand:hover { color: var(--ink); text-decoration: none; } }
.sp-brand .lp-sun { width: 24px; height: 24px; }
.sp-back { font-size: 13.5px; font-weight: 800; color: var(--muted-text); /* d11 */ text-decoration: none; white-space: nowrap; }
@media (hover: hover) { .sp-back:hover { color: var(--ink); text-decoration: underline; text-underline-offset: 2px; } }
.sp-main { flex: 1 0 auto; width: 100%; max-width: 36rem; padding: 34px 0 44px; }
.sp-main .sub { font-size: 12px; font-weight: 800; letter-spacing: .1em; text-transform: uppercase; color: var(--muted2-text); /* d11 */ margin: 0 0 10px; }
.sp-main h1 { font-family: 'Lora', serif; font-weight: 600; font-size: 42px; line-height: 1.08; letter-spacing: -.01em; color: var(--ink); margin: 0 0 8px; }
.sp-main .updated { font-size: 13px; font-weight: 700; color: var(--muted-text); /* d11 */ margin: 0 0 30px; }
.sp-main h2 { font-family: 'Lora', serif; font-weight: 600; font-size: 22px; line-height: 1.25; color: var(--ink); margin: 34px 0 10px; }
.sp-main p, .sp-main li { font-size: 16px; font-weight: 600; line-height: 1.65; color: var(--ink2); }
.sp-main p { margin: 0 0 14px; }
.sp-main ul { margin: 0 0 14px; padding-left: 22px; }
.sp-main li { margin: 0 0 8px; }
.sp-main strong { font-weight: 800; color: var(--ink); }
.sp-main .lead { font-size: 17.5px; color: var(--ink); }
.sp-main a:not(.lp-btn) { color: var(--ink); text-decoration: underline; text-underline-offset: 2px; }   /* prose links stay underlined (WCAG 1.4.1) */
@media (hover: hover) { .sp-main a:not(.lp-btn):hover { color: var(--accent-text); } }
.sp-main .note { margin: 18px 0; padding: 16px 20px; background: var(--card); border: 1px solid var(--border); border-radius: 14px; font-size: 15px; color: var(--ink2); }
.sp-main .sp-sign { margin: 40px 0 0; padding-top: 18px; border-top: 1px solid var(--border); font-size: 13px; font-weight: 700; color: var(--muted-text); /* d11 */ }
/* 404: one centred block */
.sp-main--center { display: flex; flex-direction: column; align-items: center; justify-content: center; max-width: 30rem; margin: 0 auto; text-align: center; }
.sp-main .sp-404 { font-family: 'Lora', serif; font-weight: 600; font-size: 72px; line-height: 1; letter-spacing: -.02em; color: var(--ink); margin: 0 0 10px; }
.sp-main.sp-main--center h1 { font-size: 30px; margin: 0 0 12px; }   /* beats the phone rule's .sp-main h1 */
.sp-main--center .sp-lede { margin: 0 0 26px; }
@media (max-width: 559.98px) {
  .sp-wrap { padding: 0 20px; }
  .sp-brand { font-size: 20px; }
  .sp-brand .lp-sun { width: 22px; height: 22px; }
  .sp-main { padding: 24px 0 36px; }
  .sp-main h1 { font-size: 34px; }
}

/* ---------- mobile pass (fix-v3-mobile, 2026-10-02): the phone rules that belong to no one surface. No look change
   at any width except where labelled. scripts/mobile-css.test.mjs pins every rule here. ---------- */
/* A long press on a CONTROL never starts a text selection or the iOS callout. Controls only — never a container that
   holds a field (WebKit: user-select:none on an input's ancestor can break typing on iOS); no element with one of
   these roles holds a field. */
button, [role="tab"], [role="menuitem"], [role="option"], [role="slider"], [role="switch"] { -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; }
/* Ruling 4: on a phone every overlay panel docked to the bottom edge RISES (sheetUp, no fade) instead of fading in, so
   Safari 26 samples the opaque sheet for its bottom bar on the first frame (WebKit fixedContainerEdges skips a box
   under opacity .1 and then keeps the colour it found). The centred layers (share card, feedback, auth) keep their
   fade. Name only: each panel keeps its duration and easing; a panel with no animation still has none. LABELLED:
   App v3's narrow sheets faded in (popup). */
@media (max-width: 639.98px) {
  [data-scrim]:is(.ov-scrim, .dlg-scrim) > * { animation-name: sheetUp; }
}

/* ---------- dim- : the page's dims (tidy round 2, ruling 1 — the owner's iPhone lab, variant E; round 3, ruling 1,
   2026-10-03). iPhone Safari 26 colours its status strip from what the FIXED and sticky layers paint at the top edge
   (WebKit fixedContainerEdges: a hit test there, then a snapshot of the fixed / sticky layers only): a tinted backdrop
   root made the area above a sheet darken twice (round 2), and round 2's fixed [data-covered]::after over a covered
   layer made a flat grey bar under the clock with a second layer open (round 3 — History → a row). Now every root is
   transparent and names its colour (--layer-dim), and js/page-dim.js paints EVERY open layer's dim on the page: one
   .page-dim box per layer, a child of .page — absolute over the whole page, never fixed, in no fixed root, so Safari
   meets nothing tinted at the top edge and shows the dimmed board under the clock, one layer or three — each ONE Z
   BELOW ITS LAYER (overlay.js keeps two z between stacked layers). .page is not a stacking context, so every box sits
   in the root context between the layer under it and its own: the page, the header and the docks (z 100) are dimmed
   by every open layer, a covered layer's panel (and its borders, shadow and scrolled content) by each layer above it,
   the top panel by none — the paint order and colours of one tinted scrim over another, pixel-identical (measured,
   light + dark, 390 touch + 1280, one, two and three layers). Under the focus tray's or the dock menu's dim (z 89) the
   header, the docks and the rail stay bright; the toast (z 1100) stays above every dim. No fade, no transition: a dim
   comes and goes in its layer's own frame. scripts/mobile-css.test.mjs pins every rule here. ---------- */
.page > .page-dim { position: absolute; inset: 0; z-index: var(--dim-z, 899); background: var(--dim); pointer-events: none; }
/* Lab A: on a phone no backdrop root is a scroll container — its panel scrolls itself (the 88dvh rule, section 3). At
   640 px and up the roots keep `overflow: auto` (a centred panel can exceed a short window or a landscape phone —
   measured) — they are transparent, and the lab showed a transparent scrolling root never flashes. LAST on purpose: it
   must come after every root rule that sets overflow (.ov-scrim, .share-scrim, .fb-scrim, .dlg-scrim, .auth-scrim). */
@media (max-width: 639.98px) { [data-scrim] { overflow: hidden; } }

/* ---------- kb- : the on-screen keyboard (tidy round 2, ruling 2 — the owner's iPhone: the keyboard covered the entry
   editor's note and Account's typed DELETE). iOS Safari shrinks the VISUAL viewport for the keyboard and leaves a fixed
   layer where it was; it has no `interactive-widget` viewport key and no VirtualKeyboard API. js/keyboard.js sets
   html[data-kb] + --kb (the keyboard's overlap of the layer's bottom) + --kb-top (iOS's pan of the visual viewport)
   ONLY while a field inside a layer has the focus and the keyboard covers part of the screen. The layer keeps its box
   (Safari's edge rule, the backdrop tap and the page dim are unchanged); transparent borders make its CONTENT box
   exactly the visible part; the panel fits it and scrolls itself; keyboard.js scrolls the field into view. Visual px
   ÷ --zf (the body zoom). No change without a keyboard. ---------- */
html[data-kb] [data-scrim], html[data-kb] .auth-screen { border-style: solid; border-color: transparent; border-width: calc(var(--kb-top, 0px) / var(--zf, 1)) 0 calc(var(--kb, 0px) / var(--zf, 1)); }
html[data-kb] [data-scrim] { padding-top: 0; padding-bottom: 0; }   /* LABELLED: while typing, a centred layer uses the whole visible height (a landscape phone keeps ~190 px for the panel, not 62) */
html[data-kb] [data-scrim] > * { max-height: 100% !important; overflow: auto !important; }
/* Tidy round 3 (review — ruling 1 while typing): a layer UNDER the top one (js/overlay.js data-under) stops short of the
   visible top. Its dim is the page's .page-dim box — not in a fixed root — so iPhone Safari's fixed-only snapshot would
   find that panel UNDIMMED at the top edge and draw a light bar under the clock over a panel the person sees dimmed
   (Account → Change email; History → a row → + Note). Only the TOP panel (bright, and seen bright) may reach the top.
   LABELLED: while typing in a nested layer, the covered sheet sits 24 px below the visible top (a centred one 12 px). */
html[data-kb] [data-scrim][data-under] > * { max-height: calc(100% - 24px) !important; }
html[data-kb] .auth-screen { align-items: flex-start; }   /* the reset / recovery page: a centred block taller than the visible part would lose its top … */
html[data-kb] .auth-screen-inner { margin: auto 0; }      /* … so it is centred by its margins instead (and scrolls from its top when it does not fit) */

/* ---------- ring- : the focus ring is the KEYBOARD's; a field shows its focus inside (tidy round 4 — the owner's
   reports, 2026-10-03: "sometimes the keyboard focus ring shows even when i am on my phone"; + New → the Name field:
   "is this the keyboard focus ring? … it looks like an inspect element tool bug"). LAST in the file on purpose: the
   field rule weighs one class (its :where() list counts nothing, :focus one), so it must come after every field's own
   rule; a state rule with more weight keeps its border (the New tag / Tags rename error: --danger); the guard outranks
   every ring rule (!important).
   Ruling C (LABELLED — the site's look; App v3 writes outline:none and a --muted2 border, 1.9:1 — under WCAG's 3:1):
   a TEXT FIELD (an <input> of js/input-modality.js TEXT_TYPES, or none; a <textarea>) never draws the outside ring —
   a browser matches :focus-visible on EVERY focused text field (mouse, touch or keyboard), and the 2-px ring 2 px
   outside the field's own border read as a dev-tools highlight. Its focus shows INSIDE the field, in every modality:
   the border turns --ink2 (5.5:1 or more against the border tokens and every surface, 3:1 or more against every
   field's own resting border but one — below — every palette, light and dark) with a soft 3-px halo of the same ink at 14 % (the board search's own look — its wrapper is that field, so it
   joins the rule). A <select> keeps the ring (a button-like control: it opens a picker, no caret — the record editor's
   Hour / Minute sit beside its date BUTTON), and so do the button pickers (.home-select, the store's category combobox).
   Ruling A: while the last input was a pointer (html[data-input="pointer"] — js/input-modality.js, after a tap, a
   click or a pen) NO ring is drawn: the global :focus-visible ring and its on-colour variants, the dealt card's inside
   ring, the store picker's active option, the pack tile — whatever a script focus (a sheet's restored opener, a
   menu's first item) made match :focus-visible. The first key that moves through the page brings them back (Option+Tab
   too — Safari's way to Tab to a button). Written once here; nothing changes where the focus goes.
   scripts/mobile-css.test.mjs pins the field rule, its two exceptions and the guard. ---------- */
:where(input:not([type]), input[type="text"], input[type="search"], input[type="email"], input[type="password"], input[type="number"], input[type="url"], input[type="tel"], textarea):focus,
.cb-search:focus-within { outline: none; border-color: var(--ink2); box-shadow: 0 0 0 3px color-mix(in oklab, var(--ink2) 14%, transparent); }
/* Two fields whose RESTING border is not a plain border token (round 4 review): the Danger zone's typed DELETE box rests
   on a --danger tint that --ink2 clears by only 2.9:1, so its focused border is the text ink (4.6:1 light, 4.8 dark —
   LABELLED, the one field that needs it; the tripwire resolves every field's resting border); the New tag / Tags rename
   field with an error (aria-invalid) keeps App v3's --danger border while focused (the error must stay), so its focus
   shows as that border doubled — a 1-px --danger ring on it (4.9:1 or more on the panel) — with the soft halo in
   --danger (the conventional error + focus look). */
.acs-arm-input--danger:focus { border-color: var(--ink); }
.tk-input[aria-invalid="true"]:focus { box-shadow: 0 0 0 1px var(--danger), 0 0 0 4px color-mix(in oklab, var(--danger) 14%, transparent); }
/* The guard is TWO rules on purpose: a browser without :has() drops a whole selector list holding one, so the main
   guard stands alone (those browsers drop the two :has() ring rules themselves anyway). */
html[data-input="pointer"] :focus-visible { outline: none !important; }
html[data-input="pointer"] .store-pick:has(.store-pick-btn:focus-visible) .store-opt.is-active,
html[data-input="pointer"] .store-pack:has(.store-pack-open:focus-visible) { outline: none !important; }
