/* opencode dark: one renderer, near-black field, the system monospace everywhere, square corners; chrome is sentence case. */
* { box-sizing: border-box; min-width: 0; border-radius: 0; }
/* Things UI cleanup (Task 7, 2026-09-23): the root follows the platform's
   own text-size setting. 17px is the fallback for browsers without the
   -apple-system-body text style (every --fs-* rem token in tokens.css is
   relative to this); on iOS Safari/WKWebView the @supports rule swaps in
   the system Dynamic Type "body" style, so the whole rem-based scale
   grows or shrinks with the user's iPhone text-size setting. That
   shorthand also carries its own font-family + weight, so body
   re-asserts var(--font) at normal weight underneath it. */
html { font-size: 17px; background: var(--field); color: var(--text); -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }
@supports (font: -apple-system-body) { html { font: -apple-system-body; } }
body { margin: 0; background: var(--field); color: var(--text); overflow-wrap: anywhere; font-family: var(--font); font-weight: 400; font-size: 15px; line-height: 1.47; }
button, input, textarea, select { font: inherit; color: inherit; background: transparent; }
input, textarea { caret-color: var(--accent); }
/* Thick block cursor on every field (block-caret.js draws it; iOS has no caret-shape). */
html.block-caret-on textarea, html.block-caret-on input:not([type]), html.block-caret-on input:is([type=text], [type=search], [type=password], [type=tel], [type=url]) { caret-color: transparent; }
.block-caret { position: absolute; z-index: var(--z-toast); pointer-events: none; background: var(--accent-bg); color: var(--accent-ink); white-space: pre; text-align: center; overflow: hidden; animation: logo-blink 1.05s steps(1) infinite; }
@media (prefers-reduced-motion: reduce) { .block-caret { animation: none; } }
button { border: 0; padding: 4px; min-height: 44px; cursor: pointer; text-align: left; touch-action: manipulation; }
a { color: inherit; overflow-wrap: anywhere; }
button:disabled { color: var(--dim); cursor: default; }
input, textarea, select { border: var(--seam); width: 100%; min-height: 44px; padding: 8px 4px; }
input[type=checkbox], input[type=radio] { width: 44px; accent-color: var(--accent-line-on-ink); }
input[type=range] { accent-color: var(--accent-line-on-ink); padding: 0; }
textarea { resize: none; }
input::placeholder, textarea::placeholder { color: var(--dim); opacity: 1; }
button:focus-visible, a:focus-visible, input:focus-visible, textarea:focus-visible, select:focus-visible, [tabindex]:focus-visible, summary:focus-visible { outline: 1px solid var(--control-edge); outline-offset: -1px; }
/* Things has no hover: nothing rings or boxes under the pointer. A press
   dims the control (UIKit's highlighted state) and fades back on release;
   controls with their own pressed background keep just that. */
/* Only lists bounce, never the whole page (native apps keep bars fixed). */
html { -webkit-tap-highlight-color: transparent; overscroll-behavior: none; touch-action: manipulation; }
body { overscroll-behavior: none; }
/* A long press never selects the app's own text or pops the copy / look-up
   callout, as in a native app. Fields keep both. */
body { -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; }
:is(input, textarea, [contenteditable]) { -webkit-user-select: text; user-select: text; -webkit-touch-callout: default; }
img { -webkit-user-drag: none; }
:where(button, a) { transition: opacity .2s; }
:where(button:not(:disabled), a, summary.list-menu):not(.settings-row, .pin-key, .xp-ico, .snooze-key, .cnk-key, .nl-chooser__opt, .list-row, .c-cb > button):active { opacity: .4; transition: none; }
.list-row:is(:focus, :focus-visible),.new-list-link:is(:focus, :focus-visible),.nl-chooser__opt:is(:focus, :focus-visible),.settings-link:is(:focus, :focus-visible),.capture-fab:is(:focus, :focus-visible),.list-back:is(:focus, :focus-visible) { outline: none; }
h1,h2,h3,h4,p,figure { margin: 0; font: inherit; }
p + p { margin-top: 16px; }
strong,b { font-weight: 700; }
code,kbd,pre { font-family: var(--font); }
pre { white-space: pre-wrap; overflow-wrap: anywhere; }
img,svg,canvas { max-width: 100%; }
[hidden] { display: none !important; }
#app { height: 100dvh; max-width: var(--app-max); margin: auto; padding: env(safe-area-inset-top, 0px) var(--space-5) var(--home-pad); display: flex; flex-direction: column; gap: 0; }
.workbench-view { flex: 1; min-height: 96px; overflow-y: auto; border: 0; position: relative; }
.list { --list-pad-b: 72px; min-height: 0; overflow-y: auto; overscroll-behavior-y: contain; flex: 1; padding: 0 0 var(--list-pad-b); }
.topbar, .dbar-wrap { flex: none; padding: 0; }
/* Search affordance sits ABOVE the screen heading (F3). Heading is 44px; filters pin right. */
.topbar { padding-bottom: var(--space-2); margin-bottom: 0; }
.list-back { width: 44px; min-width: 44px; height: 44px; display: grid; place-items: center; padding: 0; font: 400 1.647rem/2.588rem var(--font); color: var(--ink-secondary); text-align: center; }
.head-line { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--space-2); min-height: 44px; }
.head-line .h1 { flex: none; display: flex; align-items: baseline; gap: var(--space-2); font-family: var(--font); font-weight: 700; font-size: 22px; line-height: 40px; letter-spacing: 0; text-transform: none; }


.search-open { flex: none; display: flex; align-items: center; gap: var(--space-2); padding: 8px 0; }
.search-field { flex: 1; min-width: 0; display: flex; align-items: center; width: 100%; min-height: 44px; padding: 0 8px 0 12px; background: var(--surface-pressed); border: 0; box-shadow: inset 3px 0 0 var(--accent); border-radius: 0; caret-color: var(--accent); }
.search-field .search-input { flex: 1; min-width: 0; min-height: 44px; padding: 0 8px; border: 0; background: transparent; font: var(--type-input); }
.search-field .search-input:focus-visible { outline: 0; }
/* Clear: a small blue text button inside the field, shown only once the field has text. */
.search-count { flex: none; padding: var(--space-2) 0; border-top: 1px solid var(--rule); font: 400 var(--fs-meta)/1.3 var(--font); color: var(--ink-secondary); }
.search-count:empty { display: none; }
.search-open .search-close { flex: none; min-width: 44px; min-height: 44px; padding: 0 4px; font: 500 0.882rem/1.176rem var(--font); color: var(--accent-text); }
.search-section { display: flex; justify-content: space-between; margin: var(--space-4) 0 2px; padding-bottom: var(--space-2); border-bottom: 1px solid var(--rule); font: 700 var(--fs-meta)/1.3 var(--font); color: var(--upcoming); }
.search-section b { font-weight: 400; color: var(--ink-muted); }
/* Quick find: jump strip, one chip per group. */
.qf-jump { flex: none; display: flex; gap: var(--space-2); }
.qf-jump:empty { display: none; }
.qf-jump__chip { flex: 1; min-height: 44px; display: flex; align-items: center; justify-content: center; gap: 6px; padding: 0 4px; background: var(--surface); border-bottom: 1px solid var(--rule); color: var(--ink-secondary); font: 400 var(--fs-meta)/1.3 var(--font); }
.qf-jump__chip b { font-weight: 400; color: var(--ink-muted); }

.dest-tile { width: 28px; height: 28px; margin: 0 auto; border-radius: 0; display: inline-grid; place-items: center; overflow: hidden; font: 400 1.059rem/1 var(--font); font-variant-emoji: emoji; color: var(--ink); vertical-align: middle; background: transparent; }
.h1 > .dest-tile { margin-left: 0; margin-right: 8px; align-self: center; }

.dest-tile--inbox { background: transparent; color: var(--capture); }
.dest-tile--today { background: transparent; color: var(--today); }
.dest-tile--anytime { background: transparent; color: var(--anytime); }
.dest-tile--someday { background: transparent; color: var(--someday); }

.count { font: var(--type-meta); color: var(--ink-secondary); padding-right: 4px; }
.hair { height: 1px; background: var(--rule); margin: var(--space-2) 0; border: 0; }
/* Anytime rows due today or earlier carry the Today star before the title. */
.today-mark { display: inline-flex; vertical-align: -2px; margin-right: 6px; }
.today-mark .dest-tile, .today-mark .dest-tile svg { width: 14px; height: 14px; margin: 0; }
/* Someday is parked, visually quiet (mockup .row.quiet); the heading icon keeps full weight. */
.view--someday .group-rows .title-hit { opacity: 0.75; }

.gsegs { display: flex; align-items: stretch; flex-wrap: wrap; }

/* Page headings are 22px everywhere, like the tab heads. */
.h1 { font: var(--weight-emphasis) 22px/30px var(--font); }
/* Shell heading: a muted # leads the name (CSS, so the title text stays clean). The icon tile is dropped. */
.head-line .h1::before { content: '# '; white-space: pre; color: var(--ink-muted); font-weight: 400; order: -1; }
.h1 > .dest-tile { display: none; }

/* Pane title on the left, an optional banner in the dead space to its right.
   The banner is the only button here, so the row costs the 44px tap floor
   once instead of stacking a 16px title band on top of a 44px banner band. */
.head-line .enable-reminders { margin-left: auto; padding: 0 var(--space-3); }
.head-line .enable-reminders { align-self: center; }
/* A control, not a colour cue: ⚐ glyph + label carry the meaning (R21); hairline edge marks the target. */
.enable-reminders { display: inline-flex; align-items: center; gap: 6px; min-height: var(--tap-min); color: var(--ink); background: var(--surface); border: 0; border-radius: 0; font: 500 calc(var(--fs-chrome) + 2px)/18px var(--font); }
.enable-reminders .eb-icon { display: inline-flex; color: var(--accent-line); }
.group { padding-top: 0; }
.gstrip { border-bottom: var(--seam); display: flex; align-items: center; gap: 1ch; padding: 0 4px; min-height: 16px; flex-wrap: wrap; }
/* Section labels, one rule everywhere (lists, Ahead, Done, Settings, sheets): 13px bold purple, no hairline; late is the only red one. */
.group-head,.done-month-head { display: flex; align-items: center; gap: var(--space-2); padding: var(--space-6) 0 var(--space-2); min-height: 16px; flex-wrap: wrap; color: var(--upcoming); font: 700 0.765rem/1.059rem var(--font); }

.gstrip__txt { flex: 1; }
.gstrip--takeover { flex: none; }
.gsegs > * + * { border-left: var(--seam); }
/* Dark Loom row (grammar R7, R11–R13): 44px checkbox column | content | optional 44px trailing
   action column. 48px minimum, never fixed; a wrapped title adds 24px per line, meta adds 8 + 16. */
.row,.rowd,.row-today,.done-row { display: grid; grid-template-columns: var(--tap-min) minmax(0,1fr); column-gap: var(--space-2); min-height: var(--row-min); border-bottom: 0; position: relative; background: var(--field); font-size: var(--fs-rows); line-height: 20px; }
.row.has-tail,.rowd.has-tail,.row-today.has-tail { grid-template-columns: var(--tap-min) minmax(0,1fr) var(--tap-min); }
/* R18 one hairline owner: rows own their bottom rule; the last row in a list or section owns none. */
.row:last-child,.rowd:last-child,.row-today:last-child,.done-row:last-child { border-bottom: 0; }
.c-cb { grid-column: 1; align-self: stretch; position: relative; }
.c-title { grid-column: 2; padding: 6px 0; min-width: 0; }
/* Trailing column: ONLY subtask disclosure and the counter (actions that differ from the row tap),
   plus the non-interactive overdue mark (R23). Stacked 44px targets when more than one. */
