/* PHASE·TIMELINE (603) — the milestone year, five checkpoint cards. D-652 · D-653 · D-654.
 *
 * EXTRACTED 2026-07-30 from workbench/phase/_bakeoffs/timeline-v2.html's inline <style>,
 * VERBATIM. Nothing was redesigned on the way across: the settled design is nine live
 * rounds old (the record lives in the card page header, workbench/phase/timeline.html)
 * and a promotion is not a design round. Selector for selector, value for value, this is
 * the bake-off's stylesheet — which is what makes the extraction checkable by diff.
 *
 * ONE DEFINITION. The bake-off page is DELETED; the WB card page and a future app mount
 * both link this file. There is no second copy to drift from.
 *
 * ⚠️ TOKENISATION OWED (the debt travels with the code, unchanged from the bake-off, and
 * it is the same debt 602/604 carry): the 6px trail stroke, pebble radii (48), glyph sizes
 * (20px), the 2.5px/1.5px pebble and button borders, the popup art height and the pill's
 * 70px park are ENGINE numbers in JS or bare px here, not CSS tokens. Marked
 * token-exception where the linter sees them; owed properly at the app build.
 *
 * ⚠️ THE ONE SCOPING DELTA. The bake-off page ended with a bare `svg { display: block; }`,
 * which was legal inside one page's <style> and is not legal in shared card CSS — it would
 * restyle every <svg> in the app. It is scoped to `.mtl-wrap svg` here, which covers exactly
 * the elements it covered before (the river, every glyph, the popup art) and nothing else.
 *
 * ⚠️ NOT FIXED, DELIBERATELY (flagged, per the promotion rule — see the card page header):
 * `.mtl-cta` and `.mtl-pill` carry `:active` but NO `:focus-visible`, while every other
 * control in this card carries both. Check 18 (G6 micro-states) does not bite at `designed`;
 * it will the day 603 moves to `draft`. Adding the two rules here would have been a design
 * change smuggled in under a port, so they are named instead.
 *
 * ⚠️ THE ONE ADDITION AT PORT — `.mtl-calm`. The reduced-motion state has to be REVIEWABLE,
 * which means forced in the frame rather than left to the reviewer's OS setting (a state
 * nobody can see is not a state). `.mtl-calm` is a class-selector MIRROR of the
 * @media (prefers-reduced-motion: reduce) block below — same declarations, same order, no
 * new behaviour. The media query stays and still governs real users. If you edit one block
 * you edit both, or the forced state stops telling the truth about the real one.
 *
 * SaMD (D-396 r5/7, D-630): parent-led marking only; no counts, scores, percentages or
 * on-track verdicts; checkpoints never gate; unmarked pebbles sit calm forever.
 */

/* ── the surface ─────────────────────────────────────────────────────────── */
.mtl-wrap { height: 100%; display: flex; flex-direction: column; background: var(--surface-ground); position: relative; }
.mtl-sc { flex: 1; overflow-y: auto; scrollbar-width: none; position: relative; }
.mtl-sc::-webkit-scrollbar { display: none; }

