/* The drawn app components (spec section 5). Every app screen on the page is
   this markup and these rules, never a picture. Tokens only, no colour literal;
   quadrant hues come from --q-*.

   Sizes are in em. Each frame sets its own font size from its width, so a
   model drawn inside it scales with the frame:
     phone: 1em = --phone-w / 24, about the app's 16 pt body on a 393 pt screen;
     Mac:   1em = --mac-w / 64, about the app's 13 pt body in an 845 pt window.
   The px radius ladder in styles.css cannot scale with a frame, so each frame
   restates the app's ladder steps (sm 6, md 10, lg 14, xl 22, in the app's own
   points) in its em.

   Every size under 1em is written max(<em>, var(--model-min-text)). Under
   900 px of width the floor is 7 px, so no label in a model falls under 7 px
   on a phone (Task 11: on a 375 x 629 iPhone mini the phone's base text is
   7.05 px and its 0.6875em labels were 4.86 px). The floor covers the phone
   layouts only, by the controller's ruling in Task 11 fix round 1: at 900 px
   and wider the models are pictures of the apps at device scale, as in the
   prototype, with the page's heading beside them, so there the floor is 0
   and the labels keep the app's proportions. */
:root { --model-min-text: 0px; }

@media (max-width: 899px) {
  :root { --model-min-text: 7px; }
}

.device-phone {
  /* The app's sm/md/lg/xl radius ladder restated in em, so the models scale with their frame. */
  --radius-model-sm: 0.375em;
  --radius-model-md: 0.625em;
  --radius-model-lg: 0.875em;
  --radius-model-xl: 1.375em;
  --radius-model-full: 999em;
  /* An iPhone's proportions at any size (spec section 5, MISTAKES
     2026-10-08): the corner radius is 15 percent of the frame's width and the
     rim 2.5 percent, so the screen's radius, the outer one minus the rim, is
     12.5 percent of the width: 3em, since the frame is 24em wide. */
  --rim-w: calc(var(--phone-w, 300px) * 0.025);
  --radius-phone: calc(var(--phone-w, 300px) * 0.15);
  --radius-phone-screen: calc(var(--radius-phone) - var(--rim-w));
  width: var(--phone-w, 300px);
  font-size: calc(var(--phone-w, 300px) / 24);
  line-height: 1.3;
  padding: var(--rim-w);
  background: var(--rim);
  border-radius: var(--radius-phone);
  box-shadow: var(--shadow-device);
}

/* The Mac's em is its width over --mac-cols (64, about the app's 13 pt body
   in an 845 pt window). Its corner radius is a fraction of its width. */
.device-mac {
  /* The app's sm/md/lg radius ladder restated in em, so the models scale with their frame. */
  --radius-model-sm: 0.46em;
  --radius-model-md: 0.77em;
  --radius-model-lg: 1.08em;
  --radius-model-full: 999em;
  --radius-window: calc(var(--mac-w, 880px) * 0.016);
  --sidebar-w: 13.5em;
  display: grid;
  grid-template-rows: auto minmax(0, 1fr);
  width: var(--mac-w, 880px);
  aspect-ratio: 16 / 10;
  font-size: calc(var(--mac-w, 880px) / var(--mac-cols, 64));
  line-height: 1.3;
  background: var(--canvas);
  border: 1px solid var(--hairline);
  border-radius: var(--radius-window);
  box-shadow: var(--shadow-device);
  overflow: hidden;
}

.device-phone,
.device-mac {
  color: var(--text-primary);
  font-family: var(--font-body);
  text-align: left;
}

/* A device's screen holds its screen layer (.screen) in one grid cell. */
.device-screen {
  display: grid;
  min-width: 0;
  min-height: 0;
}

.device-screen > .screen {
  position: relative;
  grid-area: 1 / 1;
  min-width: 0;
  min-height: 0;
  background: var(--canvas);
}

/* The phone's screen: concentric with the rim. No status bar, no camera
   cut-out: the frame is neutral (global constraints). The content keeps 3em,
   the screen's corner radius, from the top and the bottom, so nothing sits
   inside the curve. */
.device-phone .device-screen {
  aspect-ratio: 9 / 19.5;
  background: var(--canvas);
  border-radius: var(--radius-phone-screen);
  overflow: hidden;
}

.device-phone .screen {
  display: flex;
  flex-direction: column;
  padding: 3em 1em;
}

.device-mac .screen { display: grid; grid-template-rows: minmax(0, 1fr); }

/* Quadrant hue, read by bars, dots and tiles. */
[data-q="do"] { --hue: var(--q-do); }
[data-q="schedule"] { --hue: var(--q-schedule); }
[data-q="quick"] { --hue: var(--q-quick); }
[data-q="later"] { --hue: var(--q-later); }

/* Icons are inline SVG drawn in currentColor. */
.device-phone svg,
.device-mac svg {
  display: block;
  flex: none;
  width: 1.125em;
  height: 1.125em;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.4;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* Pane heading: a large title, as the app's root screens have, and an
   optional pill beside it. */
.pane-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75em;
  margin: 0 0 1em;
  padding: 0 0.25em;
}

.pane-title {
  margin: 0;
  font-size: 1.875em;
  font-weight: 700;
  line-height: 1.15;
  letter-spacing: -0.01em;
}

.pill {
  display: inline-flex;
  align-items: center;
  flex: none;
  padding: 0.25em 0.75em;
  background: var(--accent-quiet);
  color: var(--accent-text);
  border-radius: var(--radius-model-full);
  font-size: max(0.8125em, var(--model-min-text));
  font-weight: 600;
  white-space: nowrap;
}