.c-tail { grid-column: 3; align-self: stretch; display: flex; flex-direction: column; justify-content: center; }
.title,.rt-title,.rowd__name,.done-title { display: block; font: 400 var(--fs-rows)/20px var(--font); overflow-wrap: anywhere; }
/* Things: a row title is one line, cut short with …; the open card shows it whole. Meta, doses and chips below keep their own lines. */
:is(.row, .rowd, .row-today) > .c-title > :is(.title, .rowd__name) { display: flex; flex-wrap: wrap; align-items: baseline; }
:is(.row, .rowd, .row-today) .title-hit { flex: 1 1 1px; min-width: 0; /* 1px, not 0: a 100% sibling must not fit beside it */ white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
:is(.row, .rowd, .row-today) .title-hit ~ :not(.rt-thumb, .row-clock) { flex-basis: 100%; }
:is(.row, .rowd, .row-today).expanded .title-hit { white-space: normal; overflow: visible; }
/* Out-specifies `.row button` so the marker keeps its flex box and alignment. */
:is(.row, .rowd, .row-today) :is(.title-alarm, .title-warn) { display: inline-flex; align-items: center; gap: 4px; margin: 0 6px 0 0; color: var(--ink-secondary); font: 400 var(--fs-row-detail)/20px var(--font); vertical-align: top; height: 20px; }
.row button,.rowd button,.row-today button,.done-row button { display: inline; min-height: 0; padding: 0; line-height: inherit; vertical-align: baseline; }
.c-tail > button { display: flex; flex-direction: column; align-items: center; justify-content: center; min-height: var(--tap-min); min-width: var(--tap-min); padding: 0; text-align: center; font: 400 var(--fs-meta)/16px var(--font); color: var(--ink-secondary); }
.c-tail > .counter-chip { color: var(--ink); font-weight: var(--weight-emphasis); }
/* Checkbox: 44px-wide target spanning the row (the ::after pseudo below fills the cell). The visual is
   a square box (1.5px ring, square corners): open (muted ring), done (green fill, dark ✓), the next to-do
   today (peach ring, peach centre, .row--next). The completion animation pops the green box and tosses a ✓
   into the done tab (.study-b-check). The button carries its accessible label. */
.c-cb > .checkbox,.c-cb > .rt-checkbox,.c-cb > .rowd__cb { display: flex; justify-content: flex-start; align-items: flex-start; padding-top: 6px; width: var(--tap-min); height: 100%; min-height: var(--row-min); color: var(--ink); }
.c-cb > button > span:not(.cb-halo) { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.c-cb > .checkbox::before,.c-cb > .rt-checkbox::before,.c-cb > .rowd__cb::before { content: ''; box-sizing: border-box; display: grid; place-items: center; width: 18px; height: 18px; margin-top: 1px; border: 1.5px solid var(--ink-muted); background: transparent; font: 700 12px/1 var(--font); color: var(--logbook-ink); transition: transform calc(120ms * var(--motion-scale)) var(--spring-pop); }
.c-cb > .checkbox:active::before,.c-cb > .rt-checkbox:active::before,.c-cb > .rowd__cb:active::before { border-color: var(--ink); transition-duration: 0s; }
@media (prefers-reduced-motion: no-preference) { .c-cb > :is(.checkbox,.rt-checkbox,.rowd__cb):active::before { transform: scale(.88); } }
.c-cb > .checkbox.checked::before,.c-cb > .rt-checkbox.checked::before,.c-cb > .rowd__cb.is-done::before { content: '✓'; border-color: var(--logbook); background: var(--logbook); color: var(--logbook-ink); }
/* Not while completing: the tick must pop green on the next row too. */
.row--next .c-cb > .checkbox:not(.checked, .study-b-check)::before { border-color: var(--accent-text); background: linear-gradient(var(--accent-text), var(--accent-text)) center / 6px 6px no-repeat; }
.c-cb > .checkbox--gated::before,.c-cb > .rowd__cb--gated::before { opacity: .5; }
/* The box is 18x18px. `.c-cb` stretches to the row's full height and this
   pseudo fills it, so every pixel of the checkbox column toggles done —
   including the lower lines of a wrapped row, which previously fell through
   to the row body (opening WHEN instead of completing). A negative `left`
   buys nothing: `.list` sets `overflow-y: auto`, so it clips horizontally at
   its content box. */
.checkbox::after,.rt-checkbox::after,.rowd__cb::after { content: ''; position: absolute; inset: 0; }
.cb-halo,.cb-gate-dot { display: none; }
.task-due,.task-tags,.task-state,.row-list { display: inline; font-size: var(--fs-meta); }
.row-list { color: var(--ink-muted); }
/* Meta block: always its own line, always the same left edge, so the due
   times form a scannable column whether or not the title above wrapped. */
.row-meta { display: block; margin-top: var(--space-1); font: var(--type-meta); color: var(--ink-secondary); }
.late .row-meta, .rt-late-text { color: var(--overdue); }
.task-state > * + *, .task-tags > * + *, .row-meta > * + * { margin-left: var(--space-2); }
/* Meta: muted small text; a #tag is cyan text with no pill, small grey glyphs mark notes, checklist and date. */
.row-meta :is(.row-tag, .rt-tag) { display: inline-block; line-height: 16px; }
.meta-ico { display: inline-flex; vertical-align: -1px; color: var(--ink-muted); }
.meta-icons > * + * { margin-left: var(--space-1); }
.task-due .meta-ico { margin-right: 3px; color: inherit; }
/* The due time is reference data on the quiet meta line, not a coloured token (frame .meta). */
.task-due.today,.task-due.future { color: inherit; }
.task-due button,.task-tags button,.task-state button { color: inherit; }
.task-tags,.row-tag,.rt-tag { color: var(--tag); }
.task-state { color: var(--ink-secondary); }
/* P4 URGENT: weight + underline + the word itself, never colour alone (R21). */
.urgent-mark { font-weight: var(--weight-emphasis); text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 3px; }
/* P11 unseen change on a shared task: brighter rail + weight. */
.row--unseen .title,.rowd--unseen .rowd__name { font-weight: var(--weight-emphasis); }
.overdue,.preview-warn,.sync-error-banner,.task-action-btn--del,.del,.error { color: var(--overdue); }
.today { color: var(--today); }
.future { color: var(--future); }
.rt-recur-chip { color: var(--recurring); }
.row-due-in { color: var(--accent-text); }
.task-state .row-due-in:not(:first-child)::before { content: '· '; }
.rt-snooze,.snoozed { color: var(--snoozed); }
.counter-chip { color: var(--ink-muted); }
.counter-chip--low,.counter-chip--limit { color: var(--soon); }
.row-mentions,.rowd__mentions { color: var(--tag); }

/* Selected row: soft --surface-pressed fill only. No side line,
   no bold, no rotation — invisible-selection matches Things on iPhone, where a
   tap opens the row. A hardware-keyboard selection (j/k, Tab) does need to be
   seen, so keyboard focus paints an accent-tinted fill (no line), as on Things
   for Mac. 78% accent over --field reaches 3.1:1 (76% is the 3:1 floor)
   against --field; its text goes --accent-ink (5.6:1), since the row's grey
   and red meta would drop below 3:1 on the tint. */
.selected { background: var(--surface-pressed); color: var(--text); }
:is(.row, .rowd, .row-today):focus-visible:not(.expanded) { background: color-mix(in srgb, var(--accent) 92%, var(--field)); color: var(--accent-ink); border-radius: 0; }
:is(.row, .rowd, .row-today):focus-visible:not(.expanded) * { color: inherit; }
:is(.row, .rowd, .row-today):focus-visible:not(.expanded) .c-cb > *::before { color: var(--accent-ink); }
/* The fill is the row's focus indicator, so the global focus outline stays off rows. */
:is(.row, .rowd, .row-today):focus-visible { outline: none; }
.subs-list { padding-left: var(--space-5); }
.subs-more { width: 100%; min-height: var(--tap-min); color: var(--ink-secondary); font: 400 var(--fs-meta)/16px var(--font); }
/* In flow, spanning both row columns: the panel reserves its own height so the next task sits below it. */
/* Things 3 open to-do. Tap lifts the row into a card; everything else on the
   screen dims; notes, checklist and the corner icons arrive in sequence;
   rows below slide down with the block's grid-row interpolation. Spring-ish
   ease with no overshoot, ~270ms open / ~240ms close, measured off the
   official Things iPhone demo video at 30fps.
   One scrim under the card does the dimming (was: an opacity transition on
   every row, 100+ animating layers per tap, which stuttered on the phone).
   mountWorkbench sets .has-expanded on the view; the .expanded row sits
   above the scrim (z-index 2). */
.view::after { content: ''; position: fixed; inset: 0; z-index: 1; background: var(--field); opacity: 0; pointer-events: none; transition: opacity calc(400ms * var(--motion-scale)) var(--spring-list); }
.view.has-expanded::after { opacity: 0.65; }
.view.has-expanded .topbar :is(.list-back, .list-menu) { opacity: 0; pointer-events: none; }
.topbar :is(.list-back, .list-menu) { transition: opacity calc(200ms * var(--motion-scale)) ease; }
.topbar :is(.list-back, .list-menu):active { transition: none; }
:is(.row, .rowd, .row-today).expanded + .subs-list { display: none; }
:is(.row, .rowd, .row-today) { transition: transform calc(150ms * var(--motion-scale)) var(--spring-list), margin calc(400ms * var(--motion-scale)) var(--spring-list), box-shadow calc(400ms * var(--motion-scale)) var(--spring-list), background-color calc(200ms * var(--motion-scale)) ease, border-radius calc(400ms * var(--motion-scale)) var(--spring-list); }
.view :is(.row, .rowd, .row-today).expanded { background: var(--surface); border-radius: 0; margin: 10px 0 14px; box-shadow: inset 3px 0 0 var(--accent-bg); z-index: 2; opacity: 1; }
.expand-block { grid-column: 1 / -1; margin-left: -1px; position: relative; z-index: 2; background: var(--surface); display: grid; grid-template-rows: 0fr; visibility: hidden; transition: grid-template-rows calc(400ms * var(--motion-scale)) var(--spring-list), visibility 0s calc(400ms * var(--motion-scale)); }
.row.expanded .expand-block, .rowd.expanded .expand-block, .row-today.expanded .expand-block { grid-template-rows: 1fr; visibility: visible; transition: grid-template-rows calc(400ms * var(--motion-scale)) var(--spring-list); }
.expand-inner { overflow: hidden; opacity: 0; transition: opacity calc(200ms * var(--motion-scale)) ease; }
.row.expanded .expand-inner, .rowd.expanded .expand-inner, .row-today.expanded .expand-inner { opacity: 1; transition: opacity calc(200ms * var(--motion-scale)) ease 40ms; }
.tag-chip { font: var(--type-meta); color: var(--tag); background: transparent; padding: 4px 10px; min-height: 24px; display: inline-flex; align-items: center; border-radius: 0; }
/* Quick find: tag tree (nested tags under their root) and palette hits. */
.search-tag-row { display: flex; align-items: center; width: 100%; min-height: 44px; padding: 0; background: transparent; color: var(--tag); font: var(--type-body); text-align: left; }
.search-tag-row__branch { flex: none; white-space: pre; color: var(--ink-muted); }
.search-tag-row__name { flex: 1; }
.search-project-row { color: var(--upcoming); }
.search-tag-chip__n { margin-left: 6px; color: var(--ink-muted); }
.search-tag-chip__n { flex: none; }
/* Top hit: its own card, pressed fill and the field's peach bar; the key cap sits after the count. */
.qf-card { margin: var(--space-3) 0 var(--space-1); padding: var(--space-3); background: var(--surface-pressed); box-shadow: inset 3px 0 0 var(--accent); }
.qf-card__label { margin-bottom: 4px; color: var(--accent-text); font: 400 var(--fs-meta)/1.3 var(--font); }
.search-tag-row.qf-top { min-height: 36px; font-weight: 500; }
.qf-card .search-tag-chip__n { margin-right: var(--space-2); font: 400 var(--fs-meta)/1.3 var(--font); }
.qf-key { flex: none; padding: 2px 8px; background: var(--accent-bg); color: var(--accent-ink); font: 400 var(--fs-meta)/1.3 var(--font); }
/* Rows off screen skip style, layout and paint until scrolled to: a long
   list no longer costs its full height on every screen change. The open
   card is exempt (paint containment would clip its shadow). */
:is(.row, .rowd, .row-today, .done-row):not(.expanded):not(.is-expanding) { content-visibility: auto; contain-intrinsic-size: auto 52px; }
/* Stand-in for a row not built yet on a screen change (lazyRow, render.js). */
.row-lazy { height: 52px; }
.row,.rowd,.row-today { position: relative; z-index: 1; background: var(--field); touch-action: pan-y; flex: none; }
/* Done rows too: the keyboard-selected fill must not leak onto the first Done row. */
.done-row { background: var(--field); z-index: 1; touch-action: pan-y; flex: none; }
.rt-thumb { display: inline-block; width: 16px; height: 16px; vertical-align: bottom; padding: 0; }
.rt-thumb img { width: 16px; height: 16px; object-fit: cover; }

/* Things 3 Logbook: month heading over a hairline; each row leads with its blue completion date. */
/* Things 3 Logbook row: box flush with the heading, blue d/m date column, one-line title then
   repeat/tag icons (titles wrap, never cut), the project on a second line; box and date centre on both lines. The box keeps a
   44px target by reaching into the gutter and the gap. Done boxes fill the lighter blue Things uses. */
.done-row { grid-template-columns: calc(var(--check-size) + 8px) auto minmax(0,1fr); align-items: center; }
.done-row .c-cb > .checkbox { width: var(--tap-min); margin-left: -14px; padding: 0 0 0 14px; justify-content: flex-start; align-items: center; }
.done-row .c-title { grid-column: 3; }
.done-date { grid-column: 2; min-width: 6ch; color: var(--ink-muted); font: 400 var(--fs-meta)/20px var(--font); font-variant-numeric: tabular-nums; }
.done-line { display: block; }
.done-row .done-title { display: inline; color: var(--ink-muted); text-decoration: line-through; text-decoration-color: var(--control-edge); }
.done-line .meta-ico { margin-left: 6px; color: var(--ink-secondary); }
.done-row .row-meta { margin-top: 0; }
.done-row--project { width: 100%; padding: 0; border: 0; color: inherit; text-align: left; font: inherit; }
.done-proj-ico { display: flex; justify-content: center; }
/* The pill sat flush against the title ("NEWReload mechanical watch") and wore
   the title's own colour, so it read as the first word of the task. Amber +
   italic + a trailing space make it chrome, not text. */
.new-pill { color: var(--hi); font-style: italic; margin-right: var(--space-2); font: italic 400 var(--fs-meta)/16px var(--font); }
.empty,.search-empty { padding: var(--space-8) 0; color: var(--ink-muted); font: 500 0.765rem/1.176rem var(--font); }
.search-empty { padding: var(--space-6) 0; text-align: center; }
/* The empty note waits while the last rows fold away (list-motion foldOut), then fades in; an empty tab opened fresh shows it at once. */
@media (prefers-reduced-motion: no-preference) { .empty--left { transition: opacity calc(200ms * var(--motion-scale)) ease; } .view--tab:has(> .row--leaving) > .empty--left { opacity: 0; } }
.empty-cta { color: var(--ink-muted); }
.ibf { display: flex; align-items: center; gap: var(--space-1); font: 400 var(--fs-chrome)/16px var(--font); }
.ibf { min-width: 44px; min-height: 44px; padding: 0 8px; justify-content: center; color: var(--ink-muted); background: transparent; border: 0; }
/* Things filter pills: a 32px pill inside the 44px hit box, count as muted
   text inside it; the active pill is filled with the accent. */
.ibf { color: var(--ink-secondary); padding: 0 12px; }
.ibf.on { color: var(--accent-ink); font-weight: var(--weight-emphasis); background: linear-gradient(var(--accent-bg), var(--accent-bg)) center / 100% 32px no-repeat; }

.search-input { flex: 1; }
mark,.search-hit { color: var(--accent-ink); background: var(--accent-bg); font-weight: 700; text-decoration: none; padding: 0 1px; }
/* Quick find: the line recedes so the peach block is what the eye lands on. */
.search-results-scroll .title { color: var(--ink-secondary); }
/* The keyboard-selected result is filled, like the active tab. */
/* Search selection: the pressed fill plus the field's peach bar; text keeps its own colour. */
.search-results-scroll .selected { background: var(--surface-pressed); box-shadow: inset 3px 0 0 var(--accent); }
/* Lists screen: Quick Find, destinations, then Settings + the blue +. */
.device-dock { display: flex; align-items: center; flex: none; min-height: 44px; margin-top: auto; }
.settings-link { min-height: 44px; padding: 0 8px; color: var(--ink-secondary); font: 500 0.882rem/1.176rem var(--font); background: transparent; }
.capture-fab { position: fixed; z-index: 45; right: max(16px, calc((100vw - min(var(--app-max), 100vw)) / 2 + 16px)); bottom: max(12px, env(safe-area-inset-bottom, 0px)); width: 44px; height: 44px; min-width: 44px; min-height: 44px; padding: 0; border-radius: 0; background: var(--accent-bg); color: var(--accent-ink); font: 400 1.647rem/2.588rem var(--font); text-align: center; }
.nav { display: flex; flex: none; font: var(--type-meta); }
.nav > button { min-height: var(--tap-min); padding: 0; white-space: nowrap; }
/* open/close motion: composer-motion.js (Things Quick Entry keyframes) */

.sync-error-banner { display: flex; align-items: center; flex-wrap: wrap; gap: var(--space-2); min-height: 44px; padding: 0 var(--space-1); font: 400 var(--fs-meta)/16px var(--font); border-bottom: var(--seam); }
.seb-dismiss { min-width: 44px; text-align: center; color: inherit; }
/* Phase 6: temporary capture surface; one scroll region, commit above the keyboard. */
.composer--full { position: fixed; inset: 0; height: 100dvh; z-index: var(--z-composer); background: var(--field); display: flex; flex-direction: column; padding: env(safe-area-inset-top, 0px) max(var(--space-5), calc((100% - var(--content-max)) / 2)) var(--home-pad); }
/* Pulled down (sheet-drag.js) it reads as a card over the list, like .view--above; at rest the shadow is off-screen and the corners hide under the phone's own. */
.composer--full { border-radius: 0; border-top: 1px solid var(--rule); box-shadow: var(--shadow-float); }
.composer-head { display: flex; align-items: center; gap: var(--space-3); padding: var(--space-5) 0; flex: none; }
.composer-heading { flex: 1; text-align: center; font: var(--weight-emphasis) var(--type-body) var(--font); }
.composer-head .composer-clear { color: var(--ink-muted); }
.composer-head .scan { order: 2; }
.composer-head .x { order: 3; }
.composer-head button { font: var(--type-body); min-width: var(--tap-min); }
.composer-scroll { min-height: 0; overflow-y: auto; flex: 1; padding-bottom: var(--space-5); }
/* opencode's prompt box: element fill with a 3px peach bar (inset shadow, borders stay <=1px). */
.composer-input-wrap { position: relative; background: var(--surface-pressed); box-shadow: inset 3px 0 0 var(--accent-bg); border-radius: 0; }
/* The filled field and the caret mark focus; no outline box around it. */
.composer .nli-input:focus-visible { outline: 0; }
.nli-input, #composer-overlay { padding: var(--space-3); font: 400 calc(var(--fs-composer-input) + 6px)/max(var(--space-6), 1.4em) var(--font); letter-spacing: 0; white-space: pre-wrap; overflow-wrap: anywhere; }
.nli-input { min-height: var(--tap-min); border: 0; resize: none; display: block; }
#composer-overlay { position: absolute; inset: 0; color: var(--ink); pointer-events: none; }
.composer-foot { display: flex; flex: none; gap: var(--space-3); border-top: var(--seam); padding-top: var(--space-3); font: var(--type-body); }
.composer-foot > button { min-width: var(--tap-min); padding: var(--space-3); }
.composer-foot .save { flex: 1; text-align: center; background: var(--accent-bg); color: var(--accent-ink); border-radius: 0; font-weight: var(--weight-emphasis); }
.save__keys { margin-left: var(--space-2); }
.composer .input-section > .cap-type.label { display: flex; gap: var(--space-2); flex-wrap: wrap; padding-bottom: var(--space-2); font: 400 var(--fs-meta)/1.3 var(--font); color: var(--ink-secondary); }
.composer .input-section > .hair { display: none; }
.composer .input-meta, .composer .composer-shift, .composer .pv { font: var(--type-control); }
/* Things rows read at body size: Add subtask / image / counter / warnings / notes. */
.composer .composer-actions, .composer .composer-desc__toggle, .composer .warn-toggle, .composer .edit-subtasks .composer-add-sub { font: var(--type-body); }
/* Things grouped rows: one rounded surface per group, hairlines only inside it. */
.composer .composer-actions, .composer .edit-subtasks, .composer .composer-desc { display: flex; flex-direction: column; align-items: stretch; margin-top: var(--space-3); background: var(--surface); border-radius: 0; }
.composer .composer-actions > * + * { border-top: var(--seam); }
.composer .composer-actions > button, .composer .warn-toggle, .composer .edit-subtasks .composer-add-sub, .composer .composer-desc__toggle { min-height: var(--tap-min); padding: 0 var(--space-3); text-align: left; }
.composer .warn-expanded { padding: 0 var(--space-3) var(--space-3); }
.composer .composer-split-desc { width: 100%; min-height: var(--tap-min); margin-top: var(--space-3); padding: 0 var(--space-3); background: var(--surface); border-radius: 0; text-align: left; font: var(--type-body); }
.composer .nli-notes { font: 400 calc(var(--fs-composer-input) + 6px)/1.5 var(--font); }

.composer-receipt { display: contents; }
.composer-receipt-line { display: inline-flex; flex-direction: column; justify-content: center; min-height: var(--tap-min); padding: 4px 12px; border: 0; border-radius: 0; background: var(--surface); font: var(--type-meta); color: var(--ink); }
.pv > .composer-receipt-line:first-child { width: 100%; }
.composer-receipt-line > :first-child { color: var(--ink-muted); }
.composer-receipt-line > :last-child { text-align: left; overflow-wrap: anywhere; }
/* Tappable tiles underline the value like the matching token in the text. */
.composer button.composer-receipt-line > :last-child { text-decoration: underline; text-decoration-color: var(--ink-muted); text-underline-offset: 3px; }
.composer .row-pv__t, .composer .preview-tapered-title { font: var(--type-body); }
 .composer .row-pv__when, .composer .preview-ambig { color: var(--ink-secondary); }
.composer-foot .save:disabled { background: var(--surface-pressed); color: var(--ink-muted); border-color: transparent; }
/* Scanner: seven squares light in sequence while typing (copy of opencode's busy bar). */
.scan { display: inline-flex; gap: 3px; }
.scan i { width: 6px; height: 6px; background: var(--accent-bg); opacity: .14; }
.scan.busy i { animation: scan 1s linear infinite; }
.scan.busy i:nth-child(2) { animation-delay: .1s; } .scan.busy i:nth-child(3) { animation-delay: .2s; }
.scan.busy i:nth-child(4) { animation-delay: .3s; } .scan.busy i:nth-child(5) { animation-delay: .4s; }
.scan.busy i:nth-child(6) { animation-delay: .5s; } .scan.busy i:nth-child(7) { animation-delay: .6s; }
@keyframes scan { 0% { opacity: 1; } 45% { opacity: .14; } 100% { opacity: .14; } }
/* Preview parts read as tool-call lines: glyph, muted label, ink value. */
.composer-receipt-line { --pv-c: var(--ink-muted); flex-direction: row; align-items: center; justify-content: flex-start; gap: var(--space-2); width: 100%; text-align: left; }
.composer-receipt-line::before { content: '>'; flex: none; width: 1.2ch; color: var(--pv-c); }
.composer-receipt-line > :first-child { flex: none; min-width: 7ch; }
.composer-receipt-line[data-part='Count'] { --pv-c: var(--soon); } .composer-receipt-line[data-part='Count']::before { content: '×'; }
.composer-receipt-line[data-part='Warn'] { --pv-c: var(--today); } .composer-receipt-line[data-part='Warn']::before { content: '!'; }
.composer-receipt-line[data-part='Alarm'] { --pv-c: var(--today); } .composer-receipt-line[data-part='Alarm']::before { content: '◉'; }
.composer-receipt-line[data-part='Shared with']::before { content: '@'; }
/* chip strip: one chip per understood part, role colour underline, dashed ghost for what is missing */
.composer-chips { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; width: 100%; }
.composer-chip { --pv-c: var(--accent-text); display: inline-flex; align-items: center; gap: 6px; min-height: var(--tap-min); padding: 0 12px; border: 0; border-bottom: 1px solid var(--pv-c); border-radius: 0; background: var(--surface); font: var(--type-meta); color: var(--ink); text-align: left; overflow-wrap: anywhere; }
.composer-chip::before { flex: none; color: var(--pv-c); }
.composer-chip[data-part='Due']::before { content: '→'; } .composer-chip[data-part='Repeat']::before { content: '↻'; }
.composer-chip[data-part='Project']::before { content: '▸'; } .composer-chip[data-part='Tags']::before { content: '#'; }
.composer-chip[data-part='Repeat'] { --pv-c: var(--recurring); }
.composer-chip[data-part='Tags'], .composer-chip[data-part='Project'] { --pv-c: var(--tag); }
.composer-chip.is-ghost { color: var(--ink-muted); border-bottom-color: transparent; background: repeating-linear-gradient(90deg, var(--ink-muted) 0 4px, transparent 4px 8px) bottom / 100% 1px no-repeat; }
.composer-chip.is-new { animation: pv-in calc(300ms * var(--motion-scale)) var(--spring-chrome) both; }
.composer-chips__score { margin-left: auto; color: var(--ink-secondary); font: var(--type-meta); }
.composer-next { display: flex; gap: var(--space-2); width: 100%; padding: 8px 12px; background: var(--surface); font: var(--type-meta); }
.composer-next > :first-child { flex: none; min-width: 7ch; color: var(--recurring); }
.composer-next > :last-child { color: var(--ink); overflow-wrap: anywhere; }
.composer-receipt-line.is-new { animation: pv-in calc(300ms * var(--motion-scale)) var(--spring-chrome) both; }
.composer-receipt-line.is-new:nth-child(2) { animation-delay: 60ms; } .composer-receipt-line.is-new:nth-child(3) { animation-delay: 120ms; }
.composer-receipt-line.is-new:nth-child(4) { animation-delay: 180ms; } .composer-receipt-line.is-new:nth-child(n+5) { animation-delay: 240ms; }
@keyframes pv-in { from { opacity: 0; transform: translateX(-8px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .composer-receipt-line.is-new, .composer-chip.is-new { animation: none; } .scan.busy i { animation: none; opacity: .6; } }

.composer .preview-warn { padding: var(--space-3) 0; color: var(--ink); }
.composer .preview-ambig { min-height: var(--tap-min); padding: var(--space-3) 0; }
.composer [class^='token-'] { color: var(--accent-text); text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 4px; }
.composer .token-rec { color: var(--recurring); }
.composer .token-tag, .composer .token-mention { color: var(--tag); }
.composer .token-counter { color: var(--soon); }
.composer .token-alarm, .composer .token-urgent { color: var(--today); }
.composer .token-when--literal { color: var(--ink); text-decoration: none; }
.composer .token-ghost { color: var(--ink-muted); text-decoration: none; }
.composer-sheet-context { display: block; font: var(--type-meta); color: var(--ink-secondary); }
.composer .dock { flex: none; max-height: none; overflow: visible; }
.composer .dock .sheet { --scroll-bg: var(--field); border-top: 0; }
.composer .dock .sheet-head { background: var(--field); border-bottom: 0; }
body:has(.tut-coach) .composer--full { padding-bottom: calc(var(--tut-coach-h, 0px) + var(--space-4)); }
.first-task { display: flex; flex-direction: column; gap: var(--space-5); padding: var(--space-8) 0; font: var(--type-body); }
.first-task h2 { font: var(--type-heading); }
.first-task button { width: 100%; min-height: var(--tap-min); padding: var(--space-3); border-radius: 0; font: var(--type-control); }
.first-task__create { background: var(--accent-bg); color: var(--accent-ink); }
.input-meta,.input-meta__acts,.composer-actions,.composer-shift-row { display: flex; align-items: center; flex-wrap: wrap; }
.input-meta { justify-content: space-between; color: var(--dim); }
.composer-actions > * { flex: 1; }
/* "When this repeats": label over a segmented control, both on the group edge. */
.composer .composer-shift { margin-top: var(--space-4); }
.composer-shift__label, .edit-subtasks__label, .preview-tapered-head .label { padding-bottom: var(--space-2); font: 700 0.765rem/1.059rem var(--font); color: var(--upcoming); }
.composer-shift-row { flex-wrap: nowrap; gap: 2px; padding: 2px; background: var(--surface); border-radius: 0; }
.composer-shift-btn { flex: 1; justify-content: center; text-align: center; min-height: var(--tap-min); border-radius: 0; color: var(--ink-secondary); }
.composer-shift-btn.is-on { background: var(--accent-bg); color: var(--accent-ink); font-weight: 600; }
/* On a sheet the track would match the sheet itself; sink it like .snooze-unit-seg. */
:is(.sheet, .recur-card) .composer-shift-row { background: var(--field); }
.composer-desc__toggle { display: flex; align-items: center; gap: 1ch; width: 100%; }
.composer-desc:not(.is-open) .nli-notes, .composer-desc:not(.is-open) .hair { display: none; }
.composer-desc .nli-notes { border: 0; border-top: var(--seam); padding: var(--space-2) var(--space-3); }
.composer .composer-desc > .hair { display: none; }
.composer-mention-err:empty { display: none; }
.input-section > .cap-type.label,.input-section > .hair { display: none; }

.pv { display: flex; flex-wrap: wrap; gap: var(--space-2); padding: 12px 0 0; }
.row-pv { padding: 4px; border-bottom: var(--seam); }
.row-pv > * { display: inline; margin-right: 1ch; }
.row-pv__k { color: var(--dim); }
.row-pv__t { color: var(--text); }
.row-pv__when { color: var(--today); }
/* Parser-highlight date/time tokens follow the fixed accent (Task 6, Things
   UI cleanup, 2026-09-23) — was --today (Gruvbox amber), which read as an
   off-brand warm colour against the blue accent used everywhere else.
   --accent-line, not raw --accent, per the accent-as-text convention. */
.token-when { color: var(--accent-text); }
.token-tag,.token-counter { color: var(--tag); }

.token-ghost { color: var(--dim); }
.preview-warn,.preview-ambig { padding: 4px; border-bottom: var(--seam); }
.preview-ambig { cursor: pointer; color: var(--today); }
.edit-add-sub:not([data-expanded='1']) .edit-add-sub-input,.edit-add-sub[data-expanded='1'] .composer-add-sub { display: none; }
.composer .edit-subtasks { font: var(--type-control); }
.edit-subtasks__row { font: var(--type-body); }
.edit-subtasks__label { padding: var(--space-2) var(--space-3) 0; }
.edit-image-row { display: flex; align-items: center; flex-wrap: wrap; gap: 4px; }
.edit-image-row img { max-width: 80px; max-height: 80px; object-fit: contain; }
/* Attached image: one grouped row — thumbnail, label, Replace (blue) and Remove (red). */
.composer .edit-image-row { gap: 12px; margin-top: var(--space-3); padding: var(--space-2) var(--space-3); background: var(--surface); border-radius: 0; font: var(--type-control); }
.edit-image-row__preview { order: -1; width: 64px; height: 64px; border-radius: 0; background: var(--field); object-fit: cover; }
.edit-image-row__label { flex: 1; min-width: 0; }
.edit-image-row__actions { display: flex; gap: var(--space-3); }
.edit-image-row__btn { padding: 0; color: var(--accent-text); }
.edit-image-row__btn + .edit-image-row__btn { color: var(--overdue); }
.edit-subtasks__row { display: flex; align-items: center; gap: 4px; min-height: 44px; }
.warn-expanded { display: none; }
.warn-section.is-expanded .warn-expanded { display: flex; flex-wrap: wrap; }
.warn-chip,.warn-toggle { min-height: 44px; }
/* Warnings, expanded: a field textarea, a blue Add text button, the active
   warnings as removable pills. */
.composer .warn-section.is-expanded .warn-expanded { gap: var(--space-2); align-items: center; }
.composer .warn-input { flex: 1 1 100%; min-height: 64px; padding: 10px 12px; border: 0; border-radius: 0; background: var(--field); color: var(--ink); font: 500 0.882rem/1.176rem var(--font); resize: none; }
.composer .warn-input--err { box-shadow: inset 0 0 0 1px var(--overdue); }
.composer .warn-add-confirm { min-height: var(--tap-min); padding: 0 var(--space-2); color: var(--accent-text); font: 500 0.882rem/1.176rem var(--font); }
.composer .warn-chips { display: flex; flex-wrap: wrap; gap: var(--space-2); padding: 0 var(--space-3) var(--space-3); }
.composer .warn-chip { display: inline-flex; align-items: center; gap: 6px; min-height: 36px; padding: 0 12px; border: 0; border-radius: 0; background: var(--surface-pressed); color: var(--ink); font: 500 0.882rem/1.176rem var(--font); }
.warn-chip__glyph { color: var(--today); }
.warn-chip__x { color: var(--ink-muted); }
/* Sub-task list and the child's Parent block: grouped rows like every composer group. */
.composer .edit-subtasks > * + *, .edit-subtasks__list > * + * { border-top: var(--seam); }
.edit-subtasks__row { gap: 12px; width: 100%; padding: 0 var(--space-3); text-align: left; }
.edit-subtasks__check { flex: none; color: var(--ink-muted); white-space: pre; }
.edit-subtasks__title { flex: 1; min-width: 0; overflow-wrap: anywhere; }
.edit-subtasks__row--done .edit-subtasks__check { color: var(--logbook); }
.edit-subtasks__row--done .edit-subtasks__title { color: var(--ink-muted); text-decoration: line-through; }
.composer .edit-parent-block { display: flex; flex-direction: column; font: var(--type-control); margin-top: var(--space-3); background: var(--surface); border-radius: 0; }
.edit-parent-row { display: flex; align-items: center; gap: 12px; min-height: var(--tap-min); padding: 0 var(--space-3); }
.edit-parent-row__label { flex: none; color: var(--ink-secondary); }
.edit-parent-row__title { flex: 1; min-width: 0; text-align: right; overflow-wrap: anywhere; }
.edit-detach-btn { min-height: var(--tap-min); padding: 0 var(--space-3); border-top: var(--seam); color: var(--accent-text); text-align: left; }
/* Tapered preview: one grouped card, a phase per row, meta joined by middots. */
.composer .preview-tapered { margin-top: var(--space-3); background: var(--surface); border-radius: 0; }
.preview-tapered-head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-2); padding: var(--space-2) var(--space-3) 0; color: var(--ink-secondary); font: 500 0.765rem/1.059rem var(--font); }
.preview-tapered-row { padding: 10px var(--space-3); box-shadow: inset 2px 0 0 var(--recurring); }
.preview-tapered-when { color: var(--accent-text); }
.preview-tapered-recur { color: var(--recurring); }
.preview-tapered-row + .preview-tapered-row { border-top: var(--seam); }
.preview-tapered-meta,.preview-tapered-tags { color: var(--ink-secondary); font: 500 0.882rem/1.176rem var(--font); }
.preview-tapered-tags { color: var(--tag); }
.preview-tapered-meta > * + *::before { content: ' · '; }
/* Shared to-dos: soft-delete and edit-proposal cards stack under the row, aligned with its title. */
.proposal-cards { display: flex; flex-direction: column; gap: var(--space-2); }
.soft-delete-card,.proposal-card { margin: 0 0 var(--space-2) 52px; padding: var(--space-2) var(--space-3); background: var(--surface); border-radius: 0; color: var(--ink-secondary); font: 500 0.824rem/1.176rem var(--font); }
.proposal-cards > .proposal-card { margin-bottom: 0; }
.row-stack > .proposal-cards { margin-bottom: var(--space-2); }
.soft-delete-card__lbl,.proposal-card__head { color: var(--ink-secondary); }
.soft-delete-card__actions,.proposal-card__actions { display: flex; gap: var(--space-4); }
.soft-delete-card__btn,.proposal-card__btn { min-height: var(--tap-min); padding: 0; color: var(--accent-text); font: 500 0.882rem/1.176rem var(--font); }
.soft-delete-card__btn--dismiss { color: var(--overdue); }
.proposal-card__btn--approve { font-weight: 600; }
.proposal-card__row { display: flex; flex-wrap: wrap; align-items: baseline; column-gap: 6px; padding: 4px 0; }
.proposal-card__field { flex-basis: 100%; color: var(--ink-secondary); font: 500 0.765rem/1.059rem var(--font); }
.proposal-card__old { color: var(--ink-muted); text-decoration: line-through; }
.proposal-card__arrow { color: var(--ink-muted); }
.proposal-card__new { color: var(--ink); }
/* Overlays. A bottom sheet rises from the home edge on the raised surface (rounded, grabber — see the
   Task 12 block at the end); a centred dialog owns its own four edges; the scrim is --backdrop-tint. */
.modal-shell,.sheet-overlay,.recur-overlay { position: fixed; inset: 0; z-index: var(--z-sheet); display: flex; align-items: flex-end; justify-content: center; padding: 0; }
.modal-shell--center { align-items: center; padding: var(--space-5); }

.sheet-backdrop { position: absolute; inset: 0; background: var(--backdrop-tint); }
.sheet,.recur-card { position: relative; width: 100%; max-width: var(--app-max); max-height: calc(100dvh - max(47px, env(safe-area-inset-top, 0px))); overflow-y: auto; background: var(--surface); border: 0; border-top: 1px solid var(--rule); padding: var(--space-5) var(--space-5) calc(var(--space-5) + var(--home-pad)); }

.modal-shell--center .sheet,.modal-shell--center .recur-card { border: 1px solid var(--rule); padding: var(--space-5); max-height: calc(100dvh - 2 * var(--space-5)); }
/* Sheets rise on the sheet spring (zeta 0.75, 0.3 s); the scrim fades in with them. Reduced motion is handled by the global rule below. */
.modal-shell:not(.dock) .sheet,.modal-shell:not(.dock) .recur-card { animation: sheetUp calc(300ms * var(--motion-scale)) var(--spring-sheet); }
/* The scrim fades in under the rising sheet (iOS). */
.modal-shell:not(.dock) > .sheet-backdrop { animation: scrim-in calc(300ms * var(--motion-scale)) var(--spring-sheet); }
@keyframes scrim-in { from { opacity: 0; } }

.modal-shell--center .sheet,.modal-shell--center .recur-card { animation-name: dialogIn; }
@keyframes dialogIn { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: translateY(0); } }
/* A .recur-overlay sheet carries no backdrop child (its shell handles the outside tap), so the
   shell itself paints the scrim. Takeovers and docked panes never paint one. */
.modal-shell:not(.dock):not(.takeover):not(:has(> .sheet-backdrop)) { background: var(--backdrop-tint); }

/* R37 stacking rule: overlay shells STACK, but only ONE scrim paints. app.js mounts every body-level shell
   in a fixed order, so the first painting shell in DOM order keeps its scrim and every later sibling shell
   (and its backdrop child) goes transparent. Two #19191DCC scrims would otherwise compound to ~96 %.
   Docked panes (WHEN, RESCHEDULE, SNOOZE, composer) REPLACE each other inside #app and paint no scrim. */
.modal-shell:not(.dock):not(.takeover):not(.sheet--leaving) ~ .modal-shell:not(.dock):not(.takeover),.modal-shell:not(.dock):not(.takeover):not(.sheet--leaving) ~ .modal-shell:not(.dock):not(.takeover) > .sheet-backdrop { background: transparent; }
.dock { position: relative; inset: auto; order: 1; flex: 0 1 auto; max-height: 55dvh; padding: 0; overflow-y: auto; display: block; }
.dock .sheet-backdrop { display: none; }
/* A docked pane sits in the app column (already 20px gutters). */
.dock .sheet { max-width: none; max-height: none; padding: var(--space-5) 0; animation: none; }
.sheet-head { position: sticky; top: 0; background: var(--surface); z-index: 1; display: flex; align-items: flex-start; gap: var(--space-2); }
.sheet-head .gstrip__txt { flex: 1; min-width: 0; }
.sheet-title { display: block; font: 400 1.059rem/1.471rem var(--font); overflow-wrap: anywhere; }
.sheet-eyebrow { display: block; font: 700 var(--fs-chrome)/16px var(--font); color: var(--ink-secondary); }
.sheet-close,.auth-close { flex: none; width: var(--tap-min); height: var(--tap-min); min-width: var(--tap-min); display: grid; place-items: center; padding: 0; font: 400 1.412rem/1.412rem var(--font); }

/* Commit controls: the one accent on the sheet (R20/R22). */
.rs-save,.tut-finish-ok,.rt-btn--primary { width: 100%; min-height: var(--tap-min); margin-top: var(--space-4); background: var(--accent); color: var(--accent-ink); border: 0; text-align: center; font: 600 0.882rem/1.176rem var(--font); border-radius: 0; }
.rt-btn--primary { width: auto; margin-top: 0; padding: 0 var(--space-5); }
/* Every action on an overlay is at least 44x44 (the unit steppers, the strip close, SAVE/CANCEL). */
.modal-shell button,.recur-card button,.recur-skip-card button,.tut-coach button,.tut-finish-overlay button,.edit-image-fullscreen button,.toast button { min-width: var(--tap-min); min-height: var(--tap-min); }
/* Sheet body text; small grey section labels. */
.sheet,.recur-card,.recur-skip-card,.tut-coach,.tut-finish-overlay { font: var(--type-control); }
.sheet .gstrip:not(.sheet-head),.recur-card .gstrip { font: 700 0.765rem/1.059rem var(--font); color: var(--upcoming); padding: 0; border: 0; min-height: 0; }
.sheet input,.sheet textarea,.recur-card input,.recur-card textarea { border: 1px solid var(--control-edge); background: var(--field); }
/* A disabled commit is not accent: the accent is spent only when the tap will do something (R22). */
.rs-save:disabled,.tut-finish-ok:disabled,.rt-btn--primary:disabled { background: var(--surface-pressed); color: var(--ink-muted); }


/* Things row sheets (repeat-late Stay/Shift, skipped slots, counter attach, window notice):
   the weekly-archive grammar — head with title + secondary line, inset groups on --field,
   rows title-left / value-right with a secondary line, text buttons and one filled pill. */
.sheet-head__txt { flex: 1; min-width: 0; }
.sheet-sub { margin-top: 2px; color: var(--ink-secondary); font: 500 0.882rem/1.176rem var(--font); overflow-wrap: anywhere; }
.sheet--rows .settings-group { margin-top: var(--space-4); background: var(--field); }
.sheet--rows .wr-section + .settings-group { margin-top: var(--space-2); }
.sheet--rows .settings-note { margin-top: var(--space-2); }
.settings-row__sub { display: block; margin-top: 2px; color: var(--ink-secondary); font: 500 0.765rem/1.059rem var(--font); }
.sheet-actions { display: flex; align-items: center; gap: var(--space-2); margin-top: var(--space-5); }
.sheet-actions > .rt-btn--primary { margin-left: auto; }
/* Counter fields: label left, iOS stepper / segmented control right (8px radius, fill only). */
.cz-frow { flex-wrap: wrap; }
.cz-stepper,.cz-seg { flex: none; display: flex; align-items: center; gap: 2px; padding: 2px; background: var(--surface-pressed); border: 1px solid var(--control-edge); border-radius: 0; }
.cz-step-btn,.cz-step-val,.sheet .cz-step-input { min-height: 44px; min-width: 44px; display: grid; place-items: center; padding: 0; border: 0; border-radius: 0; background: transparent; color: var(--ink); font: 500 0.882rem/1.176rem var(--font); text-align: center; font-variant-numeric: tabular-nums; }
.cz-step-btn { font-size: 22px; }
.sheet .cz-stepper .cz-step-input { width: 5ch; padding: 0; background: transparent; }
.cz-seg-btn { min-height: 44px; padding: 0 var(--space-3); border: 0; border-radius: 0; background: transparent; color: var(--ink-secondary); font: 500 0.882rem/1.176rem var(--font); }
.cz-seg-btn.on { background: var(--accent-bg); color: var(--accent-ink); font-weight: 600; }
.cz-step-ask { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: var(--space-2); }

.tutorial-overlay,.edit-image-fullscreen,.e2ee-gate-overlay,.takeover { position: fixed; inset: max(8px, env(safe-area-inset-top, 0px)) max(8px, calc((100vw - var(--app-max))/2)) max(8px, env(safe-area-inset-bottom, 0px)); z-index: var(--z-modal); display: flex; flex-direction: column; background: var(--field); border: var(--seam); overflow-y: auto; }

/* Calendar agenda row: title left, time (↻ when it repeats) right, 44px like every list row. */
.expand-inner button.tag-chip { display: inline-flex; min-width: var(--tap-min); min-height: var(--tap-min); align-items: center; padding: 4px 8px; }
/* Sits above the dock (prompt box + tabs) so Undo is never covered. */
.toast { position: fixed; bottom: calc(max(26px, env(safe-area-inset-bottom, 0px)) + 118px); left: var(--space-5); right: var(--space-5); margin: auto; max-width: var(--content-max); z-index: var(--z-toast); display: flex; align-items: center; gap: var(--space-2); border: 0; border-radius: 0; padding: 0 var(--space-1) 0 var(--space-4); min-height: var(--tap-min); background: var(--surface); box-shadow: inset 3px 0 0 var(--accent), var(--shadow-pop), var(--edge-light); font: 500 calc(var(--fs-chrome) + 2px)/18px var(--font); }
/* Clears the raised + (64pt above the bar's bottom padding) by 8pt. Taps pass through but the button. */
.toast { pointer-events: none; transition: opacity calc(300ms * var(--motion-scale)) var(--spring-chrome), transform calc(300ms * var(--motion-scale)) var(--spring-chrome); animation: toast-in calc(300ms * var(--motion-scale)) var(--spring-chrome) backwards; }
.toast--still { animation: none; }
.toast.fade { opacity: 0; transform: translateY(8px); }
@keyframes toast-in { from { opacity: 0; transform: translateY(14px); } }
/* The peach line shrinks over the undo window (autoDismiss 5000 in toast.js). */
.toast:has(.toast__undo)::after { content: ''; position: absolute; left: 0; right: 0; bottom: 0; height: 0; border-top: 1px solid var(--accent); transform-origin: left; animation: toast-run 5000ms linear forwards; }
.toast--still:has(.toast__undo)::after { animation: toast-run 5000ms linear forwards; }
@keyframes toast-run { to { transform: scaleX(0); } }
.toast button { pointer-events: auto; }
.toast__msg { flex: 1; padding: var(--space-2) 0; color: var(--ink); }
.toast button { color: var(--accent-text); font-weight: 700; min-width: var(--tap-min); min-height: var(--tap-min); padding: 0 var(--space-3); align-self: stretch; }

.edit-image-fullscreen { position: fixed; inset: 0; z-index: var(--z-img-full); background: var(--field); display: flex; flex-direction: column; padding: env(safe-area-inset-top, 0px) 0 var(--home-pad); }
.edit-image-fullscreen__frame { flex: 1; min-height: 0; display: grid; place-items: center; padding: 0; overflow: hidden; }
.edit-image-fullscreen img { object-fit: contain; max-width: 100%; max-height: 100%; }
.edit-image-fullscreen button { color: var(--accent-text); }
@media (prefers-reduced-motion: no-preference) { .edit-image-fullscreen { animation: oc-fade calc(200ms * var(--motion-scale)) ease backwards; } }
@keyframes oc-fade { from { opacity: 0; } }
.tap-pulse { animation: oc-tap calc(200ms * var(--motion-scale)) ease; }
@keyframes oc-tap { from { background-color: color-mix(in srgb, var(--accent) 22%, transparent); box-shadow: inset 3px 0 0 var(--accent); } }

@media (prefers-reduced-motion: reduce) { *,*::before,*::after { animation: none !important; transition: none !important; } }
.task-state--skipped { font-weight: 700; color: var(--overdue); }
/* The SELECTED pane: no pane title, no index, keys as quiet legend (see PHASE4-REPORT trace). */
.rowd__content .row-tag { font-size: var(--fs-row-detail); }
.cwn-ok { width: 100%; min-height: 50px; margin-top: var(--space-5); border: 0; border-radius: 0; color: var(--accent-ink); background: var(--accent); font: 600 0.882rem/1.176rem var(--font); text-align: center; }
.conn-overlay,.tut-finish-overlay { position: fixed; inset: 0 max(0px,calc((100vw - var(--app-max))/2)); z-index: var(--z-modal); background: var(--field); border: 0; display: flex; flex-direction: column; overflow-y: auto; padding: env(safe-area-inset-top, 0px) var(--space-5) var(--home-pad); }
.conn-body,.tut-scroll { flex: 1; min-height: 0; overflow-y: auto; padding: 0; }


.tut-finish-overlay { inset: auto 0 0; max-height: 65dvh; background: var(--surface); border-top: 1px solid var(--control-edge); padding: var(--space-5) var(--space-5) calc(var(--space-5) + var(--home-pad)); animation: sheetUp calc(300ms * var(--motion-scale)) var(--spring-sheet); }


.pin-keypad { display: grid; grid-template-columns: repeat(3,minmax(0,1fr)); }
.pin-key { display: grid; place-items: center; text-align: center; }
.e2ee-gate-card:has(.pin-keypad) { margin-top: auto; flex-shrink: 0; }
/* E2EE gate: every phase is one centred opencode lock screen (kn logo mark, bold title, one muted line,
   prompt-box fields, one peach primary, peach text buttons). Keypad phases add .pin-unlock: square keys,
   square ledger cells, and no card entrance replay on every digit. */
.e2ee-gate-overlay > .e2ee-gate-card { flex: 1; display: flex; flex-direction: column; text-align: center; }
.e2ee-gate-card > * + * { margin-top: var(--space-3); }
.pin-brand { display: flex; align-items: center; justify-content: center; gap: 10px; color: var(--ink); font: 700 1.176rem/1 var(--font); }
.e2ee-gate-card > .pin-brand { margin-top: 76px; }
.pin-brand__name { white-space: nowrap; }
.pin-brand__tile { flex: none; width: 34px; height: 34px; display: grid; place-items: center; background: var(--accent-bg); color: var(--accent-ink); font: 700 0.882rem/1 var(--font); letter-spacing: -.5px; }
.gate-scan { display: inline-flex; gap: 3px; justify-content: center; align-items: center; height: 30px; }
.gate-scan i { width: 6px; height: 8px; background: var(--accent-bg); opacity: .5; animation: gateWave calc(1050ms * var(--motion-scale)) ease-in-out infinite both; }
.gate-scan i:nth-child(2) { animation-delay: calc(90ms * var(--motion-scale)); } .gate-scan i:nth-child(3) { animation-delay: calc(180ms * var(--motion-scale)); } .gate-scan i:nth-child(4) { animation-delay: calc(270ms * var(--motion-scale)); }
.gate-scan i:nth-child(5) { animation-delay: calc(360ms * var(--motion-scale)); } .gate-scan i:nth-child(6) { animation-delay: calc(450ms * var(--motion-scale)); } .gate-scan i:nth-child(7) { animation-delay: calc(540ms * var(--motion-scale)); }
@keyframes gateWave { 0%, 100% { height: 8px; opacity: .5; } 35% { height: 30px; opacity: 1; } }
/* First-run motion (mockup U10b M14 to M17). Reduced motion: still stepped bars, no loop. */
.gate-scan i:nth-child(1), .gate-scan i:nth-child(7) { --still: 6px; } .gate-scan i:nth-child(2), .gate-scan i:nth-child(6) { --still: 11px; }
.gate-scan i:nth-child(3), .gate-scan i:nth-child(5) { --still: 16px; } .gate-scan i:nth-child(4) { --still: 21px; }
@media (prefers-reduced-motion: reduce) { .gate-scan i { animation: none; height: var(--still); opacity: .6; } }
.pin-brand--fresh .pin-brand__tile { animation: frTile calc(300ms * var(--motion-scale)) var(--spring-pop) calc(550ms * var(--motion-scale)) both; }
@keyframes frTile { from { opacity: 0; transform: scale(.3); } to { opacity: 1; transform: none; } }
.fr-rise > .gstrip, .fr-rise .signin-modal-card > :not(.pin-brand) { animation: frRise calc(340ms * var(--motion-scale)) var(--spring-list) calc(var(--i, 0) * 65ms * var(--motion-scale)) both; }
.fr-rise .signin-modal-card > :nth-child(3) { --i: 1; } .fr-rise .signin-modal-card > :nth-child(4) { --i: 2; } .fr-rise .signin-modal-card > :nth-child(5) { --i: 3; }
.fr-rise .signin-modal-card > :nth-child(6) { --i: 4; } .fr-rise .signin-modal-card > :nth-child(7) { --i: 5; } .fr-rise .signin-modal-card > :nth-child(8) { --i: 6; }
@keyframes frRise { from { opacity: 0; transform: translateY(16px); } to { opacity: 1; transform: none; } }
.signin-btn--sweep { position: relative; overflow: hidden; }
.signin-btn--sweep::after { content: ''; position: absolute; top: 0; bottom: 0; left: 0; width: 40%; background: linear-gradient(100deg, transparent, color-mix(in srgb, var(--ink) 45%, transparent), transparent); animation: frSweep calc(700ms * var(--motion-scale)) var(--spring-list) calc(900ms * var(--motion-scale)) both; pointer-events: none; }
@keyframes frSweep { from { transform: translateX(-100%); } to { transform: translateX(260%); } }
@media (prefers-reduced-motion: reduce) { .pin-brand--fresh .pin-brand__tile, .fr-rise > .gstrip, .fr-rise .signin-modal-card > :not(.pin-brand), .signin-btn--sweep::after { animation: none; } }
.e2ee-gate-card > .signin-title { margin-top: 22px; font: 700 1.294rem/1.647rem var(--font); }
.e2ee-gate-card > .signin-title + .signin-sub { margin-top: 6px; }
.e2ee-gate-card > .signin-sub + :is(.signin-fields, .signin-btn--primary, .e2ee-reccode) { margin-top: var(--space-6); }
.pin-unlock .e2ee-gate-card { border: 0; margin-top: 0; flex: 1; display: flex; flex-direction: column; align-items: center; text-align: center; animation: none !important; }
.pin-unlock .e2ee-gate-card > .pin-ledger { margin-top: 30px; }
.pin-unlock .pin-ledger__slots { display: flex; gap: 20px; }
.pin-unlock .pin-slot { width: 22px; height: 22px; border: 1px solid var(--control-edge); border-radius: 0; }
.pin-unlock .pin-slot--cur { border-color: var(--accent); }
.pin-unlock .pin-slot--on { border-color: var(--accent-bg); background: var(--accent-bg); animation: gatePop calc(120ms * var(--motion-scale)) var(--spring-pop); }
@keyframes gatePop { from { transform: scale(.6); } to { transform: scale(1); } }
/* Lock motion (pin-motion.js): digit ripple, wrong-code shake + drain + grey message, and the unlock clone. */
.pin-unlock .pin-slot { position: relative; }
.pin-ring { position: absolute; inset: -1px; border: 1px solid var(--accent); pointer-events: none; }
.pin-msg { color: var(--ink-secondary); font: 500 0.882rem/1.176rem var(--font); }
@keyframes pin-shake { 15% { transform: translateX(-12px); } 30% { transform: translateX(12px); } 50% { transform: translateX(-9px); } 70% { transform: translateX(9px); } 85% { transform: translateX(-4px); } }
@keyframes pin-drain { from { background: var(--accent-bg); border-color: var(--accent-bg); } }
.pin-wrong .pin-ledger__slots { animation: pin-shake calc(340ms * var(--motion-scale)) ease-out; }
.pin-wrong .pin-slot { animation: pin-drain calc(120ms * var(--motion-scale)) backwards; }
.pin-wrong .pin-slot:nth-child(4) { animation-delay: calc(340ms * var(--motion-scale)); }
.pin-wrong .pin-slot:nth-child(3) { animation-delay: calc(410ms * var(--motion-scale)); }
.pin-wrong .pin-slot:nth-child(2) { animation-delay: calc(480ms * var(--motion-scale)); }
.pin-wrong .pin-slot:nth-child(1) { animation-delay: calc(550ms * var(--motion-scale)); }
.pin-ghost { pointer-events: none; }
/* Decoding text (done-animation.js decodeText): the real text stays in the DOM, read aloud and found by tests; the noise is painted from data-d. */
.dcd-vis::before { content: attr(data-d); content: attr(data-d) / ""; }
.dcd-real { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
.pin-unlock .e2ee-gate-card > .pin-keypad { width: 258px; grid-template-columns: repeat(3, 72px); justify-content: space-between; row-gap: 10px; margin-top: 40px; }
.pin-unlock .pin-key { width: 62px; height: 62px; min-height: 62px; margin: auto; border: 0; border-radius: 0; font: 400 1.353rem/1 var(--font); color: var(--ink); }
.pin-unlock button.pin-key { background: var(--surface-pressed); }
.pin-unlock button.pin-key:active { background: var(--accent-bg); color: var(--accent-ink); }
.pin-unlock .pin-key--del { font-size: 20px; color: var(--ink-secondary); }
.pin-unlock button.pin-key--del { background: transparent; }
.pin-unlock .e2ee-gate-card > .pin-foot { margin-top: auto; padding-top: var(--space-4); display: flex; flex-direction: column; align-items: center; }
.pin-unlock .pin-foot .signin-btn-link:last-child { color: var(--ink-secondary); }
/* Sign in and the E2EE gate share their form parts. */
.signin-sub { color: var(--ink-secondary); font: 500 0.882rem/1.176rem var(--font); }
.signin-fields { display: flex; flex-direction: column; gap: var(--space-2); border-radius: 0; }
.recur-card .signin-fields > .acc-input { min-height: 44px; margin: 0; padding: 11px var(--space-4); border: 0; border-left: 3px solid var(--accent-bg); border-radius: 0; background: var(--surface-pressed); caret-color: var(--accent); color: var(--ink); font: 500 0.882rem/1.294rem var(--font); text-align: left; }
.recur-card .signin-btn--primary { display: block; width: 100%; min-height: 50px; padding: 0 var(--space-4); border: 0; border-radius: 0; background: var(--accent); color: var(--accent-ink); font: 700 0.882rem/1.294rem var(--font); text-align: center; }
.recur-card .signin-btn--primary:disabled { background: var(--surface-pressed); color: var(--ink-muted); }
.recur-card .signin-btn-link { display: block; width: 100%; min-height: 44px; padding: 0 var(--space-2); color: var(--accent-text); font: 500 0.882rem/1.294rem var(--font); text-align: center; }
.recur-card .signin-btn-link--dim { color: var(--ink-secondary); }
.signin-err { color: var(--overdue); font: 500 0.882rem/1.176rem var(--font); }
.signin-warn { padding: var(--space-3) var(--space-4); border-radius: 0; background: var(--surface-pressed); text-align: left; }
.signin-warn__head { color: var(--ink); font: 600 0.882rem/1.176rem var(--font); }
.signin-warn--hard .signin-warn__head { color: var(--overdue); }
.signin-warn__body { margin-top: 2px; color: var(--ink-secondary); font: 500 0.882rem/1.176rem var(--font); }
.e2ee-reccode { padding: var(--space-4); border-radius: 0; background: var(--surface-pressed); color: var(--ink); font: 600 1.059rem/1.647rem var(--font); letter-spacing: 1px; word-spacing: .6em; text-align: left; font-variant-numeric: tabular-nums; -webkit-user-select: all; user-select: all; -webkit-touch-callout: default; overflow-wrap: anywhere; }
.e2ee-reccode-actions { display: flex; justify-content: center; gap: var(--space-4); }
.recur-card .e2ee-reccode-actions .signin-btn-link { width: auto; }
.e2ee-ack { display: flex; align-items: center; gap: var(--space-3); min-height: 44px; padding: 10px var(--space-4); border-radius: 0; background: var(--surface-pressed); color: var(--ink); font: 500 0.882rem/1.176rem var(--font); text-align: left; }
.recur-card .e2ee-ack input[type=checkbox] { flex: none; appearance: none; -webkit-appearance: none; display: grid; place-items: center; width: 22px; height: 22px; min-height: 0; margin: 0; padding: 0; border: 1px solid var(--control-edge); background: transparent; }
.recur-card .e2ee-ack input[type=checkbox]:checked { background: var(--accent-bg); border-color: var(--accent-bg); }
.recur-card .e2ee-ack input[type=checkbox]:checked::after { content: '✓'; color: var(--accent-ink); font: 700 0.882rem/1 var(--font); }
.takeover { justify-content: flex-start; align-items: stretch; padding: 4px; }
.takeover .recur-card,.takeover .sheet { max-width: none; max-height: none; }
.takeover .sheet-backdrop { display: none; }
@media (hover: hover) { .task-link:hover { text-decoration: underline; } }

@keyframes sheetUp { from { transform: translateY(100%); } to { transform: translateY(0); } }
/* Things/iOS push between screens (app.js _slideViews): the old view slides under or out. */
.view--leaving { position: fixed; inset: 0; z-index: 0; pointer-events: none; background: var(--field); }
.view--above { position: relative; z-index: 1; background: var(--field); box-shadow: -1px 0 0 var(--rule); }
/* The sliding screen spans the app's side gutters too, so the screen under it never shows at its edge; its content stays put. */
.view--above:not(.view--leaving) { margin-inline: calc(-1 * var(--space-5)); padding-inline: var(--space-5); }
.view--leaving.view--above { position: fixed; z-index: 2; }
@keyframes xtn-slideup { 0% { transform: translateY(100%); } 100% { transform: translateY(0); } }
.row .checkbox,.rowd__cb,.rt-checkbox,.edit-image-fullscreen__frame { border-width: 1px; }
/* Notification focus: one soft highlight, no catalog (Things UI cleanup, Task 3).
   No !important: instead, each ambient background rule the row can carry is
   matched directly at higher specificity — the bare row fallback plus the
   named context .view--circles .row-today (line ~906). :not(.expanded) is deliberate: an expanded row's own elevated
   background (line ~202, var(--surface), the lifted-card look) must keep
   winning even while it carries the mark — !important would have flattened
   it for the mark's whole duration. */
[data-focus-fx="soft"]:not(.expanded),
.view--circles [data-focus-fx="soft"]:not(.expanded) { background: var(--surface-pressed); box-shadow: inset 3px 0 0 var(--accent); }
[data-focus-fx="soft"] { transition: background calc(500ms * var(--motion-scale)) var(--spring-default), box-shadow calc(500ms * var(--motion-scale)) var(--spring-default); }
.rowd__name { font-size: var(--fs-rows); }
.subs-list .row.row--sub .title { font-size: var(--fs-rows); }
@media (hover: none) and (pointer: coarse) {
  .input-meta__keys { display: none; }
}
/* Meta is one quiet secondary line (frame .meta): recurrence and snooze read as text beside the time. */
.task-state .rt-snooze { color: inherit; }


@media (prefers-reduced-motion: reduce) { *,*::before,*::after { animation: none !important; transition: none !important; } }

.task-due,.task-tags,.task-state { line-height: 16px; }
.tut-coach { position: fixed; bottom: 0; left: 0; right: 0; max-width: var(--app-max); margin: 0 auto; z-index: var(--z-coach); max-height: 45dvh; overflow-y: auto; background: var(--surface); border: 0; border-top: 1px solid var(--control-edge); padding: var(--space-5) var(--space-5) calc(var(--space-5) + var(--home-pad)); animation: sheetUp calc(300ms * var(--motion-scale)) var(--spring-sheet); }
/* Coach and finish card: square --surface sheets on a --control-edge hairline, peach counter. */
.tut-coach,.tut-finish-overlay { border-radius: 0; }
body:has(.tut-coach) .capture-fab { bottom: calc(var(--tut-coach-h, 0px) + var(--space-4)); }
.tut-coach__head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); margin-top: -12px; }
.tut-coach__step { color: var(--accent-text); font: 500 0.765rem/1.059rem var(--font); }
.tut-coach .tut-coach__skip { margin-right: -8px; padding: 0 8px; color: var(--accent-text); font: 500 0.882rem/1.176rem var(--font); }
.tut-coach__title,.tut-finish-title { color: var(--ink); font: 700 1.059rem/1.529rem var(--font); }
.tut-coach__prompt,.tut-finish-body { margin-top: var(--space-1); color: var(--ink); font: 500 0.882rem/1.176rem var(--font); }
.tut-finish-body > p { margin: 0; color: var(--ink-secondary); }
.tut-coach__hint { margin-top: var(--space-2); color: var(--ink-secondary); font: 500 0.882rem/1.176rem var(--font); }
.tut-coach__ex { padding: 0 4px; background: var(--surface-pressed); color: var(--ink); }
.tut-coach__fill { height: 3px; margin-top: var(--space-3); background: var(--rule); }
.tut-coach__fill i { display: block; height: 100%; background: var(--accent); color: var(--accent-ink); transform-origin: left; transform: scaleX(var(--to)); animation: frFill calc(520ms * var(--motion-scale)) var(--spring-list) both; }
@keyframes frFill { from { transform: scaleX(var(--from)); } }
/* M18: parts of a later step slide in (they are new nodes, keyed by step); a redraw keeps still. */
.tut-coach--slide { animation: frCard calc(340ms * var(--motion-scale)) var(--spring-list) both; }
@keyframes frCard { from { opacity: 0; transform: translateX(28px); } to { opacity: 1; transform: none; } }
.tut-spot { position: fixed; left: 0; top: 0; width: 0; height: 0; z-index: calc(var(--z-coach) - 1); pointer-events: none; opacity: 0; box-shadow: 0 0 0 100vmax color-mix(in srgb, var(--field) 55%, transparent); }
.tut-spot.is-on { opacity: 1; }
.tut-spot.is-gliding { transition: left calc(520ms * var(--motion-scale)) var(--spring-list), top calc(520ms * var(--motion-scale)) var(--spring-list), width calc(520ms * var(--motion-scale)) var(--spring-list), height calc(520ms * var(--motion-scale)) var(--spring-list), opacity calc(200ms * var(--motion-scale)) ease; }
.tut-spot i { position: absolute; width: 14px; height: 14px; animation: frBracket calc(1400ms * var(--motion-scale)) ease-in-out infinite; background: linear-gradient(var(--accent), var(--accent)) var(--x) var(--y) / 100% 2px no-repeat, linear-gradient(var(--accent), var(--accent)) var(--x) var(--y) / 2px 100% no-repeat; }
.tut-spot i:nth-child(1) { left: -3px; top: -3px; --x: 0; --y: 0; --dx: -3px; --dy: -3px; } .tut-spot i:nth-child(2) { right: -3px; top: -3px; --x: 100%; --y: 0; --dx: 3px; --dy: -3px; }
.tut-spot i:nth-child(3) { left: -3px; bottom: -3px; --x: 0; --y: 100%; --dx: -3px; --dy: 3px; } .tut-spot i:nth-child(4) { right: -3px; bottom: -3px; --x: 100%; --y: 100%; --dx: 3px; --dy: 3px; }
@keyframes frBracket { 50% { transform: translate(var(--dx), var(--dy)); opacity: .6; } }
@media (prefers-reduced-motion: reduce) { .tut-coach--slide, .tut-coach__fill i { animation: none; } .tut-spot.is-gliding { transition: none; } .tut-spot i { animation: none; } }
.edit-image-fullscreen .gstrip { padding: 0 var(--space-5); }

