/* Saqme To Do PWA. Colours, type and spacing come from tokens.css (generated from design/tokens.json,
   shared with the desktop widget); see docs/design.md. */

* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }
html, body { height: 100%; margin: 0; }
html { background: var(--frame); }
body {
  font-family: var(--font); font-size: var(--t-body-size); line-height: var(--t-body-line);
  color: var(--ink); background: var(--frame); overscroll-behavior: none;
  -webkit-text-size-adjust: 100%; text-size-adjust: 100%; font-kerning: normal;
  -webkit-font-smoothing: antialiased;
}
button { font: inherit; color: inherit; background: none; border: 0; padding: 0; cursor: pointer; }
/* read by screen readers, not shown */
.sr-only { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
input, textarea { font: inherit; color: var(--ink); }
svg { display: block; }
[hidden] { display: none !important; }
.tnum, .count, .meta, .pill, .time-input { font-variant-numeric: tabular-nums; }
/* The focus ring is for the keyboard: after a tap or a click there is none, also where a browser would draw one (a text
   box, focus that the app moves after a tap). app.js keeps the last kind of input on the root, data-input. */
:root { --ring: 2px solid var(--violet); }
:root[data-input="pointer"] { --ring: none; }
:focus-visible { outline: var(--ring); outline-offset: 2px; border-radius: var(--r-control); }
.row:focus-visible, .g-row:focus-visible { outline-offset: -2px; border-radius: 0; }
.group :focus-visible { outline-offset: -2px; }   /* (a card clips what is drawn outside it) */
/* Press feedback (docs/design.md, "Motion"): what is pressed tints at once and fades back; buttons also shrink a little.
   In fast, out eased; the transition on :active is the way in. With reduce motion only the tint, no shrinking. */
:root { --press-in: 80ms; --press-out: 120ms; --ease-out: cubic-bezier(.33, 1, .68, 1); --press-chip: .86; --press-icon: .92; --press-button: .97; --press-wide: .98; }
@media (prefers-reduced-motion: reduce) { :root { --press-chip: 1; --press-icon: 1; --press-button: 1; --press-wide: 1; } }
/* inside a card, where a task's chip and its text start (edge 2 + grip 14 + chevron 24 + 4, then the chip and 8):
   the list's headings line up with the chips; hairlines, notes and the add line's text with the text */
:root { --head-x: 44px; --text-x: 70px; }

/* ------------------------------------------------------------------ frame */
.card {
  position: fixed; inset: 0; display: flex; flex-direction: column; background: var(--surface);
  max-width: 760px; margin: 0 auto; overflow: hidden;   /* (a list swiped sideways never widens the page) */
}
@media (min-width: 800px) {
  .card { inset: 24px auto 24px auto; left: 0; right: 0; border: 1px solid var(--edge); border-radius: var(--r-container);
    overflow: hidden; box-shadow: 0 18px 48px rgba(0, 0, 0, .28); }
}

/* ------------------------------------------------------------------ header: Settings, the list's name, sync */
/* (above the list, so that the lists menu in it and its scrim cover the list; the header itself stays clear) */
.strip {
  position: relative; z-index: 6; display: flex; align-items: center; gap: var(--space-2); flex: none;
  padding: calc(env(safe-area-inset-top) + var(--space-3)) calc(env(safe-area-inset-right) + var(--space-3)) var(--space-3) calc(env(safe-area-inset-left) + var(--space-3));
  background: var(--frame);
}
.logo {
  flex: none; width: 40px; height: 44px; display: grid; place-items: center; border-radius: var(--r-control); color: var(--smoke);
  transition: background-color var(--press-out) var(--ease-out), color var(--press-out) var(--ease-out), transform var(--press-out) var(--ease-out);
}
.logo svg { width: 22px; height: 22px; }
.logo:active { background: var(--tab-hover); transform: scale(var(--press-icon)); transition-duration: var(--press-in); }
@media (hover: hover) { .logo:hover { background: var(--tab-hover); } }
/* In Settings (any view but the list) the header is only ☰, pressed like a selected tab: it says where you are and
   takes you back. The list's name, conflicts and sync step aside, keeping their room so nothing moves (app.js makes
   them inert at once; visibility follows the fade). */
.logo[aria-pressed="true"], .logo[aria-pressed="true"]:hover { background: var(--selected); color: var(--ink); }
/* (with the view under them: out in 120 ms, in from 60 ms on in 160 ms; app.js, "moving between views") */
.strip :is(.switcher, .conflicts-badge, .sync) { transition: opacity .16s var(--ease-out) .06s, transform .16s var(--ease-out), visibility 0s; }
.card.in-settings .strip :is(.switcher, .conflicts-badge, .sync) {
  opacity: 0; transform: translateX(-6px); visibility: hidden; pointer-events: none;
  transition: opacity .12s var(--ease-out), transform .12s var(--ease-out), visibility 0s .12s;
}
/* The title (the one bold place): the current list's name in display type, a small ⌄ and, when another list has
   something due, the violet dot; one button that opens the lists menu. A long name ends in "…" (whole in the menu). */
.switcher {
  display: flex; align-items: center; gap: 6px; flex: 0 1 auto; min-width: 0; height: 44px; margin-right: auto;
  padding: 0 var(--space-3) 0 var(--space-2); border-radius: var(--r-control); text-align: left;
  user-select: none; -webkit-user-select: none; -webkit-touch-callout: none;
}
.switcher-name {
  min-width: 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
  font-size: var(--t-display-size); line-height: var(--t-display-line); font-weight: var(--t-display-weight);
}
.switcher-chev { display: grid; place-items: center; flex: none; color: var(--smoke); }
.switcher-chev svg { width: 13px; height: 13px; transition: transform .15s; }
.switcher[aria-expanded="true"] .switcher-chev svg { transform: rotate(180deg); }
.switcher .dot { margin: 0 0 0 2px; }
.switcher:active, .switcher[aria-expanded="true"] { background: var(--tab-hover); }
.switcher:active { transform: scale(var(--press-wide)); transition-duration: var(--press-in); }
@media (hover: hover) { .switcher:hover { background: var(--tab-hover); } }
.sync, .conflicts-badge { flex: none; height: 44px; min-width: 40px; display: grid; place-items: center; border-radius: var(--r-control); color: var(--smoke); }
.sync:active, .conflicts-badge:active { background: var(--tab-hover); transform: scale(var(--press-icon)); transition-duration: var(--press-in); }
.sync svg { width: 19px; height: 19px; }
.sync.state-syncing { color: var(--violet); }
.sync.state-syncing svg { animation: pulse 1.2s ease-in-out infinite; }
.sync.state-idle, .sync.state-unpaired { opacity: .7; }
.sync.state-offline { opacity: .45; }
.sync.state-error { color: var(--alert); }
.conflicts-badge { display: flex; align-items: center; gap: var(--space-2); padding: 0 var(--space-3); color: var(--amber); font-size: var(--t-small-size); font-weight: 600; }
.conflicts-badge svg { width: 15px; height: 15px; }
@keyframes pulse { 50% { opacity: .35; } }

/* ------------------------------------------------------------------ the lists menu (the title opens it) */
/* Under the title, over a scrim on the list and the add line (the header stays clear, so the turned chevron shows): a
   card of one row per list (the current one checked, its open tasks or "2 due" on the right), then "New list" in a
   card of its own after a small gap. app.js sizes the scrim to the window and places the menu (--menu-top, left);
   with many lists their card scrolls and "New list" stays in view. */
.list-menu-wrap { position: absolute; left: 0; right: 0; top: 100%; height: 100vh; }
.list-menu-scrim { position: absolute; inset: 0; background: var(--backdrop); animation: fade .16s ease-out; }
.list-menu {
  position: absolute; top: var(--menu-top, 64px); display: flex; flex-direction: column; gap: var(--space-3);
  width: min(320px, calc(100% - 2 * var(--card-inset)));
  max-height: calc(100% - var(--menu-top, 64px) - env(safe-area-inset-bottom) - var(--card-inset));
  transform-origin: top left; animation: drop .16s cubic-bezier(.2, .8, .2, 1);
}
@keyframes drop { from { opacity: 0; transform: translateY(-6px) scale(.97); } }
.list-menu .group { flex: none; margin: 0; }
.list-menu .lm-lists { flex: 0 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain; }
/* a list's name is your own words: it wraps here instead of ending in "…" (the title cuts it), the check, badge and
   value on its first line */
.g-row.lm-item {
  --line-x: calc(var(--card-padding) + 28px); align-items: flex-start; padding-top: 11px; padding-bottom: 11px;
  -webkit-touch-callout: none; user-select: none; -webkit-user-select: none;
}
.lm-item .check, .lm-item .shared-badge { height: var(--t-body-line); }
.lm-item .g-label { flex: 0 1 auto; white-space: normal; overflow-wrap: anywhere; }   /* (a shared list's badge right after its name) */
.lm-item .g-value { margin-left: auto; white-space: nowrap; }
.lm-item .g-value.lm-over { color: var(--alert); }
.lm-item .g-value.lm-soon { color: var(--amber); }

/* ------------------------------------------------------------------ the list: lines in grouped cards */
.list {
  position: relative; flex: 1; overflow-y: auto; overflow-x: hidden; -webkit-overflow-scrolling: touch; outline: none; overscroll-behavior: contain;
  padding: var(--space-3) calc(env(safe-area-inset-right) + var(--card-inset)) calc(env(safe-area-inset-bottom) + var(--space-7)) calc(env(safe-area-inset-left) + var(--card-inset));
}
/* Moving between views (app.js, "moving between views"): the view left behind, in a copy of the list's box over or
   under the new one, slides or fades out; it takes no taps, focus or screen reader. Both are opaque meanwhile. */
.list.ghost { position: absolute; z-index: 1; overflow: hidden; pointer-events: none; background: var(--surface); }
.card[data-move] .list { background: var(--surface); }
/* with more than one list a sideways swipe on it goes to the next or previous list (app.js); up and down stay the
   browser's scroll, and pinch zoom stays on */
.list.swipeable { touch-action: pan-y pinch-zoom; }
/* no add line under it (Settings, a view-only list): the list runs to the bottom edge, over the home indicator */
.card.no-add .list { padding-bottom: calc(env(safe-area-inset-bottom) + var(--space-7)); }
.list::-webkit-scrollbar { width: 6px; }
.list::-webkit-scrollbar-thumb { background: var(--thumb); border-radius: 3px; }

/* A card of a grouped list (docs/design.md, "Grouped lists"): a shade lighter than the window, rounded, its rows
   one line each with a hairline between two rows from where the lower row's text starts. A list's tasks are one
   card; every view of Settings is cards of rows, a heading above and a footnote below. */
.group { margin-top: var(--card-gap); background: var(--card); border-radius: var(--r-card); overflow: hidden; }
.group > * { position: relative; }
.group > * + *::before {
  content: ''; position: absolute; z-index: 1; top: 0; right: 0; left: var(--line-x, var(--card-padding)); height: 1px;
  background: var(--separator); pointer-events: none;
}
.g-head {
  margin: var(--card-gap) var(--card-padding) 6px; color: var(--smoke); overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
  font-size: var(--t-small-size); line-height: var(--t-small-line); font-weight: var(--t-small-weight);
}
.g-head + .group, .g-head + .tasks { margin-top: 0; }
.g-foot, .g-note { margin: 6px var(--card-padding) 0; color: var(--smoke); font-size: var(--t-meta-size); line-height: var(--t-meta-line); overflow-wrap: anywhere; }
.g-note { margin-top: var(--card-gap); }
.g-foot.alert { color: var(--alert); }
.g-foot a, .g-note a { color: var(--violet); }
/* the first block of a view sits close under its header (or the top of the list) */
.view-header + *, .list > h1.sr-only:first-child + .group, .list > :first-child { margin-top: var(--space-2); }

.tasks { --line-x: calc(var(--text-x) + var(--depth, 0) * var(--row-indent)); }
.task-item { --line-x: calc(var(--text-x) + var(--depth) * var(--row-indent)); }
.list-head { margin-left: var(--head-x); }
.row {
  --depth: 0;
  position: relative; display: grid; grid-template-columns: 14px 24px 26px minmax(0, 1fr) 40px; align-items: start;
  min-height: var(--row-min-touch); padding: 9px 0 9px calc(var(--depth) * var(--row-indent));
  border-left: 2px solid transparent; user-select: none; -webkit-user-select: none; -webkit-touch-callout: none;
  transition: background-color var(--press-out) var(--ease-out);
}
@media (pointer: fine) { .row { min-height: var(--row-min-pointer); padding-top: 6px; padding-bottom: 6px; } }
.row.with-notes { padding-bottom: 3px; }   /* its notes follow right under the text */
.row.sel { background: var(--card-selected); border-left-color: var(--violet); }
/* a task a tapped reminder opened: the selection colour fades in and out for a moment */
.row.flash { animation: flash 1.8s var(--ease-out) 1; }
@keyframes flash { 0%, 55% { background: var(--card-selected); box-shadow: inset 0 0 0 2px var(--violet); } 100% { box-shadow: inset 0 0 0 2px transparent; } }
@media (hover: hover) { .row:hover { background: var(--card-hover); } .row.sel:hover { background: var(--card-selected); } .row:hover .grip { opacity: .8; } }
/* pressing a task's text (which edits it, or opens its menu held down) tints its line; its buttons answer by themselves */
.row:not(.sel):has(.text:active) { background: var(--card-pressed); transition-duration: var(--press-in); }
.list.swiping .row:not(.sel):has(.text:active) { background: var(--card); }   /* (a swipe is not a press) */
.row.dragging { opacity: .45; }
.grip { display: grid; place-items: center; height: 30px; opacity: .3; touch-action: none; cursor: grab; }
.grip svg { width: 7px; height: 12px; color: var(--smoke); }
.chev {
  display: grid; place-items: center; width: 24px; height: 30px; border-radius: var(--r-control); color: var(--smoke);   /* >= 24 px target (WCAG 2.5.8) */
  transition: background-color var(--press-out) var(--ease-out), transform var(--press-out) var(--ease-out);
}
.chev:disabled { cursor: default; }
.chev:not(:disabled):active { background: var(--card-pressed); transform: scale(var(--press-icon)); transition-duration: var(--press-in); }
.chev svg { width: 11px; height: 11px; transition: transform .15s; }
.chev.open svg { transform: rotate(90deg); }
.chip-btn { display: grid; place-items: start center; width: 26px; height: 30px; padding-top: 6px; }   /* the 18 px chip, 4 px each side */
.chip {
  width: 18px; height: 18px; border-radius: var(--r-chip); border: 1.5px solid var(--status-todo);
  display: grid; place-items: center; flex: none; transition: transform var(--press-out) var(--ease-out);
}
button.chip-btn:active .chip { transform: scale(var(--press-chip)); transition-duration: var(--press-in); }
.chip svg { width: 10px; height: 10px; }
.chip.s-prog { border-color: var(--status-prog); background: linear-gradient(90deg, var(--status-prog) 50%, transparent 50%); }
.chip.s-done { border-color: var(--status-done); background: var(--status-done); color: var(--status-done-glyph); }
.chip.s-post { border-color: var(--status-post); background: var(--status-post); color: var(--status-post-glyph); }
.chip.s-block { border-color: var(--status-block); background: var(--status-block); color: var(--status-block-glyph); }
.chip.s-rej { border-color: var(--status-rej); background: var(--status-rej); color: var(--status-rej-glyph); }
.chip.s-aband { border-color: var(--status-aband); background: var(--status-aband); color: var(--status-aband-glyph); }

.main { display: flex; flex-direction: column; min-width: 0; padding: 4px 0 4px calc(var(--row-chip-gap) - 8px); }
.text { display: block; width: 100%; text-align: left; color: var(--ink); overflow-wrap: break-word; hyphens: auto; white-space: pre-wrap; cursor: text; }
.text.empty { color: var(--smoke); font-style: italic; }
.t-post { color: var(--smoke); font-style: italic; }
.t-done, .t-rej { color: var(--closed); text-decoration: line-through; text-decoration-thickness: 1px; }
.t-aband { color: var(--closed); text-decoration: line-through; text-decoration-thickness: 1px; font-style: italic; }
/* a status just set to closed: ::after draws the line (js playStatusAnim); the text's own line waits for it */
.text.striking { position: relative; text-decoration-color: transparent; }
.text.striking::after {
  content: attr(data-text); position: absolute; inset: 0; pointer-events: none; color: transparent;
  text-decoration: line-through; text-decoration-thickness: 1px; text-decoration-color: var(--closed);
}
/* (on the selected row's tint closed grey falls under 4.5 : 1; smoke stays above it, the strike-through says closed) */
.row.sel .t-done, .row.sel .t-rej, .row.sel .t-aband { color: var(--smoke); }
.editor {
  display: block; width: 100%; margin: 0; padding: 0 0 2px; resize: none; overflow: hidden; border: 0; border-radius: 0;
  border-bottom: 1.5px solid var(--violet); background: transparent; outline: none; caret-color: var(--violet);
  font-size: var(--t-body-size); line-height: var(--t-body-line);
}
@media (pointer: coarse) { .editor, .add input, .field, .g-input, .time-input, .notes textarea { font-size: 16px; } }   /* no iOS zoom on focus */
/* a task's deadline, subtask count and notes mark: under its text on a phone held upright, on the right of its first
   line from 440 px on (as the value of a row; the deadline rightmost), where the text still keeps a wide column */
.meta {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-1) var(--space-4); margin-top: var(--row-meta-gap);
  color: var(--smoke); font-size: var(--t-meta-size); line-height: var(--t-meta-line);
}
@media (min-width: 440px) {
  .main { flex-direction: row; align-items: flex-start; gap: var(--space-4); }
  .main > .text, .main > .editor { flex: 1 1 0; min-width: 0; }
  .meta { flex: none; flex-wrap: nowrap; height: var(--t-body-line); margin-top: 0; gap: var(--space-4); }
  .meta .m-notes { order: 1; } .meta .m-progress { order: 2; } .meta .m-due { order: 3; }
}
.meta .item { display: inline-flex; align-items: center; gap: var(--space-2); }
.meta svg { width: 13px; height: 13px; }
/* For Today: the list a task is in; a tap opens the task there */
.meta .m-list { max-width: 11em; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--smoke); text-decoration: underline dotted; text-underline-offset: 3px; }
button.m-list:active { color: var(--violet); }
.due { display: inline-flex; align-items: center; min-height: 24px; color: var(--smoke); white-space: nowrap; }
.pill { display: inline-flex; align-items: center; height: 24px; padding: 0 var(--space-3); border-radius: var(--r-control); font-weight: 500; white-space: nowrap; }
button.m-due { transition: transform var(--press-out) var(--ease-out); }
button.m-due:active { transform: scale(var(--press-button)); transition-duration: var(--press-in); }
/* very narrow (200% zoom on a phone): no drag handle column, half the indent, so the text keeps its width */
@media (max-width: 280px) {
  :root { --row-indent: 10px; --head-x: 30px; --text-x: 56px; }
  .row { grid-template-columns: 0 24px 26px minmax(0, 1fr) 32px; }
  .grip { visibility: hidden; overflow: hidden; }
}
.pill.over { background: var(--alert-wash); color: var(--alert); }
.pill.soon { background: var(--amber-wash); color: var(--amber); }
.more {
  display: grid; place-items: center; width: 40px; height: 30px; border-radius: var(--r-control); color: var(--smoke); opacity: .7;
  transition: background-color var(--press-out) var(--ease-out), transform var(--press-out) var(--ease-out);
}
.more svg { width: 17px; height: 17px; }
button.more:active { background: var(--card-pressed); transform: scale(var(--press-icon)); transition-duration: var(--press-in); }
@media (pointer: coarse) { .more { opacity: .5; } }
@media (hover: hover) { .more { opacity: 0; } .row:hover .more, .row.sel .more, .more:focus-visible { opacity: .8; } }