/* Task row: open circle, then the title over its meta line. The completion
   control is an open circle on every surface of the app, never a square. */

.task-list,
.quad-list {
  margin: 0;
  padding: 0;
  list-style: none;
}

.task-list {
  padding-block: 0.25em;
  background: var(--surface);
  border-radius: var(--radius-model-xl);
}

.task-row {
  position: relative;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: start;
  gap: 0.75em;
  padding: 0.75em 1em 0.75em 1.5em;
}

/* The quadrant bar at the row's leading edge, as the app's iOS rows draw it.
   Untriaged Inbox rows carry the Later grey. */
.task-row[data-q]::before,
.chip--task::before {
  content: "";
  position: absolute;
  left: 0.625em;
  top: 0.75em;
  bottom: 0.75em;
  width: 0.1875em;
  background: var(--hue);
  border-radius: var(--radius-model-full);
}

/* Separator between rows, inset to start under the title. */
.task-row + .task-row::after,
.chip--task + .chip--task::after {
  content: "";
  position: absolute;
  top: 0;
  left: 3.625em;
  right: 1em;
  height: 1px;
  background: var(--hairline);
}

.t-check {
  position: relative;
  display: grid;
  place-items: center;
  width: 1.375em;
  height: 1.375em;
  border: 0.09375em solid var(--text-tertiary);
  border-radius: 50%;
  color: var(--surface);
}

.t-check svg {
  width: 0.875em;
  height: 0.875em;
  stroke-width: 2.2;
}

/* A ticked circle: a filled disc with the tick, laid over the open circle
   and its border, so a scene can fill it with transform and opacity alone.
   A done row's disc is the tertiary ink; a picked row's is the accent. */
.t-tick {
  position: absolute;
  inset: -0.09375em;
  display: grid;
  place-items: center;
  background: var(--text-tertiary);
  color: var(--surface);
  border-radius: 50%;
}

.t-check--pick .t-tick {
  background: var(--accent);
  color: var(--on-accent);
}

.t-body { min-width: 0; }

/* A title in a model truncates on one line, as a row in the app does. */
.t-title {
  display: block;
  font-size: 1.0625em;
  line-height: 1.3;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.t-meta {
  display: flex;
  align-items: center;
  gap: 0.5em;
  min-width: 0;
  margin-top: 0.125em;
  color: var(--text-secondary);
  font-size: max(0.8125em, var(--model-min-text));
  line-height: 1.3;
  white-space: nowrap;
  overflow: hidden;
}

/* A long list name truncates inside the row instead of widening it. */
.t-meta > * { flex: none; }
.t-meta > .chip--list {
  flex: 0 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
}

.chip--list { color: var(--text-secondary); }

/* Priority: the app's words (High, Medium, Low) in a capsule, the tint on the
   text, a quiet wash and a weaker stroke of the same tint (PriorityChip.swift).
   The app tints High red and Medium orange; the token table has no signal
   colours, so High takes the accent and Medium and Low stay neutral. */
.chip--prio {
  --tint: var(--accent-text);
  padding: 0 0.5em;
  /* A 10 percent wash: at 14 the High text on it was 4.44 to 1 (axe, Task 11). */
  background: color-mix(in srgb, var(--tint) 10%, transparent);
  border: 1px solid color-mix(in srgb, var(--tint) 35%, transparent);
  color: var(--tint);
  border-radius: var(--radius-model-full);
}

.chip--prio-medium { --tint: var(--text-primary); }
.chip--prio-low { --tint: var(--text-secondary); }

.t-date { margin-left: auto; color: var(--text-secondary); }

.task-row--done .t-title {
  color: var(--text-tertiary);
  text-decoration: line-through;
}

/* Inbox. */

.inbox {
  display: flex;
  flex-direction: column;
}

/* Triage card: the card in front, two cards behind it, then the four
   destinations that end the card. */

.triage-card {
  display: flex;
  flex-direction: column;
}

.card-stack {
  position: relative;
  isolation: isolate;
  margin-bottom: 2em;
}

.card-stack::before,
.card-stack::after {
  content: "";
  position: absolute;
  z-index: -1;
  top: 0;
  background: var(--surface-raised);
  border: 1px solid var(--hairline);
  border-radius: var(--radius-model-xl);
}

.card-stack::before { left: 1.5em; right: 1.5em; bottom: -1.25em; }
.card-stack::after { left: 0.75em; right: 0.75em; bottom: -0.625em; }

.card {
  padding: 1.25em;
  background: var(--surface);
  border: 1px solid var(--hairline);
  border-radius: var(--radius-model-xl);
}

.card-eyebrow {
  margin: 0 0 0.5em;
  color: var(--accent-text);
  font-size: max(0.8125em, var(--model-min-text));
  font-weight: 600;
  letter-spacing: 0.04em;
}

.card .t-title {
  font-size: 1.5em;
  font-weight: 700;
  letter-spacing: -0.01em;
}

.card .t-meta {
  margin-top: 0.5em;
  font-size: max(0.9375em, var(--model-min-text));
}

.card-hint {
  margin: 0.75em 0 0;
  color: var(--text-secondary);
  font-size: max(0.875em, var(--model-min-text));
}

.dest-label {
  margin: 0 0 0.5em;
  padding: 0 0.25em;
  color: var(--text-secondary);
  font-size: max(0.875em, var(--model-min-text));
  font-weight: 600;
}

.dest {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.5em;
}

/* A destination tile: the quadrant's hue as a light wash and a border, the one
   place the app lets a quadrant colour fill an area. */
.dest-btn {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: center;
  column-gap: 0.375em;
  padding: 0.75em 0.5em;
  background: color-mix(in srgb, var(--hue) 8%, var(--surface));
  border: 1px solid color-mix(in srgb, var(--hue) 45%, transparent);
  border-radius: var(--radius-model-lg);
}

.dest-dot {
  width: 0.5em;
  height: 0.5em;
  background: var(--hue);
  border-radius: 50%;
}

.dest-name {
  font-weight: 600;
  white-space: nowrap;
}

/* A note that does not fit wraps rather than ending in an ellipsis: on the
   7 px floor "Sets High priority" is about as wide as its button on a 375 px
   iPhone mini (Task 11). */
.dest-note {
  grid-column: 1 / -1;
  min-width: 0;
  margin-top: 0.125em;
  color: var(--text-secondary);
  font-size: max(0.8125em, var(--model-min-text));
  line-height: 1.2;
}

/* Matrix. On the phone the four quadrants stack, each a heading over a
   grouped list, as the app's iPhone Matrix does. */

.matrix {
  display: flex;
  flex-direction: column;
  gap: 0.875em;
  min-height: 0;
}

.quad { min-width: 0; }

.quad-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.5em;
  margin-bottom: 0.375em;
  padding: 0 0.75em;
  color: var(--text-secondary);
  font-size: max(0.9375em, var(--model-min-text));
  font-weight: 600;
}