.command-preview { padding: 8px 4px; color: var(--today); }

small, sub, sup { font-size: inherit; }

/* Late tasks show a red date only (Things UI cleanup, Task 4): the row keeps
   the normal field background, no decorative pattern. --overdue is the
   existing red token (reused rather than adding a new one). */
.task-due.late-due { color: var(--overdue); }

/* Phase 5: deep surfaces use one reading column; task rows/chrome stay shared. */




.e2ee-gate-overlay,.tutorial-overlay,.signin-modal-overlay { inset: 0 max(0px, calc((100vw - var(--content-max) - 2 * var(--space-5))/2)); border: 0; padding: env(safe-area-inset-top, 0px) var(--space-5) var(--home-pad); }
:is(.conn-overlay,.tutorial-overlay,.signin-modal-overlay) > .gstrip { border: 0; padding: var(--space-4) 0; gap: var(--space-2); font: var(--type-control); }

.e2ee-gate-overlay { inset: 0; padding-inline: max(var(--space-5), env(safe-area-inset-left, 0px), env(safe-area-inset-right, 0px), calc((100% - var(--content-max)) / 2)); }
.conn-overlay { inset-inline: max(0px, calc((100vw - var(--content-max) - 2 * var(--space-5))/2)); }




/* Deep-view forms retain a reading column and room for action labels. */
.signin-modal-overlay > .signin-modal-card,.e2ee-gate-overlay > .e2ee-gate-card { width: 100%; max-height: none; border: 0; padding: 0 0 var(--space-5); background: var(--field); font: var(--type-body); overflow-y: visible; }
.signin-modal-card > * + * { margin-top: var(--space-3); }
.signin-modal-card > .pin-brand { justify-content: flex-start; }
.signin-modal-card > .signin-fields,.signin-modal-card > .signin-warn { margin-top: var(--space-6); }