/* an open task's notes: quiet text under its text, in the same card (no box of its own, no hairline above) */
.notes {
  --depth: 0;
  padding: 0 var(--space-5) 10px calc(var(--text-x) + var(--depth) * var(--row-indent));
  color: var(--note-ink); font-size: var(--t-meta-size); line-height: 20px; white-space: pre-wrap; overflow-wrap: anywhere; cursor: text;
}
.notes a { color: var(--violet); text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 2px; }
.notes textarea {
  display: block; width: 100%; min-height: 40px; padding: 0 0 2px; border: 0; border-bottom: 1.5px solid var(--violet); border-radius: 0;
  background: transparent; resize: none; outline: none; color: var(--ink); caret-color: var(--violet); font-size: var(--t-meta-size); line-height: 20px;
}
.notes textarea::placeholder { color: var(--smoke); }
.notes .notes-actions { display: flex; justify-content: flex-end; margin-top: var(--space-2); }

/* Postponed, Completed: the headings of their cards, in line with the status chips */
h2.completed-heading { margin: var(--card-gap) 0 0; font: inherit; }
.completed-toggle {
  display: flex; align-items: flex-end; gap: var(--space-2); width: 100%; min-height: 44px; margin-top: -20px;
  padding: 0 var(--card-padding) 6px var(--head-x); border-radius: var(--r-control); color: var(--smoke); text-align: left;
  font-size: var(--t-small-size); line-height: var(--t-small-line); font-weight: var(--t-small-weight);
  transition: color var(--press-out) var(--ease-out);
}
.completed-toggle:active { color: var(--ink); transition-duration: var(--press-in); }
.completed-toggle .count { font-weight: 400; }
.completed-toggle svg { width: 10px; height: 10px; margin: 0 0 3px auto; transition: transform .15s; }
.completed-toggle.open svg { transform: rotate(90deg); }
@media (hover: hover) { .completed-toggle:hover { color: var(--ink); } }
.completed-heading + .tasks { margin-top: 0; }
.empty-state { margin: var(--space-6) var(--card-padding) 0 var(--head-x); color: var(--smoke); }
.view-header ~ .empty-state { margin-left: var(--card-padding); }
/* where a dragged task would go: 2 px of violet over the hairline, taking no room */
.drop-line {
  position: relative; z-index: 2; height: 2px; margin: -1px var(--space-3) -1px calc(var(--text-x) + var(--depth, 0) * var(--row-indent));
  background: var(--violet); border-radius: 1px; pointer-events: none;
}
/* a list someone shares with this device: where it comes from (and that it is view-only), above its cards */
.shared-note { margin: 0 var(--card-padding) var(--space-2) var(--head-x); color: var(--smoke); font-size: var(--t-meta-size); line-height: var(--t-meta-line); }
.shared-note b { color: var(--ink); font-weight: 600; }
.shared-note.trouble { color: var(--ink); }