.quad-count { font-variant-numeric: tabular-nums; }

.quad-list {
  padding-block: 0.125em;
  background: var(--surface);
  border-radius: var(--radius-model-xl);
}

.chip--task {
  position: relative;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: center;
  gap: 0.75em;
  padding: 0.5em 1em 0.5em 1.5em;
}

.chip--task::before { top: 0.5em; bottom: 0.5em; }

.chip--task .t-title { font-size: 1em; }

/* Mac Matrix: two by two cells, chrome and a hairline, no wash. The hue is a
   short bar beside the quadrant's name and the count trails. */

.matrix--mac {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  grid-template-rows: repeat(2, minmax(0, 1fr));
  flex: 1;
  gap: 0.625em;
  min-height: 0;
}

.matrix--mac .quad {
  display: flex;
  flex-direction: column;
  min-height: 0;
  padding: 0.75em 0.5em 0.5em;
  background: var(--surface);
  border: 1px solid var(--hairline);
  border-radius: var(--radius-model-md);
  overflow: hidden;
}

.matrix--mac .quad-head {
  margin-bottom: 0.375em;
  padding: 0 0.25em;
  color: var(--text-primary);
  font-size: 1em;
}

.matrix--mac .quad-name {
  display: flex;
  align-items: center;
  gap: 0.5em;
  font-weight: 700;
}

.matrix--mac .quad-name::before {
  content: "";
  width: 0.2em;
  height: 1.1em;
  background: var(--hue);
  border-radius: var(--radius-model-full);
}

.matrix--mac .quad-count {
  color: var(--text-tertiary);
  font-size: max(0.8125em, var(--model-min-text));
  font-weight: 400;
}

.matrix--mac .quad-list {
  padding: 0;
  background: none;
  border-radius: 0;
}

.matrix--mac .chip--task {
  gap: 0.625em;
  padding: 0.5em 0.5em 0.5em 0.75em;
}

.matrix--mac .chip--task::before,
.matrix--mac .chip--task + .chip--task::after { display: none; }

.matrix--mac .t-check {
  width: 1em;
  height: 1em;
  border-width: 0.08em;
}

/* Mac window: a title bar with three neutral dots, then sidebar and main.
   The bar's left part continues the sidebar plate, as the app's window does. */

.mac-bar {
  display: flex;
  align-items: center;
  gap: 0.5em;
  height: 2.5em;
  padding: 0 1em;
  background: linear-gradient(to right, var(--sidebar-plate) var(--sidebar-w), var(--canvas) var(--sidebar-w));
}

.mac-bar .dot {
  width: 0.875em;
  height: 0.875em;
  background: var(--rim);
  border-radius: 50%;
}

.mac-body {
  display: grid;
  grid-template-rows: minmax(0, 1fr);
  grid-template-columns: var(--sidebar-w) minmax(0, 1fr);
  min-height: 0;
}

.mac-sidebar {
  display: flex;
  flex-direction: column;
  gap: 0.125em;
  min-height: 0;
  padding: 0.25em 0.625em 0.75em;
  background: var(--sidebar-plate);
  border-right: 1px solid var(--hairline);
  overflow: hidden;
}

.side-label {
  margin: 0.75em 0 0.25em;
  padding: 0 0.5em;
  color: var(--text-secondary);
  font-size: max(0.8125em, var(--model-min-text));
  font-weight: 600;
}

.side-label:first-child { margin-top: 0; }

.side-item {
  display: flex;
  align-items: center;
  gap: 0.5em;
  padding: 0.375em 0.5em;
  border-radius: var(--radius-model-sm);
  white-space: nowrap;
}

/* Sidebar icons are one neutral ink, never the smart-view tints
   (SIFT-TOKENS section 2). */
.side-item svg { color: var(--text-secondary); }

.side-count {
  margin-left: auto;
  color: var(--text-tertiary);
  font: 400 max(0.8125em, var(--model-min-text))/1 var(--font-mono);
}

/* The accent text ink, not the accent: white on the accent is 4.36 to 1, under
   the 4.5 the page keeps for text (axe, Task 11). */
.side-item.is-selected {
  background: var(--accent-text);
  color: var(--on-accent);
}

.side-item.is-selected svg,
.side-item.is-selected .side-count { color: var(--on-accent); }