/* ⚠️ 603 AT DESKTOP WIDTH — added 2026-07-30, Gate 2 item 1. ONE rule now, scoped to 603's
   own box. This comment used to open "Two rules, both scoped to 603's own boxes. Do not
   generalise either to #app or any shared container." It was RIGHT about (2) and WRONG about
   (1), and being wrong about (1) in writing is how the same defect then shipped three more
   times inside twenty-four hours.

   (1) THE COLUMN — GENERALISED, AND IT SHOULD HAVE BEEN FROM THE START (D-711). It was never
   603's rule. It was the app's single content column, restated by hand on six drill-in roots
   and FORGOTTEN on two more: 701 search, 405 About and the collection not-found all reached
   Andrew running against the window edge after this comment was written telling the next
   reader not to generalise it. Four instances of one defect is a missing mechanism (D-706).
   The column now lives once, as `.appcol` in app.css, carried by the fixed host — so
   `.mtl-wrap` no longer restates it, and a new drill-in cannot omit it (check 47).

   The distinction the original comment missed: a value is 603's to keep when it is derived
   from 603's own geometry. `VW = 338` is. `--layout-col-max` never was.

   (2) THE DRAWING BLOCK — STILL 603's, STILL NOT TO BE GENERALISED. `.mtl-cw` is the one box
   on this surface that cannot reflow:
   the engine draws at a FIXED card width (timeline.render.js `VW = 338`), so pebble
   centres, the river's sample points and every label box are absolute card-local
   pixels — and left-side labels are laid from the card's RIGHT edge (`right: VW - edge`).
   Drawing and labels only line up when the block is ACTUALLY 338 wide. They came apart
   by the width of a window at desktop width (trail pinned at 338 on the left, every
   label flung to the right margin) and — quieter, and the reason item 3's collisions
   were real while `verify()` read zero — by 20px at phone width too: the WB app frame
   gives 603 a 370px screen (390 − 2×10 bezel), the app has no bezel and handed it 390.
   `verify()` measures in the engine's own 338 frame, so it could not see the gap between
   what it planned and what the browser drew. Pinning the block closes it: 18 rendered
   trail×label overlaps at 390 → 0.

   Everything else on the surface — the intro carousel, the safety band, the checkpoint
   prose, the sources box — keeps reflowing exactly as it does now.

   🔴 DO NOT make the timeline responsive instead. Its geometry was tuned at this one
   width and `verify()` has only ever measured collisions here; a fluid timeline is a
   separate piece of work with its own bake-off. */
.mtl-cw { width: 338px; margin-inline: auto; } /* token-exception */ /* = timeline.render.js VW */

/* slim drill-in TOP BAR — page chrome lives above the cards, never inside one
   (Andrew, round 6: "should we have something different at the top?") */
.mtl-top { flex: none; display: flex; align-items: center; gap: var(--space-8); padding: var(--space-12) var(--space-16) var(--space-4); }
.mtl-toplab { font-family: var(--font-label); font-size: var(--size-10, 10px); font-weight: var(--weight-700); letter-spacing: var(--tracking-05); text-transform: uppercase; color: var(--text-secondary); } /* token-exception */
.mtl-back { width: var(--dim-32); height: var(--dim-32); border-radius: var(--radius-round); border: 0; background: none; color: var(--text-secondary); cursor: pointer; display: flex; align-items: center; justify-content: center; margin-left: calc(-1 * var(--space-8)); }
.mtl-back svg { width: var(--dim-16); height: var(--dim-16); }
.mtl-back:active { opacity: 0.72; }
.mtl-back:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; } /* token-exception */

/* hero (drill-in intro) — a 2-SLIDE CAROUSEL card (Andrew, round 7): slide 1 the
   intro, slide 2 Caïa's record. D-458 grammar: one-at-a-time, swipe/snap or tap a
   dot, stops at the ends, NO arrows. */
