/* Cinematic briefing. Page-specific styling; Scrollcraft's engine is unchanged. */
:root {
  --sc-canvas: var(--bg); --sc-surface: var(--surface); --sc-ink: var(--text);
  --sc-ink-soft: var(--text-2); --sc-accent: var(--accent); --sc-accent-ink: var(--on-accent);
  --sc-font-display: 'Newsreader', Georgia, serif; --sc-font-text: 'Public Sans', sans-serif;
  --sc-font-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  --radius: 6px; --radius-sm: 4px; --radius-lg: 8px; --brief-gutter: clamp(24px, 6vw, 96px);
  --brief-bar: 72px; color-scheme: light;
}
/* G1: the Compare cities scene sits on a dark scrim over the neighborhood
   still in both themes, so it takes the dark token set in both themes: light
   text, dark surfaces and inputs. In the light theme it used to keep the
   light theme's dark text on that dark scrim (about 1.1:1). */
:root[data-theme="dark"], .cities-scene {
  color-scheme: dark;
  --bg:#111416; --surface:#181c1f; --surface-2:#1c2124; --sunken:#23292d;
  --line:#343e42; --line-strong:#465258; --input-border:#79878d;
  --text:#e8eaec; --text-2:#bfc5ca; --text-3:#aeb8bd;
  --accent:#6cc3d2; --accent-hover:#8ad3df; --accent-soft:#15303a; --accent-ink:#9dd6e0; --on-accent:#08262c;
  --focus:#8ddbe7; --pos:#7fd1a1; --pos-bg:#15291f; --pos-line:#2c5a40;
  --warn:#f2c27d; --warn-bg:#2b2113; --warn-line:#6b4e22; --neg:#f4a596; --neg-bg:#2e1814; --neg-line:#6e3328;
  --info:#8fd0dc; --info-bg:#122428; --info-line:#2a5961; --muted-bg:#262b2f;
  --v-buy-bg:#7fd1a1; --v-buy-fg:#0b2417; --v-wait-bg:#b4bbf2; --v-wait-fg:#161a3d;
  --v-wait-line:#b4bbf2; --v-even-bg:#15303a; --v-even-fg:#9dd6e0; --v-even-line:#2a5961;
  --v-thin-fg:#c9cfd4; --v-thin-line:#8c969e; --v-na-bg:#262b2f; --v-na-fg:#b5bcc2;
}
@media(prefers-color-scheme:dark){:root:not([data-theme="light"]){color-scheme:dark;--text-3:#aeb8bd;}}
/* The single scroll offset for every jump: a scene's top lands here, just
   clear of the step bar. No other rule may add to it. */
/* B6 S11: a field that lands flush with the bottom edge had its focus ring
   clipped. Bottom padding as well as top keeps the ring inside the screen. */
html { scroll-padding-top: calc(var(--brief-bar) + 24px); scroll-padding-bottom: 40px; }
body { background:var(--bg); color:var(--text); }
.app { display:block; max-width:none; margin:0; padding:0; }
.main { width:100%; max-width:none; margin:0; padding:0; }
/* One offset, not two. html already holds the step-bar gap, and scroll-margin
   on the scene itself would be added to it, so every anchor jump landed a whole
   bar too low and a phone's next heading started below the fold. */
.scene { position:relative; margin:0; border:0; scroll-margin-top:0; }
/* A grid item defaults to min-width:auto, so an unsized still or a fallback
   font's min-content in one scene can inflate the track and overflow a 320px
   window by 7px in the first frame. This lets the track shrink; it clips
   nothing. */
.main > .scene { min-width:0; }
.scene-wrap { width:100%; max-width:1440px; padding-inline:var(--brief-gutter); margin-inline:auto; }
h1,h2,h3,p { text-wrap:pretty; }
h1,h2 { font-family:var(--font-serif); font-weight:400; letter-spacing:-.045em; text-wrap:balance; }
.scene h2 { font-size:clamp(44px,5.8vw,84px); line-height:1.03; max-width:900px; }
.scene h3 { font-family:var(--font-sans); font-size:20px; font-weight:600; letter-spacing:-.02em; }
.scene p { line-height:1.65; }
.scene .section-head { margin-bottom:32px; min-width:0; grid-template-columns:minmax(0,1fr); }
.scene .section-head > :is(h2,p) { min-width:0; max-width:100%; overflow-wrap:anywhere; }
.scene .section-lede,.scene-heading>p { max-width:58ch; font-size:17px; margin-top:24px; color:var(--text-2); }
button,a,input,select,summary { -webkit-tap-highlight-color:transparent; }
button,summary { touch-action:manipulation; }
button { transition:transform 160ms ease-out; }
button:active,summary:active { transform:translateY(1px); }
button:disabled { cursor:not-allowed; opacity:.65; }
:focus-visible { outline:3px solid var(--focus); outline-offset:4px; }
a { text-underline-offset:.25em; }
.text-link { display:inline-block; padding:12px 0; color:var(--accent); text-decoration:underline; font-weight:600; }
input,select { min-height:48px; }
.status-bar.rail {
  position:sticky; inset:0 0 auto; z-index:80; display:flex; align-items:center;
  gap:28px; width:100%; height:var(--brief-bar); padding:0 32px; overflow:visible;
  background:var(--bg); color:var(--text); border:0; border-bottom:1px solid var(--line); box-shadow:none;
}
.status-bar .brand { flex:none; padding:0; margin:0; gap:10px; }
.status-bar .brand-mark { width:28px; height:28px; }
.status-bar .brand-name { font-size:18px; letter-spacing:-.03em; }
.pipeline-nav { flex:1; min-width:0; }
.pipeline-nav ol { display:flex; justify-content:center; gap:4px; list-style:none; margin:0; padding:0; }
.pipeline-nav a { display:block; color:var(--text-2); font-size:12px; font-weight:550; white-space:nowrap; padding:16px 14px; text-decoration:none; border-bottom:2px solid transparent; }
.pipeline-nav a[aria-current] { color:var(--accent); border-color:var(--accent); background:var(--accent-soft); }
/* C1: off a phone the long label is the visible one and the short one is not
   rendered at all, so the six labels read as the spec table names them. */
.step-long{display:inline;}
.step-short{display:none;}
.pipeline-nav a:focus-visible{outline:none;box-shadow:inset 0 0 0 3px var(--focus-ring,currentColor);border-radius:2px;}
/* B1: a field's own message, and the one-place list under the button. */
.field-error{display:block;margin-top:6px;font-size:13px;line-height:1.45;color:#a3341f;}
.form-errors[hidden]{display:none;}
.form-errors{margin-top:12px;padding:12px 14px;border-left:3px solid #a3341f;background:var(--surface-2,transparent);font-size:14px;}
.form-error-list{margin:0;padding-left:20px;}
.form-error-list li{margin-block:4px;}
/* P5: the figure written the way money reads, under the field while it is
   typed. The field itself keeps the digits typed into it. */
.field-echo{display:block;margin-top:6px;color:var(--text-2);font-size:13px;font-variant-numeric:tabular-nums;}
.field-echo:empty{display:none;}
/* S5: Compare cities sits on the dark scrim in both themes, so the light
   theme's #a3341f landed on the dark strip at about 1.05:1. A light tint of the
   same red is used there instead; the strip's own dark text token was not
   inherited by these two rules. The light theme's colours above are untouched. */
.cities-scene .field-error{color:#ffb4a8;}
.cities-scene .form-errors{color:#e8eaec;border-left-color:#ffb4a8;}
.cities-scene .form-errors .form-error-list li{color:inherit;}
/* S4: the Sign in control inside the written read's failure box. It sits in a
   run of prose, so it takes the box's line box rather than the 44px touch row
   the standalone link buttons get. */
.ai-body .info-box .ai-signin-btn{min-height:0;padding:0 2px;vertical-align:baseline;}
/* B3: the sign-in box that stands beside the written read's own button. */
.read-signin{border:1px solid var(--line-strong);border-radius:6px;padding:20px;margin-block:16px;}
.read-signin[hidden]{display:none;}
/* G3: the same sign-in box, at the top of the page, for a visitor who asks to
   sign in before the Answer (where it normally sits) has opened. */
.signin-panel{margin:16px var(--brief-gutter);background:var(--surface);}
/* E9: the panel is a popover under the fixed bar, so opening it leaves the page
   where it was. It sits outside <main>, whose containment would otherwise make
   it a box in the page's own scroll. */
.signin-panel{position:fixed;z-index:75;top:calc(var(--brief-bar) + 8px);left:var(--brief-gutter);right:var(--brief-gutter);margin:0;max-width:560px;max-height:calc(100dvh - var(--brief-bar) - 16px);overflow:auto;box-shadow:0 8px 24px rgba(0,0,0,.28);}
@media(min-width:761px){
 .signin-panel{left:auto;right:32px;width:560px;}
}
.read-signin h4{margin:0 0 8px;font-size:16px;}
.read-signin p{margin:0 0 14px;font-size:14px;color:var(--text-2);}
.sign-in-email-field{display:flex;flex-direction:column;gap:6px;margin-bottom:12px;}
.sign-in-email-label{font-size:13px;font-weight:600;}
/* A3: the one plain sentence that replaces a form that cannot work. */
.search-paused{margin-block:12px 20px;font-size:15px;line-height:1.5;color:var(--text-2);}
.house-paused{margin-block:12px;font-size:15px;line-height:1.5;color:var(--text-2);}
.house-choose{margin-block:8px 16px;font-size:15px;line-height:1.5;color:var(--text-2);max-width:60ch;}
.compare-cities-status,.sr-only,.visually-hidden{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;}
/* B6 S21: a source link is a control a finger has to hit. They measured 15 to
   19px tall; the padding brings every one of them to at least 24px. */
a.source-link{display:inline-flex;align-items:center;min-height:24px;padding-block:2px;}
/* P7: a source link that is a line or a row of its own is a touch target and
   takes 44px. A link inside a sentence or a label keeps the 24px above. */
.field-note a.source-link,.field-help a.source-link,.card-links a.source-link,.evidence-list a.source-link,.news-body a.source-link,.rec-detail a.source-link{min-height:44px;}
.page-footer a{display:inline-flex;align-items:center;min-height:44px;padding-inline:6px;}
/* B6 S5: the light card inside the dark hero showed its placeholder at 2.02:1.
   The muted token is 6.09:1 on that card. */
.question-scene input::placeholder{color:#5c636a;opacity:1;}
.status-actions { display:flex; gap:18px; align-items:center; font-size:12px; }
.status-actions a { display:inline-flex; align-items:center; min-height:44px; padding-block:0; }
#themeToggle { border:1px solid var(--input-border); border-radius:4px; background:transparent; padding:10px 12px; min-height:44px; }
.question-scene { background:#111416; color:#f5f4f0; position:relative; min-height:min(58vh,560px); overflow:hidden; }
.question-scene .hero-media { position:absolute; inset:0; overflow:hidden; }
.question-scene .hero-media img, .question-scene .hero-media video { position:absolute; inset:0; width:100%; height:100%; object-fit:cover; }
.question-scene h1 { color:inherit; font-size:clamp(56px,7vw,96px); font-weight:400; line-height:.94; margin:0 0 20px; max-width:720px; }
.question-copy { position:relative; z-index:4; width:min(580px,calc(100% - 48px)); margin-inline:var(--brief-gutter); padding-block:56px; }
.question-copy>p { font-size:16px; color:#e2e8e9; max-width:40ch; margin:0; }
/* E1: the hero's one way in, and the only control in it. The hero photo is
   dark in both themes, so it carries the dark theme's accent pair in both:
   the page's own primary colour, which reads at 7.8:1 for its label and 9:1
   against the scrim behind it. It is sized for a thumb and it does not move
   the headline, which sits above it. */
.hero-cta { display:inline-flex; align-items:center; justify-content:center; min-height:44px; min-width:160px; margin-top:16px; padding:10px 22px; border-radius:4px; background:#6cc3d2; color:#08262c; font-size:1rem; font-weight:600; line-height:1.2; text-decoration:none; }
.hero-cta:hover { background:#8ad3df; color:#08262c; }
.hero-scrim { position:absolute; inset:0; z-index:1; pointer-events:none; background:linear-gradient(90deg,rgba(10,19,23,.96) 0%,rgba(10,19,23,.85) 31%,rgba(10,19,23,.18) 65%,transparent 80%); }
.costs-scene { padding-block:96px; }
.costs-opening { display:grid; grid-template-columns:1.1fr 1fr; column-gap:8%; row-gap:48px; align-items:start; }
.costs-photo { margin:0; overflow:hidden; }
.scene-photo { width:100%; height:auto; object-fit:cover; }
.costs-photo img { aspect-ratio:1.22; height:auto; object-fit:cover; }
.cost-ledger { grid-column:1/-1; display:grid; grid-template-columns:1fr 1fr; gap:8%; padding-top:28px; border-top:1px solid var(--line-strong); }
.cost-ledger h3 { font-size:30px; font-family:var(--font-serif); font-weight:500; margin-bottom:16px; }
.cost-ledger p { color:var(--text-2); max-width:42ch; }
.cost-context { grid-column:1/-1; color:var(--text-2); }
.costs-opening>.work-disclosure { grid-column:1/-1; }
.work-disclosure { border:0; border-top:1px solid var(--line-strong); border-bottom:1px solid var(--line-strong); border-radius:0; margin:0; padding:0; background:transparent; }
.work-disclosure>summary { cursor:pointer; padding:22px 4px; font-size:15px; font-weight:600; color:var(--text); list-style-position:inside; }
.work-disclosure>summary:hover { color:var(--accent); }
.work-disclosure[open]>summary { margin-bottom:24px; }
.work-disclosure>div,.work-disclosure>section { margin-bottom:24px; }
.market-opening { background:#111416; color:#f5f4f0; }
/* C2: the neighborhood clip behind the Compare cities heading. It is a ScrollCraft
   "flow" act, so the engine maps the clip across the element's whole on-screen
   life and nothing is pinned: the clip scrubs with the scroll as the heading
   leaves the screen. The still is the poster and, under reduced motion, the
   only thing that paints: no source is handed to the engine, so no video is
   fetched. */
.cities-scene { position:relative; overflow:hidden; }
.cities-scene .cities-media { position:absolute; inset:0; overflow:hidden; z-index:0; }
.cities-scene .cities-media img, .cities-scene .cities-media video { position:absolute; inset:0; width:100%; height:100%; object-fit:cover; }
.cities-scene .cities-scrim { position:absolute; inset:0; z-index:1; pointer-events:none;
  background:linear-gradient(180deg,rgba(10,19,23,.62) 0%,rgba(10,19,23,.5) 40%,rgba(10,19,23,.9) 100%); }
.cities-scene .scene-wrap { position:relative; z-index:2; }
.market-copy { position:absolute; left:var(--brief-gutter); bottom:16vh; z-index:4; }
.market-copy h2 { font-size:clamp(48px,6vw,84px); }
.market-copy p { margin-top:24px; color:#dce8ea; }
.market-scrim { position:absolute; inset:0; z-index:1; background:linear-gradient(90deg,rgba(10,19,23,.98),rgba(10,19,23,.85) 33%,transparent 72%); }
.market-work { padding-block:64px 0; }
.analysis-console { background:#111c20; color:#e3ecee; border:1px solid #405359; padding:28px; margin-bottom:48px; }
.console-head { display:flex; align-items:center; justify-content:space-between; gap:16px; padding-bottom:20px; border-bottom:1px solid #405359; }
.console-head h3 { font-size:17px; color:#e3ecee; }
#analysisLogState { font:12px/1.6 var(--sc-font-mono); color:#9fced6; }
#analysisLogEmpty { font:14px/1.7 var(--sc-font-mono); color:#b9cdd1; padding-block:24px 0; }
#analysisLog { font:12px/1.7 var(--sc-font-mono); max-height:380px; overflow:auto; }
.log-line { display:grid; grid-template-columns:minmax(130px,1.3fr) 100px 75px minmax(120px,1.5fr); gap:16px; padding-block:16px; border-bottom:1px solid #334a52; }
.log-line:last-child { border:0; }
.log-status { color:#96d9b4; }.log-time { color:#bed1d5; text-align:right; }.log-summary { color:#d9e6e8; }
.log-error .log-status { color:#ffb7a4; }
.market-work .section { padding:0; margin:0; border:0; max-width:none; background:transparent; box-shadow:none; border-radius:0; }
.market-work .section h2,.market-work .section h3 { font-family:var(--font-sans); }
.market-work .city-inputs { display:grid; grid-template-columns:repeat(5,minmax(0,1fr)); gap:16px; }
.market-work .form-actions { margin-block:24px; }
.market-work .snapshot { display:block; margin-top:24px; }
.market-work .snapshot>.subhead { padding-top:0; }
.market-tools { display:grid; grid-template-columns:1fr 1fr; gap:32px; margin-top:32px; align-items:start; }
.market-tools .work-disclosure[open] { grid-column:1/-1; }
.market-pause { padding:64px 0 56px; font-size:22px; color:var(--text-2); max-width:40ch; }
.scenarios-scene { background:var(--bg); }
.scenario-peak { color:var(--text); background:var(--bg); }
.peak-wipe { position:absolute; inset:0; background:var(--accent-soft); }
.peak-content { position:relative; z-index:2; padding-top:calc(var(--brief-bar) + 44px); }
.peak-content .section-head { display:grid; grid-template-columns:1.25fr 1fr; gap:8%; align-items:end; }
.peak-content h2 { font-size:clamp(48px,5.7vw,80px); max-width:700px; }
.peak-content .section-lede { font-size:15px; margin:0; }
.scenario-lens { margin-top:48px; border-top:1px solid var(--input-border); padding-top:24px; }
#lensContext { color:var(--text-2); font-size:14px; }
.lens-equation { display:flex; gap:28px; align-items:center; margin-top:28px; font-family:var(--font-serif); font-size:clamp(24px,4vw,54px); color:var(--accent-ink); }
.lens-equation span:nth-child(even) { font-family:var(--font-sans); font-size:24px; color:var(--text-3); }
.lens-answer { font-family:var(--font-serif); font-size:clamp(24px,3.2vw,48px); line-height:1.08!important; color:var(--accent-ink); letter-spacing:-.035em; margin-block:28px 20px; }
#lensDetail { max-width:72ch; color:var(--text-2); font-size:14px; }
.lens-price-note { max-width:72ch; font-size:14px; color:var(--text-2); }
.lens-price-note[hidden] { display:none; }
.lens-summary { color:var(--text-2); font-size:15px; max-width:60ch; }
.lens-summary:empty { display:none; }
.lens-stale { max-width:72ch; margin:0 0 12px; padding:0; color:var(--text); font-size:14px; font-weight:600; }
.lens-stale:empty { margin:0; }
.lens-stale:not(:empty) { padding:8px 12px; background:var(--sunken); border-left:3px solid var(--accent-ink); }
.lens-note { max-width:72ch; margin:6px 0 0; font-size:14px; color:var(--text-2); }
.lens-note[hidden] { display:none; }
.lens-controls { display:flex; gap:16px; align-items:center; margin-top:20px; }
.lens-controls label { flex:none; font-size:13px; }.lens-controls select { max-width:550px; }
/* A6: one arrow, not a custom chevron beside the browser's own. The label the
   native control paints is kept and the added one is taken away, so the picker
   shows a single disclosure and keyboard behaviour is untouched. */
.lens-controls select {
  appearance:none; -webkit-appearance:none;
  padding-right:34px;
  background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5 6 6.5 11 1.5' fill='none' stroke='%235c636a' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat:no-repeat; background-position:right 12px center;
}
@media (prefers-color-scheme:dark){ .lens-controls select{ background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5 6 6.5 11 1.5' fill='none' stroke='%23aeb8bd' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E"); } }
.scenario-detail { padding-block:48px 64px; }
.scenario-detail .empty-state { margin-top:24px; }
.read-scene { padding-block:80px; background:var(--surface); }
.read-layout { display:grid; grid-template-columns:.85fr 1fr; gap:8%; align-items:start; }
.read-photo { margin:0; }.read-photo img { height:650px; width:100%; object-fit:cover; }
.read-content { padding-block:32px; }.read-content .section-lede { font-size:16px; }
.read-content .recommendation { background:transparent; border:0; padding:0; }
.read-content #aiAnalyzeBtn { margin-top:32px; }
.numbers-scene { padding-block:88px 56px; }
.numbers-opening { display:grid; grid-template-columns:1fr .75fr; gap:10%; align-items:center; margin-bottom:48px; }
.home-photo { height:320px; width:100%; object-fit:cover; }
.numbers-scene .buyer-grid { grid-template-columns:repeat(3,minmax(0,1fr)); gap:28px; }
.numbers-scene .form-group { background:transparent; border-radius:0; padding:28px 0; border:0; border-top:1px solid var(--line-strong); }
.numbers-scene .account-note { margin-top:24px; }
.numbers-scene .account-slot { margin-bottom:32px; }
.numbers-scene .buyer-actions { margin-top:24px; }
/* P6: the fieldset's own legend repeated the heading directly above it, so it
   keeps its accessible name and stops being drawn. This outranks the page's
   .form-group > legend rule, so nothing here floats or fills the row. */
.numbers-scene .form-group > legend.sr-only { position:absolute; float:none; display:block; width:1px; height:1px; margin:-1px; padding:0; overflow:hidden; clip-path:inset(50%); }
/* E8: the Enter hint sits on the button row, so it is read with the press it
   describes rather than below it. */
.numbers-scene .buyer-actions .form-hint { align-self:center; margin-top:0; }
/* P6: the message list under the button and the disclaimer under it were
   touching; the list now ends clear of the line below. */
.numbers-scene .form-errors { margin-bottom:16px; }
.numbers-scene .page-footer { margin:24px 0; padding:16px 0; max-width:70ch; }
/* WCAG 2.5.8: footer links were 15px tall. Padding lifts the hit area to 25px without moving the text much. */
.page-footer a { display:inline-block; padding:5px 4px; }
/* WCAG 1.4.3: hint text sits on scrubbed video, so a bright frame could drop it under 4.5:1. A translucent scene-colour backing holds about 6:1 even against a pure white frame. */
#sec-markets .form-hint { display:inline-block; margin-left:-8px; padding:4px 8px; border-radius:6px; background:color-mix(in oklab, var(--bg) 85%, transparent); }
#sec-markets .label-note { padding:0 6px; border-radius:4px; background:color-mix(in oklab, var(--bg) 85%, transparent); }
/* Real data uses rules and whitespace rather than nested card decoration. */
.dashboard { gap:24px; }.card,.result-tile { box-shadow:none; border-radius:4px; }
.scene .info-box,.scene .warning-box { border-left-width:1px; }
@media(hover:hover) and (pointer:fine){ #runAnalysis:hover{background:#114b57;} .pipeline-nav a:hover{background:var(--accent-soft);} }
@media(max-width:1100px){
 .status-bar.rail{gap:16px;padding-inline:20px;}.pipeline-nav a{padding-inline:8px;}.status-actions{gap:10px;}
}
@media(max-width:760px){
 :root{--brief-bar:72px;--brief-gutter:24px;}
 .status-bar.rail{height:var(--brief-bar);display:grid;grid-template-columns:1fr auto;grid-template-rows:56px 60px;gap:0;padding-inline:16px;}
 .pipeline-nav{grid-column:1/-1;grid-row:2;overflow-x:visible;padding-bottom:4px;}
 /* C1: all six labels fit at 390px and at 360px with the bar at scroll 0. The
    short labels are the default on a phone and the long one is dropped, the
    padding is tightened, and the focus ring is inset so the bar's own edge
    cannot clip it (B6 S2). Nothing here scrolls sideways. */
 .pipeline-nav ol{justify-content:space-between;gap:0;width:100%;flex-wrap:wrap;}
 .pipeline-nav li{flex:1 1 0;min-width:0;}
 .pipeline-nav a{font-size:11px;padding:15px 2px;text-align:center;white-space:normal;line-height:1.2;
  box-shadow:inset 0 0 0 0 transparent;transition:box-shadow .12s ease;}
 .pipeline-nav a:focus-visible{outline:none;box-shadow:inset 0 0 0 3px var(--focus-ring,currentColor);border-radius:2px;}
 .step-long{display:none;}
 .step-short{display:inline;}
 .status-actions{grid-column:2;grid-row:1;}.status-bar .brand-name{font-size:17px;}
 /* The phone hero is laid out by the block at the end of this file, where its
    copy is in normal flow instead of hung off the bottom of the stage. */
 .question-copy>p{font-size:15px;max-width:30ch;margin-bottom:20px;}
 .hero-command-row{flex-direction:column;gap:10px;}.hero-command{padding:14px;}.hero-command input{padding:10px;}
 .scene h2{font-size:48px;}.scene .section-lede{font-size:15px;}
 .costs-scene{padding-block:56px;}.costs-opening{display:flex;flex-direction:column;gap:28px;}
 .costs-photo{width:100%;}.costs-photo img{aspect-ratio:1.8;}.cost-ledger{gap:24px;}.cost-ledger h3{font-size:26px;}.cost-ledger p{font-size:14px;}
 .cost-context{font-size:14px;}.costs-opening>.work-disclosure{width:100%;}
 .market-copy{bottom:14vh;right:24px;}.market-scrim{background:linear-gradient(to top,rgba(10,19,23,.98),rgba(10,19,23,.8) 40%,transparent 90%);}
 .market-work{padding-top:32px;}.analysis-console{padding:20px;margin-bottom:36px;}.console-head{display:block;}.console-head h3{margin-bottom:10px;}
 /* B6 S18: log text was 11px on a phone, under the 13px floor. */
 .log-line{grid-template-columns:1fr auto;gap:4px 12px;font-size:13px;}.log-source{grid-column:1/-1;}.log-summary{grid-column:1/-1;}.log-time{text-align:right;}
 #analysisLog,#analysisLogEmpty,#analysisLogState{font-size:13px;}
 .market-work .city-inputs{grid-template-columns:1fr 1fr;}.market-work .city-inputs>.field:first-child{grid-column:1/-1;}
 .market-tools{display:block;}.market-tools>.work-disclosure{margin-top:16px;}.market-pause{padding:40px 0;font-size:20px;}
 .peak-content{padding-top:calc(var(--brief-bar) + 20px);}.peak-content .section-head{display:block;margin-bottom:20px;}.peak-content h2{font-size:44px;}
 .peak-content .section-lede{font-size:13px;margin-top:16px;line-height:1.55;}.scenario-lens{margin-top:20px;padding-top:16px;}
 .lens-equation{gap:16px;font-size:30px;margin-top:16px;}.lens-equation span:nth-child(even){font-size:16px;}
 .lens-answer{font-size:30px;margin-block:20px 16px;}#lensDetail{font-size:13px;}.lens-controls{display:block;margin-top:12px;}.lens-controls select{width:100%;font-size:13px;margin-top:8px;}
 .scenario-detail{padding-block:32px 48px;}.read-scene{padding-block:48px;}.read-layout{display:flex;flex-direction:column;gap:28px;}.read-photo{width:100%;}.read-photo img{height:240px;}.read-content{padding:0;}
 .numbers-scene{padding-block:56px 40px;}.numbers-opening{display:flex;flex-direction:column;gap:24px;margin-bottom:32px;align-items:stretch;}.home-photo{height:180px;}
 .numbers-scene .buyer-grid{grid-template-columns:1fr;gap:24px;}.numbers-scene .form-group{padding-block:24px;}
}
@media(max-height:720px) and (min-width:761px){.question-copy{bottom:8vh;}.question-scene h1{font-size:88px;}.peak-content{padding-top:92px;}.scenario-lens{margin-top:20px;}.lens-answer{font-size:34px;}.lens-equation{font-size:32px;}}
@media(prefers-reduced-motion:reduce){
 html{scroll-behavior:auto;}
 .question-copy{transform:none!important;opacity:1!important;}
 /* Defensive: an inline transform written by the engine cannot reintroduce motion. */
 [data-sc-rise],[data-sc-cue],[data-sc-parallax]{transform:none!important;opacity:1!important;}
}
/* Reset the original desktop sidebar's direction, not just its placement. */
.status-bar.rail { flex-direction:row; justify-content:space-between; align-items:center; }
.scene :is(.update-cities-btn,.btn-primary,.search-btn,.secondary-btn) { border-radius:4px; }
.market-copy h2 { color:#f5f4f0; }
.peak-content .section-head { display:block; max-width:none; width:100%; }
.peak-content h2 { max-width:100%; font-size:clamp(44px,4.5vw,64px); }
.peak-content .section-lede { margin-top:20px; max-width:72ch; }
.cost-values { margin-top:24px; }
.cost-values>div { display:flex; flex-wrap:wrap; gap:12px; justify-content:space-between; border-top:1px solid var(--line); padding-block:14px; font-size:13px; }
.cost-values dt { color:var(--text-2); }.cost-values dd { margin:0; color:var(--accent-ink); font-weight:600; }
@media(min-width:761px){.lens-answer{font-size:clamp(28px,3.8vw,56px);}}
@media(max-width:760px){.cost-values>div{display:block;}.cost-values dd{margin-top:6px;}.peak-content .section-lede{margin-top:16px;}.peak-content h2{font-size:44px;}}
@media(max-height:700px) and (max-width:760px){
 .peak-content{padding-top:calc(var(--brief-bar) + 12px);}.peak-content h2{font-size:36px;}
 .peak-content .section-lede{font-size:12px;margin-top:12px;}.scenario-lens{margin-top:12px;padding-top:12px;}
 .lens-answer{font-size:28px;margin-block:16px 12px;}#lensDetail{font-size:12px;}.lens-controls{margin-top:8px;}
}
/* What-if fits the pinned stage, or it is not pinned.
   The stage is 100svh with a clipped overflow, so a lens taller than the
   stage puts the answer, the detail line and the "Set your numbers" link
   below its bottom edge, where no amount of scrolling reaches them: a
   landscape phone loses the whole point of the scene. Two rules cover it.
   Between the heights a full-size lens needs and the heights it can still
   fit, the type compacts and the stage keeps pinning. Below that, the peak
   takes the same unpinned layout the reduced-motion path already uses, so
   the content is an ordinary scroll region instead of a hidden one.
   briefing.js applies the same unpinned layout by measuring the real
   content, which covers the heights no breakpoint can predict (a longer
   translation, a larger lens detail line, a zoomed viewport). */
@media(min-width:761px) and (max-height:720px){
 .peak-content{padding-top:calc(var(--brief-bar) + 16px);}
 .scenario-lens{margin-top:14px;padding-top:14px;}
 .lens-equation{font-size:26px;margin-top:16px;}
 .lens-answer{font-size:32px;margin-block:16px 12px;}
}
@media(max-height:590px){
 .scenario-peak{height:auto!important;}
 .scenario-peak .sc-stage{height:auto;min-height:80svh;overflow:visible;}
 .peak-content{padding-top:calc(var(--brief-bar) + 16px);padding-bottom:32px;}
 .peak-content h2{font-size:34px;}
 .peak-content .section-lede{font-size:12px;margin-top:10px;}
 .scenario-lens{margin-top:14px;padding-top:14px;}
 .lens-equation{font-size:24px;margin-top:14px;gap:18px;}
 .lens-answer{font-size:28px;margin-block:14px 10px;}
 #lensDetail{font-size:12px;}.lens-controls{margin-top:10px;}
}
.scenario-peak[data-sc-unpinned]{height:auto!important;}
.scenario-peak[data-sc-unpinned] .sc-stage{height:auto;min-height:80svh;overflow:visible;}
.scenario-peak[data-sc-unpinned] .scenario-lens{transform:none!important;}
/* Fixed app chrome is outside the scene timeline, including contrast sampling. */
.status-bar.rail { position:fixed; }
.main { padding-top:var(--brief-bar); }

/* Preserve provenance status logic while adapting its legacy inline colors to the theme. */
#recommendation .rate-status-warn { color:var(--warn)!important; }
#recommendation .rate-status-ok { color:var(--pos)!important; }

/* A clip whose shape no longer matches the stage. The engine has begun loading
   it and will not fetch the other shape, so a phone turned after the first
   frame painted would otherwise crop a 9:16 clip into a 16:9 stage: the clip
   stops painting and the <picture> beside it, which the engine took down when
   that frame painted, is what the stage shows. Both selectors out-specify
   scrollcraft.css, so the order the two sheets load in cannot undo them. */
[data-sc-stage].sc-clip-wrong-shape video[data-sc-scrub] { opacity: 0; }
[data-sc-stage].sc-clip-wrong-shape .sc-stage__poster { opacity: 1; }

/* The hero on a phone and on a short window is laid out at the end of this
   file, in normal flow, once and for every height. Every rule this paragraph
   used to own is gone: they anchored `.question-copy` to the bottom or the top
   of a stage whose box only exists after the scroll engine has mounted. */
/* A phone step bar in two rows spends 116px of a 375px window on navigation.
   From the height where the hero type compacts it is one row again, and every
   offset that follows the bar follows this one: main's padding, the anchor
   jump's scroll-padding, the stage's top and the copy's own offsets. The steps
   scroll sideways in the row they share rather than being dropped. */
@media(max-width:760px) and (max-height:520px){
  :root{--brief-bar:56px;}
  .status-bar.rail{height:var(--brief-bar);grid-template-columns:auto minmax(0,1fr) auto;grid-template-rows:56px;gap:10px;padding-inline:12px;}
  .pipeline-nav{grid-column:2;grid-row:1;min-width:0;padding-bottom:0;}
  .status-actions{grid-column:3;grid-row:1;gap:8px;}
  .status-bar .brand-name{font-size:15px;}
  .status-actions a{font-size:11px;padding-block:8px;}
  #themeToggle{padding:6px 8px;min-height:36px;font-size:11px;}
  .pipeline-nav a{font-size:11px;padding:18px 8px;}
}
/* A landscape phone has the width for the input and the button side by side
   again, so the command costs one row of height instead of two. */
@media(min-width:520px) and (max-height:520px){
  .hero-command-row{flex-direction:row;gap:10px;}
  .hero-command input{flex:1 1 auto;}
}

/* ===================================================== THE HERO, IN FLOW ==
   A phone, or any window no taller than 700px.

   `.question-copy` was position:absolute and hung off the bottom of a stage
   whose box only comes into existence when the scroll engine mounts
   (`sc-ready`, 170-730ms after first paint), so the headline and the form were
   placed against geometry that does not exist yet and were measured from an
   edge that moves with the font. Measured in Chrome at the previous commit:
   before the engine mounted the stage was 870px of unsized still and "Run the
   analysis" sat at y 780-828, off the screen of every phone here; under
   prefers-reduced-motion the stage was pinned at min-height 760px and the form
   sat at y 670-718, below the fold at 320x521, 320x568, 320x600, 360x640 and
   375x667; and in the real Newsreader web font a 320-wide phone could wrap
   "or wait?" to a third line, which grew the bottom-anchored copy up under the
   fixed 116px step bar. Four rounds of review found one of those three.

   The copy is in normal flow here: it starts one gap under the step bar and is
   followed by the form, whatever the engine does to the stage, whether motion
   is reduced, and which lines the headline wraps to. The still and the clip
   stay the stage behind it and the scrub still runs; only the text and the
   control stop depending on the stage's absolute box.

   Nothing here waits for the engine. Every selector is an attribute the markup
   already carries, the stage is sized in CSS, the media are taken out of flow
   in CSS, and the act's own height is declared here as well, so the first
   painted frame is the final layout and the first frame is measurable at all. */
@media (max-width:760px), (max-height:700px){
  /* The hero is a short static section on a phone and a short window too: the
     still stays behind the copy, the copy is in flow, and the scene stays short
     enough that the top of Today is inside the first screen. */
  .question-scene { min-height:min(58vh,560px); }
  .question-scene .hero-media { position:absolute; inset:0; overflow:hidden; }
  .question-copy {
    position:relative; z-index:4; top:auto; right:auto; bottom:auto; left:auto;
    width:auto; margin-inline:var(--brief-gutter);
    padding-block:20px 24px;
  }
  /* " or wait?" is 3.83em wide in Newsreader and the gutters leave 272px of it
     on a 320-wide phone, so the question sets as two lines only at or below
     70px there. A clamp, not a fixed size: one rule has to hold for a 320-wide
     phone and a 760-wide one. */
  .question-scene h1 { font-size:clamp(44px,18.5vw,68px); line-height:.94; margin:0 0 12px; }
  .question-copy>p { margin:0; }
  .hero-scrim {
    background:linear-gradient(to bottom,rgba(10,19,23,.97) 0%,rgba(10,19,23,.94) 46%,rgba(10,19,23,.86) 68%,rgba(10,19,23,.72) 100%);
  }
}
/* A short window has the least room of all, so the copy it does have is
   compacted: the gaps shrink and the controls keep a 44px target. The height,
   not the width, is what is scarce here. */
@media (max-height:700px){
  .question-copy { padding-block:14px 20px; }
  .question-copy>p { font-size:14px; line-height:1.5; margin:0 0 12px; }
  .hero-command { padding:12px; }
  .hero-command label { margin-bottom:6px; }
  .hero-command input { min-height:44px; padding:9px; }
  #runAnalysis { min-height:44px; padding:9px 16px; }
}
/* Below the height the phone bar is one row again, and the type compacts for
   the last time. */
@media (max-height:520px){
  .question-scene h1 { font-size:clamp(30px,7.5vh,48px); line-height:.98; margin-bottom:10px; }
  .question-copy>p { max-width:34ch; }
}
/* A 320px-tall window with the input and the button stacked is about nine
   pixels short of the copy: measured at 320x320, 360x320, 390x320 and 414x320,
   the form ended at y 329. The gaps and the command's own padding give up those
   nine pixels; the 44px touch targets do not. */
@media (max-height:360px){
  .question-copy { padding-block:8px 12px; }
  .question-scene h1 { margin-bottom:8px; }
  .question-copy>p { margin:0 0 8px; }
  .hero-command { padding:10px; }
}

/* ================================================= FLOW V2 SCENES ==========
   Today, Your numbers, Your answer, Compare cities, Find deals, Analyze a house.
   The answer is an ordinary scroll section directly under the form; there is no
   pinned stage to fit. */
.today-scene, .answer-scene, .cities-scene, .deals-scene, .house-scene { padding-block:64px; }
.today-scene .scene-wrap, .answer-scene .scene-wrap, .cities-scene .scene-wrap, .deals-scene .scene-wrap, .house-scene .scene-wrap { padding-inline:var(--brief-gutter); }
.today-rate { margin:0 0 28px; }
#recommendation.today-rate .rec-detail p { font-size:16px; }
#recommendation.today-rate .rec-detail small { display:block; margin-top:6px; color:var(--text-2); }
.answer-scene .scenario-lens { margin-top:4px; border-top:1px solid var(--input-border); padding-top:24px; }
.answer-scene .caveat { color:var(--text-2); font-size:15px; margin-top:10px; }
.answer-scene .cost-ledger { margin-top:40px; }
.answer-scene .analysis-console { margin-top:40px; }
.answer-scene .work-disclosure { margin-top:24px; }
.answer-scene .buyer-intro { margin-top:24px; }
.answer-scene .read-content { margin-top:48px; padding-top:40px; border-top:1px solid var(--line-strong); }
.answer-scene .read-content #aiAnalyzeBtn { margin-top:24px; }
.answer-scene .read-content .ai-hint { color:var(--text-3); font-size:14px; margin-top:10px; }
/* E2: the four fields a run cannot start without say so, in the note the
   optional labels already use. */
.req { color:var(--text-3); font-weight:500; }
.field-error { display:block; color:var(--neg); font-size:0.875rem; margin-top:6px; }
.field-error[hidden] { display:none; }
input[aria-invalid="true"] { border-color:var(--neg); box-shadow:0 0 0 1px var(--neg); }
.news-section { margin-top:8px; }
@media (max-width:760px){
  .today-scene, .answer-scene, .cities-scene, .deals-scene, .house-scene { padding-block:40px; }
}

/* Header height comes from its contents; the measured offset never sizes it. */
.status-bar.rail { height:auto; min-height:72px; }
@media(max-width:760px) and (min-height:521px) {
 .status-bar.rail { display:flex; flex-wrap:wrap; min-height:72px; gap:0; }
 .status-bar .brand, .status-actions { min-height:44px; }
 .status-actions { margin-left:auto; flex-shrink:0; }
 .pipeline-nav { order:3; flex:1 0 100%; padding-bottom:0; }
 .pipeline-nav ol { flex-wrap:wrap; }
 .pipeline-nav li { flex:1 0 auto; margin:0; }
 .pipeline-nav a { display:flex; align-items:center; justify-content:center; min-height:27px; white-space:nowrap; padding-block:0; padding-inline:3px; }
}
/* P11: on a phone the bar is 72px, a 44px row for the brand and the two
   controls over a 27px row of steps (and the bar's 1px rule). A step whose scene is not on the page yet
   (Answer, before the first run) keeps its place and is only not seen, so the
   other steps do not move when it appears. visibility:hidden also takes it out
   of the tab order and the accessibility tree. The page's own [hidden] rule is
   !important, so this one has to be as well. */
@media(max-width:760px){
 .pipeline-nav li[hidden]{display:block!important;visibility:hidden;}
}


/* ================================================= P3 FIXES =================
   P3: at 1440px wide the cities row leaves empty thirds when only one
   city card renders (the grid keeps three columns for one card). Let the
   cards share the row with an auto-fit grid, without changing
   phone/tablet layouts. (The cost ledger already fills its row with two
   side-by-side cards under the base 1fr 1fr rule, so it needs no change.) */

/* Dashboard grid: use auto-fit at wider widths so cards fill available space
   Use container query to match existing pattern in index.html */
@container main (min-width: 880px) {
  .dashboard {
    grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
  }
}

/* ================================================= P4 FIXES =================
   P4: the cities scene is an abrupt dark island in light mode.
   Add a smooth transition at the top and bottom edges of the scene in
   light mode (a gradient band from the page background into the scene color,
   about 48 to 72px), with no change in dark mode. Text inside must keep
   contrast of at least 4.5:1. */

/* Light mode only: add gradient transition bands at top and bottom of cities scene */
@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) .cities-scene::before,
  :root:not([data-theme="dark"]) .cities-scene::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    height: 72px;
    z-index: 1;
    pointer-events: none;
  }

  :root:not([data-theme="dark"]) .cities-scene::before {
    top: 0;
    background: linear-gradient(180deg, var(--bg) 0%, rgba(17, 20, 22, 0.8) 40%, rgba(17, 20, 22, 0.95) 100%);
  }

  :root:not([data-theme="dark"]) .cities-scene::after {
    bottom: 0;
    background: linear-gradient(0deg, var(--bg) 0%, rgba(17, 20, 22, 0.8) 40%, rgba(17, 20, 22, 0.95) 100%);
  }
}

/* ================================================= S7 FIXES =================
   S7: while house search is paused, both the Deals and House scenes are
   near-empty, and tapping "Deals" in the nav highlights "House".

   (a) nav active state must follow the scene that is actually in view
       (fixed in layout.js with most-visible-area tie-break)

   (b) when search is paused, collapse the empty scenes' vertical padding
       so the page does not show two big empty bands, keeping one calm
       status line. The paused-message dedupe (HOUSE_PAUSED logic) is
       unchanged. */

/* (b) Collapse empty scenes when search is paused */
.deals-scene.paused .scene-wrap,
.house-scene.paused .scene-wrap {
  padding-block: 24px;
}

.deals-scene.paused .search-filters,
.deals-scene.paused .search-actions,
.house-scene.paused #houseChoose,
.house-scene.paused #houseGoToSearch {
  display: none;
}

.deals-scene.paused .search-paused,
.house-scene.paused .house-paused {
  display: block;
  padding: 24px 0;
  font-size: 18px;
  color: var(--text-2);
  max-width: 50ch;
  text-align: center;
  margin: 0 auto;
}

@media(max-width:760px) and (max-height:520px) {
 .status-bar.rail { height:56px; min-height:56px; grid-template-rows:56px; }
 .pipeline-nav { overflow-x:auto; }
 .pipeline-nav ol { flex-wrap:nowrap; width:max-content; min-width:100%; }
 .pipeline-nav li { flex:1 0 auto; }
}

/* ================================================= L2 FIXES =================
   P8: the news card sat as a padded box inside the column, so its text started
   41px right of the heading above it. It is a ruled block on the column now,
   like the rest of the scene. The deal filters were a 4-column grid with spans,
   which made one row 2+1+1 and the next 1+1+2; at desktop widths they are six
   equal cells in three columns. The Analyze label stays on one line beside the
   card text, and where it has to wrap (a phone) it wraps in balanced halves. */
.today-scene .news-section { padding:0; background:transparent; border:0; border-top:1px solid var(--line); border-radius:0; }
.listing-card .secondary-btn { text-wrap:balance; }
@container main (min-width: 760px) {
  .deals-scene .search-filters { grid-template-columns:repeat(3,minmax(0,1fr)); }
  .deals-scene .search-filters > * { grid-column:auto; }
  .listing-card .secondary-btn { white-space:nowrap; }
}

/* P10: the numbers form on a wide screen is three equal columns, and no field
   sits alone on the last row. A group whose last row would hold one field
   makes its last four (or, with two left over, its last two) fields half-width
   so the rows read 3+2+2 or 2+2. Both optional groups take the ruled style of
   the first group rather than one of them being a filled box. */
.numbers-scene .assumptions { background:transparent; border:0; border-top:1px solid var(--line-strong); border-radius:0; padding:28px 0; }
@media(max-width:760px){
  .numbers-scene .assumptions { padding-block:24px; }
}
@media(min-width:761px){
  .numbers-scene .buyer-grid { grid-template-columns:repeat(6,minmax(0,1fr)); }
  .numbers-scene .buyer-grid > .buyer-field { grid-column:span 2; }
  .numbers-scene .buyer-grid:has(> .buyer-field:nth-child(3n+1):last-child) > .buyer-field:nth-last-child(-n+4),
  .numbers-scene .buyer-grid:has(> .buyer-field:nth-child(3n+2):last-child) > .buyer-field:nth-last-child(-n+2) { grid-column:span 3; }
}

/* ================================================= DESIGN PASS 2026-10 ======
   Tokens. Spacing and the type ramp reuse --sc-1..--sc-11 and --sc-t-* from
   scrollcraft.css and the colours reuse the --text / --accent / --warn sets
   above; these three are the only additions. Each screen patch uses them. */
:root {
  --fs-fine: 0.8125rem;   /* 13px: the smallest size for notes, meta and log rows */
  --fs-small: 0.9375rem;  /* 15px: supporting copy under a figure or a heading */
  --fs-figure: clamp(2.75rem, 2.1rem + 3.4vw, 4.25rem); /* the one number a scene is about */
}

/* ---- 01 Today: the rate is the figure of this scene, and its absence is said.
   The number is a span written by renderRecommendation(); the sentence under it
   keeps the publisher and the date. On a phone the hero stops reserving empty
   dark space under its button, so the figure lands inside the first screen. */
#recommendation.today-rate .rec-detail { margin-top:0; }
.today-rate .rate-figure {
  display:block; margin-bottom:var(--sc-2);
  font-family:var(--font-serif); font-weight:400; font-size:var(--fs-figure);
  line-height:1; letter-spacing:-.04em; color:var(--accent-ink);
}
.today-rate .rate-missing {
  padding:var(--sc-3) var(--sc-4); border:1px solid var(--warn-line); border-radius:var(--radius-sm);
  background:var(--warn-bg); color:var(--text);
}
/* Loading: the rate's place is held (no jump when it arrives) and says what it waits for. */
#recommendation.today-rate:empty { min-height:calc(var(--fs-figure) + 5rem); }
.today-rate .rate-loading { margin:0; min-height:calc(var(--fs-figure) + 5rem); color:var(--text-2); font-size:var(--fs-small); }
@media (max-width:760px) {
  .question-scene { min-height:0; }
  .today-scene { padding-top:var(--sc-6); }
  .today-scene .section-head { margin-bottom:var(--sc-5); }
  .today-scene .section-head h2 { font-size:40px; }
  .today-scene .section-lede { margin-top:var(--sc-3); }
}

/* ---- 02 Your numbers: one voice for labels, hints and the lines under the button.
   A label that holds "(required)" lost the space between the two once the label
   became a flex row (560px and wider), the rate field's placeholder was 13px
   beside 16px everywhere else, and the three lines under the button used three
   sizes and two colours. */
@container main (min-width: 560px) {
  .buyer-grid > .buyer-field > label { flex-wrap:wrap; column-gap:.3em; }
}
#buyerUserRate::placeholder { font-size:inherit; }
.numbers-scene .buyer-actions { align-items:center; gap:var(--sc-3) var(--sc-4); }
.numbers-scene #buyerCalculate { min-height:52px; padding-inline:var(--sc-5); }
.numbers-scene .form-hint,
.numbers-scene .caveat { font-size:var(--fs-fine); line-height:1.5; color:var(--text-2); margin-top:var(--sc-2); }
.numbers-scene .caveat { margin-bottom:0; }

/* ---- 03 Answer: the answer line leads, the scene heading is a label for it.
   The "Buy now or wait: your answer" heading was set larger than the answer it
   introduces, so the eye landed on the label first. The supporting lines were
   five different sizes with no grouping; the assumptions now sit in one ruled
   block, and the scenario picker reads at 16px (a 13px control makes iOS Safari
   zoom the page when it takes focus) with room for its text. */
.answer-scene .section-head h2 { font-size:clamp(32px, 3.4vw, 44px); letter-spacing:-.03em; }
.answer-scene .section-head { margin-bottom:var(--sc-5); }
.answer-scene .scenario-lens { padding-top:var(--sc-5); }
@media(min-height:721px){.answer-scene .lens-answer { font-size:clamp(34px, 4.6vw, 56px); margin-block:var(--sc-2) var(--sc-4); }}
.answer-scene .scenario-lens > p { margin:0; }
.answer-scene .scenario-lens > p + p { margin-top:var(--sc-2); }
.answer-scene .scenario-lens :is(.lens-summary, #lensContext, #lensDetail, .lens-price-note) { font-size:var(--fs-small); line-height:1.55; color:var(--text-2); }
.answer-scene .lens-note {
  margin-top:var(--sc-3); padding-left:var(--sc-3); border-left:2px solid var(--line-strong);
  font-size:var(--fs-small); line-height:1.55; color:var(--text-2);
}
.answer-scene .lens-controls { margin-top:var(--sc-4); }
.answer-scene .lens-controls label { font-size:var(--fs-small); font-weight:600; }
.answer-scene .lens-controls select {
  min-height:48px; padding-left:var(--sc-3); font-size:1rem;
  background-color:var(--surface); border:1px solid var(--input-border); border-radius:var(--radius-sm);
}
.answer-scene .caveat { display:inline; font-size:var(--fs-fine); margin-top:0; }
.answer-scene .caveat + .caveat::before { content:" "; }
.answer-scene .scenario-lens #lensDetail { margin-top:var(--sc-3); color:var(--text); }
.answer-scene .scenario-lens { margin-bottom:var(--sc-4); }

/* ---- 04 Find deals / Analyze a house, paused. A pause is neutral, not a fault of
   the visitor's, so it is the page's info notice (hourglass, left aligned, same
   box as .info-box) instead of one centred 18px sentence floating in an empty
   band. */
.deals-scene.paused .search-paused,
.house-scene.paused .house-paused {
  position:relative; max-width:60ch; margin:0 0 var(--sc-4); padding:var(--sc-3) var(--sc-4) var(--sc-3) 3rem;
  border:1px solid var(--info-line); border-radius:var(--radius-sm); background:var(--info-bg);
  color:var(--text); font-size:1rem; line-height:1.5; text-align:left;
}
.deals-scene.paused .search-paused::before,
.house-scene.paused .house-paused::before {
  content:""; position:absolute; left:var(--sc-4); top:var(--sc-3); width:1.25rem; height:1.5rem;
  background:var(--info); -webkit-mask:var(--i-hourglass) center / contain no-repeat; mask:var(--i-hourglass) center / contain no-repeat;
}

/* ---- 05 Header and step bar. Step labels were 11px on a phone, under the 13px
   floor the log and notes already hold to. 13px keeps all six steps on one row
   from 361px up (12px below, where 320px has no slack) and leaves the 72px bar
   alone (P11). The Sign in link was 38px wide, under the 44px touch row its
   neighbour has. */
@media (max-width:760px) {
  .pipeline-nav a { font-size:12px; letter-spacing:0; }
}
@media (min-width:361px) and (max-width:760px) {
  .pipeline-nav a { font-size:var(--fs-fine); }
}
.status-actions a { min-width:44px; justify-content:center; }