/* A list's dot. The app draws each list in the user's own colour; the token
   table has no list colours, so the model draws them in one neutral ink. */
.side-dot {
  flex: none;
  width: 0.625em;
  height: 0.625em;
  margin-inline: 0.25em;
  background: var(--text-tertiary);
  border-radius: 50%;
}

.mac-main {
  display: flex;
  flex-direction: column;
  min-width: 0;
  min-height: 0;
  padding: 0 0.875em 0.875em;
}

.mac-main .pane-title {
  margin: 0 0 0.625em;
  font-size: 1.375em;
}

/* Daily review on the Mac, its last step: the four steps with Focus
   current, the question, and the tasks it offers. */

.review {
  display: flex;
  flex-direction: column;
  max-width: 40em;
  padding: 1em 1.25em 0.75em;
  background: var(--surface);
  border: 1px solid var(--hairline);
  border-radius: var(--radius-model-md);
}

.review-steps {
  display: flex;
  align-items: center;
  gap: 0.375em;
  margin: 0 0 1em;
  padding: 0;
  list-style: none;
  color: var(--text-secondary);
  font-size: max(0.8125em, var(--model-min-text));
}

.review-step {
  display: flex;
  align-items: center;
  gap: 0.375em;
  white-space: nowrap;
}

/* A step's node and label. Each step draws both of its looks in one grid
   cell, the done look (a filled node, the secondary ink) and the current
   one (a ring and the label in the accent, bold), and shows one of them by
   opacity, so the review scene (js/scenes/review.js) can walk the steps
   without changing the layout: the cell is as wide as the bold label. The
   line between two steps comes first in the second. */
.rs-node,
.rs-label { display: inline-grid; }

.rs-node { place-items: center; }

.rs-node > span,
.rs-label > span { grid-area: 1 / 1; }

.rs-node > span {
  width: 0.625em;
  height: 0.625em;
  border-radius: 50%;
}

.rs-dot { background: var(--text-tertiary); }

/* The ring is the node with its border outside it, 1em across, as the
   current step's node was before it had a done look beside it. */
.rs-ring { border: 0.1875em solid var(--accent-text); }

/* A step not reached yet: the node's outline only, in the done node's ink,
   inside the same 0.625em, so the strip reads done (filled), current (the
   ring) and to come (hollow). The authored state has no step to come, so
   it is shown only by the start state below and by the review scene. */
.rs-todo {
  box-sizing: border-box;
  border: 0.125em solid var(--text-tertiary);
  opacity: 0;
}

.rs-now { color: var(--accent-text); font-weight: 600; }

.rs-ring,
.rs-now,
.review-step.is-current .rs-dot,
.review-step.is-current .rs-plain { opacity: 0; }

.review-step.is-current .rs-ring,
.review-step.is-current .rs-now { opacity: 1; }

.review-step + .review-step::after {
  content: "";
  order: -1;
  flex: none;
  width: 1.5em;
  height: 1px;
  background: var(--hairline);
}

.review-q {
  margin: 0;
  font-size: 1.375em;
  font-weight: 700;
  line-height: 1.2;
}

.review-note {
  margin: 0.25em 0 0.75em;
  color: var(--text-secondary);
  font-size: max(0.9375em, var(--model-min-text));
}

.review .quad-list {
  padding: 0;
  background: none;
  border-radius: 0;
}

.review .chip--task {
  gap: 0.625em;
  padding: 0.5em 0.5em 0.5em 1em;
}

.review .chip--task::before { left: 0.25em; }
.review .chip--task + .chip--task::after { left: 2.625em; right: 0; }

.review .t-check {
  width: 1em;
  height: 1em;
  border-width: 0.08em;
}

/* Tomorrow's focus on the iPhone: the tasks grouped by why each one is
   offered, a tick on each one picked. */

.picker-note {
  margin: -0.5em 0 1em;
  padding: 0 0.25em;
  color: var(--text-secondary);
  font-size: max(0.875em, var(--model-min-text));
}

.picker-group + .picker-group { margin-top: 0.875em; }

.picker-head,
.focus-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.5em;
  margin: 0 0 0.375em;
  padding: 0 0.75em;
  color: var(--text-secondary);
  font-size: max(0.9375em, var(--model-min-text));
  font-weight: 600;
}

/* Today on the iPhone: the focus with its count, then the card that shows
   once every focus task is done. The count's numerals share one grid cell;
   the scene steps through them and the end state shows the last. */

.focus-count { font-variant-numeric: tabular-nums; }

.count-steps { display: inline-grid; }

.count-steps > span { grid-area: 1 / 1; }
.count-steps > span:not(:last-child) { opacity: 0; }

.focus-done {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: center;
  gap: 0.75em;
  margin-top: 0.875em;
  padding: 0.875em 1em;
  background: var(--surface);
  border-radius: var(--radius-model-xl);
}

/* The ring: a track and an arc of the same circle. Its radius makes the
   circumference 100 user units, the same as pathLength, so the arc's dash
   is 100 and stroke-dashoffset runs from 100 (empty) to 0 (full) in every
   engine. The arc starts at the top. The ring and its tick are the done
   green, as the app draws the Focus done card (FocusDoneCardMac.swift); an
   accent ring in the app is the Overview's "left today". */
.device-phone .ring {
  width: 2.5em;
  height: 2.5em;
  stroke-width: 3;
}

.ring-track { stroke: color-mix(in srgb, var(--text-secondary) 25%, transparent); }

.ring-arc {
  stroke: var(--done);
  stroke-dasharray: 100;
  stroke-dashoffset: 0;
}

.ring-tick {
  stroke: var(--done);
  stroke-width: 2.4;
}