.mtl-intro { margin: var(--space-4) var(--space-16) var(--space-12); background: var(--surface-card); border-radius: var(--radius-card-lg); padding: 0; overflow: hidden; }
.mtl-cart { display: flex; overflow-x: auto; scroll-snap-type: x mandatory; scrollbar-width: none; }
.mtl-cart::-webkit-scrollbar { display: none; }
.mtl-slide { flex: 0 0 100%; scroll-snap-align: start; padding: var(--space-16) var(--space-16) var(--space-8); }
.mtl-dots { display: flex; gap: var(--space-8); justify-content: center; padding: var(--space-8) 0 var(--space-12); }
.mtl-dot { width: var(--dim-6); height: var(--dim-6); border-radius: var(--radius-round); background: var(--cream-450); border: 0; padding: 0; cursor: pointer; } /* token-exception */
.mtl-dot.on { background: var(--accent); }
/* slide 2 — the record's CTA */
.mtl-cta { display: inline-flex; align-items: center; gap: var(--space-8); margin-top: var(--space-12); border: 0; border-radius: var(--radius-pill); background: var(--accent); color: var(--text-on-accent); font-family: var(--font-body); font-size: var(--size-12); font-weight: var(--weight-600); padding: var(--space-8) var(--space-16); cursor: pointer; }
.mtl-cta svg { width: var(--dim-12, 12px); height: var(--dim-12, 12px); } /* token-exception */
.mtl-cta:active { background: var(--accent-hover); }
.mtl-ie { font-family: var(--font-label); font-size: var(--size-10, 10px); font-weight: var(--weight-700); letter-spacing: var(--tracking-05); text-transform: uppercase; color: var(--accent); } /* token-exception */
.mtl-it { font-family: var(--font-display); font-weight: var(--weight-600); font-size: var(--size-20); margin-top: var(--space-4); line-height: var(--leading-120, 1.2); } /* token-exception */
.mtl-it i, .mtl-hm i, .mtl-pt i, .mtl-cft i { color: var(--accent); font-style: normal; }
.mtl-ib { font-size: var(--size-12); line-height: var(--leading-140); color: var(--text-secondary); margin-top: var(--space-4); }
/* sources box — the weeks-article grammar (read.css .wkr-sources), verbatim */
.mtl-sources { margin: var(--space-4) var(--space-16) var(--space-16); background: var(--surface-card); border: 1px solid var(--border-hairline); border-radius: var(--radius-card); padding: var(--space-16); } /* token-exception */
.mtl-sources .ttl { font-family: var(--font-label); font-size: var(--size-10, 10px); font-weight: var(--weight-600); text-transform: uppercase; letter-spacing: var(--tracking-05); color: var(--text-tertiary); margin-bottom: var(--space-8); } /* token-exception */
.mtl-sources ul { list-style: none; margin: 0; padding: 0; }
.mtl-sources li { font-size: var(--size-12); line-height: var(--leading-150); padding-left: var(--space-16); position: relative; margin-bottom: var(--space-4); color: var(--text-secondary); }
.mtl-sources li::before { content: "—"; position: absolute; left: 0; color: var(--text-tertiary); }
.mtl-sources li b { color: var(--text-primary); }
.mtl-sources a { color: var(--accent); }
.mtl-sources b a { color: var(--text-primary); text-decoration-color: var(--accent); }
/* the act-early band — the D-614 watchbox grammar, verbatim from read.css */
.mtl-safe { margin: 0 var(--space-16) var(--space-12); background: var(--gold-90); border: 1px solid var(--gold-200); border-radius: var(--radius-card); padding: var(--space-16); } /* token-exception */
.mtl-sqk { display: flex; align-items: center; gap: var(--space-4); font-family: var(--font-label); font-size: var(--size-10, 10px); font-weight: var(--weight-700); letter-spacing: var(--tracking-05); text-transform: uppercase; color: var(--gold-700); } /* token-exception */
.mtl-sqk svg { width: var(--dim-16); height: var(--dim-16); }
.mtl-safe p { font-size: var(--size-13); line-height: var(--leading-150); margin: var(--space-8) 0 0; }

/* ── ONE CHECKPOINT PER CARD (Andrew: "one checkpoint per card, split — 5 cards").
   Header in flow at the card's top, the river restarting below it. D-435: tone
   lift, one level of carding. */
.mtl-card { margin: 0 var(--space-16) var(--space-16); background: var(--surface-card); border-radius: var(--radius-card-lg); overflow: hidden; }
.mtl-hd { padding: var(--space-16) var(--space-16) var(--space-8); }
.mtl-hk { font-family: var(--font-label); font-size: var(--size-10, 10px); font-weight: var(--weight-700); letter-spacing: var(--tracking-05); color: var(--accent-hover); text-transform: uppercase; } /* token-exception */
.mtl-hm { font-family: var(--font-display); font-weight: var(--weight-600); font-size: var(--size-20); margin-top: 2px; line-height: var(--leading-120, 1.2); } /* token-exception */
.mtl-ho { font-size: var(--size-12); line-height: var(--leading-140); color: var(--text-secondary); margin-top: var(--space-4); }
.mtl-how { font-size: var(--size-12); line-height: var(--leading-140); color: var(--accent); font-weight: var(--weight-700); margin-top: var(--space-8); }
.mtl-cw { position: relative; }