/* ------------------------------------------------------------------ add line: a card of its own, right under the last task */
/* the "+" sits in the chip column and the text in the task text column, like the next line of the list; it scrolls with the list */
.add { margin: var(--space-3) 0 0; padding: 0; scroll-margin-bottom: var(--space-4); }
.add-card {
  display: flex; align-items: center; gap: var(--space-3); min-height: var(--row-min-touch);
  padding: 0 var(--card-padding) 0 var(--head-x); border-radius: var(--r-card); background: var(--card);
}
@media (pointer: fine) { .add-card { min-height: var(--row-min-pointer); } }
.add-plus, .add-go { display: grid; place-items: center; width: 18px; height: 18px; color: var(--violet); flex: none; }
.add-plus svg { width: 15px; height: 15px; }
.add-go { width: 32px; height: 32px; margin-right: -8px; border-radius: 50%; }
.add-go svg { width: 16px; height: 16px; }
.add input { flex: 1; min-width: 0; padding: var(--space-3) 0; border: 0; background: transparent; outline: none; caret-color: var(--violet); }
.add input::placeholder { color: var(--smoke); }

/* ------------------------------------------------------------------ sheets (menus, pickers, dialogs) */
.sheet-wrap { position: fixed; inset: 0; z-index: 20; }
.sheet-backdrop { position: absolute; inset: 0; background: var(--backdrop); animation: fade .16s ease-out; }
.sheet {
  position: absolute; left: 0; right: 0; bottom: 0; max-width: 560px; max-height: 86%; margin: 0 auto; overflow-y: auto;
  padding: var(--space-3) var(--space-3) calc(env(safe-area-inset-bottom) + var(--space-4));
  background: var(--frame); border-top: 1px solid var(--edge); border-radius: var(--r-container) var(--r-container) 0 0;
  animation: rise .2s cubic-bezier(.2, .8, .2, 1); overscroll-behavior: contain;
}
@media (min-width: 800px) { .sheet { bottom: auto; top: 12%; border: 1px solid var(--edge); border-radius: var(--r-container); } }
@keyframes rise { from { transform: translateY(24px); opacity: 0; } }
@keyframes fade { from { opacity: 0; } }
.sheet-handle { width: 36px; height: 4px; border-radius: 2px; background: var(--edge); margin: 2px auto var(--space-4); }
.sheet h2 {
  margin: 0 var(--space-4) var(--space-3); color: var(--smoke); overflow-wrap: anywhere;
  font-size: var(--t-meta-size); line-height: var(--t-meta-line); font-weight: 500;
}
.menu-item {
  display: flex; align-items: center; gap: var(--space-4); width: 100%; min-height: 48px; padding: var(--space-3) var(--space-4);
  border-radius: var(--r-control); text-align: left; color: var(--ink); transition: background-color var(--press-out) var(--ease-out);
}
.menu-item:active, .menu-item.current { background: var(--menu-hover); }
.menu-item:not(:disabled):active { transition-duration: var(--press-in); }
@media (hover: hover) { .menu-item:hover { background: var(--menu-hover); } }
.menu-item .hint { margin-left: auto; color: var(--smoke); font-size: var(--t-meta-size); font-variant-numeric: tabular-nums; }
.menu-item svg { width: 17px; height: 17px; color: var(--smoke); flex: none; }
.menu-item.danger, .menu-item.danger svg { color: var(--alert); }
.menu-sep { height: 1px; margin: var(--space-2) var(--space-4); background: var(--line); }
.field {
  display: block; width: 100%; margin: var(--space-2) 0; padding: 10px var(--space-4); border: 1px solid var(--line);
  border-radius: var(--r-control); background: var(--surface); color: var(--ink); outline: none; caret-color: var(--violet);
}
.field:focus { border-color: var(--violet); }
.field.bad { border-color: var(--alert); }
.field-row { display: flex; align-items: center; gap: var(--space-3); padding: var(--space-2) var(--space-2); }
.field-row .field { flex: 1; min-width: 0; }
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--space-3); min-height: 44px;
  padding: var(--space-3) var(--space-5); border-radius: var(--r-control); background: var(--button-bg); color: var(--ink);
  font-size: var(--t-label-size); line-height: var(--t-label-line); font-weight: var(--t-label-weight); white-space: nowrap;
  transition: background-color var(--press-out) var(--ease-out), filter var(--press-out) var(--ease-out), transform var(--press-out) var(--ease-out);
}
.btn svg { width: 15px; height: 15px; flex: none; }
.btn.primary { background: var(--violet); color: var(--on-violet); font-weight: 600; }
.btn.danger { color: var(--alert); }
.btn:disabled { opacity: .5; }
/* (pressed: a step more ink, as a card's rows; the violet one a little darker) */
.btn:not(:disabled):active { background: var(--line); transform: scale(var(--press-button)); transition-duration: var(--press-in); }
.btn.primary:not(:disabled):active { background: var(--violet); filter: brightness(.88); }
.btn-row { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: var(--space-3); padding: var(--space-3) var(--space-2) var(--space-1); }
.sheet p { margin: var(--space-2) var(--space-4) var(--space-4); color: var(--smoke); }