.focus-done-title {
  margin: 0;
  font-weight: 600;
}

.focus-done-line {
  margin: 0.125em 0 0;
  color: var(--text-secondary);
  font-size: max(0.875em, var(--model-min-text));
}

/* Overview (spec 5), after the app's OverviewFiguresIOS.swift and its Mac
   sidebar panel. On the iPhone: the Overview sheet on its Attention panel, a
   ring for what is left today (the accent), focus pips (done ones filled in
   the done green, the rest an accent outline), overdue dots in the overdue
   red (SiftPalette.signalRed) and the pill to the Inbox. In the Mac sidebar:
   the Trend panel, seven bars for the week (today in the accent), a green
   dot over each day whose focus was finished, a dashed line at the average
   and the streak. Sizes are the app's points over 16 (phone) or 13 (Mac). */

/* The sheet comes up over Today, as in the app: Today stays behind it,
   dimmed, and the sheet reaches the bottom of the screen while its content
   keeps clear of the screen's corners. */
.ov-behind {
  flex: 1;
  min-height: 0;
  opacity: 0.4;
}

.ov-sheet {
  display: flex;
  flex-direction: column;
  gap: 0.875em;
  margin: 0 -0.5em -3em;
  padding: 1em 0.5em 3em;
  background: var(--canvas);
  border-radius: var(--radius-model-xl) var(--radius-model-xl) 0 0;
  box-shadow: 0 -1px 0 var(--hairline);
}

.ov-head {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  padding: 0 0.25em;
}

.ov-title {
  grid-column: 2;
  font-size: 1.0625em;
  font-weight: 600;
}

.ov-close {
  justify-self: end;
  color: var(--accent-text);
  font-weight: 600;
}

/* The segmented control, Attention chosen. */
.ov-seg {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  padding: 0.125em;
  background: color-mix(in srgb, var(--text-secondary) 14%, transparent);
  border-radius: var(--radius-model-md);
  font-size: max(0.8125em, var(--model-min-text));
  text-align: center;
}

.ov-seg > span {
  padding: 0.375em 0;
  border-radius: var(--radius-model-sm);
  white-space: nowrap;
}

.ov-seg > .is-on {
  background: var(--surface);
  font-weight: 600;
}

.ov-sheet .ov {
  display: flex;
  flex-direction: column;
  gap: 0.875em;
  padding: 1em;
  background: var(--surface);
  border-radius: var(--radius-model-lg);
}

.ov-attn {
  display: flex;
  align-items: center;
  gap: 1em;
}

/* The day ring: 96 pt with a 9 pt stroke. The circle's radius makes its
   circumference 100, the same as pathLength, so the arc's dash is 100 and
   its stroke-dashoffset is the part left undrawn: 40 at 60 percent. */
/* The ring keeps its ratio to its label (6em to 0.6875em, about 8.7 to 1)
   when the label stands on the 7 px floor, so "left today" stays inside the
   arc on a phone (Task 11). */
.ov-ring {
  position: relative;
  display: grid;
  place-items: center;
  flex: none;
  width: max(6em, 8.7 * var(--model-min-text));
  height: max(6em, 8.7 * var(--model-min-text));
}

.device-phone .ov-ring svg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  stroke-width: 3.75;
}

.ov-track { stroke: var(--hairline); }

.ov-arc {
  stroke: var(--accent);
  stroke-dasharray: 100;
  stroke-dashoffset: 40;
}

.ov-centre {
  display: grid;
  justify-items: center;
  line-height: 1.1;
}

.ov-num {
  font-size: 1.375em;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

.ov-label {
  color: var(--text-secondary);
  font-size: max(0.6875em, var(--model-min-text));
  white-space: nowrap;
}

.ov-side {
  display: grid;
  gap: 0.75em;
  min-width: 0;
}

.ov-pips,
.ov-dots {
  display: flex;
  align-items: center;
  gap: 0.3125em;
  white-space: nowrap;
}

.ov-word {
  margin-left: 0.1875em;
  color: var(--text-secondary);
  font-size: max(0.9375em, var(--model-min-text));
}

/* A pip: 14 pt, an accent outline while its task is open. A done pip is
   filled in the done green: the fill lies over the outline, so a scene can
   fill it with transform and opacity alone. */
.pip {
  position: relative;
  flex: none;
  width: 0.875em;
  height: 0.875em;
  border: 0.125em solid var(--accent);
  border-radius: 50%;
}

.pip-fill {
  position: absolute;
  inset: -0.125em;
  background: var(--done);
  border-radius: 50%;
}

.ov-count {
  margin-right: 0.125em;
  color: var(--overdue);
  font-size: 1.25em;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  line-height: 1;
}

.ov-dots .dot {
  flex: none;
  width: 0.5em;
  height: 0.5em;
  background: var(--overdue);
  border-radius: 50%;
}

.ov-pill {
  display: flex;
  align-items: center;
  justify-content: space-between;
  min-height: 2.75em;
  padding: 0 0.75em;
  background: var(--accent-quiet);
  color: var(--accent-text);
  border-radius: var(--radius-model-md);
  font-size: max(0.9375em, var(--model-min-text));
  font-weight: 600;
}

.ov-pill svg {
  width: 0.875em;
  height: 0.875em;
  stroke-width: 2;
}

/* The Mac sidebar's Overview section: its heading, the profile in the accent
   text, then the Trend panel at sidebar size. */
.side-ov {
  display: grid;
  gap: 0.375em;
  margin-bottom: 0.25em;
  padding: 0 0.5em;
}

.side-ov-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  color: var(--text-secondary);
  font-size: max(0.8125em, var(--model-min-text));
  font-weight: 600;
}