/* Study B: neutral fill, check, then secondary title; commit owns removal. */
.study-b-check { position: relative; }
/* The box (rows area): the tick pops it green, then a copy is tossed into the done tab
   (done-animation.js) and the box dims. The title decodes (JS swaps the characters, .study-b-hot
   flickers it peach), then dims. No strike line. */
.c-cb > .study-b-check::before { content: '✓'; border-color: var(--logbook); background: var(--logbook); color: var(--logbook-ink); animation: study-b-pop calc(500ms * var(--motion-scale)) var(--spring-delight) both; }
.c-cb > .study-b-tossed::before { opacity: .4; transition: opacity calc(200ms * var(--motion-scale)) ease 90ms; }
.study-b-check > svg { display: none; }
.study-b-title { animation: study-b-title calc(80ms * var(--motion-scale)) var(--spring-chrome) 400ms forwards; }
.study-b-title.study-b-hot { color: var(--accent-text); }
@keyframes study-b-pop { from { transform: scale(.9); } to { transform: scale(1); } }
@keyframes study-b-title { from { color: var(--ink); } to { color: var(--ink-secondary); } }
/* The tossed ✓: fixed above every layer, never hit-tested. The done tab squashes and flashes green on the catch. */
.done-toss { position: fixed; left: 0; top: 0; z-index: var(--z-toast); pointer-events: none; color: var(--logbook); font: 700 0.882rem/1.176rem var(--font); text-shadow: 0 0 8px color-mix(in srgb, var(--logbook) 60%, transparent); will-change: transform; }
.tabbar__tab.done-hit { animation: done-hit calc(500ms * var(--motion-scale)) var(--spring-delight); }
.tabbar__tab.done-hit .tabbar__cnt { animation: done-hit-cnt calc(500ms * var(--motion-scale)) var(--spring-delight); }
@keyframes done-hit-cnt { 0% { color: var(--logbook-ink); } 60% { color: var(--logbook-ink); } 100% { color: var(--ink-muted); } }
@keyframes done-hit { 0% { background: var(--logbook); color: var(--logbook-ink); transform: scale(1.14, .86); } 35% { transform: scale(.96, 1.06); } 100% { transform: none; } }
/* M1: a square ring leaves the box as it ticks (done-animation.js places it over the 18px box). */
.done-ring { position: fixed; z-index: var(--z-toast); width: 18px; height: 18px; box-sizing: border-box; border: 1.5px solid var(--logbook); pointer-events: none; animation: done-ring-grow calc(420ms * var(--motion-scale)) var(--spring-default) both, done-ring-fade calc(420ms * var(--motion-scale)) linear both; }
@keyframes done-ring-grow { from { transform: scale(1); } to { transform: scale(2.8); } }
@keyframes done-ring-fade { 0% { opacity: 1; } 55% { opacity: .8; } 100% { opacity: 0; } }
/* M6: counts roll like an odometer (rollNumber in done-animation.js). Only while rolling is the number a clipped window. */
.is-rolling { display: inline-block; overflow: hidden; height: var(--roll-h, 1.333em); vertical-align: bottom; }
.tabbar__cnt .is-rolling { --roll-h: 1.2em; }
.roll-col { display: flex; flex-direction: column; }
.roll-col > i { font-style: normal; height: var(--roll-h, 1.333em); line-height: var(--roll-h, 1.333em); }
/* M9: the All clear band across the middle of the screen when the last to-do due today is done. */
.all-clear { position: fixed; left: 0; right: 0; top: 50%; height: 64px; margin-top: -32px; display: grid; place-items: center; z-index: var(--z-toast); pointer-events: none; background: var(--logbook); color: var(--logbook-ink); font: 700 1rem/1.25rem var(--font); }
.completion-status { position: fixed; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }

/* ── Things 3 device chrome (pass 7) ────────────────────────────────
   The three spec shots: near-black field, no hairlines or tap boxes on
   dest/list rows, pill Quick Find with a magnifier, Settings text +
   sliders glyph + blue + with chevron in the home band, Today headed by
   a big title-case title under a back/dots bar, and one muted pill
   group heading ("08:00 work") above the day's rows. */

/* Back + dots menu share one bar above the heading (Today shot). */
.topbar-row { position: relative; display: flex; align-items: center; justify-content: space-between; min-height: var(--tap-min); transition: box-shadow calc(200ms * var(--motion-scale)) ease; }
/* Things large title: the heading scrolls away with the list; this small
   centred title (and a hairline) fade into the fixed bar once it has gone. */
.nav-title { position: absolute; left: 56px; right: 56px; top: 0; height: 44px; display: flex; align-items: center; justify-content: center; text-align: center; font: 600 0.882rem/1.2 var(--font); color: var(--ink); overflow-wrap: anywhere; pointer-events: none; opacity: 0; transform: translateY(8px); transition: opacity calc(200ms * var(--motion-scale)) ease, transform calc(300ms * var(--motion-scale)) var(--spring-chrome); }
.topbar--titled .nav-title { opacity: 1; transform: none; }
.topbar--titled .topbar-row { box-shadow: 0 1px 0 var(--rule); }
.topbar--lifted { padding-bottom: 0; }
.list-head { padding-bottom: var(--space-2); }
/* Things tag bar: grey rounded pills under a list title; the active one fills blue. */
.tag-bar { display: flex; flex-wrap: wrap; gap: 0 var(--space-2); margin-left: calc(var(--space-3) * -1); }
.tag-bar__tag { min-height: var(--tap-min); padding: 0 var(--space-3); color: var(--ink-secondary); font: 500 0.765rem/1.176rem var(--font); }
.tag-bar__tag::before { content: '#'; color: var(--tag); }
/* The active tag is a square 32px peach block inside its 44px hit box. */
.tag-bar__tag.on { color: var(--accent-ink); background: linear-gradient(var(--accent-bg), var(--accent-bg)) center / 100% 32px no-repeat; }
.tag-bar__tag.on::before { color: var(--accent-ink); }
@media (prefers-reduced-motion: reduce) { .nav-title, .topbar-row { transition: none; } }
.list-menu { display: grid; place-items: center; width: var(--tap-min); height: var(--tap-min); min-width: var(--tap-min); padding: 0; color: var(--ink-secondary); }
/* No tap rectangles anywhere on the list chrome. */
.list-menu:is(:focus, :focus-visible) { outline: none; }
.topbar-row button:is(:focus, :focus-visible) { outline: none; }

/* Quick Find: pill, muted, magnifier + label, generous top inset. */
.quick-find__ico { display: inline-grid; place-items: center; color: var(--ink-muted); }

/* Dest + personal rows: icon, title-case label, optional count. Comfortable
   height, no boxes, no hairlines. */
/* Muted grey count on the right (Today shows 2). */

/* Bottom dock: Settings (sliders glyph + text, centred-leftish) with the
   blue + sitting in the home-indicator band. */
.device-dock { padding: var(--space-2) 0 var(--space-2) 96px; justify-content: flex-start; }
.settings-link { display: inline-flex; align-items: center; gap: 7px; color: var(--ink-muted); font: 500 0.882rem/1.176rem var(--font); }
.settings-link__ico { display: inline-grid; place-items: center; color: var(--ink-muted); }
.capture-fab { width: 56px; height: 56px; min-width: 56px; min-height: 56px; display: inline-flex; align-items: center; justify-content: center; }

/* Today: big title-case heading, then the muted pill group heading. */
.head-line .h1 { font-size: 22px; line-height: 44px; }
/* Google Calendar event pill: Things 3 style, sits above task rows in Today and Calendar */

/* Rows read quieter than the old TUI: body-sans title, dim meta, no seams. */
.view--circles .row-today, .view--circles .row { background: transparent; }
.list .group-head { text-transform: none; letter-spacing: 0; }
.group-head:has(> .home-head) { align-items: baseline; flex-wrap: nowrap; gap: 6px; padding: var(--space-5) 0 var(--space-2); }
/* Anytime: tappable project / area heading, a plain section label. */
/* Negative margin keeps the 44px tap target without padding the heading. */
.home-head { margin: -11px 0; display: inline-flex; align-items: center; gap: 8px; padding: 0; border: 0; background: none; color: inherit; font: inherit; cursor: pointer; }