/* the river svg inside each card */
.mtl-svg { position: absolute; left: 0; top: 0; z-index: 2; pointer-events: none; }

/* pebbles — 3D flip pin */
.mtl-pw { position: absolute; z-index: 4; background: none; border: 0; padding: 0; cursor: pointer; transform: scale(0); transition: transform var(--duration-400, .45s) cubic-bezier(.34,1.56,.5,1); perspective: 300px; } /* token-exception */
.mtl-pw.on { transform: scale(1); }
.mtl-pw:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: var(--radius-round); } /* token-exception */
.mtl-pin { display: block; position: relative; width: 100%; height: 100%; transform-style: preserve-3d; transition: transform var(--duration-500, .6s) cubic-bezier(.4,.1,.2,1); } /* token-exception */
.mtl-pw.met .mtl-pin { transform: rotateY(180deg); }
.mtl-face { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; border-radius: var(--radius-round); backface-visibility: hidden; -webkit-backface-visibility: hidden; }
/* unmet: the OUTLINE carries colour(t) (the shade the met face flips to), but the
   GLYPH is always dark ink — legibility beats the gradient (Andrew: "the question
   mark is not legible enough. should be in dark, as well as other icons not
   marked") */
.mtl-f0 { background: var(--cream-50); border: 2.5px solid var(--teal-200); color: var(--ink-900); } /* token-exception */
.mtl-f1 { color: var(--text-on-accent); transform: rotateY(180deg); }
.mtl-face svg { width: 20px; height: 20px; } /* glyph up from 16 (Andrew: "slightly bigger") */ /* token-exception */

/* labels — bare text, close to their pebbles, balanced lines (Andrew feedback:
   pills gone is fine · closer to the circles · no line massively longer · ≤4 lines).
   font-size/line-height ON the label: without them the line boxes carry the
   parent's 16px strut and every line silently advances ~18px instead of 15. */
.mtl-lab { position: absolute; z-index: 3; cursor: pointer; opacity: 0; transform: translateY(var(--dim-12)); transition: opacity var(--duration-400, .4s), transform var(--duration-400, .4s); padding: 2px 0; font-size: var(--size-12); line-height: var(--leading-125, 1.25); text-wrap: balance; } /* token-exception */
.mtl-lab.on { opacity: 1; transform: none; }
.mtl-nm { font-size: var(--size-12); font-weight: var(--weight-600); line-height: var(--leading-125, 1.25); } /* token-exception */

/* Now — visually removed (round 6); a zero-height anchor keeps open-at-now +
   the Back-to-today pill working while the presence question stays open */
.mtl-nowanchor { height: 0; margin: 0; visibility: hidden; }