.side-ov-profile { color: var(--accent-text); font-weight: 400; }

.ov--side { display: grid; }

/* The chart: seven columns over the bars' area. Each column holds its bar,
   --h of the area's height, and the green dot of a finished focus above it;
   the dashed line sits at --a of the height. */
.ov-bars {
  position: relative;
  display: flex;
  justify-content: space-between;
  height: 6.5em;
}

.ov-col {
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  align-items: center;
  gap: 0.25em;
  width: 1.125em;
}

.ov-col .ov-bar {
  width: 100%;
  height: calc(var(--h) * (100% - 0.75em));
  background: color-mix(in srgb, var(--text-secondary) 35%, transparent);
  border-radius: var(--radius-model-sm);
  transform-origin: 50% 100%;
}

.ov-col .ov-bar--today { background: var(--accent); }

.ov-col .win {
  width: 0.4em;
  height: 0.4em;
  background: var(--done);
  border-radius: 50%;
}

.ov-avg {
  position: absolute;
  left: 0;
  right: 0;
  bottom: calc(var(--a) * (100% - 0.75em));
  border-top: 0.1em dashed var(--text-tertiary);
}

.ov-days {
  display: flex;
  justify-content: space-between;
  margin-top: 0.25em;
  color: var(--text-tertiary);
  font-size: max(0.6875em, var(--model-min-text));
}

.ov-days > span { width: 1.6364em; text-align: center; }

.ov-avg-text {
  margin-top: 0.125em;
  color: var(--text-tertiary);
  font-size: max(0.6875em, var(--model-min-text));
}

.ov-streak {
  margin-top: 0.375em;
  color: var(--text-secondary);
  font: 400 max(0.75em, var(--model-min-text))/1.3 var(--font-mono);
}

/* A Mac list pane: rows without the phone's grouped plate. */
.mac-list {
  padding: 0;
  background: none;
  border-radius: 0;
}

.mac-list .chip--task {
  gap: 0.625em;
  padding: 0.5em 0.5em 0.5em 1em;
}

.mac-list .chip--task::before { left: 0.25em; }
.mac-list .chip--task + .chip--task::after { left: 2.625em; right: 0; }

.mac-list .t-check {
  width: 1em;
  height: 1em;
  border-width: 0.08em;
}

/* Capture (spec 5): Safari in front of Sift's main pane, a drawn page with
   its address field, and Sift's share card over it (ShareCardView.swift on
   the Mac: "Add to Sift", the title field, the link line, the cancel cross
   and Add). In the editorial plate (d-0050 Task 4) the card is the subject
   and the crop on a phone shows it, so its end state is the card shown over
   the page, not the card gone to the Inbox. */
/* The share card is drawn over the main pane rather than inside Safari's
   window, which clips its content: on its way to the Inbox the card leaves
   the window. */
.mac-main--safari { position: relative; padding-top: 0.25em; }

/* The Lists group: part of the sidebar's column. */
.side-lists { display: contents; }

.safari {
  position: relative;
  display: flex;
  flex-direction: column;
  flex: 1;
  min-height: 0;
  background: var(--surface);
  border: 1px solid var(--hairline);
  border-radius: var(--radius-model-md);
  overflow: hidden;
}

.safari-bar {
  display: grid;
  place-items: center;
  flex: none;
  height: 2.5em;
  background: var(--surface-raised);
  border-bottom: 1px solid var(--hairline);
}

.safari-field {
  width: 60%;
  padding: 0.25em 0;
  background: var(--canvas);
  color: var(--text-secondary);
  border-radius: var(--radius-model-sm);
  font-size: max(0.8125em, var(--model-min-text));
  text-align: center;
  white-space: nowrap;
}

.safari-page {
  display: flex;
  flex-direction: column;
  gap: 0.625em;
  padding: 1.5em 1.75em;
}

.safari-h {
  margin: 0 0 0.375em;
  font-size: 1.5em;
  font-weight: 700;
  line-height: 1.2;
}

.safari-page .line {
  width: calc(var(--w) * 100%);
  height: 0.5em;
  background: var(--hairline);
  border-radius: var(--radius-model-full);
}

.share {
  position: absolute;
  top: 3.75em;
  left: 50%;
  width: min(26em, 100% - 2em);
  margin-left: calc(min(26em, 100% - 2em) / -2);
}

.share-card {
  position: relative;
  padding: 1.5em;
  background: var(--surface-raised);
  border: 1px solid var(--hairline);
  border-radius: var(--radius-model-lg);
  box-shadow: var(--shadow-device);
}

.share-form {
  display: grid;
  gap: 1.0769em;
}

/* The card's confirmation after Add, as ShareCardView.swift draws it: a
   filled check in the accent (32 pt) over "Added to Sift" (15 pt
   semibold), 10 pt apart, centred on the card's surface. The em here is
   the card's 13 pt. It is hidden until the capture scene shows it
   (js/scenes/capture.js); without script the card shows its form. */
.share-done {
  position: absolute;
  inset: 0;
  display: grid;
  place-content: center;
  justify-items: center;
  gap: 0.7692em;
  opacity: 0;
}

/* Scoped to the Mac window, as the generic icon rule above is. */
.device-mac .share-tick { width: 2.4615em; height: 2.4615em; stroke: none; }
.share-tick circle { fill: var(--accent); }