/* Open to-do card contents (Things 3). */
.expand-inner > * { margin: 0 16px 0 52px; }
.expand-inner > :last-child { margin-bottom: 10px; }
.expand-inner .notes { font: var(--type-input); color: var(--ink-muted); padding: 2px 0 10px; white-space: pre-wrap; cursor: text; }
.expand-inner .notes--empty { opacity: 0.6; }
.xp-checklist { padding: 2px 0 8px; }
.xp-check { display: flex; align-items: center; gap: 12px; min-height: 36px; border-bottom: 1px solid var(--rule); font: var(--type-meta); color: var(--ink); }
.xp-check:last-child { border-bottom: 0; }
.xp-check__dot { flex: none; }
.xp-check__dot::before { content: ''; box-sizing: border-box; display: grid; place-items: center; width: 14px; height: 14px; border: 1.5px solid var(--ink-muted); font: 700 10px/1 var(--font); color: var(--logbook-ink); }
.xp-check.is-done .xp-check__t { color: var(--ink-muted); }
.xp-check.is-done .xp-check__dot::before { content: '✓'; border-color: var(--logbook); background: var(--logbook); }
.expand-inner .tags { display: flex; flex-wrap: wrap; gap: 6px; padding: 2px 0 8px; }
.expand-inner button.tag-chip { position: relative; z-index: 0; padding: 0 10px; background: transparent; }
.xp-foot { display: flex; align-items: center; justify-content: space-between; gap: 8px; min-height: 36px; }
.xp-when { font: var(--type-meta); color: var(--ink-muted); min-width: 0; overflow-wrap: anywhere; }
.xp-icons { display: flex; gap: 2px; margin-right: -10px; }
.xp-ico { width: var(--tap-min); height: var(--tap-min); display: inline-grid; place-items: center; color: var(--ink-muted); }
.xp-ico:active { background: var(--surface-pressed); }
.expand-inner .xp-step { opacity: 0; transform: translateY(-6px); transition: opacity calc(200ms * var(--motion-scale)) ease, transform calc(200ms * var(--motion-scale)) ease; }
:is(.row, .rowd, .row-today).expanded .xp-step { opacity: 1; transform: none; transition: opacity calc(200ms * var(--motion-scale)) ease, transform calc(300ms * var(--motion-scale)) var(--spring-chrome); }
:is(.row, .rowd, .row-today).expanded .xp-step:nth-child(1) { transition-delay: 60ms; }
:is(.row, .rowd, .row-today).expanded .xp-step:nth-child(2) { transition-delay: 110ms; }
:is(.row, .rowd, .row-today).expanded .xp-step:nth-child(3) { transition-delay: 160ms; }
:is(.row, .rowd, .row-today).expanded .xp-step:nth-child(4) { transition-delay: 210ms; }
.xp-bar { position: fixed; z-index: 45; left: 0; right: 0; bottom: 0; max-width: calc(var(--content-max) + 32px); margin: 0 auto; display: flex; flex-direction: column; gap: 8px; padding: 12px 16px max(16px, env(safe-area-inset-bottom, 0px)); background: var(--surface); color: var(--ink); border-top: 1px solid var(--rule); animation: xp-bar-in calc(300ms * var(--motion-scale)) var(--spring-chrome) 80ms both; }
.xp-bar button { min-width: var(--tap-min); min-height: var(--tap-min); display: inline-flex; align-items: center; justify-content: center; gap: 6px; padding: 0 12px; border-radius: 0; font: 500 0.882rem/1.176rem var(--font); color: inherit; }
.xp-bar__row { display: flex; gap: 6px; }
.xp-bar__row button { flex: 1 1 0; min-width: 0; min-height: 48px; flex-direction: column; gap: 2px; background: var(--surface-pressed); font-size: 0.75rem; }
/* Done is the one primary; Delete is small, red and set apart from the row. */
.xp-bar .xp-bar__done { width: 100%; min-height: 48px; background: var(--accent-bg); color: var(--accent-ink); font-weight: 700; font-size: 0.938rem; gap: 10px; }
.xp-bar .xp-bar__delete { align-self: center; margin-top: 4px; min-height: var(--tap-min); padding: 0 20px; font-size: 0.75rem; color: var(--overdue); }
.xp-bar button:active { background: var(--surface); color: var(--ink); }
.xp-bar button[disabled] { opacity: 0.4; }
.xp-bar.is-leaving { animation: xp-bar-out calc(180ms * var(--motion-scale)) ease forwards; }
@keyframes xp-bar-in { from { opacity: 0; transform: translateY(24px); } to { opacity: 1; transform: none; } }
@keyframes xp-bar-out { to { opacity: 0; transform: translateY(24px); } }
@media (prefers-reduced-motion: reduce) { .expand-block, .expand-inner, .expand-inner .xp-step, :is(.row, .rowd, .row-today), .view :is(.topbar, .group-head, .subs-list), .xp-bar, .toast { transition: none; animation: none; } }
.xp-bar button { white-space: nowrap; }
:is(.row, .rowd, .row-today).expanded .expand-block { background: transparent; }
.expand-inner .notes { font: var(--type-control); font-weight: 400; }
.xp-check { font: var(--type-control); font-weight: 400; }
/* Things: the open card shows the bare title; date moves to the card foot. */
:is(.row, .rowd, .row-today).expanded :is(.row-meta, .c-tail, .row-clock) { opacity: 0; visibility: hidden; }
:is(.row, .rowd, .row-today).expanded .row-meta { display: none; }
/* Pressing the checkbox presses only the checkbox. */
:is(.row, .rowd, .row-today):not(.expanded):active:not(:has(.c-cb:active)) { background: var(--surface-pressed); transition: none; }
.list-row:active { background: var(--surface-pressed); }
.expand-inner .notes:active,.preview-ambig:active { opacity: .4; }
/* Notes + checklist at title size. */
.expand-inner .notes, .xp-check { font: var(--type-task); }
.xp-checklist { border-top: 1px solid var(--rule); }
.xp-check, .xp-check:last-child { border-bottom: 1px solid var(--rule); min-height: 40px; }
.xp-bar button { font-weight: 400; color: var(--ink-muted); }
.view.has-expanded .list { --list-pad-b: 260px; }
:is(.row, .rowd, .row-today).is-collapsing + .subs-list { display: none; }
.xp-check { width: 100%; text-align: left; cursor: pointer; }
.xp-check.is-done .xp-check__t { text-decoration: line-through; }
.expand-inner button.xp-check { display: flex; align-items: center; gap: 12px; min-height: 40px; padding: 0; line-height: 20px; }
.expand-inner .xp-check__dot { display: block; }

/* Things 3 main-screen lists: same icon column as the destination rows. */
.list-group { margin-top: var(--space-5); }
/* Things area page: projects sit straight under the notes. */
.view--list .list-head + .list-group { margin-top: 0; }
.list-row { display: grid; grid-template-columns: var(--tap-min) minmax(0, 1fr) auto; column-gap: var(--space-2); align-items: center; width: 100%; min-height: 44px; padding: 0; border: 0; background: transparent; text-align: left; color: var(--ink); }
.list-row .name { font: 500 0.882rem/1.412rem var(--font); overflow-wrap: anywhere; }
.list-row .count { color: var(--ink-muted); font: 500 0.706rem/1.176rem var(--font); padding-right: 4px; }
.list-row__ico { width: 20px; height: 20px; margin: 0 auto; color: var(--ink-muted); display: inline-grid; place-items: center; }
.list-row__ico--project { color: var(--projects); }
.list-row--area .name { font-weight: 700; }
.view--nodate .device-dock { padding-left: 0; gap: var(--space-2); }
.new-list-link { display: inline-flex; align-items: center; gap: 7px; min-height: 44px; padding: 0 8px; color: var(--ink-muted); font: 500 0.882rem/1.176rem var(--font); background: transparent; }
.new-list-link__plus { font: 400 1.176rem/1 var(--font); }
.nl-chooser { position: fixed; inset: 0; z-index: var(--z-sheet); display: flex; align-items: flex-end; justify-content: center; padding: 0 8px max(8px, env(safe-area-inset-bottom, 0px)); background: var(--scrim); }
.nl-chooser__sheet { width: 100%; max-width: 420px; padding: 8px 0; border-radius: 0; background: var(--surface); }
.nl-chooser__opt { display: grid; grid-template-columns: var(--tap-min) minmax(0, 1fr); column-gap: var(--space-2); align-items: center; width: 100%; min-height: 60px; padding: 0 12px 0 4px; border: 0; background: transparent; text-align: left; color: var(--ink); }
.nl-chooser__opt:active { background: var(--surface-pressed); }
.nl-chooser__text { display: grid; gap: 2px; }
.nl-chooser__title { font: 600 0.882rem/1.176rem var(--font); }
.nl-chooser__sub { font: 500 0.765rem/1.059rem var(--font); color: var(--ink-muted); }

.move-overlay { position: fixed; inset: 0; z-index: var(--z-sheet); background: var(--scrim); display: flex; align-items: flex-end; justify-content: center; }

.list-row--nested { padding-left: var(--space-5); }

/* Project / area screen (viewList): `# Name` heading like every other screen. */
/* A long project or area name wraps beside its icon instead of running off the edge. */
.view--list .head-line .h1 { flex: 0 1 auto; min-width: 0; max-width: 100%; overflow-wrap: anywhere; }
.list-notes { display: block; width: 100%; resize: none; border: 0; background: transparent; font: var(--type-control); color: var(--ink-muted); padding: 4px 0 12px 2ch; }
.list-notes:focus { outline: none; color: var(--ink-secondary); }
.list-menu-pop { position: relative; }
.list-menu-pop > summary { list-style: none; cursor: pointer; }
.list-menu-pop > summary::-webkit-details-marker { display: none; }
.list-menu-pop__items { position: absolute; right: 0; top: 44px; z-index: 50; min-width: 200px; padding: 0; background: var(--surface); border: 0; box-shadow: var(--shadow-pop), var(--edge-light); border-radius: 0; display: grid; }
.list-menu-pop__items button { min-height: 44px; padding: 0 16px; border: 0; background: transparent; text-align: left; font: var(--type-body); color: var(--ink); }
.list-menu-pop__items button:active { background: var(--surface-pressed); }
.list-menu-pop__items .list-menu-pop__danger { color: var(--overdue); }
.list-menu-pop__items button { display: flex; align-items: center; }
/* Menu opens from its anchor corner: scale .85 to 1 on the pop spring, opacity a little faster. */
.list-menu-pop[open] > .list-menu-pop__items { transform-origin: top right; animation: pop-scale calc(100ms * var(--motion-scale)) var(--spring-pop), pop-fade calc(80ms * var(--motion-scale)) ease; }
@keyframes pop-scale { from { transform: scale(.85); } }
@keyframes pop-fade { from { opacity: 0; } }
.list-menu-pop__check { margin-left: auto; padding-left: 16px; color: var(--accent-text); }
.list-menu-pop__note { padding: 10px 16px; border-top: 1px solid var(--rule); font: var(--type-meta); color: var(--ink-secondary); }
.head-line__aside { display: flex; flex-wrap: wrap; gap: var(--space-2); margin-left: auto; }

/* ── Things settings sheet and sheets (Task 12) ─────────────────────────
   Settings is one rounded sheet over the list (grammar §4.10): the sheet is
   the grouped-list background and each .settings-group an inset card. Rows:
   label left, value / switch / chevron right, hairline between rows inside a
   group only. */
.settings-overlay { position: fixed; inset: 0; z-index: 40; background: var(--field); }
.settings-sheet { position: absolute; inset: 0 max(0px, calc((100vw - var(--content-max) - 2 * var(--space-5))/2)); display: flex; flex-direction: column; overflow: hidden; background: var(--field); padding: env(safe-area-inset-top, 0px) var(--space-5) 0; }
.settings-sheet .acc-top { flex: none; display: flex; flex-direction: column; gap: var(--space-2); padding: var(--space-4) 0 var(--space-3); }
.settings-sheet .acc-top__bar { display: flex; align-items: center; min-height: 44px; }
.settings-sheet .acc-top__title { font: 700 1.294rem/1.647rem var(--font); color: var(--ink); }
.settings-close,.sheet-close,.recur-card > .auth-close { flex: none; width: 44px; height: 44px; min-width: 44px; min-height: 44px; display: grid; place-items: center; padding: 0; border: 0; border-radius: 0; background: transparent; color: var(--ink-secondary); font: 600 0.882rem/1 var(--font); text-align: center; }
.settings-sheet .settings-close { width: auto; margin: 0 -8px 0 auto; padding: 0 8px; border-radius: 0; background: none; color: var(--accent-text); font: 600 0.882rem/1.176rem var(--font); }
.settings-back { margin-left: -8px; min-height: 44px; padding: 0 8px; background: transparent; color: var(--accent-text); font: 500 0.882rem/1.176rem var(--font); }
.settings-sheet .sync-error-banner { flex: none; border: 0; padding: 0; }
.settings-sheet .acc-grid { flex: 1; min-height: 0; overflow-y: auto; display: flex; flex-direction: column; gap: 24px; padding: 4px 0 calc(24px + var(--home-pad)); }
.settings-group { flex: none; display: flex; flex-direction: column; overflow: hidden; background: var(--surface); border: 1px solid var(--rule); border-radius: 0; }
.settings-row { display: flex; align-items: center; gap: 12px; width: 100%; min-height: 44px; margin: 0; padding: 10px 16px; border: 0; background: transparent; color: var(--ink); text-align: left; text-decoration: none; font: 500 0.882rem/1.176rem var(--font); }
.settings-row + .settings-row { background-image: linear-gradient(var(--rule), var(--rule)); background-position: 0 0; background-size: 100% 1px; background-repeat: no-repeat; }
:is(button, a).settings-row:active { background-color: var(--surface-pressed); }
.settings-row__label { flex: 1; min-width: 0; overflow-wrap: anywhere; }
.settings-row__value { flex: none; max-width: 55%; color: var(--ink-secondary); text-align: right; overflow-wrap: anywhere; }
.settings-row__chev { flex: none; margin-right: -4px; color: var(--ink-muted); font: 400 1.294rem/1.294rem var(--font); }
.settings-row__check { flex: none; color: var(--accent-text); font: 600 0.882rem/1.176rem var(--font); }
.settings-row--link { color: var(--accent-text); }
.settings-row--danger { color: var(--overdue); }
.settings-note { margin: 0; color: var(--ink-muted); font: 500 0.765rem/1.059rem var(--font); }
.acc-grid > .settings-note { margin-top: -16px; }
.settings-footer { margin: 0; color: var(--ink-muted); font: 500 0.765rem/1.059rem var(--font); text-align: center; }
/* Square opencode switch: 51x44 hit box, square track with a 1px edge, square knob. */
.appearance-switch { position: relative; flex: none; width: 51px; min-width: 51px; height: 44px; min-height: 44px; padding: 0; border: 0; background: transparent; }
/* The 44px hit area overhangs the row padding so a switch row stays 44px like every other row. */
.settings-row > .appearance-switch { margin: -10px -2px -10px 0; }
.appearance-switch::before { content: ''; position: absolute; inset: 7px 0; border: 1px solid var(--control-edge); border-radius: 0; background: var(--surface-pressed); transition: background-color var(--dur-base), border-color var(--dur-base); }
.appearance-switch.on::before { background: var(--accent-bg); border-color: var(--accent-bg); color: var(--accent-ink); }
.appearance-switch::after { content: ''; position: absolute; top: 11px; left: 4px; width: 22px; height: 22px; border-radius: 0; background: var(--ink); transition: transform var(--dur-base) var(--spring-chrome), background-color var(--dur-base); }
.appearance-switch.on::after { transform: translateX(21px); background: var(--accent-ink); }
.settings-label { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; margin: 0 0 -16px; color: var(--upcoming); font: 700 0.765rem/1.059rem var(--font); }
.settings-label em { font-style: normal; font-weight: 500; color: var(--ink-muted); }
.settings-pill { padding: 2px 8px; border: 1px solid var(--rule); font: 600 0.765rem/1.059rem var(--font); }
.settings-pill--ok { color: var(--logbook); border-color: var(--logbook); }
.settings-group--danger { border-color: var(--overdue); }
.settings-row--stack { flex-wrap: wrap; }
.settings-previews { flex: 1 0 100%; display: flex; gap: 8px; }
.settings-prev { flex: 1; min-width: 0; padding: 8px 10px; background: var(--field); border: 1px solid var(--rule); color: var(--ink-secondary); font: 500 0.765rem/1.059rem var(--font); }
.accent-swatches { flex: 1 0 100%; display: flex; flex-wrap: wrap; gap: 6px; }
.accent-swatch { width: 44px; height: 44px; padding: 0; border: 0; border-radius: 0; }
.accent-swatch.on { outline: 1px solid var(--ink); outline-offset: 2px; }
.settings-prev.on { border-color: var(--accent-text); color: var(--ink); }
.settings-prev__cap { display: block; color: var(--ink-muted); }
.settings-prev__hi { color: var(--accent-text); }
.settings-prev__ok { color: var(--logbook); }
.settings-row__sub { display: block; color: var(--ink-muted); font: 500 0.765rem/1.059rem var(--font); }
@media (prefers-reduced-motion: reduce) { .appearance-switch::before, .appearance-switch::after { transition: none; } }

.sheet { border: 0; border-radius: 0; }
/* Sheets: rounded on the surface, a grabber, sentence-case title, Things
   list rows, blue text buttons, red for destructive. */
