/* The Inquiry — plate design language */
:root {
  /* The glass: the screen less the status bar and the home indicator. The iOS
     shell draws the web view edge to edge, so both insets are real there, and
     .inquiry pads by them; a screen that fills "the viewport" must fill this
     instead, or the page runs taller than the phone by exactly the two insets
     and the bottom row slips under the home indicator. */
  --safe-top: env(safe-area-inset-top, 0px);
  --safe-bottom: env(safe-area-inset-bottom, 0px);
  --glass: calc(100svh - var(--safe-top) - var(--safe-bottom));
  --ecru: #F5F1EA;
  --bone: #EBE5DA;
  --ink: #211C15;
  --panel: #14100B;
  --umber: #8B7A5E;
  --clay: #9C5F4E;
  --hairline: rgba(33, 28, 21, 0.2);
  --align-close: #D89653; /* warm ochre — "nearly there", at home in the palette */
  --align-ok: #86BE79;    /* muted verdigris — unmistakably yes, never traffic-light */
  --quiet: rgba(33, 28, 21, 0.8);  /* 8:1 on ecru. 0.68 cleared AA on paper and went grey at 10px weight 300 on a phone */
  --umber-text: #5F5139; /* umber for words: the mark tone reads 3.7:1 on ecru, this one 6.9:1 */
  --clay-text: #7A4335;  /* clay for words, 7:1 */
  --umber-light: #B9A98C; /* umber for words on the panel, 8:1 — --umber-text is 2.2:1 there */
  --clay-light: #D08C7A;  /* clay for words on the panel, 7:1 */
  --serif: 'Cormorant Garamond', Georgia, serif;
  --sans: 'Jost', 'Helvetica Neue', sans-serif;
}
* { margin: 0; padding: 0; box-sizing: border-box; }
html { scroll-behavior: smooth; }
/* Inside the app, no rubber band past either end (app.js sets the class).
   Safari keeps its bounce and its pull-to-refresh. */
html.in-app, html.in-app body { overscroll-behavior-y: none; }
body {
  background: var(--ecru);
  color: var(--ink);
  font-family: var(--serif);
  font-weight: 400;
  font-size: 19px;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
}
button { font: inherit; color: inherit; background: none; border: none; cursor: pointer; }
/* viewport-fit=cover (index.html) means the page starts at the top of the
   glass. In Safari that is free — its toolbar covers the top edge and the
   inset is 0. Inside the native shell the WKWebView ignores the safe area on
   purpose, so without these two lines the first thing on every screen sits
   under the Dynamic Island. The insets live INSIDE min-height (border-box),
   so the column still fills the glass; its content just starts below it. */
/* pan-y: vertical scrolling stays the browser's; a mostly-horizontal touch
   is delivered to the page instead of cancelled as a scroll attempt, which
   is what lets the swipe navigation in app.js ever see a pointerup. */
.inquiry { min-height: 100vh; display: flex; flex-direction: column; padding-top: var(--safe-top); padding-bottom: var(--safe-bottom); touch-action: pan-y pinch-zoom; }

/* movements progress */
.movements {
  display: flex; align-items: center; gap: 10px;
  max-width: 560px; width: 100%;
  margin: 26px auto 0; padding: 0 24px; height: 20px;
}
.movements[hidden] { display: none; }
.movements span { font-family: var(--sans); font-weight: 400; font-size: 12px; letter-spacing: 0.24em; color: var(--umber-text); }
.movements i { flex: 1; height: 1px; background: var(--hairline); transition: background 0.4s, height 0.4s; }
.movements i.done { background: var(--ink); }
.movements i.active { background: var(--umber); height: 2px; }
/* the preparations are three movements; the questions keep all four */
.movements.three span:nth-of-type(4), .movements.three i[data-m="3"] { display: none; }

#stage { flex: 1; display: flex; justify-content: center; padding: 24px; }
.screen { width: 100%; max-width: 560px; animation: rise 0.6s cubic-bezier(0.16, 1, 0.3, 1); }
@keyframes rise { from { opacity: 0; transform: translateY(16px); } to { opacity: 1; transform: none; } }

/* type helpers */
.eyebrow { font-family: var(--sans); font-weight: 400; font-size: 13px; letter-spacing: 0.32em; text-transform: uppercase; color: var(--clay-text); }
.eyebrow.umber { color: var(--umber-text); }
.wordmark { font-family: 'Didot', 'Bodoni 72', 'Baskerville', serif; font-size: clamp(20px, 6vw, 28px); letter-spacing: 0.26em; line-height: 1.3; text-transform: uppercase; }
.wordmark small { display: block; font-family: var(--sans); font-weight: 400; font-size: 11px; letter-spacing: 0.36em; color: var(--quiet); margin-top: 12px; }
.title-caps { font-family: var(--sans); font-weight: 300; font-size: clamp(26px, 7.4vw, 36px); letter-spacing: 0.32em; text-transform: uppercase; line-height: 1.4; }
.script { font-style: italic; font-size: 21px; color: rgba(33, 28, 21, 0.9); }
.rule { width: 44px; height: 1px; background: var(--ink); margin: 24px auto; }
.btn {
  display: inline-block; padding: 16px 36px;
  border: 1px solid var(--ink);
  font-family: var(--sans); font-weight: 400; font-size: 13px;
  letter-spacing: 0.32em; text-transform: uppercase;
  transition: background 0.3s, color 0.3s;
  color: var(--ink); text-decoration: none;
}
.btn:hover, .btn:focus-visible { background: var(--ink); color: var(--ecru); }
.btn:disabled { opacity: 0.3; cursor: not-allowed; }
.btn:disabled:hover { background: none; color: var(--ink); }
.btn-quiet {
  font-family: var(--sans); font-weight: 400; font-size: 12px;
  letter-spacing: 0.3em; text-transform: uppercase; color: var(--umber-text);
  padding: 14px 10px; transition: color 0.3s;
}
.btn-quiet:hover { color: var(--ink); }
button:focus-visible, input:focus-visible { outline: 2px solid var(--clay); outline-offset: 3px; }

/* ---------- arrival ---------- */
/* Centred composition: the typology is the hero, the lockup and the entry
   sit close around it. No space-between — it strands the blocks at the edges. */
.arrival {
  text-align: center;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: clamp(44px, 8vh, 84px);
  min-height: calc(var(--glass) - 48px);
  padding: 28px 0 40px;
}
/* the lockup recedes by scale and weight, not by fading — it stays legible */
.arrival .wordmark small { color: var(--quiet); }

/* the five architectures, named */
.typology { display: flex; justify-content: center; align-items: flex-end; gap: clamp(16px, 4.6vw, 34px); list-style: none; }
.typology li { display: flex; flex-direction: column; align-items: center; gap: 18px; transition: opacity 0.45s ease; }
.typology-mark { display: block; }
.typology svg { display: block; height: clamp(96px, 17vh, 140px); stroke: var(--ink); fill: none; }
.typology-name {
  font-family: var(--sans); font-weight: 400; font-size: 11px;
  letter-spacing: 0.26em; text-transform: uppercase; color: var(--quiet);
  transition: color 0.45s ease;
}
/* hovering the set recedes the others — "which one is mine" made physical */
.typology:hover li { opacity: 0.3; }
.typology li:hover { opacity: 1; }
.typology li:hover .typology-name { color: var(--ink); }
.typology-thesis { margin-top: 34px; }
.arrival-entry { display: flex; flex-direction: column; align-items: center; gap: 30px; }
.arrival-entry .title-caps { margin-bottom: 2px; }
.arrival-note {
  font-family: var(--sans); font-weight: 400; font-size: 12px;
  letter-spacing: 0.2em; text-transform: uppercase; color: var(--quiet);
}

/* the frieze writes itself, one architecture at a time */
.typology .draw { stroke-dasharray: 300; stroke-dashoffset: 300; animation: draw 1.1s cubic-bezier(0.22, 1, 0.36, 1) forwards; }
.typology-name, .typology-thesis { opacity: 0; animation: settle 0.7s ease forwards; }
.typology li:nth-child(1) .draw { animation-delay: 0.05s; }
.typology li:nth-child(2) .draw { animation-delay: 0.16s; }
.typology li:nth-child(3) .draw { animation-delay: 0.27s; }
.typology li:nth-child(4) .draw { animation-delay: 0.38s; }
.typology li:nth-child(5) .draw { animation-delay: 0.49s; }
.typology li:nth-child(1) .typology-name { animation-delay: 0.75s; }
.typology li:nth-child(2) .typology-name { animation-delay: 0.86s; }
.typology li:nth-child(3) .typology-name { animation-delay: 0.97s; }
.typology li:nth-child(4) .typology-name { animation-delay: 1.08s; }
.typology li:nth-child(5) .typology-name { animation-delay: 1.19s; }
.typology-thesis { animation-delay: 1.42s; }
@keyframes settle { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }

@media (max-width: 560px) {
  /* Columns are sized by their names (34px at the narrowest), not the marks
     (24.5px), so the glyphs have room to grow without widening the row.
     The vertical budget is the tight one — tighten the section gaps to pay
     for the taller marks and keep arrival on a single screen. */
  .arrival { gap: clamp(30px, 5.5vh, 56px); }
  .typology { gap: 10px; width: 100%; justify-content: space-between; padding: 0 2px; align-items: flex-end; }
  .typology li { gap: 13px; }
  .typology svg { height: clamp(112px, 16svh, 150px); }
  .typology-name { font-size: 10px; letter-spacing: 0.12em; }
}

.frieze { display: flex; justify-content: center; align-items: center; gap: 30px; margin: 0 auto; }
.frieze svg { height: 140px; stroke: var(--ink); fill: none; }
.frieze svg .draw { stroke-dasharray: 300; stroke-dashoffset: 300; animation: draw 1.4s ease-out forwards; }
@keyframes draw { to { stroke-dashoffset: 0; } }
@media (prefers-reduced-motion: reduce) {
  .frieze svg .draw, .typology .draw, .lines-figure .draw { animation: none; stroke-dashoffset: 0; }
  .typology-name, .typology-thesis { animation: none; opacity: 1; transform: none; }
  .typology li, .typology-name { transition: none; }
  .screen { animation: none; }
}