.share-tick path {
  stroke: var(--on-accent);
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.share-done-text {
  margin: 0;
  font-size: 1.1538em;
  font-weight: 600;
  white-space: nowrap;
}

.share-head {
  margin: 0;
  font-size: 1.3em;
  font-weight: 600;
}

.share-field {
  display: block;
  min-width: 0;
  padding: 0.6667em;
  background: var(--canvas);
  border-radius: var(--radius-model-sm);
  font-size: 1.1538em;
}

.share-field .t-title { font-size: 1em; }

.share-link {
  display: flex;
  align-items: center;
  gap: 0.4615em;
  min-width: 0;
  color: var(--accent-text);
  white-space: nowrap;
}

.share-link svg { width: 0.9em; height: 0.9em; }

.share-btns {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.share-cancel {
  display: grid;
  place-items: center;
  width: 2.4615em;
  height: 2.4615em;
  background: var(--canvas);
  color: var(--text-secondary);
  border-radius: 50%;
}

.share-cancel svg { width: 1em; height: 1em; stroke-width: 2; }

/* The accent text ink, as the sidebar's selected item: white on the accent
   is 4.36 to 1 (axe, d-0050 Task 4, once the card was shown in the plate). */
.share-add {
  padding: 0.5333em 1.2em;
  background: var(--accent-text);
  color: var(--on-accent);
  border-radius: var(--radius-model-full);
  font-size: 1.1538em;
  font-weight: 600;
}

/* Triage scene: the cards that leave the deck. They lie over the next card,
   the same size, and are gone in the end state: without script, and once the
   scene has played, the deck shows the next card. */

.card-stack > .card--fly {
  position: absolute;
  inset: 0;
  opacity: 0;
}

.q-tiles-label { margin-top: 1em; }

/* The four quadrants under the destinations, each with its count. A count is
   two numerals in one grid cell; the scene swaps their opacity as a card
   lands. The end state shows the second. */
.q-tiles {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 0.25em;
}

/* The rows start at the top, so the counts stay in line when one name wraps
   to two lines (Task 11 fix round 1). */
.q-tile {
  display: grid;
  align-content: start;
  justify-items: center;
  gap: 0.25em;
  padding: 0.5em 0.125em 0.5em;
  background: var(--surface);
  border: 1px solid var(--hairline);
  border-radius: var(--radius-model-md);
}

.q-tile::before {
  content: "";
  width: 1.25em;
  height: 0.1875em;
  background: var(--hue);
  border-radius: var(--radius-model-full);
}

.q-tile-count {
  display: grid;
  font-size: 1.125em;
  font-weight: 700;
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
}

.q-tile-count > span { grid-area: 1 / 1; }
.q-tile-count > span:first-child { opacity: 0; }

/* A name that does not fit on one line wraps rather than ending in an
   ellipsis: on the 7 px floor "Quick Wins" is about as wide as its tile on a
   360 px phone (Task 11). */
.q-tile-name {
  max-width: 100%;
  color: var(--text-secondary);
  font-size: max(0.6875em, var(--model-min-text));
  line-height: 1.1;
  text-align: center;
}

/* Matrix scene: the chips fly in from the middle of the Matrix, across the
   other quadrants, so the Mac's quadrants do not clip them here. Three chips
   fit a quadrant at rest, so nothing overflows once they have landed. */
.screen[data-for="matrix"] .matrix--mac .quad { overflow: visible; }

/* Models in the plates (spec 2026-10-10 section 8). A model takes its size
   from its plate, an inline-size container (styles.css): a Mac window is as
   wide as the frame, whose 16 by 10 matches the window's; a phone is at most
   300 px wide and stands at the frame's left edge. */
.model {
  --mac-w: 100cqw;
  --phone-w: min(300px, 100cqw);
}

/* Under 760 px a Mac model is a crop of its window: the region the chapter
   talks about ([data-crop-region]) is scaled about its origin so that it
   fills the frame's width less 12 px on each side, and everything else in
   the window is hidden, so no text is cut at the frame's edge.

   The unscaled window is the frame's width less the two insets (--mac-w),
   drawn as the full-size window is, 64em across. Each model below gives
   the region's left, top and height as fractions of the window's width
   (measured at 390 px in Chrome, d-0050 Task 4), and its scale is the
   window's width over the region's (64em over the region's ems), so the
   region fills the inset width at every width.
   The labels' 7 px floor is divided by the scale, since the scale enlarges
   them afterwards. The clipping box carries the window's corner radius,
   1.6 percent of the unscaled width, times the scale. */
@media (max-width: 759px) {
  .model[data-crop] {
    --mac-w: calc(100cqw - 24px);
    --model-min-text: calc(7px / var(--crop-scale));
    --crop-x: calc(12px - var(--crop-scale) * var(--crop-left) * var(--mac-w));
    --crop-y: calc(12px - var(--crop-scale) * var(--crop-top) * var(--mac-w));
    height: calc(var(--crop-scale) * var(--crop-height) * var(--mac-w) + 24px);
    overflow: clip;
    background: var(--canvas);
    border-radius: calc(var(--mac-w) * 0.016 * var(--crop-scale));
    box-shadow: 0 0 0 1px var(--hairline), var(--shadow-device);
  }

  .model[data-crop] > .device-mac {
    transform-origin: 0 0;
    transform: translate(var(--crop-x), var(--crop-y)) scale(var(--crop-scale));
    visibility: hidden;
    box-shadow: none;
  }

  .model[data-crop] [data-crop-region] { visibility: visible; }

  /* The Matrix crop: the quadrants are at most 43em across (48.75em in the
     full window), so their text is at least 7 px as drawn at 360 px of
     width (the inset width, 304 px, over 43) and the titles keep room. */
  .model[data-crop="quadrants"] .matrix--mac { max-width: 43em; }

  .model[data-crop="quadrants"] {
    --crop-scale: 1.4884; /* 64 / 43 */
    --crop-left: 0.2276;
    --crop-top: 0.0801;
    --crop-height: 0.5282;
  }

  .model[data-crop="review"] {
    --crop-scale: 1.6; /* 64 / 40, the review's max-width */
    --crop-left: 0.2276;
    --crop-top: 0.0801;
    --crop-height: 0.2675;
  }

  .model[data-crop="share-card"] {
    --crop-scale: 2.4615; /* 64 / 26, the share card's width */
    --crop-left: 0.4023;
    --crop-top: 0.1006;
    --crop-height: 0.2398;
  }
}

/* The erasure's figure, sweep and rule. The page's erasure (figure#erase,
   styles.css) takes its width and font size from .erase here and its rows,
   layers and handle from styles.css. The story round's list erasure that
   these rules were written for is drawn only in tools/gallery.html now, and
   its own rules (.erase-list, .erase-row, .sift-*, .erase-caption) live in
   the gallery's <style> (fix round C). It is not inside a device, so its em
   is the figure's own font size. */
.erase {
  width: min(100%, 40rem);
  margin: 0;
  font-size: 1rem;
}

@media (max-width: 599px) {
  .erase { font-size: 0.875rem; }
}

/* The sweep is as wide as the list; the scene moves it by its own width, so
   the rule at its left edge crosses the list. The list clips it. */
.erase-sweep {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.erase-rule {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  width: 2px;
  background: var(--accent);
  opacity: 0;
}

/* Start states of the played models (spec 2026-10-10 section 5). A model's
   animations are created only when it plays, so until then these rules hold
   its first frame. They key on data-played on the .model, which js/play.js
   sets; without script nothing sets it and every model shows its end state,
   the authored HTML. Overview scrubs (js/scrubs.js) and is not listed. */
.model[data-model="inbox"][data-played="idle"] .task-row,
.model[data-model="inbox"][data-played="idle"] .pill,
.model[data-model="matrix-mac"][data-played="idle"] .matrix--mac .chip--task,
.model[data-model="matrix-phone"][data-played="idle"] .chip--task { opacity: 0; }

.model[data-model="triage"][data-played="idle"] .card--fly,
.model[data-model="triage"][data-played="idle"] .q-tile-count > span:first-child { opacity: 1; }
.model[data-model="triage"][data-played="idle"] .q-tile-count > span:last-child { opacity: 0; }

/* Review: the walk starts on its first step, Overdue current and the
   other three to come (hollow nodes); the question and the three picks'
   ticks are not there yet.
   Today: the ticks, the count's later numerals and the Focus done card;
   the rows read as not done and the ring is empty. Capture: the share card
   has not come up. */
.model[data-model="review-mac"][data-played="idle"] .review-ask,
.model[data-model="review-mac"][data-played="idle"] .t-tick,
.model[data-model="review-mac"][data-played="idle"] .rs-ring,
.model[data-model="review-mac"][data-played="idle"] .rs-now,
.model[data-model="review-mac"][data-played="idle"] .rs-dot,
.model[data-model="review-mac"][data-played="idle"] .review-step:first-child .rs-plain,
.model[data-model="review-mac"][data-played="idle"] .review-step:first-child .rs-todo,
.model[data-model="today"][data-played="idle"] .t-tick,
.model[data-model="today"][data-played="idle"] .count-steps > span,
.model[data-model="today"][data-played="idle"] .focus-done,
.model[data-model="capture"][data-played="idle"] .share-card { opacity: 0; }

.model[data-model="review-mac"][data-played="idle"] .rs-plain,
.model[data-model="review-mac"][data-played="idle"] .rs-todo,
.model[data-model="review-mac"][data-played="idle"] .review-step:first-child .rs-ring,
.model[data-model="review-mac"][data-played="idle"] .review-step:first-child .rs-now,
.model[data-model="today"][data-played="idle"] .count-steps > span:first-child { opacity: 1; }

.model[data-model="today"][data-played="idle"] .task-row--done .t-title {
  color: var(--text-primary);
  text-decoration: none;
}

.model[data-model="today"][data-played="idle"] .ring-arc { stroke-dashoffset: 100; }

.model[data-model="capture"][data-played="idle"] .share { opacity: 1; }

/* Capture and the Inbox beside it (spec 2026-10-10 section 14 item 6). The
   authored HTML, which a visitor without script or with reduced motion
   sees, is the moment before Add: the card shows its form, the Mac's
   sidebar and the iPhone Inbox count 5, and the Inbox holds five tasks.
   Only the played scene goes further. js/play.js sets data-run on the
   capture model when its scene starts and on the Inbox when its second
   part starts (the task arriving), and these rules hold where each ends
   once its animations are released: the card shows "Added to Sift" (and
   from 760 px, where the whole window is drawn, it has left), both counts
   read 6 and the new task is first in the Inbox. */
.model[data-model="capture"]:not([data-run]) .count-steps > span:first-child,
.model[data-model="inbox"]:not([data-run]) .count-steps > span:first-child { opacity: 1; }

.model[data-model="capture"]:not([data-run]) .count-steps > span:last-child,
.model[data-model="inbox"]:not([data-run]) .count-steps > span:last-child { opacity: 0; }

.model[data-model="inbox"]:not([data-run]) .task-row--new { display: none; }

.model[data-model="capture"][data-run] .share-form { opacity: 0; }
.model[data-model="capture"][data-run] .share-done { opacity: 1; }

@media (min-width: 760px) {
  .model[data-model="capture"][data-run] .share { opacity: 0; }
}