.modal-shell--bottom > .recur-card { border: 0; border-radius: 0; padding: 8px var(--space-5) calc(var(--space-5) + var(--home-pad)); }
.dock .sheet { padding: 8px var(--space-4) var(--space-4); }
.modal-shell > .sheet::before,.modal-shell--bottom > .recur-card::before,.move-sheet::before { content: ''; display: block; width: 36px; height: 5px; margin: 0 auto 8px; border-radius: 0; background: var(--control-edge); }
.sheet-head { align-items: center; gap: var(--space-2); min-height: 0; padding: 0 0 var(--space-2); border: 0; background: inherit; }
.sheet-head .gsegs > * + * { border-left: 0; }
.sheet-eyebrow { font: 500 0.765rem/1.059rem var(--font); color: var(--ink-secondary); }
.sheet-title,.cnk-title,.rt-card .rt-title,.signout-title,.acct-del__title { font: 600 1.059rem/1.471rem var(--font); color: var(--ink); overflow-wrap: anywhere; }
.sheet-text-btn { min-height: 44px; padding: 0 var(--space-3); border: 0; background: transparent; color: var(--accent-text); font: 500 0.882rem/1.176rem var(--font); text-align: center; }
.sheet-text-btn--danger { color: var(--overdue); }
.sheet input:not([type=checkbox]),.modal-shell--bottom > .recur-card input { min-height: 44px; padding: 10px 12px; border: 0; border-radius: 0; background: var(--field); color: var(--ink); font: 500 0.882rem/1.176rem var(--font); }
.sheet-group { display: flex; flex-direction: column; }
.sheet-group + .sheet-group { margin-top: var(--space-3); border-top: 1px solid var(--rule); }
.task-action-btn { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); width: 100%; min-height: 48px; padding: 10px 0; border: 0; background: transparent; color: var(--ink); text-align: left; font: 500 0.882rem/1.176rem var(--font); }
.task-action-btn + .task-action-btn { border-top: 1px solid var(--rule); }
.task-action-btn__sub { color: var(--ink-secondary); font: 500 0.882rem/1.176rem var(--font); text-align: right; }
.task-action-btn--disabled { color: var(--ink-muted); }
.task-action-btn--disabled .task-action-btn__sub { color: var(--ink-muted); }
.task-action-btn--del { color: var(--overdue); }
/* Snooze */
.sheet .gstrip:not(.sheet-head) { margin: var(--space-2) 0 6px; }
.snooze-key { min-height: 44px; border: 0; border-radius: 0; background: var(--surface-pressed); color: var(--ink); text-align: center; font: 500 0.882rem/1.176rem var(--font); }
.snooze-key:active { background: var(--rule); }
.snooze-key--neg { color: var(--ink-secondary); }
.rs-input-wrap { display: flex; align-items: center; gap: var(--space-2); }
.rs-input-wrap input { flex: 1; }
.rs-input-wrap .rs-save { width: auto; min-width: 88px; margin: 0; }
.rs-reads { min-height: 18px; padding: var(--space-1) var(--space-1) 0; font: 500 0.765rem/1.059rem var(--font); color: var(--ink-secondary); font-variant-numeric: tabular-nums; }
/* When sheet: tabs, Today / This evening, month calendar, Someday, typed box. */
.when-sheet { display: flex; flex-direction: column; gap: var(--space-3); }
.when-body { display: flex; flex-direction: column; gap: var(--space-3); }
.when-row .settings-row__label { display: flex; align-items: center; gap: var(--space-3); }
.when-ic { width: 20px; text-align: center; color: var(--ink-secondary); }
.when-ic--today { color: var(--today); }
.when-ic--evening { color: var(--accent-text); }
/* When picker: week rows, compact 4 weeks or a scrolling grid (Things 3). */
.when-cal { --cal-row: 36px; --cal-t: calc(0.2s * var(--motion-scale)); }
.when-cal__weekdays, .when-cal__week { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); text-align: center; font-variant-numeric: tabular-nums; }
.when-cal__dow { padding-bottom: var(--space-1); font: 500 0.647rem/0.941rem var(--font); color: var(--ink-muted); }
.when-cal__body { position: relative; }
.when-cal__scroll { overflow: hidden; }
.when-cal--open .when-cal__scroll { height: calc(var(--cal-row) * 9); overflow-y: auto; overscroll-behavior: contain; scrollbar-width: none; }
.when-cal__day, .when-cal__week > span { height: var(--cal-row); }
.when-cal__day { padding: 0; display: grid; place-items: center; text-align: center; font: 500 0.882rem/1 var(--font); color: var(--ink); border: 1px solid transparent; border-radius: 0; background: transparent; transition: opacity var(--cal-t), background-color var(--cal-t); }
.when-cal__day:disabled { color: var(--ink-muted); opacity: 0.6; }
@media (hover: hover) { .when-cal__day:not(:disabled):hover { background: color-mix(in srgb, var(--accent-bg) 20%, transparent); } }
.when-cal__day:not(:disabled):active { background: var(--surface-pressed); }
.when-cal__day:focus-visible { outline: 1px solid var(--accent-bg); outline-offset: -1px; }
.when-cal__day.is-today { color: var(--accent-text); font-weight: 700; }
.when-cal__day.is-due { background: var(--accent-bg); border-color: var(--accent-bg); color: var(--accent-ink); font-weight: 700; }
.when-cal__label { position: absolute; inset: 0; display: grid; place-items: center; pointer-events: none; opacity: 0; transition: opacity var(--cal-t); font: 700 1.647rem/1 var(--font); color: var(--ink); }
.when-cal.is-scrolling .when-cal__label { opacity: 1; }
.when-cal.is-scrolling .when-cal__day { opacity: 0.15; }
.when-cal__fade { position: absolute; left: 0; right: 0; bottom: 0; height: 10px; pointer-events: none; background: linear-gradient(transparent, var(--surface)); transition: height calc(0.3s * var(--motion-scale)); }
.when-cal.is-away .when-cal__fade { height: 29px; }
.when-cal__home { position: absolute; left: 50%; bottom: 2px; transform: translateX(-50%); padding: 0 var(--space-3); font: 500 0.706rem/1.647rem var(--font); color: var(--accent-text); opacity: 0; pointer-events: none; transition: opacity var(--cal-t); }
.when-cal.is-away .when-cal__home { opacity: 1; pointer-events: auto; }
.when-cal__more { display: block; width: 100%; min-height: 44px; text-align: center; font: 500 0.765rem/1.059rem var(--font); color: var(--accent-text); }
@media (prefers-reduced-motion: reduce) { .when-cal__day, .when-cal__label, .when-cal__fade, .when-cal__home { transition: none; } }
.when-chips { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--space-2); }
.when-chip { min-height: 44px; padding: 0 var(--space-2); border: 1px solid var(--control-edge); border-radius: 0; background: var(--surface-pressed); color: var(--ink); text-align: center; font: 500 0.882rem/1.176rem var(--font); font-variant-numeric: tabular-nums; }
/* Reschedule */
.when-chip--neg { color: var(--ink-secondary); }
.snooze-total { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); min-height: 44px; }
.snooze-total__main { display: flex; flex-direction: column; min-width: 0; }
.snooze-total__val { font: 700 1.647rem/1.882rem var(--font); color: var(--accent-text); font-variant-numeric: tabular-nums; }
.snooze-total__at { font: 500 0.765rem/1.059rem var(--font); color: var(--ink-secondary); }
.snooze-reset { min-height: 44px; min-width: 44px; padding: 0 var(--space-3); border: 1px solid var(--control-edge); border-radius: 0; background: transparent; color: var(--ink); font: 500 0.882rem/1.176rem var(--font); }
.snooze-reset:disabled { color: var(--ink-muted); }
.snooze-done { width: 100%; text-align: center; min-height: 44px; border: 1px solid var(--accent-bg); border-radius: 0; background: var(--accent-bg); color: var(--accent-ink); font: 700 0.882rem/1.176rem var(--font); }
.snooze-done:disabled { background: var(--surface-pressed); border-color: var(--control-edge); color: var(--ink-muted); }
.when-chip:active,.snooze-key:active { background: var(--accent-bg); border-color: var(--accent-bg); color: var(--accent-ink); }
/* Reschedule / Snooze tabs: the active one is the filled accent. */
.when-sheet .composer-shift-row { background: transparent; gap: var(--space-2); padding: 0; }
.when-sheet .composer-shift-btn { border: 1px solid var(--control-edge); background: var(--surface-pressed); }
.when-sheet .composer-shift-btn.is-on { background: var(--accent-bg); border-color: var(--accent-bg); color: var(--accent-ink); }
.when-sheet .composer-shift-btn:disabled { color: var(--ink-muted); background: transparent; }
/* Counter keypad + edit */
.sheet--counter-keypad { position: relative; }
.sheet--counter-keypad > .sheet-close { position: absolute; right: var(--space-2); top: var(--space-4); z-index: 2; }
.cnk-head { display: block; position: static; padding: 0 52px 0 0; margin-bottom: var(--space-4); }
.cnk-display { margin-top: var(--space-1); color: var(--ink-secondary); font: 500 0.882rem/1.176rem var(--font); }
.cnk-modes { display: flex; gap: 2px; padding: 2px; margin-bottom: var(--space-3); border-radius: 0; background: var(--field); }
.cnk-mode { flex: 1; min-height: 44px; border: 0; border-radius: 0; background: transparent; color: var(--ink-secondary); text-align: center; font: 500 0.882rem/1.176rem var(--font); }
.cnk-mode.on { background: var(--accent-bg); color: var(--accent-ink); font-weight: 600; }
.cnk-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-2); }
.cnk-key { min-height: 48px; border: 0; border-radius: 0; background: var(--surface-pressed); color: var(--ink); text-align: center; font: 400 1.294rem/1.647rem var(--font); }
.cnk-key:active { background: var(--rule); }
.cnk-meter { display: flex; gap: 3px; margin: var(--space-2) 0 0; }
.cnk-meter i { flex: 1; height: 8px; background: var(--accent-bg); }
.cnk-meter i.off { background: var(--surface-pressed); }
.cnk-key--back { background: transparent; }
.cnk-key:disabled { opacity: .4; }
.cnk-key--ok { background: var(--accent-bg); color: var(--accent-ink); border: 0; font: 600 0.882rem/1.176rem var(--font); }
.cnk-remove { width: 100%; min-height: 44px; margin-top: var(--space-3); border: 0; background: transparent; color: var(--overdue); text-align: center; font: 500 0.882rem/1.176rem var(--font); }
.cnk-remove--armed { font-weight: 600; }
/* Snooze chips editor */
.snooze-chips-editor { display: flex; flex-direction: column; }
.snooze-chips-editor > .settings-note { margin: 0 0 var(--space-2); }
.snooze-chip-row { display: grid; grid-template-columns: 20px 44px 56px minmax(0, 1fr) 48px; align-items: center; gap: var(--space-2); padding: 6px 0; }
.snooze-chip-row + .snooze-chip-row { border-top: 1px solid var(--rule); }
.snooze-chip-row--abs { grid-template-columns: 20px 80px; }
.snooze-chip-row__idx { color: var(--ink-muted); font: 500 0.765rem/1.059rem var(--font); }
.snooze-chip-row__preview { color: var(--ink-secondary); font: 500 0.882rem/1.176rem var(--font); text-align: right; }
.sheet input.snooze-mag-input { padding: 10px 4px; text-align: center; appearance: textfield; }
.snooze-mag-input::-webkit-inner-spin-button,.snooze-mag-input::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; }
.snooze-unit-seg { display: flex; gap: 2px; padding: 2px; border-radius: 0; background: var(--field); }
.snooze-unit-seg .snooze-key { flex: 1; min-width: 0; border-radius: 0; background: transparent; color: var(--ink-secondary); font-size: 15px; }
.snooze-unit-seg .snooze-key--active { background: var(--accent-bg); color: var(--accent-ink); font-weight: 600; }
.snooze-abs-head { margin: var(--space-4) 0 var(--space-1); color: var(--ink-secondary); font: 500 0.765rem/1.059rem var(--font); }
.snooze-chips-editor__actions { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); margin-top: var(--space-4); }
.snooze-chips-editor__actions .rs-save { width: auto; min-width: 120px; margin: 0; }
/* Sheet close: a square 44px box, not the round Settings chip. */
.sheet-close,.recur-card > .auth-close { border-radius: 0; background: var(--surface-pressed); border: 1px solid var(--control-edge); color: var(--ink); }
/* Rename tag, sign-out and account-delete sheets */
.modal-shell--bottom > .recur-card > .auth-close { position: absolute; right: var(--space-2); top: var(--space-4); z-index: 2; }
.rt-card .rt-title,.signout-title,.acct-del__title { margin: var(--space-1) 52px var(--space-2) 0; }
.signout-meta,.signout-body,.acct-del__body,.rt-from { margin-top: var(--space-1); color: var(--ink-secondary); font: 500 0.882rem/1.176rem var(--font); }
.signout-meta b,.rt-from b { color: var(--ink); font-weight: 600; }
.acct-del__list { margin: var(--space-2) 0 0; padding-left: var(--space-5); }
.acct-del__shout { color: var(--overdue); font-weight: 600; }
.acct-del__error { margin-top: var(--space-2); color: var(--overdue); font: 500 0.882rem/1.176rem var(--font); }
.signout-actions,.acct-del__actions,.rt-btns { display: flex; align-items: center; justify-content: flex-end; gap: var(--space-2); margin-top: var(--space-4); }
/* Connections: large title under a Settings back, grouped cards. */
/* How to use: each section is a label over one grouped card of examples (typed line in ink,
   result secondary under it), then the section's plain sentence as a footnote. */
.tut-subtitle { color: var(--ink-secondary); font: 500 0.882rem/1.176rem var(--font); }
.tut-redo-cta { min-height: 44px; margin: var(--space-2) 0 0 -8px; padding: 0 8px; color: var(--accent-text); font: 500 0.882rem/1.176rem var(--font); }
.tut-sec-label { margin: var(--space-6) 0 var(--space-2); color: var(--upcoming); font: 700 0.765rem/1.059rem var(--font); }
.tut-sec-body { overflow: hidden; border-radius: 0; background: var(--surface-pressed); }
.tut-ex-row { display: grid; gap: 2px; padding: 10px var(--space-4); }
.tut-ex-row + .tut-ex-row { border-top: 1px solid var(--rule); }
.tut-ex-input { color: var(--ink); font: 500 0.882rem/1.294rem var(--font); }
.tut-ex-result { color: var(--ink-muted); font: 500 0.765rem/1.059rem var(--font); }
.tut-note { margin: var(--space-2) 0 0; color: var(--ink-secondary); font: 500 0.765rem/1.059rem var(--font); }
.tut-scroll { padding-bottom: var(--space-8); }
/* Connections, How to use and Sign in share one nav bar: the back on its own row at the left, the large title under it. */
:is(.conn-overlay, .tutorial-overlay, .signin-modal-overlay) > .gstrip .gsegs { order: -1; flex-basis: 100%; }
:is(.conn-overlay, .tutorial-overlay, .signin-modal-overlay) > .gstrip .gstrip-back { width: auto; min-height: 44px; margin: 0 0 0 -8px; padding: 0 8px; color: var(--accent-text); font: 500 0.882rem/1.176rem var(--font); }
:is(.conn-overlay, .tutorial-overlay, .signin-modal-overlay) > .gstrip .gstrip__txt { font: 700 1.294rem/1.647rem var(--font); color: var(--ink); }
.conn-intro { color: var(--ink-secondary); font: 500 0.882rem/1.176rem var(--font); }
.conn-section { margin-top: var(--space-6); }
.conn-section__h { margin: 0 0 var(--space-2); color: var(--upcoming); font: 700 0.765rem/1.059rem var(--font); }
.conn-invite-row { display: flex; align-items: center; gap: var(--space-2); padding: 0 var(--space-1) 0 var(--space-4); border: 1px solid var(--rule); border-radius: 0; background: var(--surface); }
.conn-invite-input { flex: 1; width: auto; min-height: 44px; padding: 0; border: 0; background: transparent; font: 500 0.882rem/1.176rem var(--font); }
.conn-invite-send { flex: none; min-height: 44px; padding: 0 var(--space-3); color: var(--accent-text); font: 600 0.882rem/1.176rem var(--font); }
.conn-invite-err { margin: var(--space-2) 0 0; color: var(--overdue); font: 500 0.765rem/1.059rem var(--font); }
.conn-cards { display: flex; flex-direction: column; overflow: hidden; border: 1px solid var(--rule); border-radius: 0; background: var(--surface); }
.conn-card { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: 2px var(--space-3); padding: 10px var(--space-2) 10px var(--space-4); }
.conn-card + .conn-card { border-top: 1px solid var(--rule); }
.conn-card__lbl { font: 500 0.882rem/1.176rem var(--font); }
.conn-card__sub { grid-column: 1; color: var(--ink-secondary); font: 500 0.765rem/1.059rem var(--font); }
.conn-card__actions { grid-column: 2; grid-row: 1 / span 2; display: flex; }
.conn-card__warn { grid-column: 1 / -1; padding-top: var(--space-1); color: var(--ink-secondary); font: 500 0.765rem/1.059rem var(--font); }
.conn-card--rename { grid-template-columns: minmax(0, 1fr); }
.conn-card--rename .conn-card__actions { grid-column: 1; grid-row: auto; justify-content: flex-end; }
.conn-rename-input { min-height: 44px; padding: 10px 12px; border: 0; border-radius: 0; background: var(--field); }
.conn-btn { min-height: 44px; padding: 0 var(--space-2); background: transparent; color: var(--accent-text); font: 500 0.882rem/1.176rem var(--font); }
.conn-btn--decline { color: var(--overdue); }
.conn-empty { padding: 12px var(--space-4); border-radius: 0; background: var(--surface); color: var(--ink-secondary); font: 500 0.882rem/1.176rem var(--font); }
.move-sheet { width: min(100%, var(--app-max)); max-height: 80dvh; overflow-y: auto; background: var(--surface); border-radius: 0; padding: 8px var(--space-5) calc(var(--space-5) + var(--home-pad)); animation: xtn-slideup calc(300ms * var(--motion-scale)) var(--spring-sheet) both; }
.move-sheet__head { display: flex; align-items: center; justify-content: space-between; min-height: var(--tap-min); font: 600 0.882rem/1.176rem var(--font); }
.move-sheet__cancel { min-height: var(--tap-min); color: var(--accent-text); }
/* ↑ Move sheet (.move-overlay rule sits with the list rows): files the open task into Inbox / a project / an area. */
.rt-inp-row { display: flex; align-items: center; margin-top: var(--space-3); padding-left: var(--space-3); border-radius: 0; background: var(--field); }
.rt-inp-pre { color: var(--ink-muted); font: 500 0.882rem/1.176rem var(--font); }
.modal-shell--bottom > .recur-card .rt-input { flex: 1; padding-left: 2px; background: transparent; }
.rt-inp-row .rt-input:focus-visible { outline: 0; }
.rt-status,.rt-preview { margin-top: var(--space-2); color: var(--ink-secondary); font: 500 0.765rem/1.059rem var(--font); }
.rt-status--err,.rt-status--warn { color: var(--overdue); }
.rt-preview { display: flex; flex-wrap: wrap; gap: var(--space-1) var(--space-2); }
.rt-preview-strike { text-decoration: line-through; }
.rt-preview-new { color: var(--ink); }
.sheet-head > .sheet-title { flex: 1; }
/* A docked sheet (snooze, reschedule, task actions) owns the bottom edge. */
#app:has(.modal-shell.dock) .capture-fab { display: none; }
/* Nothing tappable behind Settings: the scrim covers the whole screen and the + steps aside. */
#app:has(.settings-overlay) .capture-fab { display: none; }
/* Weekly archive: a bottom sheet of grouped rows; the groups sit on --field against the sheet surface. */
.sheet--wr .settings-group { margin-top: var(--space-4); background: var(--field); }
.wr-week { margin-top: 2px; color: var(--ink-secondary); font: 500 0.882rem/1.176rem var(--font); }
.sheet--wr .settings-note { margin-top: var(--space-2); }
.wr-section { margin: var(--space-5) 0 var(--space-2); color: var(--upcoming); font: 700 0.765rem/1.059rem var(--font); }
.sheet--wr .wr-section + .settings-group { margin-top: var(--space-2); }
.sheet--wr .wr-download { width: 100%; min-height: 50px; margin-top: var(--space-5); }
.wr-delete { display: block; width: 100%; margin-top: var(--space-2); }
/* Logbook clear actions: small blue text buttons at the end of each date head. */