/* ------------------------------------------------------------------ Settings and the views it opens */
/* a view's header: Back (to where the view was opened from) and its title */
.view-header { display: flex; align-items: center; gap: var(--space-2); width: 100%; min-height: 48px; padding: var(--space-2) var(--space-3) var(--space-2) 0; cursor: pointer; }
.view-header .back {
  display: grid; place-items: center; width: 44px; height: 44px; border-radius: var(--r-control);
  transition: background-color var(--press-out) var(--ease-out), transform var(--press-out) var(--ease-out);
}
/* (the whole header goes back: pressing anywhere on it presses Back) */
.view-header:active .back { background: var(--hover); transform: scale(var(--press-icon)); transition-duration: var(--press-in); }
@media (hover: hover) { .view-header:hover .back { background: var(--hover); } }
.view-header svg { width: 13px; height: 13px; color: var(--smoke); }
.view-header h1 { margin: 0; min-width: 0; overflow-wrap: anywhere; font-size: var(--t-title-size); line-height: var(--t-title-line); font-weight: var(--t-title-weight); }

/* A row of a card, all on one line: [icon] label ...... [dot] value [chevron | switch | text button]. The label gives
   way first (it ends in "..."; a long value is the one cut instead: .long); what a second line used to say is in the
   footnote under the card, the row's tooltip and what a screen reader reads. */