/* back-to-today pill */
.mtl-pill { position: absolute; bottom: var(--space-16); left: 50%; transform: translateX(-50%) translateY(70px); background: var(--surface-inverse); color: var(--text-on-dark, #fffbf2); border: 0; border-radius: var(--radius-pill); padding: var(--space-8) var(--space-16); font-family: var(--font-body); font-size: var(--size-12); font-weight: var(--weight-600); cursor: pointer; transition: transform var(--duration-200); z-index: 8; } /* token-exception */
.mtl-pill.show { transform: translateX(-50%); }
.mtl-pill:active { opacity: 0.85; }

/* anchored popup */
.mtl-pop { position: absolute; left: var(--space-16); right: var(--space-16); background: var(--cream-50); border-radius: var(--radius-card-lg); padding: var(--space-16); box-shadow: var(--shadow-sheet); z-index: 9; display: none; }
.mtl-pop.show { display: block; }
.mtl-art { height: 120px; border-radius: var(--radius-12); background: var(--teal-100); display: flex; flex-direction: column; align-items: center; justify-content: center; gap: var(--space-8); margin-bottom: var(--space-12); color: var(--accent-hover); } /* token-exception */
.mtl-art svg { width: var(--dim-40); height: var(--dim-40); }
.mtl-artc { font-family: var(--font-display); font-size: var(--size-11); font-style: italic; color: var(--text-secondary); text-align: center; padding: 0 var(--space-16); }
/* the labelled area chip — icon + area name together, icon in the pebble's own
   colour(t); sits bare above the title (D-435: chips are not boxed) */
.mtl-chip { display: inline-flex; align-items: center; gap: var(--space-8); font-family: var(--font-label); font-size: var(--size-10, 10px); font-weight: var(--weight-700); letter-spacing: var(--tracking-05); text-transform: uppercase; color: var(--text-secondary); margin-bottom: var(--space-4); } /* token-exception */
.mtl-chip-ic { display: inline-flex; }
.mtl-chip-ic svg { width: var(--dim-16); height: var(--dim-16); }
.mtl-pt { font-family: var(--font-display); font-weight: var(--weight-600); font-size: var(--size-16); }
.mtl-pdesc { font-size: var(--size-12); line-height: var(--leading-140); color: var(--text-secondary); margin-top: var(--space-4); }
.mtl-pr { font-family: var(--font-display); font-size: var(--size-12); color: var(--text-secondary); margin-top: var(--space-8); }
.mtl-pq { font-family: var(--font-display); font-weight: var(--weight-600); font-size: var(--size-14); margin-top: var(--space-12); }
.mtl-pb { display: flex; gap: var(--space-8); margin-top: var(--space-12); }
.mtl-btn { flex: 1; border-radius: var(--radius-12); padding: var(--space-12); font-family: var(--font-body); font-size: var(--size-12); font-weight: var(--weight-600); cursor: pointer; }
.mtl-btn:active { opacity: 0.85; }
.mtl-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; } /* token-exception */
/* Yes + any selected answer wear the pebble's own colour(t) — set per-popup as --sel-col */
.mtl-yes { background: var(--sel-col, var(--accent)); color: var(--sel-on, var(--text-on-accent)); border: 0; }
.mtl-no { background: none; border: 1.5px solid var(--cream-450); color: var(--text-primary); } /* token-exception */
.mtl-no:active { border-color: var(--sel-col, var(--accent)); color: var(--sel-col, var(--accent)); opacity: 1; }
.mtl-conf { text-align: center; padding: var(--space-4) 0; animation: mtlIn var(--duration-150) ease-out; }
@keyframes mtlIn { from { opacity: 0; } to { opacity: 1; } }
.mtl-pop.hide { opacity: 0; transform: translateY(8px); transition: opacity var(--duration-150), transform var(--duration-150); } /* token-exception */
.mtl-cft { font-family: var(--font-display); font-weight: var(--weight-600); font-size: var(--size-16); }
.mtl-cfs { font-size: var(--size-11); color: var(--text-secondary); margin-top: var(--space-4); }
/* WHEN did it happen (Andrew: parents may not have been in for a while) — a
   persistent SLIDER on the confirmation (a stepper is 18 taps for months-ago);
   annotates, never nags. When? + Week N in teal bold. */
.mtl-when { display: flex; align-items: center; justify-content: center; gap: var(--space-12); margin-top: var(--space-12); }
.mtl-whenq { font-size: var(--size-11); font-weight: var(--weight-700); color: var(--accent); }
.mtl-range { flex: 1; min-width: 0; accent-color: var(--sel-col, var(--accent)); }
.mtl-wlab { min-width: 64px; text-align: right; font-size: var(--size-12); font-weight: var(--weight-700); color: var(--accent); } /* token-exception */
.mtl-done { flex: none; display: block; margin: var(--space-12) auto 0; padding: var(--space-8) var(--space-24); }
/* the reopened, already-marked popup states it plainly, in teal */
.mtl-ach { font-family: var(--font-display); font-weight: var(--weight-600); font-size: var(--size-12); color: var(--accent); margin-top: var(--space-12); }

/* the ONE gold moment (D-440) */
.mtl-ring { position: absolute; border-radius: var(--radius-round); border: 3px solid var(--gold-500); pointer-events: none; z-index: 7; animation: mtlRg .7s ease-out forwards; } /* token-exception */
@keyframes mtlRg { from { opacity: .9; transform: scale(.4); } to { opacity: 0; transform: scale(1.9); } }

/* reduced motion: same DOM, laid out static, fully inked (JS also skips choreography) */
@media (prefers-reduced-motion: reduce) {
  .mtl-pw, .mtl-lab { opacity: 1; transform: none; transition: none; }
  .mtl-pin { transition: none; }
  .mtl-ring { animation: none; opacity: 0; }
}
/* ⚠️ THE FORCED MIRROR of the block above — see the header. Same declarations, same
   order. Edit both or neither: a forced state that has drifted from the real one is a
   state review passes and a real parent never sees. */
.mtl-calm .mtl-pw, .mtl-calm .mtl-lab { opacity: 1; transform: none; transition: none; }
.mtl-calm .mtl-pin { transition: none; }
.mtl-calm .mtl-ring { animation: none; opacity: 0; }
.mtl-wrap svg { display: block; }


/* ═══ HER OWN FIRSTS — the gold pebble (2026-08-09) ═══════════════════════════════════
   🔴 THERE IS ALMOST NOTHING HERE, AND THAT IS THE POINT. A first uses .mtl-pw untouched —
   same 48px node, same two-face flip, same glyph, same planner. Its provenance is carried by
   COLOUR ALONE, and the colour is set in pass 2 of timeline.render.js because that is where
   every other pebble gets its own: inline styles from the ramp, which override any background
   declared here. My first attempt set the fill in this file and it never once applied.
   ⚠️ NO SIZE, NO WEIGHT, NO BADGE. The moment a first is bigger or louder than the milestone
   beside it, the surface has started ranking her record against a screening instrument.

   ⚠️ THE LEAD-DOT ON THE LABEL IS GONE (Andrew: "remove the bullet next to the text, not
   needed"). It was belt-and-braces for a provenance the pebble already states, and a second
   marker for one fact is clutter dressed as clarity. */

/* A character cap cannot promise pixels — the add field caps a title at 30 characters, measured
   against a real .mtl-lab, but one 30-letter word overflows the planner's narrowest placement at
   any count. Without this the failure is text hanging off a drawn path. */
.mtl-lab { overflow-wrap: anywhere; }

/* ═══ ADD A FIRST — the affordance and the sheet (2026-08-09) ══════════════════════════
   Andrew: "we need a place for… an affordance to add milestones that is easy to notice."
   🔴 IT IS A CARD, NOT A LINK. Everything else on this scroll is a card; a text link under the
   intro would read as a footnote to the intro rather than as a thing you can do. The subtitle
   is doing the real work — it names what belongs here (a tooth, a laugh) so a parent does not
   have to guess whether her own material is welcome on CDC's list. */
.mtl-addfirst { display: block; width: auto; margin: 0 var(--space-16) var(--space-16);
  text-align: left; cursor: pointer; border: 0; border-radius: var(--radius-card-lg);
  background: var(--surface-card); box-shadow: var(--shadow-card);
  padding: var(--space-16) var(--space-20); position: relative; }
.mtl-addfirst .pl { position: absolute; right: var(--space-20); top: 50%; transform: translateY(-50%);
  width: var(--dim-32); height: var(--dim-32); border-radius: var(--radius-round);
  background: var(--accent); color: var(--cream-50); font-size: var(--size-20); /* token-exception */ /* glyph in a 32px well, not type */
  line-height: var(--dim-32); text-align: center; } /* token-exception */
.mtl-addfirst .t { display: block; font-family: var(--font-display); font-size: var(--text-subtitle);
  font-weight: var(--weight-600); color: var(--text-primary); padding-right: var(--space-40); }
.mtl-addfirst .s { display: block; font-size: var(--text-caption); color: var(--text-secondary);
  margin-top: var(--radius-2); padding-right: var(--space-40); line-height: var(--leading-140); }
.mtl-addfirst:active { opacity: 0.72; }
.mtl-addfirst:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; } /* token-exception */