/* Ahead and No date, the two top-level tabs (mockups/ahead variants 1 and 5). */
.view--tab { display: flex; flex-direction: column; flex: 1; min-height: 0; }
/* Logo row (name, path; Settings at the right end), then the shell heading with counts. */
.tab-head { flex: none; padding: 4px 0 6px; border-bottom: 1px solid var(--rule); }
.tab-head__logo { display: flex; align-items: center; gap: var(--space-2); min-height: 44px; }
.logo { flex: 1; display: flex; align-items: center; gap: 10px; min-width: 0; font: 700 1rem/1 var(--font); white-space: pre; }
.logo__path { color: var(--ink-muted); font: 500 0.706rem/1 var(--font); padding-top: 3px; }
.logo--prompt { font-size: 22px; gap: 0; }
.logo__gt { color: var(--accent-text); margin-right: .55ch; }
.logo__caret { width: .55em; height: 1.05em; margin-left: 2px; background: var(--accent-bg); animation: logo-blink 1.05s steps(1) infinite; }
@keyframes logo-blink { 50% { opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .logo__caret { animation: none; } }
.tab-head__line { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 0 var(--space-2); min-height: 44px; }
.tab-head__title { display: flex; align-items: baseline; font: 700 1.294rem/2.588rem var(--font); }
.logo__name { color: var(--ink); }
.ahead-head--month { padding-top: 24px; }
.tab-head__hash { color: var(--ink-muted); font-weight: 400; white-space: pre; }
.tab-head__aside { margin-left: auto; color: var(--ink-muted); font: 500 0.706rem/0.941rem var(--font); }
.tab-head__late { color: var(--overdue); }
.tab-head__sync { flex-basis: 100%; text-align: right; color: var(--ink-muted); font: 500 0.706rem/0.941rem var(--font); }
.tab-head__line .list-menu-pop { margin-right: -12px; align-self: center; }
.tab-head .settings-link { min-width: 44px; justify-content: center; padding: 0; margin-right: -12px; }
.list--ahead { --list-pad-b: 104px; padding: 8px 0 var(--list-pad-b); }
.ahead-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; width: 100%; min-height: 0; margin: 0 0 4px; padding: 20px 0 6px; color: var(--upcoming); font: 700 0.765rem/1.059rem var(--font); text-align: left; }
.ahead-head__name { color: var(--upcoming); font-weight: 700; }
.ahead-head--day { justify-content: flex-start; align-items: baseline; gap: var(--space-1) 0; font-size: 0.824rem; }
.ahead-head__num { margin-right: 0.353rem; color: var(--upcoming); font: 700 1.47rem/1.65rem var(--font); }
.ahead-head--day .ahead-head__name { font: 700 0.824rem/1.06rem var(--font); }
/* Today is the anchor: orange head, orange count of what is left. */
.ahead-head[data-bucket=today] :is(.ahead-head__num, .ahead-head__name) { color: var(--today); }
.ahead-head__left { font-weight: 500; color: var(--today); }
.ahead-head__aside { margin-left: auto; color: var(--ink-muted); font: 500 0.706rem/0.941rem var(--font); }
/* Google events: read-only, muted title, a 2px cyan bar in the checkbox column, cyan time. */
/* Things upcoming events: a tinted box (event cyan at low alpha, square, padding 8/10); all-day ones get a 3x9 tick. */
.ahead-ev { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: baseline; margin: var(--space-1) 0; padding: 0.47rem 0.588rem; background: color-mix(in srgb, var(--event-bar) 10%, transparent); color: var(--ink-secondary); font: 500 0.882rem/1.18rem var(--font); }
.ahead-ev--allday::before { content: ''; grid-area: 1 / 1; align-self: center; justify-self: start; width: 3px; height: 9px; margin-right: 0.47rem; background: var(--event-bar); }
.ahead-ev--allday { --ev-col: 2; grid-template-columns: auto minmax(0, 1fr) auto; }
.ahead-ev__tm { grid-area: 1 / -2; padding-left: var(--space-2); color: var(--event-bar); font-size: var(--fs-meta); font-variant-numeric: tabular-nums; text-align: right; }
.ahead-ev__ti { grid-area: 1 / var(--ev-col, 1); min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.view--tab :is(.row, .rowd) { grid-template-columns: 44px minmax(0, 1fr); column-gap: 0; min-height: 0; }
.view--tab .c-title { padding: 9px 0; }
.view--tab :is(.title, .rowd__name), .view--tab .subs-list .row.row--sub .title { font: 500 0.882rem/1.176rem var(--font); }
.view--tab .c-cb > :is(.checkbox, .rowd__cb) { width: 44px; min-height: 0; padding-top: 9px; justify-content: flex-start; }
/* The completion tick sits on that 20px circle, not centred in the 44px column. */
.view--tab .c-cb > .study-b-check > svg { left: 0; top: 9px; width: 20px; height: 20px; transform: none; }
/* Logbook box sits centred on its row; the tab padding-top above pushed it 5px low. */
.view--tab .done-row .c-cb > .checkbox { padding-top: 0; }
.view--tab .row-meta { margin-top: 2px; font: 500 0.706rem/0.941rem var(--font); color: var(--dim); }
.view--tab .row-meta > * + * { margin-left: 0; }
.view--tab .row-meta > * + *::before { content: '·'; margin: 0 4px; color: var(--dim); }
/* One right-hand column of times on the title line. The next row's is a peach chip, a late one bold red. */
.row-clock { flex: none; min-width: 46px; margin-left: var(--space-2); font: 500 var(--fs-meta)/1.176rem var(--font); font-variant-numeric: tabular-nums; text-align: right; color: var(--ink-secondary); }
.row--next .row-clock { padding: 0 4px; background: var(--accent-bg); color: var(--accent-ink); font-weight: 700; }
.row--next .title-hit { font-weight: 700; }
.late .row-clock { color: var(--overdue); font-weight: 700; }
.view--tab .task-due.late-due { color: var(--overdue); }
/* The open card keeps the circle clear of its edge. It cannot grow into the
   gutter instead: the list's scroll box clips at the column edge. */
.view--tab :is(.row, .rowd, .row-today).expanded { padding-inline: 10px; }
.view--tab .expand-inner > * { margin-left: 44px; }
.view--tab :is(.task-state .rt-recur-chip, .ahead-rep) { color: var(--recurring); }
/* Dose list under an Ahead repeat row: the row's day, tree or cells. Display only. */
.doses { margin-top: 6px; font: 500 0.676rem/1.118rem var(--font); color: var(--ink-secondary); }
/* Tree = timeline rail: a square node per dose (green ✓ taken, peach current, hollow upcoming, red late)
   on a rail that is green down to the current dose. Text is the task title's size, nodes match it. */
.doses--tree { display: grid; margin-left: 2px; font: 500 0.882rem/1.176rem var(--font); }
.doses--tree .dose { position: relative; display: grid; grid-template-columns: 14px 5ch minmax(0, 1fr); column-gap: 10px; align-items: center; padding: 3px 0; }
/* The hollow upcoming node is an inset shadow, not a border: borders stay <= 1px. */
.doses--tree .dose::before, .doses--tree .dose::after { content: ''; position: absolute; left: 6px; width: 2px; background: var(--rule); }
.doses--tree .dose::before { top: 0; height: 50%; }
.doses--tree .dose::after { top: 50%; bottom: 0; }
.doses--tree .dose:first-child::before, .doses--tree .dose:last-child::after { display: none; }
.doses--tree .dose--taken::before, .doses--tree .dose--taken::after, .doses--tree .dose--current::before { background: var(--logbook); }
.doses--tree .dose__m { position: relative; z-index: 1; box-sizing: border-box; width: 14px; height: 14px; display: grid; place-items: center; background: var(--field); box-shadow: inset 0 0 0 2px var(--ink-muted); font: 700 10px/1 var(--font); color: var(--logbook-ink); }
.doses--tree .dose--taken .dose__m { background: var(--logbook); box-shadow: none; }
.doses--tree .dose--current .dose__m { background: var(--accent-bg); box-shadow: none; }
.doses--tree .dose--late .dose__m { background: var(--overdue); }
.dose__w { color: var(--ink-secondary); }
.dose--current .dose__w { color: inherit; }
.doses--tree .dose--current { color: var(--accent-text); }
.doses--tree .dose--current .dose__t { font-weight: 700; }
.doses--tree .dose--late { color: var(--overdue); }
.doses--cells { display: flex; flex-wrap: wrap; gap: 4px; }
.doses--cells .dose { min-width: 52px; padding: 3px 0 2px; text-align: center; font-size: 11px; line-height: 15px; background: var(--surface-pressed); color: var(--ink-secondary); border: 1px solid transparent; }
.doses--cells .dose--taken { background: var(--logbook); color: var(--logbook-ink); }
.doses--cells .dose--current { border-color: var(--accent); color: var(--accent-text); font-weight: 700; }
.doses--cells .dose--late { border-color: var(--overdue); color: var(--overdue); }
.doses__count { width: 100%; font-size: 11px; color: var(--ink-secondary); }
:is(.row, .rowd, .row-today).expanded .doses { display: none; }
@media (prefers-reduced-motion: no-preference) {
  .doses--cells .dose--current { animation: dose-breathe 2.4s ease-in-out infinite; }
  .doses--tree .dose--current:not(.dose--late) .dose__m { animation: dose-ring 2.4s ease-out infinite; }
  .dose--arrive { animation: dose-arrive calc(500ms * var(--motion-scale)) var(--spring-delight); }
}
@keyframes dose-breathe { 50% { box-shadow: inset 0 0 0 1px currentColor; } }
@keyframes dose-ring { 0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent) 45%, transparent); } 70%, 100% { box-shadow: 0 0 0 5px transparent; } }
@keyframes dose-arrive { from { background-color: color-mix(in srgb, var(--accent) 22%, transparent); transform: translateY(-4px); opacity: 0.4; } }
.view--nodate .list-group { margin-top: var(--space-5); }
/* Dock: an opencode prompt box (a button) over the tabs row. 8 + 44 + 6 + 44 + 1 = 103px above the bottom pad. */
.tabbar { position: fixed; z-index: 45; left: 0; right: 0; bottom: 0; max-width: calc(var(--content-max) + 16px); /* 8px side padding: the prompt row sits on the 680 column */ margin: 0 auto; display: flex; flex-direction: column; gap: 6px; padding: 8px 8px max(26px, env(safe-area-inset-bottom, 0px)); border-top: 1px solid var(--rule); background: var(--field); }
.tabbar__add { display: flex; align-items: stretch; width: 100%; min-height: 44px; padding: 0; background: var(--surface); border: 1px solid var(--accent); color: var(--ink-secondary); font: 400 var(--fs-meta)/1.3 var(--font); text-align: left; }
.tabbar__txt { flex: 1; min-width: 0; display: flex; align-items: center; flex-wrap: wrap; padding: 0 12px; }
.tabbar__eg { margin-left: 1ch; color: var(--ink-muted); }
.tabbar__cap { flex: none; display: flex; align-items: center; padding: 0 14px; background: var(--accent-bg); color: var(--accent-ink); font-weight: 700; }
.tabbar__tabs { display: flex; }
.tabbar__tab { position: relative; flex: 1; min-height: 48px; padding: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; color: var(--ink-muted); font: 500 var(--fs-meta)/1.2 var(--font); text-align: center; }
.tabbar__tab.on { color: var(--accent-text); font-weight: 700; }
.tabbar__cnt { display: flex; align-items: center; gap: 4px; min-height: 1em; font-size: 0.65rem; color: var(--ink-muted); }
.tabbar__late { padding: 0 5px; background: var(--overdue); color: var(--field); font-weight: 700; line-height: 1.3; }
.tab-head { position: relative; }
@media (prefers-reduced-motion: no-preference) {
  .tabbar__add { animation: add-breathe 3s ease-in-out infinite; }
}
@keyframes add-breathe { 50% { border-color: color-mix(in srgb, var(--accent) 35%, transparent); } }
.tabbar button:is(:focus, :focus-visible) { outline: none; }
body:has(.tut-coach) .tabbar { bottom: var(--tut-coach-h, 0px); padding-bottom: 8px; }
/* Entering a tab: the list rises in, 18ms apart. Same-screen redraws stay still. */
@keyframes ahead-rise { from { opacity: 0; transform: translateY(5px); } }
.view--rise .list > * { animation: ahead-rise calc(300ms * var(--motion-scale)) var(--spring-chrome) backwards; animation-delay: calc(var(--rise, 0) * 18ms * var(--motion-scale)); }
@media (prefers-reduced-motion: reduce) { .view--rise .list > * { animation: none; } }

/* Scroll hint: no scrollbars anywhere; a small chevron at the right edge says
   there is more above or below. Pure CSS: the "local" covers scroll with the
   content and hide each chevron while its edge is reached. */
* { scrollbar-width: none; }
*::-webkit-scrollbar { display: none; }
.composer-scroll,.sheet,.recur-card,.dock,.conn-body,.tut-scroll,.settings-sheet .acc-grid,.move-sheet,.tut-coach,.workbench-view,.takeover,.e2ee-gate-overlay { --scroll-bg: var(--field);
  background:
    linear-gradient(var(--scroll-bg), var(--scroll-bg)) top / 100% 24px no-repeat local,
    linear-gradient(var(--scroll-bg), var(--scroll-bg)) bottom / 100% 24px no-repeat local,
    var(--more-up) right 8px top 8px / 12px 8px no-repeat scroll,
    var(--more-down) right 8px bottom 8px / 12px 8px no-repeat scroll,
    var(--scroll-bg); }
.sheet,.recur-card,.move-sheet,.tut-coach { --scroll-bg: var(--surface); }
/* The sheet spring overshoots ~3%: a skirt of surface below the sheet hides the gap. */
.modal-shell--bottom .sheet,.modal-shell--bottom .recur-card,.move-sheet,.tut-coach,.tut-finish-overlay { box-shadow: 0 3rem 0 var(--surface); }
/* List rows are opaque, so on .list a background chevron would sit under
   them. Its chevrons are sticky pseudo-elements above the rows instead, shown by a
   scroll-driven animation only while there is more that way. No scroll timeline
   (short list, or no browser support) leaves them hidden. The down one sits 8px
   above the fixed tab bar, as the up one sits 8px below the header: 8px + the
   bar's 103px + its bottom pad, less #app's own bottom pad (the home indicator,
   which lifts the list but not the fixed bar) and the list's bottom padding
   (sticky measures from inside it; --list-pad-b, 104px on Ahead). */
#app:has(> .tabbar) .list { --list-pad-b: 140px; }
#app:has(> .tabbar) .list--ahead { --list-pad-b: 172px; }
.list::before,.list::after { content: ''; position: sticky; z-index: 3; display: block; width: 12px; height: 8px; margin-left: auto; margin-right: 8px; pointer-events: none; opacity: 0; animation: more-shown linear; animation-timeline: scroll(); }
.list::before { top: 8px; margin-bottom: -8px; background: var(--more-up); animation-range: 16px 100%; }
.list::after { bottom: calc(115px + max(26px, env(safe-area-inset-bottom, 0px)) - var(--home-pad) - var(--list-pad-b)); margin-top: -8px; background: var(--more-down); animation-range: 0 calc(100% - 16px); }
@keyframes more-shown { from, to { opacity: 1; } }
/* Settings and composer cards fill their column; the scroller reaches into the sheet's
   side gutter so the chevrons have room beside them. */
.settings-sheet .acc-grid,.composer-scroll { margin-inline: calc(-1 * var(--space-5)); padding-inline: var(--space-5); }

/* Icon-button tooltip (tip() in html-builder.js): shown on mouse hover and
   keyboard focus only, never on touch. */
.list-back,.list-menu { position: relative; }
/* The ‹ glyph lives in CSS so the button's only name is its aria-label. */
.list-back::before { content: '‹'; }
.tip { position: absolute; z-index: 60; top: calc(100% + 4px); left: 0; display: none; padding: 2px 6px; white-space: nowrap; background: var(--surface-pressed); color: var(--ink); border: 1px solid var(--rule); font: var(--type-meta); pointer-events: none; }
.list-menu > .tip { left: auto; right: 0; }
.capture-fab > .tip { top: auto; bottom: calc(100% + 4px); left: auto; right: 0; }
@media (hover: hover) { :hover > .tip { display: block; } }
:focus-visible > .tip { display: block; }

/* U8.2: project progress. Square cells (--rule border, --projects fill) pop in staggered; reduced motion shows them at rest. */
.list-prog { display: flex; gap: 2px; height: 8px; width: 110px; }
.list-prog i { flex: 1; border: 1px solid var(--rule); }
.list-prog i.f { background: var(--projects); border-color: var(--projects); }
.list-prog--done i.f { background: var(--logbook); border-color: var(--logbook); }
@media (prefers-reduced-motion: no-preference) { .list-prog i { animation: list-pop calc(350ms * var(--motion-scale)) var(--spring-delight) both; animation-delay: calc(var(--i) * 35ms + 150ms); } }
@keyframes list-pop { from { opacity: 0; transform: translateY(8px) scale(.6); } }
.list-row .list-prog { margin-right: 4px; }
.list-card { background: var(--surface); border: 1px solid var(--rule); padding: 14px 16px; margin: 6px 0 10px; display: grid; gap: 10px; }
.list-card--done { border-color: var(--logbook); }
.list-card__big { font: 700 1.375rem/1.2 var(--font); }
.list-card--done .list-card__big { color: var(--logbook); }
.list-card__big small { font: 500 0.8125rem var(--font); color: var(--ink-muted); margin-left: 6px; }
.list-card .list-prog { width: 100%; }
.list-card__lab { color: var(--ink-muted); font: 500 0.75rem/1rem var(--font); }
.list-nextlab { color: var(--accent-text); font: 500 0.75rem/1rem var(--font); padding: 8px 0 2px; }
.next-up { background: var(--surface); }
.list-complete { display: block; width: 100%; min-height: 48px; background: var(--accent-bg); color: var(--accent-ink); font: 700 0.875rem var(--font); text-align: center; }

/* U9.2: reschedule tiles, snooze groups, confirm halves, empty-state button. */
.when-tiles { display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; gap: var(--space-2); }
.when-tiles .when-tile { display: grid; place-items: center; align-content: center; gap: 2px; min-height: 64px; padding: 6px; border: 1px solid var(--control-edge); background: var(--surface-pressed); color: var(--ink); font: 500 0.8125rem/1.1rem var(--font); text-align: center; }
.when-tile .settings-row__label { display: grid; justify-items: center; gap: 2px; }
.when-tile:active { background: var(--accent-bg); border-color: var(--accent-bg); color: var(--accent-ink); }
.when-chipgroups { display: flex; flex-direction: column; gap: var(--space-2); }
.when-grp { display: flex; justify-content: space-between; color: var(--ink-secondary); font: 500 0.75rem/1rem var(--font); }
.when-grp b { color: var(--upcoming); font-weight: 600; }
.when-chips--until { grid-template-columns: repeat(3, 1fr); }
.signout-actions, .acct-del__actions { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-2); }
.signout-actions .sheet-text-btn, .acct-del__actions .sheet-text-btn { min-height: 48px; border: 1px solid var(--control-edge); background: var(--surface-pressed); color: var(--ink); font-weight: 500; }
.signout-actions .sheet-text-btn--danger, .acct-del__actions .sheet-text-btn--danger { border-color: var(--overdue); background: var(--overdue); color: var(--accent-ink); font-weight: 700; }
.empty--card { display: grid; justify-items: start; gap: var(--space-2); }
.empty-h { color: var(--ink); font: 600 1.059rem/1.471rem var(--font); }
.empty-add { min-height: 48px; padding: 0 var(--space-5); margin-top: var(--space-2); background: var(--accent-bg); color: var(--accent-ink); font: 700 0.882rem/1.176rem var(--font); }