/* ---------- info ---------- */
.info { text-align: center; padding-top: 36px; }
.field { text-align: left; max-width: 420px; margin: 0 auto 26px; }
.field label { font-family: var(--sans); font-weight: 400; font-size: 12px; letter-spacing: 0.26em; text-transform: uppercase; color: var(--umber-text); display: block; margin-bottom: 8px; }
.field input {
  width: 100%; background: transparent; border: 0;
  border-bottom: 1px solid var(--hairline); padding: 8px 10px 12px;
  font-family: var(--serif); font-style: italic; font-size: 22px; color: var(--ink);
  transition: border-color 0.3s;
}
.field input:focus { outline: none; border-bottom-color: var(--ink); }
.field-error { font-style: italic; font-size: 15px; color: #8C4A3C; margin-top: 8px; display: none; }
.field-error.show { display: block; }

/* ---------- the first measure ---------- */
.measure { text-align: center; padding-top: 60px; }
.rule-readout { font-family: var(--serif); font-weight: 300; font-size: clamp(56px, 14vw, 76px); line-height: 1; }
.rule-readout i { font-style: italic; }
.rule-row { display: grid; grid-template-columns: 40px 1fr 40px; align-items: center; gap: 6px; margin-top: 26px; }
.rule-wrap { position: relative; padding: 0 4px; touch-action: none; cursor: pointer; }
.rule-ticks { display: block; width: 100%; height: 34px; }
.rule-input {
  position: absolute; left: 0; right: 0; top: -5px;
  width: 100%; height: 44px;
  -webkit-appearance: none; appearance: none;
  background: transparent; cursor: pointer;
  pointer-events: none; /* the rule itself is the touch surface; input remains for keyboard */
}
.rule-input::-webkit-slider-runnable-track { height: 1px; background: transparent; }
.rule-input::-webkit-slider-thumb {
  -webkit-appearance: none; width: 3px; height: 38px; margin-top: -19px;
  background: var(--clay); border: 0; border-radius: 0;
}
.rule-input::-moz-range-track { height: 1px; background: transparent; }
.rule-input::-moz-range-thumb { width: 3px; height: 38px; background: var(--clay); border: 0; border-radius: 0; }
.rule-feet { display: flex; justify-content: space-between; font-family: var(--sans); font-weight: 400; font-size: 11px; letter-spacing: 0.2em; color: var(--umber-text); padding-top: 8px; }
.nudge { position: relative; width: 40px; height: 44px; opacity: 0.5; transition: opacity 0.25s; }
.nudge:hover { opacity: 1; }
.nudge::after {
  content: ''; position: absolute; left: 50%; top: 50%;
  width: 10px; height: 10px; border: solid var(--ink); border-width: 1px 0 0 1px;
  transform: translate(-30%, -50%) rotate(-45deg);
}
.nudge.up::after { transform: translate(-70%, -50%) rotate(135deg); }
.rule-phrase { font-style: italic; font-size: 17px; color: rgba(33, 28, 21, 0.82); margin-top: 20px; }
.rule-phrase b { font-style: normal; font-weight: 500; font-size: 21px; color: var(--ink); }

.privacy { margin-top: 18px; padding-top: 14px; border-top: 1px solid var(--hairline); font-style: italic; font-size: 16px; color: #3d362f; }

/* ---------- analysis ---------- */
.analysis {
  background: var(--panel); color: #fff; text-align: center;
  min-height: calc(100vh - 96px); margin: -24px; padding: 24px;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  max-width: none; width: 100vw;
}
.analysis .frieze svg { stroke: rgba(255, 255, 255, 0.85); height: 110px; }
.analysis .line { font-style: italic; font-size: 21px; color: rgba(255, 255, 255, 0.94); margin-top: 36px; }
.analysis .micro { margin-top: 22px; font-family: var(--sans); font-weight: 400; font-size: 12px; letter-spacing: 0.4em; text-transform: uppercase; color: rgba(255, 255, 255, 0.7); }

/* ---------- question ---------- */
.question { padding-top: 8px; }
.where { font-family: var(--sans); font-weight: 400; font-size: 12px; letter-spacing: 0.34em; text-transform: uppercase; color: var(--umber-text); text-align: center; margin-bottom: 14px; }
/* The slot keeps the photo's place in the page; the frame sits in it until
   she scrolls far enough that less of her would show than the docked copy
   holds, and then it pins to the top of the glass at about half size so she
   can still see herself — and the line on her — while she chooses.
   Scrolling back up drops it into the slot again. The slot's aspect ratio
   holds the space, so docking moves nothing beneath it. (2026-09-29; a
   scroll-linked shrink was tried the same day and set aside for this.)
   No edge under the docked photo: the paper behind it is the page's own and
   feathers away downward, so the answers fade under it rather than meeting
   a line. Opaque and unblurred, so nothing ghosts through beside her. */
.crop-slot { margin-bottom: 18px; }
.crop-slot.landscape { aspect-ratio: 5 / 3; }
.crop-slot.portrait { aspect-ratio: 3 / 4; max-width: 320px; margin-left: auto; margin-right: auto; }
.crop-frame {
  position: relative; border: 1px solid var(--ink); overflow: hidden;
  background: var(--bone); width: 100%;
}
.crop-frame.landscape { aspect-ratio: 5 / 3; }
.crop-frame.portrait { aspect-ratio: 3 / 4; }
.crop-slot.docked .crop-dock {
  position: fixed; top: 0; left: 0; right: 0; z-index: 6;
  padding: calc(var(--safe-top) + 10px) 24px 36px;
  background: linear-gradient(to bottom, var(--ecru) calc(100% - 44px), rgba(245, 241, 234, 0));
  animation: dock-in 0.28s ease-out;
}
.crop-slot.docked .crop-frame { width: var(--dock-w, 50%); margin: 0 auto; }
@keyframes dock-in { from { opacity: 0; transform: translateY(-10px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .crop-slot.docked .crop-dock { animation: none; } }
.crop-frame img.crop-photo { position: absolute; transform-origin: 0 0; max-width: none; }
.crop-frame .figure-fallback { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; }
.crop-frame .figure-fallback svg { height: 88%; stroke: rgba(139, 122, 94, 0.55); fill: none; }
.crop-frame svg.overlay { position: absolute; inset: 0; width: 100%; height: 100%; }
.crop-frame svg.overlay path, .crop-frame svg.overlay line, .crop-frame svg.overlay circle {
  fill: none; stroke: #fff;
  filter: drop-shadow(0 1px 3px rgba(0, 0, 0, 0.55));
  stroke-linecap: round; stroke-linejoin: round;
}
.crop-frame.no-photo svg.overlay path, .crop-frame.no-photo svg.overlay line, .crop-frame.no-photo svg.overlay circle {
  stroke: var(--clay); filter: none;
}
.crop-frame .overlay .drawn { stroke-dasharray: 400; stroke-dashoffset: 400; animation: draw 0.9s ease-out forwards; }
.q-text { font-style: italic; font-weight: 300; font-size: clamp(21px, 4vw, 26px); line-height: 1.35; text-align: center; margin: 0 auto 6px; }
.q-note { font-style: italic; font-size: 16px; color: var(--umber-text); text-align: center; margin-bottom: 16px; }
/* An answer is a symbol and a few words. The row is the reviewer's own
   (.rv-opt in review.css): a glyph tile, the short text, the letter as a
   quiet mark. The long note is not here — it appears once, beneath the
   list, for the answer she chose. */
.options { list-style: none; margin-bottom: 10px; }
.options button {
  display: grid; grid-template-columns: 56px 1fr auto; gap: 14px; align-items: center; width: 100%;
  padding: 10px 12px; border-bottom: 1px solid var(--hairline);
  font-size: 17px; text-align: left;
  transition: background 0.25s, border-color 0.25s;
}
.options .opt-glyph {
  width: 56px; height: 56px; display: grid; place-items: center;
  background: #fff; border: 1px solid var(--hairline);
  transition: background 0.25s, border-color 0.25s;
}
.options .opt-glyph svg { width: 44px; height: 44px; }
.options .opt-glyph svg path { fill: none; stroke: var(--ink); stroke-linecap: round; stroke-linejoin: round; transition: stroke 0.25s; }
.options .opt-text { line-height: 1.3; }
.options button.selected .opt-glyph { background: #1c1812; border-color: #3a342c; }
.options button.selected .opt-glyph svg path { stroke: var(--ecru); }
.chosen-note { min-height: 1.6em; margin: 0 12px 22px; font-style: italic; font-size: 16px; color: var(--quiet); }
.chosen-note[hidden] { display: none; }
.options button:hover { background: rgba(139, 122, 94, 0.08); }
.options .letter { font-style: italic; font-family: var(--serif); color: var(--umber-text); min-width: 15px; font-size: 19px; transition: color 0.25s; }
.options .opt-note { display: block; font-style: italic; font-size: 15px; color: var(--quiet); margin-top: 2px; }
.options button.selected { background: var(--ink); color: var(--ecru); border-color: var(--ink); }
.options button.selected .letter { color: rgba(245, 241, 234, 0.75); }
.options button.selected .opt-note { color: rgba(245, 241, 234, 0.65); }
.options button.suggested:not(.selected) { border: 1px solid var(--clay); background: rgba(156, 95, 78, 0.05); margin: 5px 0; }
.options .tag { margin-left: auto; font-family: var(--sans); font-size: 10px; letter-spacing: 0.3em; text-transform: uppercase; color: var(--clay-text); white-space: nowrap; align-self: center; }
.options button.selected .tag { color: rgba(245, 241, 234, 0.6); }
.q-nav { display: flex; justify-content: space-between; align-items: center; }
/* On a question, Back at the left and Yes, that's me / Continue at the
   right of the bar, under the thumb (Leland, 1 Oct); other screens keep
   theirs centred. */
.question .nav-actions { grid-template-columns: auto 1fr; }
.question .nav-actions .btn { grid-column: 2; justify-self: end; }
/* "See My Architecture →" is 257px; beside Back at 375 it ran 11px into the
   bar's margin, so narrow phones trim its sides to keep the right edge true */
@media (max-width: 380px) { .question .nav-actions .btn { padding-left: 14px; padding-right: 14px; } }

/* The tie-breaker questions (spec §7): the question screen's own rows, with
   no glyph tile, so A and B are two tall plain answers; the first screen's
   Skip sits at the right of the bar, after Continue. The screen is short, so
   the bar is pushed to the bottom of the glass, where it sits on the
   questions before it. */
.tiebreak { display: flex; flex-direction: column; padding-top: clamp(8px, 3vh, 28px); }
.tiebreak .nav-actions { margin-top: auto; }
.tiebreak .tb-lead { max-width: 22em; margin: 0 auto 18px; }
.tiebreak .q-text { margin-bottom: 18px; }
.tiebreak .options button { grid-template-columns: 1fr auto; min-height: 72px; padding: 14px 16px; }
.tiebreak .nav-actions { grid-template-columns: auto 1fr auto; }

/* ---------- result ---------- */
.result { text-align: center; padding-top: 12px; }
.result .crown { background: var(--panel); color: #fff; padding: 40px 24px 36px; margin: 0 -24px; }
.result .crown .eyebrow { color: rgba(255, 255, 255, 0.6); }
.result .glyph-big { height: 170px; display: flex; align-items: center; justify-content: center; margin: 22px 0 10px; }
.result .glyph-big.pair { gap: 28px; }
.result .glyph-big.pair svg { height: 140px; }
.result .glyph-big svg { height: 160px; stroke: #fff; fill: none; }
.result .glyph-big .draw { stroke-dasharray: 600; stroke-dashoffset: 600; animation: draw 2s ease-out 0.3s forwards; }
.result h1 { font-family: var(--sans); font-weight: 200; font-size: clamp(38px, 9vw, 62px); letter-spacing: 0.2em; text-transform: uppercase; line-height: 1.1; }
.result h1.is-compound { font-size: clamp(26px, 6.4vw, 44px); letter-spacing: 0.14em; }
.result .tagline { font-style: italic; font-size: 19px; color: rgba(255, 255, 255, 0.85); margin-top: 10px; }
.result .desc { max-width: 470px; margin: 28px auto 0; font-size: 17px; line-height: 1.75; text-align: left; }
.tally { display: grid; grid-template-columns: repeat(5, 1fr); gap: 4px; max-width: 470px; margin: 16px auto 0; }
.tally div { background: var(--bone); padding: 14px 4px; }
.tally .lbl { font-family: var(--sans); font-weight: 400; font-size: 10px; letter-spacing: 0.22em; text-transform: uppercase; color: var(--umber-text); display: block; margin-bottom: 5px; }
.tally .val { font-family: var(--sans); font-weight: 300; font-size: 22px; }
.tally div.top { background: var(--ink); }
.tally div.top .lbl { color: rgba(245, 241, 234, 0.6); }
.tally div.top .val { color: var(--ecru); }
.secondary-note { max-width: 440px; margin: 26px auto 0; font-style: italic; font-size: 17px; border-top: 1px solid var(--hairline); padding-top: 22px; }
.secondary-note strong { font-style: normal; font-weight: 500; }
.evidence-note { max-width: 470px; margin: 26px auto 0; font-size: 17px; line-height: 1.55; }
.evidence-note p { margin: 8px 0 0; }
.evidence-note p:first-child { margin-top: 0; }
.provenance-note { max-width: 470px; margin: 22px auto 0; font-size: 15px; line-height: 1.5; color: var(--quiet); }
.invitation { margin-top: 40px; border-top: 1px solid var(--hairline); padding-top: 28px; padding-bottom: 60px; }
/* the colophon carries the closing space instead, so the two don't stack up */
.invitation:not(:last-child) { padding-bottom: 40px; }
.invitation .script { margin: 12px 0 22px; }
.invite-copy {
  max-width: 470px; margin: 14px auto 24px;
  font-size: 17px; line-height: 1.75; text-align: left;
}

/* ---------- colophon ----------
   A credit, not a paragraph of the reading: hairline above, one size down from
   the smallest copy on the page, and the names lifted just clear of the text
   around them so the eye can find a person without stopping to read. */
.colophon {
  max-width: 470px; margin: 0 auto;
  border-top: 1px solid var(--hairline);
  padding: 26px 0 54px;
  text-align: left;
}
.colophon .eyebrow { display: block; font-size: 11px; letter-spacing: 0.42em; margin-bottom: 13px; }
.colophon p { font-size: 14.5px; line-height: 1.85; color: var(--quiet); }
.colophon p + p { margin-top: 11px; }
.colophon .ack-name { color: var(--ink); }
.colophon .ack-year {
  font-family: var(--sans); font-weight: 400; font-size: 12px;
  letter-spacing: 0.14em; color: var(--umber-text);
}

/* ---------- camera modal ---------- */
.camera-modal { position: fixed; inset: 0; background: #000; z-index: 50; }
.camera-modal video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.camera-guide { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; pointer-events: none; }
.camera-guide svg { height: 80%; stroke: rgba(255, 255, 255, 0.55); fill: none; }
.camera-chrome { position: absolute; inset: auto 0 0 0; padding: 18px 0 calc(30px + env(safe-area-inset-bottom, 0px)); display: flex; flex-direction: column; align-items: center; gap: 12px; background: linear-gradient(transparent, rgba(0, 0, 0, 0.55)); }
.camera-label { font-family: var(--sans); font-weight: 400; font-size: 12px; letter-spacing: 0.34em; text-transform: uppercase; color: #fff; }
.shutter { width: 58px; height: 58px; border-radius: 50%; border: 2px solid #fff; position: relative; }
.shutter::after { content: ''; position: absolute; inset: 6px; border-radius: 50%; background: #fff; }
.camera-buttons { display: flex; align-items: center; gap: clamp(14px, 6vw, 34px); }
.camera-quiet { font-family: var(--sans); font-weight: 400; font-size: 12px; letter-spacing: 0.3em; text-transform: uppercase; color: rgba(255, 255, 255, 0.8); width: 64px; }

/* the portrait she just took and how far along she is — top left, under the
   status bar, where the camera has nothing else; the buttons row is full */
.camera-strip { position: absolute; top: calc(16px + env(safe-area-inset-top, 0px)); left: 16px; z-index: 2; display: flex; align-items: center; gap: 10px; }
.camera-strip[hidden] { display: none; }
.camera-strip img { width: 42px; height: 56px; object-fit: cover; display: block; border: 1px solid rgba(245, 241, 234, .7); border-radius: 3px; background: #2A231C; }
.camera-strip span { font-family: var(--sans); font-weight: 400; font-size: 11px; letter-spacing: .2em; text-transform: uppercase; color: rgba(245, 241, 234, .8); }
.camera-modal video.mirror { transform: scaleX(-1); }

/* ---------- live dimension lines ----------
   An architect's witness line across the shoulders and hips (or the jaw, on the
   face shot), drawn from her own landmarks in the same pixels the outline lives
   in. Ghosted while she is still moving; the measurement itself only appears
   once the frame is actually right, so no number is ever read off a bad pose.
   The mapper has already mirrored the points, so this layer is never flipped. */
.camera-dims { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }

/* Her own figure, drawn live from her landmarks in place of a fixed drawing no
   body ever matched. The outline recedes while the constellation is present and
   returns the moment it is not — including every failure path, where the plain
   outline is still the whole guide. Pose shots only; Face and Hand keep the
   close-range outline. */
.camera-constellation { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }
.camera-guide.recede svg { opacity: 0; }
.camera-dims .dim-line, .camera-dims .dim-tick {
  stroke: rgba(255, 255, 255, 0.65); stroke-width: 1.5; fill: none;
  vector-effect: non-scaling-stroke; transition: opacity 260ms ease, stroke 260ms ease; opacity: 0.35;
}
.camera-dims[data-state="aligned"] .dim-line, .camera-dims[data-state="aligned"] .dim-tick {
  opacity: 0.9; stroke: var(--align-ok);
}
/* the caption is held at the same strength as the line it belongs to, or it
   shouts over a measurement that is not settled yet */
/* sized for the person the numbers describe — three metres away, not at arm's length */
.camera-dims .dim-text {
  font-family: var(--sans); font-weight: 400; font-size: 14px; letter-spacing: 0.26em;
  text-transform: uppercase; fill: rgba(255, 255, 255, 0.85); text-anchor: middle;
  paint-order: stroke; stroke: rgba(0, 0, 0, 0.35); stroke-width: 2px;
  opacity: 0.5; transition: opacity 260ms ease;
}
.camera-dims[data-state="aligned"] .dim-text { opacity: 0.95; }
/* the measurement keeps its own casing — "38 cm", never "38 CM" */
.camera-dims .dim-value { text-transform: none; }

/* ---------- live alignment ----------
   The outline is the whole interface: white while it looks for you, warm ochre when
   you're nearly there, verdigris when you've got it. Colour is never the only signal —
   stroke weight and the written hint carry the same meaning. */
.camera-guide svg { transition: stroke 260ms ease, stroke-width 260ms ease, opacity 260ms ease; }
.camera-guide[data-align="searching"] svg { animation: guide-breathe 3.4s ease-in-out infinite; }
.camera-guide[data-align="close"] svg { stroke: var(--align-close); stroke-width: 1.7; }
.camera-guide[data-align="aligned"] svg {
  stroke: var(--align-ok);
  stroke-width: 2.1;
  animation: guide-settle 420ms ease-out;
}
@keyframes guide-breathe {
  0%, 100% { opacity: 0.62; }
  50% { opacity: 1; }
}
@keyframes guide-settle {
  0% { transform: scale(1.014); }
  100% { transform: scale(1); }
}

.camera-hint {
  font-family: var(--sans);
  font-weight: 400;
  font-size: 13px;
  letter-spacing: 0.16em;
  color: #fff;
  min-height: 1.2em;
  opacity: 0;
  transition: opacity 220ms ease;
  text-shadow: 0 1px 6px rgba(0, 0, 0, 0.7);
}
.camera-hint.show { opacity: 1; }
.rule-readout.minor { font-size: 44px; min-height: 1.1em; }
/* the distance corrections — big enough to read from eight feet, without glasses */
.camera-hint.move {
  font-size: 21px;
  font-weight: 400;
  letter-spacing: 0.22em;
  text-transform: uppercase;
}

.camera-count {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
  font-family: var(--serif);
  font-size: 84px;
  line-height: 1;
  color: #fff;
  text-shadow: 0 2px 24px rgba(0, 0, 0, 0.55);
  animation: count-pulse 700ms ease-out;
}
@keyframes count-pulse {
  0% { opacity: 0; transform: scale(1.28); }
  22% { opacity: 1; transform: scale(1); }
  100% { opacity: 0.15; transform: scale(0.94); }
}

@media (prefers-reduced-motion: reduce) {
  .camera-guide svg,
  .camera-guide[data-align="searching"] svg,
  .camera-guide[data-align="aligned"] svg,
  .camera-count { animation: none; }
  .camera-guide[data-align="searching"] svg { opacity: 0.8; }
  .camera-dims * { transition: none; }
}

/* ---------- review opt-in ---------- */
.consent {
  border: 1px solid var(--hairline);
  padding: 20px 22px;
  margin: 26px 0 4px;
  text-align: left;
  background: rgba(255, 255, 255, 0.35);
}
.consent label { display: flex; gap: 13px; align-items: flex-start; cursor: pointer; }
.consent input[type="checkbox"] {
  appearance: none;
  flex: 0 0 auto;
  width: 17px;
  height: 17px;
  margin-top: 5px;
  border: 1px solid var(--umber);
  background: transparent;
  cursor: pointer;
  transition: background 160ms ease, border-color 160ms ease;
}
.consent input[type="checkbox"]:checked { background: var(--clay); border-color: var(--clay); }
.consent input[type="checkbox"]:checked::after {
  content: '';
  display: block;
  width: 4px;
  height: 9px;
  margin: 1px 0 0 5px;
  border: solid var(--ecru);
  border-width: 0 1.5px 1.5px 0;
  transform: rotate(42deg);
}
.consent input[type="checkbox"]:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
.consent .consent-title {
  font-family: var(--sans);
  font-weight: 400;
  font-size: 12px;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  display: block;
  margin-bottom: 7px;
}
.consent .consent-body { font-size: 16px; line-height: 1.6; color: var(--quiet); }
.consent .consent-body em { color: var(--ink); font-style: italic; }
.consent .consent-assure {
  display: block;
  margin-top: 9px;
  font-family: var(--sans);
  font-size: 13px;
  font-weight: 400;
  letter-spacing: 0.06em;
  line-height: 1.75;
  color: var(--quiet);
}
.consent .consent-confirm-row {
  margin-top: 18px;
  padding-left: 30px; /* aligns with the consent copy, past the checkbox */
  display: flex;
  flex-direction: column;
  gap: 10px;
  align-items: flex-start;
}
.consent .consent-confirm { width: auto; }
.consent .consent-confirm:disabled { opacity: 0.55; }
.consent .consent-said {
  font-style: italic;
  font-size: 15px;
  color: var(--quiet);
}
.consent .consent-said:empty { display: none; }
@media (max-width: 520px) {
  .consent .consent-confirm-row { padding-left: 0; }
  .consent .consent-confirm { width: 100%; }
}

@media (max-width: 520px) {
  .frieze { gap: 20px; }
  .frieze svg { height: 110px; }
}

/* ---------- was that a good photograph? ----------
   A quiet mark on a thumbnail: colour and shape both, never colour alone.
   Positioned by whoever holds it — the strip hangs it off a corner, a
   portrait card tucks it inside. */
.pip {
  position: absolute; top: 8px; right: 8px; z-index: 2;
  width: 22px; height: 22px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-family: var(--sans); font-size: 12px; line-height: 1;
  color: var(--ecru); background: var(--umber);
}
.pip.good { background: var(--align-ok); }
.pip.fair { background: var(--umber); }
.pip.retake { background: var(--clay); }

.verdict {
  font-family: var(--sans); font-size: 12px; letter-spacing: .28em;
  text-transform: uppercase; margin-bottom: 12px;
}
.verdict.good { color: var(--align-ok); }
.verdict.fair { color: var(--umber-text); }
.verdict.retake { color: var(--clay-text); }
.verdict-raw {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 12px; line-height: 1.5; color: var(--quiet);
  background: var(--bone); border: 1px solid var(--hairline);
  padding: 10px 12px; margin-bottom: 16px; overflow-x: auto;
}

/* ---------- before the portraits, one preparation per screen ----------
   The I–IV bar above the stage is the questions' own. Each screen is a
   drawing in the brand hand (ink strokes, no fill, umber accents, a hairline
   floor, Jost tracked-caps callouts), one line, and a quieter line under it;
   the bar of Back / Next holds to the bottom of the glass. */
.prep {
  text-align: center; display: flex; flex-direction: column;
  min-height: calc(var(--glass) - 48px);
  padding-top: clamp(4px, 1.4vh, 14px);
}
.prep-title { font-size: clamp(22px, 6.6vw, 30px); letter-spacing: .32em; margin: 14px 0 0; padding-left: .32em; }
.prep-scene {
  display: block; width: 100%; max-width: 342px; height: auto; margin: 12px auto 0;
  stroke: var(--ink); fill: none; stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round;
}
.prep-scene .floor { stroke: var(--hairline); }
.prep-scene .door { stroke: var(--umber); }
/* the figures are the guide's strokes scaled up; the stroke itself stays a
   pen's width whatever the scale */
.prep-scene .fig * { vector-effect: non-scaling-stroke; }
.prep-scene .fig .accent { stroke: var(--umber); stroke-width: 1.1; }
/* a wide ecru stroke behind a figure knocks the door out from behind her */
.prep-scene .knock { stroke: var(--ecru); stroke-width: 6.5; }
.prep-scene .lead { stroke: var(--umber); stroke-width: .9; }
.prep-scene .dash { stroke-dasharray: 2 5; stroke-width: 1.1; }
.prep-scene .dim { stroke: var(--umber); stroke-width: 1; }
.prep-scene .dot { fill: var(--umber); stroke: none; }
.prep-scene text { fill: var(--umber-text); stroke: none; font-family: var(--sans); font-weight: 400; font-size: 10px; letter-spacing: 2.6px; }
.prep-scene text.end { text-anchor: end; }
.prep-scene text.mid { text-anchor: middle; }
/* a caption in the drawing, in the serif: the door is an example, not the rule */
.prep-scene text.note { font-family: var(--serif); font-style: italic; font-size: 12px; letter-spacing: 0; }
.prep-you .prep-title { font-size: clamp(20px, 5.8vw, 26px); }
/* the lamp and its light stand far off at the room's edge, drawn faint, and
   the door is quieted too, so the eye goes to her and not to the fixtures.
   The drawing is wider than the others (viewBox from -20) to make that room;
   its caption is set up a size to read as the others do. */
.prep-you .lamp, .prep-you .rays { opacity: .3; }
.prep-you .prep-scene .door { opacity: .5; }
.prep-you .prep-scene text.note { font-size: 13.5px; }
/* the lamp's rays come on one after another, then their dashes drift toward
   her, two dash-lengths every 2.4s, for as long as the screen is up: the
   light travels onto her. Slow on purpose — it should read as light, not
   as something asking for attention. Still under reduced motion. */
.prep-you .rays path { animation: ray-on .5s ease-out both, ray-drift 2.4s linear infinite; }
.prep-you .rays path:nth-child(1) { animation-delay: .4s, .4s; }
.prep-you .rays path:nth-child(2) { animation-delay: .55s, .55s; }
.prep-you .rays path:nth-child(3) { animation-delay: .7s, .7s; }
@keyframes ray-on { from { opacity: 0; } }
@keyframes ray-drift { from { stroke-dashoffset: 14; } to { stroke-dashoffset: 0; } }
@media (prefers-reduced-motion: reduce) { .prep-you .rays path { animation: none; } }
.prep-line { margin: 14px 0 0; font-size: clamp(20px, 5.6vw, 23px); line-height: 1.4; }
.prep-sub { margin: 6px 0 0; font-size: 17px; line-height: 1.5; font-style: italic; color: var(--quiet); }
.prep-ask { margin-top: 6px; font-size: clamp(21px, 6vw, 24px); }
/* Today has no title (2026-09-28): the ask is the heading, under the eyebrow */
.prep-today .prep-ask { margin-top: 14px; font-weight: 400; }
/* the four essentials: a glyph and a few words each */
.essentials { list-style: none; margin: 22px 0 0; padding: 0; width: 100%; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; text-align: left; }
.essentials li { display: flex; align-items: center; gap: 12px; min-height: 64px; padding: 10px 12px; border: 1px solid var(--hairline); font-size: 18px; line-height: 1.25; }
.ess-glyph { flex: none; width: 26px; height: 32px; fill: none; stroke: var(--ink); stroke-width: 1.4; stroke-linecap: round; stroke-linejoin: round; }
.ess-glyph.backdrop { stroke: var(--umber); }
.ess-glyph .floor { stroke: var(--hairline); }

/* the chapter card before the preparations: her figure draws in head to
   foot (0.2–1.4s, each stroke's start set in app.js by its height),
   the portrait's corners close on her (1.4–2.0s, the soft tap lands with
   them), the words and the way on settle (1.9–2.8s). Each rule holds the
   finished card and its animation runs from the unfinished one, so .drawn
   (a return by Back, a tap to hurry it, reduced motion) only has to stop
   the animations. The bar ignores taps until it has settled in: a tap on
   the empty space where it will be finishes the card instead of leaving. */
.prep-intro .intro-scene { margin-top: auto; }
.intro-scene {
  display: block; width: min(60vw, 240px); height: auto; margin: 0 auto;
  fill: none; stroke-linecap: round; stroke-linejoin: round;
}
.intro-scene .fig { stroke: var(--ink); stroke-width: .62; }
.intro-scene .fig > * { stroke-dasharray: 1; stroke-dashoffset: 0; animation: intro-draw .5s cubic-bezier(.45, 0, .25, 1) .2s both; }
.intro-scene .corners { stroke: var(--umber); stroke-width: 1.3; transform-origin: 100px 116px; animation: intro-close .6s cubic-bezier(.22, 1, .36, 1) 1.4s both; }
.intro-title { margin: clamp(18px, 3.4vh, 30px) 0 0; padding-left: .32em; font-size: clamp(20px, 5.8vw, 26px); }
.intro-line { margin: 12px auto 0; max-width: 19em; font-size: clamp(20px, 5.6vw, 23px); line-height: 1.4; font-style: italic; }
.prep-intro .intro-title { animation: settle .6s ease-out 1.9s both; }
.prep-intro .intro-line { animation: settle .6s ease-out 2.05s both; }
.prep-intro .nav-actions { margin-top: auto; animation: settle .6s ease-out 2.2s both; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr); }
/* the long way on keeps the centre; Back, on the row beneath, keeps one line */
.prep-intro .nav-actions [data-nav="back"] { white-space: nowrap; }
/* "Prepare the room →" is too long to share a row with Back, so the card keeps two */
.prep-intro .nav-actions > * { grid-row: auto; }
.prep-intro:not(.drawn) .nav-actions { pointer-events: none; }
.prep-intro.drawn * { animation: none; }
@keyframes intro-draw { from { stroke-dashoffset: 1; } }
@keyframes intro-close { from { opacity: 0; transform: scale(1.16); } }
@media (prefers-reduced-motion: reduce) { .screen.prep-intro * { animation: none; } }

/* who holds the phone */
.holder { width: 100%; margin-top: 18px; }
.holder-q { font-family: var(--sans); font-weight: 400; font-size: 11px; letter-spacing: .26em; text-transform: uppercase; color: var(--umber-text); }
.seg { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; margin-top: 10px; }
.seg button {
  display: flex; align-items: center; justify-content: center; min-height: 44px;
  border: 1px solid var(--hairline); color: var(--ink);
  font-family: var(--sans); font-weight: 400; font-size: 12px; letter-spacing: .24em; text-transform: uppercase;
  transition: background .25s, border-color .25s, color .25s;
}
.seg button[aria-pressed="true"] { background: var(--ink); border-color: var(--ink); color: var(--ecru); }
.prep-camera .prep-scene { margin-top: 14px; }
.sound-note { display: flex; align-items: center; justify-content: center; gap: 10px; margin-top: 14px; font-size: 16px; font-style: italic; color: var(--quiet); }
.sound-glyph { flex: none; width: 20px; height: 20px; fill: none; stroke: var(--umber); stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }

/* today: a dress form beside each answer */
.prep-today .prep-fit { margin-top: 18px; }
.fit-glyph { flex: none; width: 34px; height: 48px; fill: none; stroke: var(--ink); stroke-width: 1.3; stroke-linecap: round; stroke-linejoin: round; }
.fit[aria-pressed="true"] .fit-glyph { stroke: var(--ecru); }
.fit-text { display: flex; flex-direction: column; gap: 3px; }

/* ---------- the strip of four ----------
   On every brief and review: taken (her thumbnail, its pip), current (ink
   border on bone), upcoming (hairline, the outline faint). The hand is
   dashed because it is optional. The active group's label is in ink. */
.strip { display: flex; justify-content: center; gap: clamp(14px, 6vw, 26px); }
.strip-group { display: flex; flex-direction: column; align-items: center; gap: 9px; }
.strip-label {
  width: 110px; padding-bottom: 5px; border-bottom: 1px solid var(--hairline); text-align: center;
  font-family: var(--sans); font-weight: 400; font-size: 10px; letter-spacing: .2em; text-transform: uppercase; color: var(--umber-text);
}
.strip-group.active .strip-label { border-bottom-color: var(--ink); color: var(--ink); }
.strip-tiles { display: flex; gap: 10px; }
.strip-tile { display: flex; flex-direction: column; align-items: center; gap: 5px; }
button.strip-tile { cursor: pointer; }  /* a taken portrait opens its review */
.strip-frame {
  position: relative; width: 50px; height: 66px; border: 1px solid var(--hairline);
  display: flex; align-items: center; justify-content: center;
}
.strip-frame svg { height: 56px; stroke: var(--umber); fill: none; stroke-width: 1.9; stroke-linecap: round; stroke-linejoin: round; }
.strip-frame img { width: 100%; height: 100%; object-fit: cover; display: block; }
.strip-tile[data-state="taken"] .strip-frame { border-color: var(--ink); background: #2A231C; }
.strip-tile[data-state="current"] .strip-frame { border: 1.5px solid var(--ink); background: var(--bone); }
.strip-tile[data-state="current"] .strip-frame svg { stroke: var(--ink); }
.strip-tile[data-optional] .strip-frame { border-style: dashed; border-color: rgba(33, 28, 21, .4); }
.strip-tile[data-optional][data-state="current"] .strip-frame,
.strip-tile[data-optional][data-state="taken"] .strip-frame { border-color: var(--ink); }
.strip-name { font-family: var(--sans); font-weight: 400; font-size: 10px; letter-spacing: .2em; text-transform: uppercase; color: var(--umber-text); }
.strip-tile[data-state="current"] .strip-name { color: var(--ink); }
.strip-frame .pip { top: -8px; right: -8px; width: 16px; height: 16px; font-size: 10px; }

/* ---------- the brief ---------- */
.brief {
  text-align: center; display: flex; flex-direction: column;
  min-height: calc(var(--glass) - 48px);
  padding-top: clamp(4px, 1vh, 30px);
}
.brief .eyebrow { margin-top: 18px; }
.brief-title { font-size: clamp(17px, 5vw, 20px); letter-spacing: .3em; margin: 8px 0 0; padding-left: .3em; }
/* the outline she is about to fill, on the camera's own dark ground */
.guide-card {
  position: relative; width: 100%; height: clamp(160px, 22vh, 232px); margin-top: 16px;
  background: linear-gradient(180deg, #241E17 0%, #171310 100%);
  display: flex; align-items: center; justify-content: center;
}
.guide-card .tick { position: absolute; width: 12px; height: 12px; border: 0 solid rgba(245, 241, 234, .6); }
.guide-card .tick:nth-child(1) { top: 8px; left: 8px; border-top-width: 1px; border-left-width: 1px; }
.guide-card .tick:nth-child(2) { top: 8px; right: 8px; border-top-width: 1px; border-right-width: 1px; }
.guide-card .tick:nth-child(3) { bottom: 8px; left: 8px; border-bottom-width: 1px; border-left-width: 1px; }
.guide-card .tick:nth-child(4) { bottom: 8px; right: 8px; border-bottom-width: 1px; border-right-width: 1px; }
.guide-card svg { height: 88%; stroke: rgba(245, 241, 234, .82); fill: none; stroke-width: .75; stroke-linecap: round; stroke-linejoin: round; }
.guide-card.hand svg { height: 82%; stroke-width: .55; }
/* three cues: a glyph and a few words */
.cues { list-style: none; margin: 18px 0 0; padding: 0; width: 100%; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; }
.cue { display: flex; flex-direction: column; align-items: center; gap: 8px; }
.cue-glyph { width: 34px; height: 34px; fill: none; stroke: var(--ink); stroke-width: 1.3; stroke-linecap: round; stroke-linejoin: round; }
.cue-glyph .accent { stroke: var(--umber); }
.cue-glyph .dash { stroke-dasharray: 2 3; }
.cue-glyph .dot { fill: var(--ink); stroke: none; }
.cue-label { font-family: var(--sans); font-weight: 400; font-size: 11px; letter-spacing: .18em; line-height: 1.45; text-transform: uppercase; color: var(--umber-text); }
.brief-sentence { margin: 16px 0 0; font-size: 18px; line-height: 1.45; }
.brief-links { margin: 10px 0 0; font-style: italic; font-size: 16px; color: var(--quiet); }
.link-quiet { font: inherit; color: inherit; text-decoration: underline; cursor: pointer; padding: 0; }
/* the filled primary: Open camera, Continue on her portraits */
.btn-ink { background: var(--ink); color: var(--ecru); }
.btn-ink:hover, .btn-ink:focus-visible { background: var(--ecru); color: var(--ink); }

/* ---------- the review, after the shutter ----------
   The camera's own dark ground, edge to edge like the analysis screen: the
   strip, her photograph large, the verdict with its pip, the reasons, Take it
   again / Use this one, and what comes next. Words on the panel use the two
   light tones — the umber and clay word colours were mixed for ecru. */
.review {
  background: var(--panel); color: var(--ecru);
  margin: -24px; padding: 24px;
  width: calc(100% + 48px); max-width: none; min-height: var(--glass);
  display: flex; flex-direction: column; align-items: center;
}
/* the dark ground runs edge to edge (above), but on anything wider than a
   phone her photograph and the two rows of controls stay a reading column,
   the same cap `.screen` holds everywhere else — never a 1200px photo. */
.review > * { width: 100%; max-width: 560px; margin-inline: auto; }
.review .strip-label { color: rgba(245, 241, 234, .65); border-bottom-color: rgba(245, 241, 234, .2); }
.review .strip-group.active .strip-label { color: var(--ecru); border-bottom-color: rgba(245, 241, 234, .7); }
.review .strip-frame { border-color: rgba(245, 241, 234, .25); }
.review .strip-frame svg { stroke: rgba(245, 241, 234, .45); }
.review .strip-tile[data-state="taken"] .strip-frame { border-color: rgba(245, 241, 234, .7); }
.review .strip-tile[data-state="current"] .strip-frame { border-color: var(--ecru); background: #2A231C; }
.review .strip-tile[data-optional] .strip-frame { border-color: rgba(245, 241, 234, .35); }
.review .strip-name { color: rgba(245, 241, 234, .65); }
.review .strip-tile[data-state="current"] .strip-name { color: var(--ecru); }
.review-photo { height: clamp(240px, 46vh, 392px); margin-top: 18px; border-radius: 6px; overflow: hidden; background: #2A231C; }
.review-photo img { width: 100%; height: 100%; object-fit: contain; display: block; }
.verdict-row { display: flex; align-items: center; gap: 10px; margin-top: 18px; }
.verdict-row .pip { position: static; width: 20px; height: 20px; }
.review .verdict { margin: 0; }
.review .verdict.good { color: var(--align-ok); }
.review .verdict.fair { color: var(--umber-light); }
.review .verdict.retake { color: var(--clay-light); }
.review-notes { list-style: none; margin: 8px 0 0; padding: 0; font-size: 18px; line-height: 1.45; color: rgba(235, 229, 218, .85); }
.review-notes li + li { margin-top: 4px; }
.review .verdict-raw { color: rgba(245, 241, 234, .7); background: rgba(245, 241, 234, .06); border-color: rgba(245, 241, 234, .2); margin-top: 12px; }
.review-actions { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; margin-top: auto; padding-top: 18px; }
.btn-dark, .btn-dark-quiet {
  display: flex; align-items: center; justify-content: center; min-height: 50px; border-radius: 2px;
  font-family: var(--sans); font-weight: 400; font-size: 12px; letter-spacing: .28em; text-transform: uppercase;
}
.btn-dark { background: var(--ecru); color: var(--panel); border: 1px solid var(--ecru); }
.btn-dark-quiet { color: var(--ecru); border: 1px solid rgba(245, 241, 234, .5); }
.review-next { margin-top: 14px; text-align: center; font-family: var(--sans); font-weight: 400; font-size: 11px; letter-spacing: .24em; text-transform: uppercase; color: rgba(245, 241, 234, .65); }
/* Back on the left, what comes next on the right, under the two choices.
   The button keeps a 44px target but gives the row only its text's height
   (negative margins), so the footer is no taller than the caption was */
.review-foot { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-top: 14px; }
.review-foot .review-next { margin-top: 0; text-align: right; }
.review-back { flex: none; padding: 14px 16px 14px 0; margin: -14px 0; line-height: 16px; color: rgba(245, 241, 234, .65); }
.review-back:hover { color: var(--ecru); }

/* ---------- your portraits ---------- */
.portraits { text-align: center; display: flex; flex-direction: column; min-height: calc(var(--glass) - 48px); padding-top: clamp(4px, 1vh, 30px); }
.portraits-title { font-size: clamp(18px, 5.4vw, 22px); letter-spacing: .3em; margin: 10px 0 0; padding-left: .3em; }
/* capped so the four, the hint and the privacy line all sit above the bar on a 14 Pro */
.portrait-grid { width: 100%; max-width: 300px; margin: 14px auto 0; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: 14px; row-gap: 8px; }
.portrait-card { display: flex; flex-direction: column; gap: 8px; text-align: left; padding: 0; }
.portrait-frame { position: relative; display: block; aspect-ratio: 1 / 1; border: 1px solid var(--ink); background: #2A231C; overflow: hidden; }
.portrait-frame img { width: 100%; height: 100%; object-fit: cover; display: block; }
.portrait-frame.empty {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 12px;
  border: 1px dashed rgba(33, 28, 21, .4); background: none;
}
.portrait-frame.empty svg { height: 70px; stroke: var(--umber); fill: none; stroke-width: 1.3; stroke-linecap: round; stroke-linejoin: round; }
.portrait-add { font-family: var(--sans); font-weight: 400; font-size: 11px; letter-spacing: .24em; text-transform: uppercase; color: var(--umber-text); }
.portrait-name { display: block; font-family: var(--sans); font-weight: 400; font-size: 11px; letter-spacing: .24em; text-transform: uppercase; color: var(--ink); }
.portrait-note { display: block; font-size: 15px; font-style: italic; line-height: 1.35; color: var(--quiet); }
.portraits-hint { margin: 12px 0 0; font-size: 17px; font-style: italic; line-height: 1.45; color: var(--quiet); }
.portraits .privacy { margin-top: 10px; }

.prep-fit { max-width: 460px; margin: 36px auto 0; text-align: left; }
.fits { display: flex; flex-direction: column; gap: 8px; }
.fit {
  display: flex; align-items: center; gap: 16px; width: 100%; text-align: left; padding: 12px 16px;
  border: 1px solid var(--hairline); transition: border-color .25s, background .25s;
}
.fit:hover { border-color: var(--umber); }
.fit[aria-pressed="true"] { background: var(--ink); border-color: var(--ink); }
.fit[aria-pressed="true"] .fit-label,
.fit[aria-pressed="true"] .fit-note { color: var(--ecru); }
.fit-label {
  display: block; font-family: var(--sans); font-size: 14px;
  letter-spacing: .24em; text-transform: uppercase; margin-bottom: 0;
}
.fit-note { display: block; font-size: 18px; color: var(--quiet); line-height: 1.35; }
/* Her drawing, offered on the way to the camera. A ticked box, not a toggle
   button: a choice that is already made for her has to read as one, and has to
   be as easy to undo as it was to arrive at. */
.prep-draw { margin-top: 28px; border: 1px solid var(--hairline); padding: 18px 20px; background: rgba(255, 255, 255, 0.35); }
.draw-optin { display: flex; gap: 13px; align-items: flex-start; cursor: pointer; }
.draw-optin input[type="checkbox"] {
  appearance: none;
  flex: 0 0 auto;
  width: 17px;
  height: 17px;
  margin-top: 4px;
  border: 1px solid var(--umber);
  background: transparent;
  cursor: pointer;
  transition: background 160ms ease, border-color 160ms ease;
}
.draw-optin input[type="checkbox"]:checked { background: var(--clay); border-color: var(--clay); }
.draw-optin input[type="checkbox"]:checked::after {
  content: '';
  display: block;
  width: 4px;
  height: 9px;
  margin: 1px 0 0 5px;
  border: solid var(--ecru);
  border-width: 0 1.5px 1.5px 0;
  transform: rotate(42deg);
}
.draw-optin input[type="checkbox"]:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
.draw-title {
  display: block; font-family: var(--sans); font-size: 12px;
  letter-spacing: .24em; text-transform: uppercase; margin-bottom: 4px;
}
.draw-body { display: block; font-size: 16px; color: var(--quiet); line-height: 1.55; }


/* ---------- the optional-notes sliders ----------
   Native range inputs in the house dress: hairline track, ink thumb, no
   browser chrome. The readout is fixed-width tabular so growing numbers never
   move the card, and a dimmed track means "not answered yet". */
.detail-value {
  display: block; font-family: var(--serif); font-size: 22px; color: var(--ink);
  font-variant-numeric: tabular-nums; text-align: right; white-space: nowrap;
  min-height: 28px; line-height: 28px;
}
.detail-clear {
  font-family: var(--sans); font-weight: 300; font-size: 20px; line-height: 1;
  color: var(--umber-text); background: none; border: 0;
  width: 32px; height: 32px; padding: 0; cursor: pointer;
}
/* hidden must still occupy its place — a row may never shift when the clear
   button arrives, or the value jumps sideways under her thumb */
.detail-clear[hidden] { display: inline-block; visibility: hidden; }
.slide-row { padding: 7px 0 3px; display: grid; grid-template-columns: 1fr; align-items: center; }
.slide-row .slide-tag {
  font-family: var(--sans); font-weight: 400; font-size: 11px; letter-spacing: .26em;
  text-transform: uppercase; color: var(--quiet); line-height: 1; margin-bottom: 2px;
}
.slide-row:has(.slide-tag) { grid-template-columns: 44px 1fr; }
.slide-row:has(.slide-tag) .slide-tag { margin-bottom: 0; }
.slide-row input[type="range"] {
  -webkit-appearance: none; appearance: none; width: 100%; height: 28px;
  background: transparent; margin: 0; display: block; touch-action: pan-y;
}
.slide-row input[type="range"]:focus-visible { outline: 1px solid var(--umber); outline-offset: 4px; }
.slide-row input[type="range"]::-webkit-slider-runnable-track { height: 2px; background: var(--hairline); border-radius: 1px; }
.slide-row input[type="range"]::-moz-range-track { height: 2px; background: var(--hairline); border-radius: 1px; }
.slide-row input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none; width: 22px; height: 22px; border-radius: 50%;
  background: var(--ink); border: 2px solid var(--ecru); box-shadow: 0 0 0 1px var(--hairline);
  margin-top: -10px; cursor: pointer;
}
.slide-row input[type="range"]::-moz-range-thumb {
  width: 18px; height: 18px; border-radius: 50%; background: var(--ink);
  border: 2px solid var(--ecru); box-shadow: 0 0 0 1px var(--hairline); cursor: pointer;
}
/* unanswered: the track fades, the thumb turns hollow */
.slide-row[data-set="0"] input[type="range"] { opacity: .55; }
.slide-row[data-set="0"] input[type="range"]::-webkit-slider-thumb { background: var(--ecru); box-shadow: inset 0 0 0 1.5px var(--umber); }
.slide-row[data-set="0"] input[type="range"]::-moz-range-thumb { background: var(--ecru); border-color: var(--umber); }

/* ---------- screens that must fit a phone ----------
   Name/email and the two measures both ran past the bottom of a small screen, so
   Continue could only be reached by scrolling — on the two screens where nothing
   below the fold suggests there is anything to scroll to. Both now lay out as a
   column that fills the viewport and no more: the head sits at the top, the
   actions at the bottom, and the middle takes what is left. Everything inside
   scales with clamp() so a 667px iPhone SE and a 932px Pro Max both land whole.

   svh rather than vh: on iOS vh counts space the browser chrome is standing in,
   which is exactly how a button ends up just under the fold. */
.info, .measure {
  display: flex; flex-direction: column;
  min-height: calc(var(--glass) - 48px);
  padding-top: clamp(10px, 3vh, 34px);
  padding-bottom: clamp(8px, 2vh, 20px);
  gap: clamp(10px, 2.2vh, 26px);
  text-align: center;
}
.screen-title { font-size: clamp(22px, 6vw, 28px); text-wrap: balance; line-height: 1.3; }
.screen-lede { font-size: clamp(18px, 4.6vw, 21px); }
.info .fields { display: flex; flex-direction: column; margin-top: clamp(20px, 5vh, 48px); gap: clamp(18px, 3.4vh, 30px); }
.info .field { margin: 0 auto; width: 100%; }
.info .field input { font-size: 22px; }
.micro { font-family: var(--sans); font-weight: 400; font-size: 13px; color: var(--quiet); }

.screen-actions {
  margin-top: auto; display: flex; flex-direction: column;
  align-items: center; gap: clamp(4px, 1.2vh, 10px);
}
.screen-actions.row { flex-direction: row; justify-content: center; gap: 18px; }
.screen-actions .btn { padding: clamp(12px, 2vh, 16px) clamp(26px, 7vw, 36px); }
.screen-actions .btn-quiet { padding: clamp(8px, 1.4vh, 14px) 10px; }

/* ---------- the way on and the way back, always within reach ----------
   From sign-up on, every screen's Back / Continue / Skip sits in one slim bar
   that holds to the bottom of the glass while she scrolls. Sticky rather
   than fixed, on purpose: the buttons stay exactly where each screen's
   handlers and the swipe navigation look for them, and a short screen keeps
   them in the flow instead of pinning a bar over nothing. One row: Back
   left, Continue centre and compact, Skip right (2026-09-28 — it was two,
   Back under Continue, and the second row cost every screen 50px of the
   glass); the quiet-row wrapper on the measure and details screens
   dissolves into the grid. */
.nav-actions {
  position: sticky; bottom: 0; z-index: 5;
  display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 12px 8px;
  margin: 16px -24px 0; padding: 12px 24px calc(12px + env(safe-area-inset-bottom, 0px));
  background: rgba(245, 241, 234, 0.94);
  -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
  border-top: 1px solid var(--hairline);
}
.nav-actions .quiet-row { display: contents; }
.nav-actions > *, .nav-actions .quiet-row > * { grid-row: 1; }
/* A screen with the bar fills the glass exactly (2026-09-28). The bar pads
   itself for the home indicator, so the stage's bottom padding and the page's
   safe-bottom beneath it counted that gap twice, and the I–III bar above the
   stage was never counted at all: on a 14 Pro every preparation scrolled
   through 50–90px of nothing. Now the bar's bottom is the phone's bottom
   whether she scrolls or not, and a screen that fits never scrolls. */
.inquiry:has(> .movements:not([hidden])) { --move-h: 46px; }  /* .movements: 26 margin + 20 */
.inquiry:has(.nav-actions) { padding-bottom: 0; }
#stage:has(> .screen > .nav-actions) { padding-bottom: 0; }
.screen:has(> .nav-actions) { min-height: calc(100svh - var(--safe-top) - var(--move-h, 0px) - 24px); }
/* While the keyboard is up the bar sits on it (--kb, set in app.js), and
   the home-indicator inset it normally pads for is under the keys, so it
   slims to take as little of what is left as it can; the screen grows by
   the keyboard's height so the field she is typing in can always be
   scrolled clear of it. */
.kb-up .nav-actions { bottom: var(--kb, 0px); padding-top: 8px; padding-bottom: 8px; }
.kb-up .screen:has(.nav-actions) { padding-bottom: var(--kb, 0px); }
.nav-actions [data-nav="back"] { grid-column: 1; justify-self: start; }
.nav-actions .btn { grid-column: 2; justify-self: center; padding: 11px clamp(16px, 6vw, 24px); font-size: 12px; letter-spacing: 0.28em; white-space: nowrap; }
.nav-actions .btn-quiet { padding: 10px 6px; font-size: 11px; white-space: nowrap; }  /* "← Back", "Skip →" never break at 375 */
.nav-actions .btn-quiet:not([data-nav]) { grid-column: 3; justify-self: end; text-align: right; }

/* the two measures, each obviously its own question */
.measure { padding-top: clamp(8px, 2vh, 26px); }
.measure-block { flex: 1; display: flex; flex-direction: column; justify-content: center; }
.measure-head { display: flex; align-items: center; justify-content: center; gap: 10px; margin-bottom: clamp(2px, 1vh, 10px); }
.measure-mark svg { display: block; height: clamp(22px, 4.4vh, 32px); stroke: var(--umber); fill: none; stroke-width: 1.3; }
.measure-mark circle { fill: var(--umber); stroke: none; }
.measure-name {
  font-family: var(--sans); font-weight: 400; font-size: 12px;
  letter-spacing: 0.3em; text-transform: uppercase; color: var(--umber-text);
}
.measure .rule-readout { font-size: clamp(38px, 10vh, 70px); }
.measure .rule-readout.minor { font-size: clamp(30px, 7vh, 46px); }
.measure .rule-row { margin-top: clamp(6px, 1.6vh, 22px); }
.measure .rule-ticks { height: clamp(22px, 4vh, 34px); }
.measure .rule-phrase { font-size: clamp(16px, 4vw, 18px); margin-top: clamp(6px, 1.4vh, 18px); }
.measure .rule-phrase b { font-size: clamp(18px, 4.4vw, 22px); }
/* Before she has touched the rule. Scoped to .measure so it outranks the size
   set by `.measure .rule-readout.minor` — an unanswered question should sit
   quieter than an answered one, not shout in italic three times the size. */
.measure .rule-readout.unset {
  font-style: italic;
  font-size: 17px;
  color: var(--quiet);
  line-height: clamp(30px, 7vh, 46px);   /* holds the space the number will take */
}

/* ---------- the first measure ----------
   A story pole with her drawn against it: she stands on the floor line and the
   marker rests on her crown, so the figure and the rule share one coordinate
   system and the number is the pencil mark at the top of her head. */
/* A definite height, not merely a minimum. The chart below works its width back
   from its height, and a height can only be worked back from if something up
   the chain actually states one — under `min-height` alone the percentage has
   nothing to resolve against and Chromium hands the chart the whole row. This
   screen was always meant to be the viewport and no more; now it says so. */
.measure {
  padding-top: clamp(8px, 2vh, 22px); gap: clamp(6px, 1.4vh, 14px);
  height: calc(var(--glass) - 48px);
}
.measure .stage {
  flex: 1; display: flex; gap: clamp(10px, 3vw, 16px);
  align-items: stretch; min-height: 0; padding-top: 0;
}
/* The chart takes its width FROM its height rather than the other way round.
   Sized by width, the drawing scaled to fit across and left whatever height it
   did not need as dead space above the seven-foot mark — a gap that read as a
   layout mistake between the title and the measure. Now the column is exactly
   as wide as the drawing needs to be at full height, and there is nothing
   left over.

   The column states that width itself, as an aspect-ratio, rather than leaving
   it to be inferred from the drawing inside. `width: auto` on the svg asks the
   browser to work the width back from the resolved height and the viewBox, and
   Safari declines: it hands the flex item a width of zero and then paints the
   full-size drawing out of the empty box, straight across the reading column.
   Chromium infers it and looks perfect, which is how this shipped — the two
   measures overlapped on a phone and on no desktop anywhere.

   And no max-width. A cap that binds is the other thing this cannot survive:
   the box goes narrow, the height stays, and `meet` shrinks the drawing and
   parks it on the floor — putting back the dead space above the seven-foot
   mark that a height-driven column exists to remove. Stating the ratio needs
   neither. The drawing is a shade over two-fifths as wide as it is tall, the
   reading column takes what is left, and both engines agree. */
.chart {
  flex: 0 0 auto; position: relative; cursor: ns-resize; touch-action: none;
  height: 100%; aspect-ratio: 168 / 470;
}
.chart svg { width: 100%; height: 100%; display: block; }
.read { flex: 1; display: flex; flex-direction: column; justify-content: center; text-align: left; min-width: 0; }

.pole-rule { stroke: var(--hairline); fill: none; stroke-width: 1; vector-effect: non-scaling-stroke; }
.pole-tick { stroke: var(--umber); fill: none; stroke-width: .9; vector-effect: non-scaling-stroke; }
.pole-tick.foot { stroke: var(--ink); }
.pole-num { font-family: var(--sans); font-size: 12px; letter-spacing: 1px; fill: var(--umber-text); }
.fig { stroke: var(--ink); fill: none; stroke-width: 1.15; vector-effect: non-scaling-stroke; }
.crown-line { stroke: var(--clay); fill: none; stroke-width: 1.5; vector-effect: non-scaling-stroke; }
.floor-line { stroke: var(--ink); fill: none; stroke-width: 1.4; vector-effect: non-scaling-stroke; }

.measure .rule-readout { font-size: clamp(38px, 12vw, 54px); }
.read-sub {
  font-family: var(--sans); font-weight: 400; font-size: 11px;
  letter-spacing: .24em; text-transform: uppercase; color: var(--quiet);
  margin-top: clamp(6px, 1.4vh, 10px); line-height: 1.7;
}

.shoe-block { margin-top: clamp(16px, 3.4vh, 28px); padding-top: clamp(12px, 2.2vh, 18px); border-top: 1px solid var(--hairline); }
.shoe-head { display: flex; align-items: center; gap: 9px; margin-bottom: 4px; }
.foot-mark { display: block; height: clamp(26px, 5vh, 34px); width: 24px; overflow: visible; opacity: .4; transition: opacity .3s; }
.foot-mark.set { opacity: 1; }
.measure .rule-readout.minor { font-size: clamp(24px, 7vw, 30px); }
.measure .rule-readout.unset {
  font-style: italic; font-size: 16px;
  color: var(--quiet); line-height: clamp(24px, 7vw, 30px);
}
.shoe-bar { position: relative; margin-top: clamp(6px, 1.4vh, 10px); cursor: ew-resize; touch-action: none; }
.shoe-bar svg { width: 100%; height: clamp(20px, 4vh, 26px); display: block; }
.pole-rule.flat { stroke: var(--umber); }

/* kept for the keyboard, out of the way of the drawing */
.sr-rule {
  position: absolute; inset: 0; width: 100%; height: 100%;
  opacity: 0; -webkit-appearance: none; appearance: none; margin: 0;
  background: transparent; cursor: inherit;
}
.sr-rule:focus-visible { opacity: 1; outline: 2px solid var(--clay); outline-offset: 2px; }

.quiet-row { display: flex; gap: 22px; align-items: center; }

/* offered after the reading, never asked for before it */
.phone-offer { max-width: 300px; margin: 22px auto 0; text-align: left; }
.phone-offer label {
  display: block; font-family: var(--sans); font-weight: 400; font-size: 12px;
  letter-spacing: .28em; text-transform: uppercase; color: var(--umber-text); margin-bottom: 7px;
}
.phone-offer input {
  width: 100%; background: transparent; border: 0;
  border-bottom: 1px solid var(--hairline); padding: 7px 2px 10px;
  font-family: var(--serif); font-style: italic; font-size: 20px; color: var(--ink);
  transition: border-color .3s;
}
.phone-offer input:focus { outline: none; border-bottom-color: var(--ink); }
.phone-said {
  display: block; font-family: var(--sans); font-size: 12px;
  letter-spacing: .1em; color: var(--quiet); min-height: 1.3em; margin-top: 6px;
}


/* ---------- the Go Pro notes ----------
   A tag that says this is the extra mile, "All optional" as the headline,
   then bra / waist / weight as hairline rows. The controls scale with the
   height of the glass (svh), so a 14 Pro gets big, easy sliders instead of a
   band of empty paper under Skip; the panel takes whatever height is left
   and shares it between the rows. Below the floors a small phone simply
   scrolls — fitting one screen is not worth shrinking the controls. */
.details {
  --ic: clamp(26px, 3.9svh, 38px);   /* icon, and the indent the sliders hang from */
  --th: clamp(24px, 3.3svh, 32px);   /* slider thumb */
  max-width: 520px; width: 100%; margin: 0 auto; text-align: center;
  display: flex; flex-direction: column;
  min-height: calc(var(--glass) - 48px);
  padding-top: clamp(4px, 1.6svh, 20px);
}
.pro-tag {
  align-self: center; display: inline-flex; align-items: stretch;
  font-family: var(--sans); font-weight: 400; font-size: clamp(11px, 1.45svh, 13px); line-height: 1;
  letter-spacing: .26em; text-transform: uppercase;
  border: 1px solid var(--clay-text);
}
.pro-tag b { font-weight: 500; background: var(--clay-text); color: var(--ecru); padding: .75em .8em .75em 1.1em; }
.pro-tag span { color: var(--clay-text); padding: .75em .8em .75em 1.1em; }
.pro-lead {
  font-family: var(--serif); font-style: italic; font-weight: 400;
  font-size: clamp(34px, 5.4svh, 48px); line-height: 1.05; color: var(--ink);
  margin: clamp(14px, 2.8svh, 30px) 0 0;
}
.pro-sub { font-size: clamp(17px, 2.2svh, 20px); line-height: 1.35; margin: clamp(6px, 1svh, 10px) auto 0; max-width: 24em; color: var(--quiet); }
.note-panel {
  flex: 1; display: flex; flex-direction: column;
  margin-top: clamp(14px, 2.8svh, 30px); border-top: 1px solid var(--hairline); text-align: left;
}
/* each row takes an even share of the spare height, its content centred in it */
.note {
  flex: 1 1 auto; display: flex; flex-direction: column; justify-content: center;
  gap: clamp(0px, .6svh, 8px);
  padding: clamp(10px, 1.8svh, 20px) 0; border-bottom: 1px solid var(--hairline);
}
.note-head { display: grid; grid-template-columns: var(--ic) 1fr auto 36px; align-items: center; gap: 14px; }
.detail-icon { width: var(--ic); height: var(--ic); color: var(--umber-text); }
.detail-icon svg { width: 100%; height: 100%; display: block; }
.detail-label { font-family: var(--sans); font-weight: 400; font-size: clamp(12px, 1.6svh, 15px); letter-spacing: 0.3em; text-transform: uppercase; color: var(--umber-text); }
.note .detail-value { font-size: clamp(22px, 3.7svh, 34px); line-height: 1.15; min-height: 1.15em; }
.note .detail-clear { width: 36px; height: 36px; font-size: clamp(20px, 2.6svh, 24px); }
/* sliders hang under the label and run to the edge */
.note .slide-row { padding: 0 2px 0 calc(var(--ic) + 14px); }
.note .slide-row:has(.slide-tag) { grid-template-columns: clamp(50px, 6.8svh, 62px) 1fr; }
.note .slide-row .slide-tag { font-size: clamp(11px, 1.45svh, 13px); }
.note .slide-row input[type="range"] { height: clamp(36px, 5.4svh, 50px); }
.note .slide-row input[type="range"]::-webkit-slider-thumb { width: var(--th); height: var(--th); margin-top: calc(1px - var(--th) / 2); }
.note .slide-row input[type="range"]::-moz-range-thumb { width: calc(var(--th) - 4px); height: calc(var(--th) - 4px); }

/* ---------- your lines and curves ----------
   Her own outline with the architect's dimensions on it, then the numbers in
   rows. The figure's marks are `currentColor`, so the box sets the ink and the
   dimension lines and their labels take the quieter clay/umber over it. */
.lines { text-align: center; }
.lines-figure-box { max-width: 340px; max-height: 58svh; margin: 8px auto 6px; color: var(--ink); }
.lines-figure-box svg { width: 100%; height: auto; max-height: 58svh; display: block; }
.lines-figure .dim { color: var(--clay-text); stroke: var(--clay); }
/* The halo lives here, the way the camera layer's does: a centred dimension
   label sits over the very lines it measures, so the type knocks them out from
   behind itself — stroke painted first, in the page's own ground colour. */
.lines-figure .dim-label {
  font-family: var(--sans); font-weight: 300; fill: var(--umber-text); letter-spacing: .12em;
  paint-order: stroke; stroke: var(--ecru); stroke-width: 1.4px;
}
/* the same hand-drawn entrance the glyphs and the frieze use — see @keyframes draw above */
.lines-figure .draw { stroke-dasharray: 300; stroke-dashoffset: 300; animation: draw 1.4s ease-out forwards; }
.measure-rows { max-width: 460px; margin: 18px auto 0; text-align: left; border-top: 1px solid var(--hairline); }
.measure-row { display: grid; grid-template-columns: 1fr auto; gap: 2px 16px; padding: 11px 0; border-bottom: 1px solid var(--hairline); align-items: baseline; }
.measure-label { font-family: var(--sans); font-weight: 400; font-size: 12px; letter-spacing: .24em; text-transform: uppercase; color: var(--umber-text); }
.measure-value { font-family: var(--serif); font-size: 21px; color: var(--ink); text-align: right; white-space: nowrap; }
.measure-note { grid-column: 1 / -1; font-size: 15px; color: var(--quiet); line-height: 1.4; }
/* the Continue button's own margin is not enough on a 390 × 844 phone, where the
   note runs to three lines and the button's top border cuts straight through it */
.lines-note { max-width: 460px; margin: 14px auto clamp(18px, 3vh, 28px); text-align: left; }
@media (max-width: 520px) { .lines-figure-box { max-width: 260px; } .measure-value { font-size: 19px; } }

/* ---------- your lines, read on her (?lines=v1 shows the old sheet) ----------
   One timeline, keyed off .play: "Here is what I read" over her photo, her
   points of light (1.0s on, delays inline), the line joining them (2.2s),
   the title (5.4s), then each finding draws its line and says itself (from
   6.0s, delays inline), and the rest of the page arrives. .done is the
   settled page — reduced motion goes straight there. */
@keyframes lrIn { from { opacity: 0; } to { opacity: 1; } }
@keyframes lrOut { from { opacity: 1; } to { opacity: 0; } }
@keyframes lrPop { 0% { opacity: 0; transform: scale(0.2); } 60% { opacity: 1; transform: scale(1.35); } 100% { opacity: 1; transform: scale(1); } }
@keyframes lrGlow { 0%, 100% { opacity: 0.25; } 50% { opacity: 0.55; } }
@keyframes lrSoften { to { opacity: 0.55; } }
@keyframes lrDim { to { opacity: 0.4; } }
.lines2 .lr-top { display: grid; place-items: center; min-height: 84px; }
.lines2 .lr-top > * { grid-area: 1 / 1; }
.lines2 .lr-intro { margin: 0; font-style: italic; font-size: 24px; opacity: 0; animation: lrIn 0.6s ease 0.1s forwards; }
.lines2 .lr-head { opacity: 0; display: flex; flex-direction: column; align-items: center; gap: 6px; }
.lines2 .lr-head .screen-title { margin: 0; }
.lines2.play .lr-intro { animation: lrOut 0.5s ease 5s both; }
.lines2.play .lr-head { animation: lrIn 0.8s ease 5.4s forwards; }
.lines2 .lr-figure { margin: 4px auto 0; }
.lines2 .lr-figure svg { display: block; width: 100%; height: 100%; }
.lines2 .lr-bone { fill: none; stroke: #FFF8EC; stroke-linecap: round; stroke-linejoin: round; stroke-dasharray: 1; stroke-dashoffset: 1; }
.lines2.play .lr-bone { animation: draw 1.6s ease-in-out 2.2s forwards, lrSoften 0.6s ease 5s forwards; }
.lines2 .lr-pt { opacity: 0; transform-box: fill-box; transform-origin: center; }
.lines2.play .lr-pt { animation: lrPop 0.45s ease-out forwards; }
.lines2 .lr-glow { fill: #FFF3DF; opacity: 0.4; }
.lines2.play .lr-glow { animation: lrGlow 1.6s ease-in-out infinite; }
.lines2 .lr-core { fill: #FFF8EC; stroke: var(--clay); }
.lines2 .lr-fm, .lines2 .lr-fh { fill: none; stroke-linecap: round; stroke-dasharray: 1; stroke-dashoffset: 1; transition: opacity 0.3s; }
.lines2 .lr-fm { stroke: var(--clay); }
.lines2 .lr-fh { stroke: #FFF8EC; opacity: 0.75; }
.lines2.play .lr-fm, .lines2.play .lr-fh { animation: draw 0.6s ease-out forwards, lrDim 0.4s ease forwards; }
.lines2 .lr-after { opacity: 0; }
.lines2.play .lr-after { animation: lrIn 0.8s ease forwards; }
/* settled */
.lines2.done .lr-intro { animation: none; opacity: 0; }
.lines2.done .lr-head, .lines2.done .lr-after, .lines2.done .lr-pt { animation: none; opacity: 1; }
.lines2.done .lr-bone { animation: none; stroke-dashoffset: 0; opacity: 0.55; }
.lines2.done .lr-fm, .lines2.done .lr-fh { animation: none; stroke-dashoffset: 0; opacity: 0.4; }
.lines2.hl .lr-fm, .lines2.hl .lr-fh { opacity: 0.12; }
.lines2.hl .lr-fm.hot { opacity: 1; }
.lines2.hl .lr-fh.hot { opacity: 0.8; }

.lines2 .lr-tile { flex: none; width: 44px; height: 44px; display: flex; align-items: center; justify-content: center; border: 1px solid var(--hairline); }
.lines2 .lr-tile svg { width: 26px; height: 26px; fill: none; stroke: var(--ink); stroke-width: 1.3; stroke-linecap: round; stroke-linejoin: round; }
/* what she found: each row rises in as its line draws, and stays */
@keyframes lrRise { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
.lines2 .lr-found { margin-top: 16px; text-align: left; }
.lines2 .lr-found-head { margin-bottom: 8px; }
.lines2 .lr-found-head, .lines2 .lr-row { opacity: 0; }
.lines2.play .lr-found-head, .lines2.play .lr-row { animation: lrRise 0.6s ease forwards; }
.lines2.done .lr-found-head, .lines2.done .lr-row { animation: none; opacity: 1; transform: none; }
.lines2 .lr-tap { margin: 8px 0 0; opacity: 0; transition: opacity 0.4s; }
.lines2.done .lr-tap { opacity: 1; }
.lines2 .lr-rows { border-top: 1px solid var(--hairline); }
.lines2 .lr-row {
  display: flex; align-items: center; gap: 14px; width: 100%; min-height: 66px; padding: 10px 12px;
  background: none; border: 1px solid transparent; border-bottom-color: var(--hairline);
  font-family: var(--serif); font-size: 20px; line-height: 1.3; color: var(--ink); text-align: left;
}
.lines2 .lr-row.on { border-color: var(--clay); background: rgba(156, 95, 78, 0.05); }
.lines2 .lr-row.on .lr-tile { border-color: var(--clay); }
.lines2 .lr-row.on .lr-tile svg { stroke: var(--clay-text); }
/* where she leans: the appetizer, drawn in the architecture's own glyph */
.lines2 .lr-lean { display: flex; align-items: center; justify-content: center; gap: 18px; margin-top: 22px; padding: 4px 0; text-align: left; opacity: 0; }
.lines2.play .lr-lean { animation: lrIn 0.8s ease forwards; }
.lines2.done .lr-lean { animation: none; opacity: 1; }
.lines2 .lr-lean-glyph { flex: none; display: flex; gap: 4px; }
.lines2 .lr-lean-glyph svg { display: block; width: 30px; height: 110px; stroke: var(--ink); fill: none; }
.lines2 .lr-lean-glyph .draw { stroke-dasharray: 300; stroke-dashoffset: 300; }
.lines2.play .lr-lean-glyph .draw { animation: draw 1.4s ease-out var(--at, 0s) forwards; }
.lines2.done .lr-lean-glyph .draw { animation: none; stroke-dashoffset: 0; }
.lines2 .lr-lean-name { margin: 6px 0 0; font-family: var(--sans); font-weight: 300; font-size: 26px; letter-spacing: 0.28em; text-transform: uppercase; line-height: 1.2; }
.lines2 .lr-lean-line { margin: 6px 0 0; font-style: italic; font-size: 20px; line-height: 1.3; }
.lines2 .lr-lean-ask { margin: 14px 0 4px; font-size: 20px; line-height: 1.35; text-align: center; }
/* said once on Your Lines, under "Fifteen questions" or the hook, so the
   Suggested tags on the questions are no surprise */
.lines2 .lr-marked { margin: 18px 0 0; text-align: center; }
.lines2 .lr-again { display: block; margin: 10px auto 0; }
.lines2 .lr-hook { margin-top: 30px; padding: 24px 20px; border: 1px solid var(--hairline); text-align: center; }
.lines2 .lr-hook-line { margin: 0; font-size: 25px; line-height: 1.25; }
.lines2 .lr-hook-sub { margin: 8px 0 0; font-style: italic; font-size: 19px; line-height: 1.4; color: rgba(33, 28, 21, 0.85); }

/* ---------- the plate ----------
   The reading's elevation: her outline from the lines sheet again, set under
   the crown as a drawing-plate. Three measures at most, the leaders dashed
   like a tailor's marks and the end ticks left solid so each still ends
   somewhere. The inscription is the one line of direction the reading gives;
   everything else waits for the consultation. */
.plate { margin-top: 36px; }
/* the date on its own line: with the eyebrow's tracking the two together
   break mid-date on a phone */
.plate-date { font-family: var(--sans); font-weight: 400; font-size: 12px; letter-spacing: .3em; text-transform: uppercase; color: var(--umber-text); margin-top: 8px; }
.plate-figure-box { max-width: 300px; margin: 16px auto 0; color: var(--ink); }
.plate-figure-box svg { width: 100%; height: auto; max-height: 56svh; display: block; }
/* dash lengths are viewBox units (vector-effect leaves them alone): at the
   300px the box renders, 1.5 is a 4.5px dash */
.plate .lines-figure .dim { stroke-dasharray: 1.5 1.4; }
.plate .lines-figure .dim-tick { stroke-dasharray: none; }
.plate-inscription {
  max-width: 400px; margin: 30px auto 0; padding: 22px 12px;
  border-top: 1px solid var(--hairline); border-bottom: 1px solid var(--hairline);
  font-style: italic; font-size: clamp(19px, 4.6vw, 23px); line-height: 1.45; color: var(--ink);
}
@media (max-width: 520px) { .plate-figure-box { max-width: 250px; } }

/* ---------- the type floor, 2026-09-21 ----------
   On a 393pt phone the labels, eyebrows and buttons had three faintnesses
   stacked: Jost at weight 300, 8–11px, in a tone at 68% ink. Each cleared a
   check on its own; together they read grey. Every caption is now 400 weight,
   nothing sans sits under 10px, and words in umber or clay use the darker
   --umber-text / --clay-text while marks keep the lighter tone. The rules
   below finish what the per-rule edits above began. */

/* arrival fills the glass the way it does on a zoomed Pro Max: the wordmark
   stacks on two lines, the button takes the column, the five names spread */
.arrival-hero { width: 100%; }
.arrival-entry .btn { width: min(100%, 360px); padding: 18px 24px; }
.typology-thesis { font-size: clamp(21px, 5.6vw, 25px); }

/* Safari paints its own yellow over a field it filled from Contacts, and
   ignores background there. It does honour an inset shadow, so the fill is
   painted as one. The plain focus state gets the same fill so a filled field
   and a typed one look alike. */
.field input:focus, .phone-offer input:focus { background: #add8e7; }
.field input, .phone-offer input { transition: background 0.3s, border-color 0.3s; }
input:-webkit-autofill, input:-webkit-autofill:hover, input:-webkit-autofill:focus {
  -webkit-box-shadow: 0 0 0 1000px #add8e7 inset; box-shadow: 0 0 0 1000px #add8e7 inset;
  -webkit-text-fill-color: var(--ink); caret-color: var(--ink);
}

/* the intro before Q1 (version 2): a few quiet lines, centred in the glass above the bar */
.q-intro .q-intro-text { margin: auto; max-width: 21em; font-size: clamp(19px, 5.2vw, 22px); }