/* The sheet is absolute to .mtl-wrap, not fixed — inside a mock phone, fixed nails it to the
   PAGE. Same correction _appframe already makes for the tab bar and the tools panel. */
.mtl-sheetwrap { position: absolute; inset: 0; z-index: 20; display: flex; align-items: flex-end;
  background: rgba(20,18,14,.40); } /* token-exception */
.mtl-sheet { width: 100%; max-height: 92%; overflow-y: auto; background: var(--surface-card);
  border-radius: var(--radius-card-lg) var(--radius-card-lg) 0 0; padding: var(--space-20); }
.mtl-sh-bar { display: flex; align-items: center; justify-content: space-between;
  font-family: var(--font-display); font-size: var(--text-subtitle); font-weight: var(--weight-600); }
.mtl-sh-x { background: none; border: 0; cursor: pointer; font-size: var(--size-24); /* token-exception */ /* close glyph, not type */
  line-height: 1; color: var(--text-secondary); padding: 0 var(--space-4); }
.mtl-sh-q { font-family: var(--font-body); font-size: var(--text-body); font-weight: var(--weight-600);
  color: var(--text-primary); margin: var(--space-20) 0 var(--space-8); }
.mtl-sh-q em { font-style: normal; font-weight: var(--weight-400); color: var(--text-tertiary);
  font-size: var(--text-caption); }