.g-row {
  display: flex; align-items: center; gap: var(--space-4); width: 100%; min-height: var(--card-row-min);
  padding: 6px var(--card-padding); background: var(--card); color: var(--ink); text-align: left;
  font-size: var(--t-body-size); line-height: var(--t-body-line);
}
.g-row.icon { --line-x: calc(var(--card-padding) + 28px); }
button.g-row { transition: background-color var(--press-out) var(--ease-out); }
button.g-row:disabled { cursor: default; opacity: .55; }
/* a row only tints when pressed (a whole line shrinking would come apart from its card) */
button.g-row:not(:disabled):active { background: var(--card-pressed); transition-duration: var(--press-in); }
@media (hover: hover) { button.g-row:not(:disabled):hover { background: var(--card-hover); } button.g-row:not(:disabled):active { background: var(--card-pressed); } }
.g-icon { display: grid; place-items: center; flex: none; width: 16px; color: var(--smoke); }
.g-icon svg { width: 16px; height: 16px; }
.g-label { flex: 1 1 0; min-width: 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.g-value { display: flex; align-items: center; flex: 0 1 auto; min-width: 0; color: var(--smoke); font-variant-numeric: tabular-nums; }
.g-vtext { min-width: 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.g-row.long .g-label { flex: none; max-width: 60%; }
.g-row.long .g-value { flex: 1 1 0; justify-content: flex-end; }
/* a row that opens a page: its name stays whole and the status after it is the one cut short (Georgian and German
   names and statuses run long: "სინქრონიზაცია და გაზიარება") */
.g-row.link .g-label { flex: 0 1 auto; max-width: 70%; }
.g-row.link .g-value { flex: 1 1 0; justify-content: flex-end; }
.g-chev { display: grid; place-items: center; flex: none; color: var(--smoke); }
.g-chev svg { width: 11px; height: 11px; transition: transform .15s; }
.g-row[aria-expanded="true"] .g-chev svg { transform: rotate(90deg); }
/* the "needs a look" mark: a violet dot, always before words that say what it is about */
.dot { flex: none; width: 7px; height: 7px; margin-right: var(--space-3); border-radius: 50%; background: var(--violet); }
/* actions are rows: their label violet, red when risky */
.g-row.action .g-label { color: var(--violet); }
.g-row.action.danger .g-label { color: var(--alert); }
/* a small button at the end of a row (Join, Leave, Restore): text only */
.g-btn {
  flex: none; min-height: 32px; margin: -4px -8px -4px 0; padding: 0 var(--space-3); border-radius: var(--r-control);
  color: var(--violet); font-weight: 500; white-space: nowrap;
  transition: background-color var(--press-out) var(--ease-out), transform var(--press-out) var(--ease-out);
}
.g-btn.danger { color: var(--alert); }
.g-btn + .g-btn { margin-left: 0; }
.g-btn:active { background: var(--card-pressed); transform: scale(var(--press-button)); transition-duration: var(--press-in); }
@media (hover: hover) { .g-btn:hover { background: var(--card-pressed); } }
@media (pointer: coarse) { .g-btn { min-height: 40px; } }
/* a switch row: the whole row is the switch. Off: a smoke track (visible on the light card, unlike a hairline grey) */
.switch { position: relative; flex: none; width: 36px; height: 20px; border-radius: 10px; background: var(--smoke); }
.switch .knob { position: absolute; top: 3px; left: 3px; width: 14px; height: 14px; border-radius: 50%; background: var(--card); transition: transform .15s; }
.switch.on { background: var(--violet); }
.switch.on .knob { transform: translateX(16px); background: var(--on-violet); }
/* a text box that is a row (a link to paste), its buttons at the end; a red line under it when it is not taken */
.g-row.input { padding-top: 0; padding-bottom: 0; }
.g-row.input:focus-within { outline: var(--ring); outline-offset: -2px; }
.g-input {
  flex: 1 1 auto; min-width: 0; height: var(--card-row-min); padding: 0; border: 0; border-radius: 0; background: transparent;
  color: var(--ink); caret-color: var(--violet); outline: none; font-size: var(--t-body-size);
}
.g-input::placeholder { color: var(--smoke); }
.g-input[readonly] { color: var(--smoke); }
.g-input.bad { box-shadow: inset 0 -1.5px 0 var(--alert); }
/* a choice of a few, on a quiet track; the current one violet */
.segmented { display: flex; flex: none; padding: 2px; border-radius: var(--r-control); background: var(--card-pressed); }
.segmented button {
  min-height: 32px; padding: var(--space-1) var(--space-4); border-radius: 5px; color: var(--smoke); font-size: var(--t-label-size); font-weight: 500;
  transition: background-color var(--press-out) var(--ease-out), transform var(--press-out) var(--ease-out);
}
.segmented button.on { background: var(--violet); color: var(--on-violet); font-weight: 600; }
.segmented button:active { transform: scale(var(--press-button)); transition-duration: var(--press-in); }
.segmented button:not(.on):active { background: var(--card-hover); }
@media (pointer: coarse) { .segmented button { min-height: 36px; } }
.time-input { flex: none; min-width: 84px; padding: var(--space-1) var(--space-3); border: 0; border-radius: var(--r-control); background: var(--card-pressed); color: var(--ink); text-align: center; }
/* a version of a task in Conflicts: your own words, so it wraps (the label in a column before it) */
.g-row.version { align-items: flex-start; padding-top: 11px; padding-bottom: 11px; }
.g-row.version .g-lead { flex: none; width: 7.5em; color: var(--smoke); }
.g-row.version .g-text { flex: 1 1 0; min-width: 0; white-space: pre-wrap; overflow-wrap: anywhere; }
/* Keyboard shortcuts: the keys as small caps on the right */
.keys { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: var(--space-2); flex: none; max-width: 55%; }
kbd { padding: 1px 6px 2px; border-radius: var(--r-chip); background: var(--card-pressed); color: var(--ink); font: inherit; font-size: var(--t-small-size); line-height: var(--t-small-line); white-space: nowrap; }
/* a long row's text at 200 % zoom: it wraps instead of being cut (nothing is lost when the screen is this narrow) */
@media (max-width: 359px) {
  .g-label, .g-vtext { white-space: normal; overflow-wrap: anywhere; }
  .g-label { min-width: 5em; }
  .g-row.long .g-label { max-width: 50%; }
}
/* the quiet line at the bottom of every Settings view: the version, and (Linux, macOS) an update waiting */
.version-line {
  display: flex; flex-wrap: wrap; align-items: center; gap: 0 var(--space-4); margin: var(--card-gap) var(--card-padding) 0;
  color: var(--smoke); font-size: var(--t-meta-size); line-height: var(--t-meta-line); font-variant-numeric: tabular-nums; text-align: left;
}
button.version-line {
  margin-left: calc(var(--card-padding) - 6px); padding: 3px 6px; border-radius: var(--r-control);
  transition: background-color var(--press-out) var(--ease-out), transform var(--press-out) var(--ease-out);
}
@media (hover: hover) { button.version-line:hover { background: var(--hover); } }
button.version-line:active { background: var(--hover); transform: scale(var(--press-button)); transition-duration: var(--press-in); }
.version-line .upd { display: inline-flex; align-items: center; color: var(--violet); }
.version-line .dot { margin-right: 6px; }
.callout {
  margin: var(--space-2) 0 0; padding: var(--space-4) var(--card-padding); border-radius: var(--r-card);
  background: var(--card); color: var(--note-ink); font-size: var(--t-meta-size); line-height: 20px;
}
.callout b { color: var(--ink); font-weight: 600; }
.callout .btn-row { padding: var(--space-2) 0 0; }
/* the cloud setup's output while it runs (Settings > Sync & sharing > Set up sync, Linux and macOS) */
.setup-log {
  margin: var(--space-3) 0 0; padding: var(--space-3) var(--card-padding); max-height: 16em; overflow: auto; border-radius: var(--r-card);
  background: var(--card); color: var(--ink); font-family: ui-monospace, Menlo, Consolas, monospace; font-size: var(--t-small-size);
  line-height: 1.5; white-space: pre-wrap; overflow-wrap: anywhere;
}
.setup-log a { color: var(--violet); }

/* welcome / pairing */
.welcome { display: flex; flex-direction: column; align-items: center; gap: var(--space-3); padding: 40px var(--space-5) var(--space-6); text-align: center; }
.welcome img { width: 76px; height: 76px; margin-bottom: var(--space-3); border-radius: 18px; }
.welcome h1 { margin: var(--space-2) 0 0; font-size: var(--t-display-size); line-height: var(--t-display-line); font-weight: var(--t-display-weight); }
.welcome p { max-width: 420px; margin: 0 0 var(--space-3); color: var(--smoke); }
.welcome .steps { max-width: 420px; margin: var(--space-2) 0 var(--space-5); padding-left: 22px; color: var(--note-ink); text-align: left; }
.welcome .steps li { margin: var(--space-2) 0; }
.welcome .steps b { color: var(--ink); font-weight: 600; }
.welcome .field-row { width: 100%; max-width: 440px; padding: 0; }
/* a one-time pairing code: large, spaced, easy to read off one screen and type on another */
.pair-code { display: flex; flex-direction: column; align-items: center; gap: var(--space-1); margin: var(--space-2) 0 var(--space-4); }
.pair-code .code { color: var(--ink); font-size: 28px; line-height: 36px; font-weight: 600; letter-spacing: .08em; font-variant-numeric: tabular-nums; user-select: all; -webkit-user-select: all; }
.pair-code .hint { color: var(--smoke); font-size: var(--t-small-size); line-height: var(--t-small-line); }
.sheet .steps { margin: 0 0 var(--space-3); padding-left: 22px; }
.sheet .steps li { margin: var(--space-2) 0; }
/* what just happened, above the steps (Use with AI: "Link copied. Paste it in the page that opened.") */
.sheet p.sheet-lead { margin: 0 0 var(--space-2); color: var(--ink); font-weight: 600; }
.sheet img.qr { display: block; width: min(260px, 70vw); height: auto; margin: var(--space-2) auto var(--space-4); border-radius: var(--r-control); image-rendering: pixelated; }

/* shared lists: the badge after a list's name (the title, the lists menu), the Share sheet (invite, people), the menu
   item that explains why not */
.shared-badge { display: grid; place-items: center; flex: none; color: var(--smoke); }
.shared-badge svg { width: 13px; height: 13px; }
.switcher .shared-badge svg { width: 16px; height: 16px; }
.menu-item:disabled { opacity: .55; }
.sheet p.sheet-note { margin: var(--space-1) var(--space-4) var(--space-3); font-size: var(--t-meta-size); line-height: var(--t-meta-line); }
/* the Share sheet: grouped like Settings (cards on the sheet's frame colour; its sections are h3 under the sheet's title) */
.sheet .group { margin-left: var(--space-1); margin-right: var(--space-1); }
.sheet .g-head { margin: var(--card-gap) var(--space-1) 6px; padding: 0 var(--card-padding); }
.sheet .g-head + .group { margin-top: 0; }
.sheet h2 + .g-head { margin-top: var(--space-2); }
.sheet p.g-foot { margin: 6px var(--space-1) 0; padding: 0 var(--card-padding); font-size: var(--t-meta-size); line-height: var(--t-meta-line); }
.sheet p.g-note { margin: var(--space-2) var(--space-1) 0; padding: 0 var(--card-padding); font-size: var(--t-meta-size); line-height: var(--t-meta-line); }
.sheet p.g-foot.alert { color: var(--alert); }
.sheet img.qr.in-group { margin-top: var(--card-gap); }
/* a person's rows, open under them: their state, the access choices, revoke */
.g-row.sub { padding-left: calc(var(--card-padding) + 28px); --line-x: calc(var(--card-padding) + 28px); }
.g-row.sub.info { color: var(--smoke); }
.g-row .check { display: grid; place-items: center; flex: none; width: 16px; color: var(--violet); }
.menu-item .check { display: grid; place-items: center; flex: none; width: 16px; }   /* (Language: the choices line up, checked or not) */
.g-row .check svg { width: 14px; height: 14px; }
.linkish { color: var(--violet); font-weight: 600; text-decoration: underline; text-underline-offset: 2px; transition: opacity var(--press-out) var(--ease-out); }
.linkish:active { opacity: .6; transition-duration: var(--press-in); }
/* join.html: the page an invite link opens */
.join-page { overflow-y: auto; }
.join-ways { display: flex; flex-direction: column; gap: var(--space-4); width: 100%; max-width: 460px; text-align: left; }
.join-ways .btn, .sheet a.btn { text-decoration: none; }
.join-way { display: flex; flex-direction: column; align-items: flex-start; gap: var(--space-2); padding: var(--space-4); border-radius: var(--r-control); background: var(--note-bg); }
.join-way h2 { margin: 0; color: var(--ink); font-size: var(--t-body-size); line-height: var(--t-body-line); font-weight: 600; }
.welcome .join-way p { margin: 0; color: var(--note-ink); }
.welcome .join-way b { color: var(--ink); font-weight: 600; }
.join-way .btn-row { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.join-cmd code { display: block; margin-top: var(--space-1); padding: var(--space-2); border-radius: var(--r-control); background: var(--surface); color: var(--ink); font-size: var(--t-small-size); line-height: var(--t-small-line); overflow-wrap: anywhere; user-select: all; -webkit-user-select: all; }
.welcome .join-note { color: var(--smoke); font-size: var(--t-meta-size); line-height: var(--t-meta-line); }
.text:not(button) { cursor: default; }   /* a view-only list's task: read, not edited */

/* toast */
.toast {
  position: fixed; left: 50%; bottom: calc(env(safe-area-inset-bottom) + 76px); z-index: 30; transform: translateX(-50%);
  display: flex; align-items: center; gap: var(--space-5); max-width: calc(100% - 32px); padding: var(--space-4) var(--space-5);
  border: 1px solid var(--edge); border-radius: var(--r-control); background: var(--frame); color: var(--ink);
  box-shadow: 0 8px 24px rgba(0, 0, 0, .25); font-size: var(--t-meta-size); line-height: var(--t-meta-line); animation: rise .18s ease-out;
}
.toast button { color: var(--violet); font-weight: 600; min-height: 32px; transition: transform var(--press-out) var(--ease-out); }
.toast button:active { transform: scale(var(--press-button)); transition-duration: var(--press-in); }

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