.mtl-sh-in { width: 100%; border: 0; border-bottom: 2px solid var(--border-hairline); /* token-exception */
  background: none; padding: var(--space-8) 0; font-family: var(--font-body);
  font-size: var(--text-subtitle); color: var(--text-primary); }
.mtl-sh-in:focus { outline: none; border-bottom-color: var(--accent); }
.mtl-sh-count { text-align: right; font-family: var(--font-label); font-size: var(--text-label);
  color: var(--text-tertiary); margin-top: var(--space-4); }
.mtl-sh-count.is-max { color: var(--gold-700); }
/* The five, as tappable glyphs — she is choosing the PICTURE as much as the category, so the
   glyph is the control rather than a decoration beside a word. */
/* Twelve wrap to a grid — five fitted a row, twelve do not, and a horizontal scroller would
   hide half the options behind a gesture nobody is told about. Four across, three deep. */
.mtl-sh-kinds { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--space-8); }
.mtl-sh-k { display: flex; flex-direction: column; align-items: center; gap: var(--space-4);
  background: none; border: 2px solid var(--border-hairline); border-radius: var(--radius-12); /* token-exception */
  padding: var(--space-8) var(--space-4); cursor: pointer;
  font-family: var(--font-label); font-size: var(--size-10); color: var(--text-secondary); }
.mtl-sh-k .ic { display: grid; place-items: center; color: var(--text-tertiary); }
.mtl-sh-k .ic svg { width: var(--dim-24); height: var(--dim-24); }
.mtl-sh-k.on { border-color: var(--gold-500); background: var(--gold-50); color: var(--text-primary); }
.mtl-sh-k.on .ic { color: var(--gold-700); }
.mtl-sh-when { display: flex; gap: var(--space-8); flex-wrap: wrap; align-items: center; }
.mtl-sh-w { background: var(--surface-well); border: 0; border-radius: var(--radius-pill);
  padding: var(--space-8) var(--space-16); cursor: pointer;
  font-family: var(--font-body); font-size: var(--size-14); color: var(--text-primary); }
.mtl-sh-w.on { background: var(--accent); color: var(--cream-50); }
.mtl-sh-date { border: 0; border-bottom: 2px solid var(--border-hairline); background: none; /* token-exception */
  font-family: var(--font-body); font-size: var(--text-body); padding: var(--space-4) 0; }
.mtl-sh-media { display: flex; align-items: center; gap: var(--space-12); }
.mtl-sh-add { width: 56px; height: 56px; border-radius: var(--radius-12); cursor: pointer; /* token-exception */ /* portrait's ruled thumb size */
  background: none; border: 2px dashed var(--border-hairline); color: var(--text-tertiary); /* token-exception */
  font-size: var(--text-subtitle); }
.mtl-sh-n { font-size: var(--text-caption); color: var(--text-secondary); }
.mtl-sh-cta { width: 100%; margin-top: var(--space-24); background: var(--accent);
  color: var(--cream-50); border: 0; border-radius: var(--radius-pill); padding: var(--space-12);
  cursor: pointer; font-family: var(--font-body); font-size: var(--text-body);
  font-weight: var(--weight-600); }
.mtl-sh-cta[disabled] { opacity: 0.45; cursor: default; }

/* The scroll-in twin of .mtl-addfirst — a disc on the RIGHT RAIL, not a pill in the header.
   🔴 IT SITS OVER THE YEAR, WHICH IS THE POINT. In the header it read as page chrome; on the
   rail it reads as belonging to the path it adds to. Vertically centred so it is always under
   the thumb of the hand already scrolling, and clear of both the header and "Back to today".
   🔴 GREY, AND QUIET. It was gold-on-the-ramp for one revision and that was wrong: a control
   nobody needs to notice was the only thing on the card changing colour as you scrolled, which
   is the definition of stealing the limelight. Gold now means one thing only — her own firsts,
   and the button that makes one. This is chrome.
   Transform + opacity only, so a control that updates on every scroll frame cannot cost one. */
.mtl-dropadd { position: absolute; right: var(--space-12); top: 50%; z-index: 12;
  width: var(--dim-28, 28px); height: var(--dim-28, 28px); border-radius: var(--radius-round); /* token-exception */
  border: 0; cursor: pointer; padding: 0;
  display: grid; place-items: center;
  font-family: var(--font-body); font-size: var(--text-body); line-height: 1;
  background: var(--surface-well); color: var(--text-tertiary);
  transform: translate(0, -50%) scale(.3); margin-top: 0; opacity: 0; pointer-events: none;
  transition: transform var(--duration-300, .3s) cubic-bezier(.34,1.2,.5,1),
              opacity var(--duration-300, .3s) ease; }
.mtl-dropadd.on { transform: translate(0, -50%) scale(1); opacity: 1; pointer-events: auto; }
.mtl-dropadd:active { transform: translate(0, -50%) scale(.92); }
.mtl-dropadd:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; } /* token-exception */
@media (prefers-reduced-motion: reduce) {
  .mtl-dropadd { transition: opacity .2s ease; transform: translate(0, -50%); }
  .mtl-dropadd.on { transform: translate(0, -50%); }
}

/* Media on any milestone — the art slot's second life. The illustration stays for the ones with
   no photo (D-541: absent is not empty); the moment there is one, her picture takes the frame. */
.mtl-addmedia { display: block; margin: var(--space-8) auto 0; background: none; border: 0;
  cursor: pointer; color: var(--accent); font-family: var(--font-body);
  font-size: var(--text-caption); font-weight: var(--weight-600); padding: var(--space-4); }
.mtl-addmedia:active { opacity: .72; }
.mtl-art.has-media { padding: var(--space-8); }
.mtl-mgrid { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--space-8); }
.mtl-mtile { aspect-ratio: 1; border-radius: var(--radius-12); background: var(--surface-well);
  display: grid; place-items: center; }
.mtl-mtile.is-add { border: 2px dashed var(--border-hairline); background: none; /* token-exception */
  color: var(--text-tertiary); font-size: var(--size-18); cursor: pointer; }
