@font-face {
  font-family: "Geist";
  font-style: normal;
  font-weight: 400 800;
  font-display: swap;
  src: url("/static/fonts/geist-latin.woff2") format("woff2");
}
@font-face {
  font-family: "Geist Mono";
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url("/static/fonts/geist-mono-latin.woff2") format("woff2");
}
/* Afterglow (DESIGN.md): a dark corridor, the ways out glow like the lines of
   an emergency light. One scheme: the plan photo is dimmed under the marks. */
:root {
  --bg: #07100c;
  --card: #0f1a15;
  --raise: #15231d;
  --fg: #eaf3ee;
  --muted: #a7b8b0;
  --line: #22332b;
  --soft: #18251f;
  --accent: #3dffa0;
  --accent-fg: #03140b;
  --logo-wall: #8faaa0;
  --logo-route: #3dffa0;
  --logo-dot: #ff7a59;
  --exit: #3dffa0;   /* the exit marks on the plan (app.js EXIT) */
  --route: #5aa2ff;  /* the route on the plan (app.js ROUTE) */
  --done: #aebdcc;   /* the legs before the current step (app.js DONE) */
  --reading: #d29bff;
  color-scheme: dark;
}
* { box-sizing: border-box; }
[hidden] { display: none !important; }
/* Parts that need the script show from the first paint when it runs (early.js adds "js"). */
html:not(.js) .js-only { display: none !important; }
.sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
body {
  margin: 0;
  background: var(--bg);
  color: var(--fg);
  font: 450 17px/1.55 "Geist", system-ui, -apple-system, "Segoe UI", sans-serif;
}
h1, h2, h3, h4 { line-height: 1.15; letter-spacing: -0.02em; font-weight: 600; }
h2 { font-size: 1.6rem; margin: 0 0 10px; letter-spacing: -0.03em; }
h3 { font-size: 1.05rem; margin: 20px 0 8px; }
a { color: var(--accent); }
.ico { width: 20px; height: 20px; flex: none; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }

/* Header: the logo and the links to the parts of the page. It stays at the top
   of the start page. With a plan open, it has the photo button and scrolls away. */
.top { position: sticky; top: 0; z-index: 10; background: rgb(7 16 12 / 0.88); -webkit-backdrop-filter: blur(12px); backdrop-filter: blur(12px); border-bottom: 1px solid var(--line); }
html.has-plan .top { position: static; background: none; -webkit-backdrop-filter: none; backdrop-filter: none; border-bottom-color: transparent; }
html:not(.has-plan) { scroll-padding-top: 76px; }
.top-in { max-width: 1200px; margin: 0 auto; padding: 0 16px; min-height: 64px; display: flex; align-items: center; gap: 4px 12px; }
.nav { display: flex; align-items: center; gap: 2px; }
.nav a { display: inline-flex; align-items: center; gap: 7px; min-height: 44px; padding: 0 10px; border-radius: 999px; color: var(--muted); font-weight: 550; font-size: 0.95rem; text-decoration: none; white-space: nowrap; }
.nav a:hover { color: var(--fg); background: var(--card); }
.nav a:focus-visible { outline: 3px solid var(--fg); outline-offset: 2px; }
.nav .ico { width: 18px; height: 18px; }
/* Narrow screens keep fewer links: the photo button and the samples come first. */
@media (max-width: 719px) { .nav-how { display: none !important; } }
@media (max-width: 479px) { .nav-demo { display: none !important; } .nav a { padding: 0 8px; } }
@media (max-width: 359px) { .nav-code { display: none !important; } }  /* the footer links the code */
/* With a plan open, the start page parts are gone: the links to them go too. */
html.has-plan .nav-how, html.has-plan .nav-demo { display: none !important; }
@media (max-width: 599px) { html.has-plan .nav-samples { display: none !important; } }
@media (max-width: 479px) { html.has-plan .nav-code { display: none !important; } }
.brand { flex: none; margin-right: auto; display: inline-flex; align-items: center; gap: 10px; text-decoration: none; color: var(--fg); min-height: 44px; }
.brand:focus-visible { outline: 3px solid var(--fg); outline-offset: 4px; border-radius: 4px; }
.logo { width: 32px; height: 31px; }
.logo .lw { stroke: var(--logo-wall); }
.logo .lr { stroke: var(--logo-route); }
.logo .ld { fill: var(--logo-dot); }
.word { font-size: 1.4rem; font-weight: 700; letter-spacing: -0.04em; line-height: 1; }
.word span { color: var(--accent); }
html:not(.has-plan) .new-photo { display: none; }
.new-photo { flex: none; }
/* With a plan open, the start page text goes. Its h1 stays for a screen reader. */
html.has-plan .intro { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
html.has-plan .intro > :not(h1), html.has-plan .demo, html.has-plan .hero, html.has-plan .how, html.has-plan .about { display: none; }
/* While a plan from the address loads, the samples wait under it, so they do not jump down. */
html.has-plan #result[hidden] ~ .gallery-wrap { display: none !important; }
.new-photo input, .shoot input { position: absolute; opacity: 0; width: 1px; height: 1px; }

/* Buttons: round ends. The photo buttons glow in the accent. */
.shoot span, .new-photo span, button {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  min-height: 48px;
  padding: 10px 20px;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: var(--card);
  color: var(--fg);
  font: inherit;
  font-weight: 550;
  cursor: pointer;
}
button:hover { background: var(--raise); }
/* A press shows (ux, 2026-11-03): the control dips while the finger is on it,
   in place of the grey flash of a phone browser. */
html { -webkit-tap-highlight-color: transparent; }
button:not(:disabled):active, .shoot:active span, .new-photo:active span { transform: scale(0.96); border-color: var(--accent); }
#ready:not(:disabled):active, .shoot:active span, .new-photo:active span, .exits button:not(:disabled):active { filter: brightness(1.12); }
button.step:active, button.sample:active { transform: none; }
button.step:active { background: var(--raise); }
button.sample:active img { transform: scale(0.97); }
@media (prefers-reduced-motion: no-preference) {
  button, .shoot span, .new-photo span, button.sample img { transition: transform 0.08s, background-color 0.12s, filter 0.12s; }
}
.shoot span, .new-photo span, #ready { background: var(--accent); border-color: var(--accent); color: var(--accent-fg); font-weight: 650; }
.shoot span { box-shadow: 0 0 32px rgb(61 255 160 / 0.32); }
.new-photo span { min-height: 44px; padding: 8px 16px; font-size: 0.95rem; }
.shoot { display: block; }
.shoot span { display: flex; width: 100%; min-height: 60px; font-size: 1.1rem; }
.shoot input:focus-visible + span, .new-photo input:focus-visible + span, button:focus-visible { outline: 3px solid var(--fg); outline-offset: 3px; }
button:disabled, .shoot input[aria-disabled="true"] + span, .new-photo input[aria-disabled="true"] + span { opacity: 0.55; cursor: progress; }

/* Page layout: one column on a phone. */
.layout { max-width: 1200px; margin: 0 auto; padding: 0 16px 48px; }
.intro h1 { font-size: 2.6rem; font-weight: 600; letter-spacing: -0.045em; line-height: 1.02; margin: 28px 0 16px; }
.intro h1 em { font-style: normal; color: var(--accent); }
.lead { margin: 0 0 24px; color: var(--muted); font-size: 1.1rem; max-width: 32ch; }
/* Under the photo button: three sample plans, for a visitor with no plan at hand. */
.try { margin: 22px 0 0; }
.try p { margin: 0 0 10px; color: var(--muted); font-size: 0.95rem; }
.try-list { list-style: none; display: flex; gap: 12px; margin: 0; padding: 0; }
.try-list li { flex: 0 1 112px; min-width: 0; display: flex; }
.try-list button.sample { width: 100%; }
.try-list button.sample img { border-radius: 10px; }
.try-list button.sample span { padding-top: 6px; font-size: 0.78rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.try-list button.sample:focus-visible { outline: 3px solid var(--fg); outline-offset: 3px; }
.demo-link { margin: 16px 0 0; }
.demo-link a { display: inline-flex; align-items: center; gap: 8px; min-height: 44px; font-weight: 550; }
.demo-link .ico { width: 16px; height: 16px; fill: currentColor; }

/* The hero: one sample plan, dimmed, with the ways out, the route and YOU on it. */
.hero { margin: 28px 0 0; }
.example-open { display: block; position: relative; overflow: hidden; border: 1px solid var(--line); border-radius: 22px; background: #000; color: var(--fg); text-decoration: none; }
.example-open:focus-visible { outline: 3px solid var(--fg); outline-offset: 3px; }
.example-pic { display: block; position: relative; overflow: hidden; aspect-ratio: var(--aspect); }
.example-pic img { position: absolute; display: block; max-width: none; height: auto; }
.example-photo { width: var(--w); left: var(--x); top: var(--y); }
.example-marks { inset: 0; width: 100%; }
.example-bar { display: flex; align-items: center; justify-content: space-between; gap: 12px;
  min-height: 52px; padding: 8px 18px; font-weight: 550; border-top: 1px solid var(--line); background: var(--card); }
.example-go { display: inline-flex; align-items: center; gap: 6px; flex: none; color: var(--accent); }
.example-open:hover .example-go { text-decoration: underline; }
.hero .credit { margin-top: 8px; font-size: 0.8rem; }
/* With the loop (app.py loop_html): a phone plays the page in use with the same
   plan, over a soft glow. The phone opens the plan, like the picture. */
.hero.has-loop { position: relative; isolation: isolate; display: flex; flex-direction: column; align-items: center; }
.hero.has-loop::before { content: ""; position: absolute; z-index: -1; left: 0; right: 0; top: 4%; height: 70%; pointer-events: none;
  background: radial-gradient(closest-side, rgb(61 255 160 / 0.13), rgb(61 255 160 / 0)); }
.has-loop .example-open { display: flex; flex-direction: column; align-items: center; width: 100%; overflow: visible; border: 0; border-radius: 0; background: none; }
.has-loop .example-open:focus-visible { border-radius: 22px; outline-offset: 8px; }
/* The phone is an iPhone 14 Pro frame after devices.css by Yan Zhu (MIT, https://github.com/picturepan2/devices.css),
   in graphite: the dark frame with a light inner rim, the side buttons, a status bar with the camera island.
   All sizes are shares of --pw. Apple's own bezels are licensed only for apps that run on Apple systems only. */
.loop-phone { position: relative; display: block; width: min(280px, 72vw); padding: calc(var(--pw) * 0.044); border-radius: calc(var(--pw) * 0.159);
  background: #010101; border: 1px solid #45484c; box-shadow: inset 0 0 4px 2px #b9bcbf, inset 0 0 0 calc(var(--pw) * 0.014) #3a3d40, 0 28px 70px -24px rgb(61 255 160 / 0.28); }
.phone-screen { position: relative; display: block; overflow: hidden; border-radius: calc(var(--pw) * 0.115); background: var(--bg); }
/* The home bar at the foot of the screen, over the loop. */
.phone-screen::after { content: ""; position: absolute; left: 50%; bottom: calc(var(--pw) * 0.022); width: calc(var(--pw) * 0.34); height: calc(var(--pw) * 0.013);
  margin-left: calc(var(--pw) * -0.17); border-radius: 999px; background: rgb(255 255 255 / 0.85); }
.phone-bar { position: relative; display: flex; align-items: center; justify-content: space-between; height: calc(var(--pw) * 0.11);
  padding: 0 calc(var(--pw) * 0.07) 0 calc(var(--pw) * 0.09); color: var(--fg); font: 600 calc(var(--pw) * 0.04)/1 Geist, system-ui, sans-serif; letter-spacing: -0.01em; }
/* The time is drawn by the style sheet: no text of the page, so a search or a copy does not find it (a11y review). */
.phone-time::before { content: "9:41"; }
.phone-island { position: absolute; left: 50%; top: calc(var(--pw) * 0.024); width: calc(var(--pw) * 0.28); height: calc(var(--pw) * 0.082); margin-left: calc(var(--pw) * -0.14);
  border-radius: 999px; background: #000; }
.phone-icons { width: calc(var(--pw) * 0.165); height: auto; fill: currentColor; }
.phone-btns, .phone-btns::before, .phone-btns::after, .phone-power { position: absolute; width: 3px; border-radius: 2px; background: #45484c; }
.phone-btns { left: -2px; top: 13%; height: 3.7%; }
.phone-btns::before, .phone-btns::after { content: ""; left: 0; height: 190%; }
.phone-btns::before { top: 260%; }
.phone-btns::after { top: 520%; }
.phone-power { right: -2px; top: 23%; height: 11.5%; }
/* The pause and play button sits on the foot of the phone screen. --pw is the phone width. */
.hero.has-loop { --pw: min(280px, 72vw, calc(100vw - 152px)); }  /* room for the button beside the phone (ux review) */
.loop-phone { width: var(--pw) !important; }
/* Beside the phone, at its foot, so it covers nothing in the loop. */
.loop-toggle { position: absolute; top: calc(2.02 * var(--pw) - 64px); left: min(calc(50% + var(--pw) / 2 + 16px), calc(100% - 44px)); width: 44px; height: 44px; min-height: 0; padding: 0;
  border-radius: 50%; background: rgb(7 16 12 / 0.82); border-color: #2f4339; color: var(--fg); }
.loop-toggle:hover { background: var(--raise); }
.loop-toggle[data-playing="true"] .i-play, .loop-toggle[data-playing="false"] .i-pause { display: none; }
.loop-toggle .ico { fill: currentColor; stroke-width: 2.4; }
.loop-toggle .i-pause { fill: none; }
.loop-phone video, .loop-still { display: block; width: 100%; height: auto; aspect-ratio: 1 / 2; background: var(--bg); }
/* Without the script the loop does not play: the poster shows, with no controls of the browser. */
html:not(.js) .loop-phone video, html:not(.js) .loop-toggle { display: none; }
/* The words for a screen reader of what the loop shows (index.html) belong to the loop only. */
.example:not(.has-loop) .loop-says { display: none; }
.has-loop .example-bar { justify-content: center; flex-wrap: wrap; gap: 4px 12px; min-height: 44px; padding: 14px 0 0; border: 0; background: none; text-align: center; }
.has-loop .credit { max-width: 52ch; margin-top: 4px; text-align: center; }

/* From photo to route: the four parts of the work, as the page shows them. */
.how { margin: 28px 0 0; border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); }
.how ol { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(auto-fit, minmax(min(210px, 100%), 1fr)); }
.how li { padding: 24px 20px 26px 0; }
.how li + li { border-top: 1px solid var(--line); }
.how .ico { width: 28px; height: 28px; color: var(--accent); }
.how .i-you { color: var(--fg); }
.how .i-route { color: var(--route); }
.how h3 { margin: 14px 0 6px; font-size: 1.2rem; }
.how p { margin: 0; color: var(--muted); }
/* About HereOut: why, the model, the honest numbers, and who built it (the usual parts of a hackathon entry). */
.about { margin: 56px 0 0; }
.about h2 { margin: 0; font-size: 1.6rem; letter-spacing: -0.02em; }
.about-list { list-style: none; margin: 18px 0 0; padding: 0; display: grid; grid-template-columns: repeat(auto-fit, minmax(min(240px, 100%), 1fr)); gap: 0 28px; border-top: 1px solid var(--line); }
.about-list li { padding: 22px 0 24px; border-bottom: 1px solid var(--line); }
.about .ico { width: 26px; height: 26px; color: var(--accent); }
.about h3 { margin: 12px 0 6px; font-size: 1.15rem; }
.about-list p { margin: 0; color: var(--muted); }
.about-foot { margin: 18px 0 0; color: var(--muted); font-size: 0.9rem; }

.demo { margin: 56px 0 8px; }
.demo h2 { margin-bottom: 16px; }
/* The player: the title frame of the film with one play button on it (app.js
   setUpDemo); a phone width has the 4:5 cut, with the title under the phone. */
.demo-player { position: relative; }
.demo video { display: block; width: 100%; height: auto; aspect-ratio: 16 / 9; border: 1px solid var(--line); border-radius: 22px; background: var(--bg); }
.demo video:focus-visible { outline: 3px solid var(--fg); outline-offset: 3px; }
.demo-play { position: absolute; inset: 0; display: block; width: 100%; height: 100%; min-height: 0; padding: 0; border: 0; border-radius: 22px; background: transparent; }
.demo-play:hover { background: rgb(234 243 238 / 0.03); }
.demo-play:not(:disabled):active { transform: none; }
.demo-play-ico { position: absolute; left: 52.6%; top: 62%; display: flex; align-items: center; justify-content: center; width: clamp(56px, 7.6vw, 84px); aspect-ratio: 1;
  border-radius: 50%; background: var(--accent); box-shadow: 0 0 40px rgb(61 255 160 / 0.45); }
.demo-play-ico svg { width: 42%; height: 42%; margin-left: 8%; fill: var(--accent-fg); }
.demo-play-time { position: absolute; left: calc(52.6% + clamp(56px, 7.6vw, 84px) + 16px); top: 62%; display: flex; align-items: center; height: clamp(56px, 7.6vw, 84px);
  font: 700 1.1rem "Geist Mono", ui-monospace, monospace; color: var(--fg); }
.demo-play:hover .demo-play-ico { filter: brightness(1.12); }
.demo-play:active .demo-play-ico { transform: scale(0.95); }
/* The 4:5 cut is there (app.py demo_page adds "vertical"): its title is under the phone. */
@media (max-width: 599px) {
  .vertical video { aspect-ratio: 4 / 5; }
  .vertical .demo-play-ico { left: 8.3%; top: 84%; width: 52px; }
  .vertical .demo-play-time { left: calc(8.3% + 64px); top: 84%; height: 52px; font-size: 1rem; }
}
.demo-meta { display: flex; flex-wrap: wrap; gap: 4px 20px; margin: 12px 0 0; color: var(--muted); font-size: 0.95rem; }
.transcript { margin-top: 12px; }
.transcript h3 { margin: 20px 0 6px; font-size: 1rem; }
.transcript summary { cursor: pointer; min-height: 24px; }
.transcript ol { padding-left: 1.4em; }
.transcript li { margin: 10px 0; }
.transcript em { display: block; margin-top: 4px; color: var(--muted); font-style: normal; }
#status { min-height: 1.5em; margin: 12px 0; color: var(--muted); }
#status:empty { margin: 8px 0; }
html.has-plan #status { margin: 6px 0; }
#reading { display: block; width: 100%; height: 6px; margin: 0 0 12px; accent-color: var(--accent); }
#reading[hidden] { display: none; }
#ready { margin: 0 0 12px; width: 100%; }
/* With a plan open, the upload bar stays at the foot of the screen. */
.upload-bar.float {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 5;
  padding: 12px 16px calc(12px + env(safe-area-inset-bottom));
  background: var(--card); border-top: 1px solid var(--line);
}
.upload-bar.float > * { max-width: 720px; margin: 0 auto; }
.upload-bar.float #reading { display: none; }  /* the note says it; no motion beside the plan */
.upload-bar.float #ready { display: flex; margin: 0 auto; }
#reading-note { margin: 0 auto; }
body { padding-bottom: var(--bar-room, 0px); }
html { scroll-padding-bottom: var(--bar-room, 0px); }
@media (prefers-reduced-motion: reduce) {
  #reading { display: none; }
}

/* The four parts above the plan: a thin line of text, not controls. The part on the plan now is lit. */
.stages { list-style: none; display: flex; gap: 4px; margin: 0 0 12px; padding: 0; font: 500 0.82rem/1.2 "Geist Mono", ui-monospace, monospace; color: var(--muted); }
.stages li { flex: 1 1 0; display: flex; flex-direction: column; gap: 7px; min-width: 0; }
.stages li::before { content: ""; height: 3px; border-radius: 2px; background: var(--line); }
.stages li.done { color: var(--fg); }
.stages li.done::before { background: rgb(61 255 160 / 0.45); }
.stages li.now { color: var(--accent); }
.stages li.now::before { background: var(--accent); box-shadow: 0 0 10px var(--accent); }
.stages li span { overflow-wrap: anywhere; }

/* The tap prompt on the plan, while the plan waits for the tap (app.js showStages). */
.stage { position: relative; }
.tap-prompt { position: absolute; left: 50%; bottom: 16px; transform: translateX(-50%); display: flex; align-items: center; gap: 10px; max-width: calc(100% - 32px);
  width: max-content; padding: 10px 18px 10px 12px; border-radius: 999px; background: rgb(7 16 12 / 0.9); border: 1px solid var(--accent); color: var(--fg); font-weight: 600; pointer-events: none;
  box-shadow: 0 0 24px rgb(61 255 160 / 0.25); }
.tap-prompt .ico { color: var(--accent); }
.tap-prompt.placed { bottom: auto; transform: none; }
/* A refused tap: the same pill with the reason, for a while (app.js refuseTap). */
.tap-prompt.note { border-color: var(--muted); box-shadow: none; border-radius: 16px; font-weight: 500; }
.tap-prompt.note .ico { display: none; }
@media (prefers-reduced-motion: no-preference) {
  .tap-prompt { animation: prompt-in 0.4s ease-out; }
  /* The step card comes in with the route, as the prompt went (one motion). */
  .now-card { animation: prompt-in 0.25s ease-out; }
  @keyframes prompt-in { from { opacity: 0; translate: 0 8px; } }
}

/* The current step, right under the plan (app.js showNow): the plan and the
   instruction are in view together. It sticks to the foot of the screen
   while its place is below it. Its size does not change from step to step. */
.now-card { position: sticky; bottom: var(--bar-room, 0px); z-index: 2; margin: 10px 0 0; padding: 12px 12px 14px;
  background: var(--card); border: 1px solid var(--line); border-radius: 22px; }
/* A card taller than 40 % of the screen, or a plan with the keyboard focus: the card stays in its place (app.js stickNow). */
.now-card.loose { position: static; }
.now-top { display: flex; align-items: center; gap: 12px; padding-inline-start: 4px; }
.badge.now-badge { min-width: 40px; height: 40px; border-radius: 12px; font-size: 1.2rem; box-shadow: 0 0 16px rgb(61 255 160 / 0.3); }
.now-head { flex: 1; margin: 0; color: var(--muted); font-size: 0.95rem; font-weight: 550; min-width: 0; }
.now-round { flex: none; width: 48px; min-height: 48px; padding: 0; }
.now-step { display: flex; align-items: center; gap: 8px; margin-top: 8px; }
.now-text { flex: 1; display: flex; align-items: center; gap: 12px; margin: 0; min-width: 0; min-height: 4.2em;
  font-size: 1.08rem; font-weight: 600; line-height: 1.35; overflow-wrap: break-word; border-radius: 10px; }
.now-text:focus { outline: none; }
.now-text:focus-visible { outline: 3px solid var(--fg); outline-offset: 3px; }
/* The last walk: the exit door in the place of "Next". */
.now-end { flex: none; display: inline-flex; align-items: center; justify-content: center; width: 56px; min-height: 64px; }
.now-end .turn { width: 32px; height: 32px; color: var(--exit); }
.now-go { flex: none; width: 56px; min-height: 64px; padding: 0; border-radius: 18px; background: var(--raise); }
.now-go .ico { width: 26px; height: 26px; }
.now-go.gone { visibility: hidden; }
[dir="rtl"] .flip { transform: scaleX(-1); }
/* A turn: one outline glyph for each kind of step, in the step list and in the card. */
.turn { width: 28px; height: 28px; flex: none; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.now-text .turn { width: 36px; height: 36px; color: var(--route); }
.now-text .turn.door { color: var(--exit); }
@media (max-width: 600px) {
  /* On a phone the card is the foot of the plan, from edge to edge. */
  .now-card { margin: 0 -16px; border-radius: 0; border-left: 0; border-right: 0; padding: 10px 12px 12px; }
}
/* Very narrow (a phone at 200 % zoom): the words of the step get their own row, the buttons go under them. */
@media (max-width: 299px) {
  .now-step { flex-wrap: wrap; justify-content: space-between; }
  .now-text { order: -1; flex: 1 0 100%; min-height: 0; }
  .now-text .turn { width: 28px; height: 28px; }
  .now-top { gap: 8px; padding-inline-start: 0; }
  .badge.now-badge { min-width: 32px; height: 32px; font-size: 1rem; }
}
/* A phone at 200 % zoom (195 px): the header, the view buttons and the keys wrap; nothing scrolls sideways. */
@media (max-width: 299px) {
  .top-in { flex-wrap: wrap; padding-top: 6px; padding-bottom: 6px; }
  .view .seg { flex: 1 1 100%; flex-wrap: wrap; border-radius: 22px; }
  .seg button { flex: 1 1 auto; }
  .look .look-key { white-space: normal; }
  .look-sheets .look-sheet { grid-template-columns: minmax(0, 1fr); }
}
/* On a wide screen the step list is beside the plan: the card would show the lit step twice (ux review). */
@media (min-width: 960px) { .now-card { display: none !important; } }

/* The plan and its controls */
/* The larger-plan key stays on the row of the view buttons: a longer label (Arabic at 390 px) takes two lines
   (judge review). The buttons go to their own row only when their longest words do not fit (larger text, ux review). */
.view { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 10px; }
.seg { display: flex; flex: 1 1 0; min-width: min-content; gap: 2px; padding: 4px; border-radius: 999px; background: var(--card); border: 1px solid var(--line); }
/* On a narrow screen a label can take two lines; it never runs under the next button. */
.seg button { flex: 1 1 auto; min-height: 40px; padding: 4px 8px; border: 0; border-radius: 999px; background: transparent; font-size: 0.85rem; line-height: 1.15; color: var(--muted); font-weight: 500; }
/* On a narrow phone, or with a larger text setting (em), the buttons share the width: a label takes two
   lines, and a button goes to a second row only when its longest word does not fit (Russian at 320 px,
   a11y review). At 390 px with normal text, "Escape map" keeps one line. */
@media (max-width: 24em) { .seg { flex-wrap: wrap; border-radius: 22px; } .seg button { flex-basis: 0; min-width: min-content; } }
.seg button[aria-pressed="true"] { background: var(--fg); color: var(--bg); font-weight: 600; }
.seg button:disabled { cursor: not-allowed; }
.enlarge { flex: none; min-width: 52px; min-height: 50px; padding: 8px 14px; }
.enlarge[aria-pressed="true"] { border-color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent); }
.enlarge-text { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
.stage { border: 1px solid var(--line); border-radius: 22px; overflow: hidden; background: #000; }
@media (max-width: 600px) {
  /* On a phone the plan uses the full width of the screen. */
  .stage { margin: 0 -16px; border-radius: 0; border-left: 0; border-right: 0; }
}
.stage.big { max-height: 80vh; overflow: auto; }
.stage.big canvas { width: var(--zoom, 220%); max-width: none; }
canvas { display: block; width: 100%; height: auto; touch-action: manipulation; cursor: crosshair; }
/* The whole plan fits on the screen; on a phone the answer heading peeks under it. */
.stage:not(.big) canvas { width: auto; max-width: 100%; max-height: calc(100svh - 230px); margin: 0 auto; }
@media (max-width: 959px) { .stage:not(.big) canvas { max-height: 66svh; } }
/* The ring goes around the plan, not over the photo. */
canvas:focus-visible { outline: none; }
.stage:has(> canvas:focus-visible) { outline: 3px solid var(--fg); outline-offset: 3px; }
.stage:focus-visible { outline: 3px solid var(--fg); outline-offset: 3px; }
.legend { display: flex; flex-wrap: wrap; gap: 6px 18px; margin: 12px 0 0; font-size: 0.85rem; color: var(--muted); }
.legend span { display: inline-flex; align-items: center; gap: 8px; }
/* Swatches sit on the dimmed plan, as the marks do. */
.legend i, .backup i { display: inline-block; flex: none; width: 30px; height: 12px; border-radius: 3px; background-color: #0b1510; box-shadow: 0 0 0 2px #0b1510; }
.sw-field { background-image: linear-gradient(90deg, rgb(61 255 160 / 0.5), rgb(61 255 160 / 0)); }
.sw-way { height: 12px !important; background: #0b1510 url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='34' height='12'%3E%3Crect x='0' y='4.5' width='34' height='3' fill='%233dffa0'/%3E%3Cpath d='M24 6 L15 1 L15 11 Z' fill='%233dffa0' stroke='%230b1510' stroke-width='1'/%3E%3C/svg%3E") no-repeat !important; }
.sw-wall { height: 3px !important; background-image: linear-gradient(#7d9188, #7d9188); }
.sw-exit { width: 14px !important; height: 14px !important; background-image: linear-gradient(#3dffa0, #3dffa0); }
.sw-route { height: 6px !important; background-image: linear-gradient(#5aa2ff, #5aa2ff); }
.sw-you { width: 10px !important; height: 10px !important; margin: 0 2px; border-radius: 50% !important; background-color: #2f7dff !important; box-shadow: 0 0 0 2.5px #ffffff !important; }
.hint { margin: 10px 0 0; font-size: 0.95rem; }
/* A tap off the floor drawing: the message stands where the eyes are. */
.hint.refused #tap-text { font-weight: 700; color: var(--fg); }
#kbd-hint { color: var(--muted); }
#kbd-hint::before { content: " "; }

/* The answer: the exit, the steps and what to do next. */
.answer-col { display: flex; flex-direction: column; gap: 14px; margin-top: 16px; }
/* On a phone the answer comes first, so the steps stay near the plan; the language row is under it. */
.answer-col > .answer { order: -1; }
.card { background: var(--card); border: 1px solid var(--line); border-radius: 22px; padding: 20px; }
.card > :first-child { margin-top: 0; }
.answer-head { display: flex; align-items: center; gap: 14px; margin-bottom: 12px; }
.answer-head p { margin: 0; display: flex; flex-direction: column; gap: 2px; }
.badge { display: inline-flex; align-items: center; justify-content: center; flex: none; min-width: 52px; height: 52px; padding: 0 8px; border-radius: 14px;
  background: var(--exit); color: var(--accent-fg); font: 700 1.6rem "Geist Mono", ui-monospace, monospace; box-shadow: 0 0 24px rgb(61 255 160 / 0.35); }
.kicker { font-size: 0.9rem; color: var(--muted); }
#answer-name { font-size: 1.35rem; line-height: 1.2; font-weight: 600; letter-spacing: -0.025em; }
.plan-status { margin: 0; font-weight: 550; font-size: 1.05rem; min-height: 1.5em; }
.backup { margin: 12px 0 0; display: grid; grid-template-columns: auto 1fr; align-items: center; gap: 8px 10px; color: var(--muted); }
.backup button { grid-column: 1 / -1; justify-self: start; min-height: 44px; padding: 6px 16px; }
#steps-head { margin-top: 18px; }
#steps-hint { margin: 0 0 8px; font-size: 0.9rem; }
#steps { list-style: none; counter-reset: step; padding: 0; margin: 0; display: flex; flex-direction: column; }
#steps li { counter-increment: step; display: flex; align-items: center; gap: 12px; margin: 0; min-height: 48px; border-top: 1px solid var(--line); }
#steps li::before { content: counter(step); display: inline-flex; align-items: center; justify-content: center; flex: none; width: 28px; height: 28px; border-radius: 50%;
  border: 1.5px solid var(--route); color: var(--route); font: 600 0.8rem "Geist Mono", ui-monospace, monospace; }
button.step { display: flex; justify-content: flex-start; gap: 12px; flex: 1; width: 100%; text-align: start; font-weight: 450; padding: 10px 4px; min-height: 48px; border: 0; border-radius: 10px; background: transparent; color: #d5e2db; }
#steps .turn { width: 24px; height: 24px; color: var(--muted); }
#steps button.step[aria-pressed="true"] .turn { color: var(--route); }
#steps .turn.door { color: var(--exit); }
/* "Then you reach the exit." ends the last walk: no number of its own (app.js walkCount). */
#steps li.arrive { counter-increment: none; gap: 16px; padding: 10px 4px 10px 0; color: var(--muted); }
#steps li.arrive::before { content: ""; border-color: transparent; }
button.step:hover { background: var(--raise); }
button.step[aria-pressed="true"] { color: #ffffff; font-weight: 600; background: rgb(90 162 255 / 0.12); padding-inline-start: 12px; }
#steps li:has(button.step[aria-pressed="true"])::before { border-color: var(--route); background: var(--route); color: var(--accent-fg); }
.check { margin: 0 0 10px; font-size: 0.9rem; }
.actions { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 16px; }
.actions button { flex: 1 1 auto; }
#fix-hint { margin: 10px 0 0; }
#exits-wrap h3 { margin: 0 0 12px; }
.exits { display: flex; flex-wrap: wrap; gap: 8px; }
/* One square for each exit, like its mark on the plan. The name is in the label. */
.exits button { min-width: 46px; min-height: 46px; padding: 0 4px; border-radius: 12px; border: 0; background: var(--exit); color: var(--accent-fg); font: 700 1.1rem "Geist Mono", ui-monospace, monospace; }
.exits button:hover { background: #8dffc7; }
.exits button[aria-pressed="true"] { box-shadow: 0 0 0 3px var(--card), 0 0 0 6px var(--route); }
.exits button:focus-visible { outline-offset: 8px; }
/* The nearest exit and the exit of the second way say so beside their number. */
.exits button.tagged { gap: 10px; padding: 0 16px 0 14px; }
.exits .tag { font: 600 0.9rem/1.2 "Geist", system-ui, sans-serif; letter-spacing: 0; }
.exits button.dead { background: transparent; color: var(--muted); border: 1.5px dashed #6f8279; }
#exits-note { margin: 10px 0 0; font-size: 0.9rem; }
.muted { color: var(--muted); margin: 0 0 12px; }
.credit { color: var(--muted); font-size: 0.85rem; margin: 0; }
#back-to-samples { align-self: flex-start; }

/* Samples */
.gallery-wrap { margin: 56px 0 8px; }
.gallery-wrap h2 { display: flex; align-items: center; gap: 12px; }
.gallery-wrap h2 .ico { width: 26px; height: 26px; color: var(--accent); }
.gallery { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 16px; margin: 20px 0 16px; padding: 0; list-style: none; }
.gallery li { display: flex; }
.gallery li > button { width: 100%; }
button.sample { padding: 0; min-height: 0; overflow: visible; display: flex; flex-direction: column; align-items: stretch; text-align: left; border: 0; border-radius: 14px; background: transparent; }
button.sample:hover { background: transparent; }
button.sample img { display: block; width: 100%; aspect-ratio: 4 / 3; object-fit: cover; background: var(--soft); border-radius: 14px; filter: brightness(0.85); }
button.sample:hover img { filter: none; }
button.sample span { padding: 10px 2px 0; font: 500 0.85rem "Geist Mono", ui-monospace, monospace; color: var(--muted); }
button.sample[aria-current="true"] img { box-shadow: 0 0 0 3px var(--accent); filter: none; }
button.sample[aria-current="true"] span { color: var(--accent); }
/* The link to the photo credits (/credits), beside the heading of the samples. */
.gallery-top { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; column-gap: 16px; }
.gallery-top h2 { margin-bottom: 0; }
.gallery-credits { margin: 0; }
.gallery-credits a { display: inline-flex; align-items: center; gap: 7px; min-height: 44px; font-weight: 550; font-size: 0.95rem; }
.gallery-credits .ico { width: 18px; height: 18px; }

/* The page of photo credits (credits.html). */
.doc { max-width: 860px; margin: 0 auto; padding: 0 16px 56px; }
.doc h1 { display: flex; align-items: center; gap: 12px; margin: 32px 0 12px; font-size: 2.2rem; letter-spacing: -0.04em; }
.doc h1 .ico { width: 30px; height: 30px; color: var(--accent); }
.credit-list { list-style: none; margin: 24px 0 0; padding: 0; color: var(--muted); font-size: 0.9rem; }
.credit-list li { padding: 12px 0; border-top: 1px solid var(--line); scroll-margin-top: 80px; }
.credit-list li:target { color: var(--fg); }
.credit-list li > a:first-child { margin-right: 6px; font: 500 0.85rem "Geist Mono", ui-monospace, monospace; }
ol:focus-visible, h2:focus-visible { outline: 2px solid var(--muted); outline-offset: 4px; }
/* The plan opens right under the header, so a scroll to it keeps the header in view. */
.result { scroll-margin-top: 140px; }
/* Only after a key: a plan opened from a link or a tap shows no frame (ux review, 2026-11-02). */
.kbd #result-head:focus + .plan-col { outline: 2px solid var(--muted); outline-offset: 4px; border-radius: 4px; }
ol:focus:not(:focus-visible), h2:focus:not(:focus-visible) { outline: none; }

@media (min-width: 600px) {
  .enlarge-text { position: static; width: auto; height: auto; overflow: visible; clip-path: none; }
  .seg { flex: 0 1 auto; }
  .seg button { padding: 6px 16px; font-size: 0.95rem; }
  .view { justify-content: space-between; }
  .how li + li { border-top: 0; border-left: 1px solid var(--line); padding-left: 20px; }
}

/* Wide screens: the start page text beside the hero plan, and an open plan beside its answer. */
@media (min-width: 960px) {
  .top-in, .layout { padding-left: 48px; padding-right: 48px; }
  .top-in { min-height: 72px; }
  .layout { display: grid; grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr); column-gap: 64px; align-items: center;
            grid-template-areas: "intro hero" "status status" "how how" "gallery gallery" "demo demo" "about about" "result result"; }
  .about { grid-area: about; }
  .intro { grid-area: intro; }
  .hero { grid-area: hero; margin-top: 24px; }
  /* The phone fits the screen height beside the start text. */
  .hero.has-loop { --pw: clamp(230px, calc((100svh - 300px) / 2), 300px); }
  .status-wrap { grid-area: status; }
  .how { grid-area: how; margin-top: 40px; }
  .result { grid-area: result; }
  .gallery-wrap { grid-area: gallery; }
  .demo { grid-area: demo; }
  .intro h1 { font-size: 4.2rem; margin-top: 24px; }
  .lead { font-size: 1.25rem; }
  .shoot span { display: inline-flex; width: auto; padding: 0 32px; }
  html.has-plan .layout { align-items: start; grid-template-areas: "status status" "result result" "gallery gallery"; }
  .result { display: grid; grid-template-columns: minmax(0, 1fr) 390px; column-gap: 28px; align-items: start; }
  .answer-col { margin-top: 0; }
  .answer-col > .answer { order: 0; }
  html:not(.has-plan) .gallery { grid-template-columns: repeat(6, minmax(0, 1fr)); }
}

/* What Muse Spark read (reading.js): a card under the answer, and a view of the plan. */
.read h3 { margin: 0 0 8px; }
#read-sum { margin: 0 0 10px; }
.read-exits { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; font-size: 0.95rem; }
.read-exits li { display: flex; align-items: flex-start; gap: 10px; }
.read-exits .rk { display: inline-flex; align-items: center; justify-content: center; flex: none; width: 26px; height: 26px; border-radius: 50%;
  border: 2.5px solid #6a1b9a; background: #ffffff; color: #6a1b9a; font-size: 0.8rem; font-weight: 800; }
.read-exits .rk.out { border-color: #5f6368; color: #5f6368; }
.read-exits .rl { font-weight: 700; overflow-wrap: anywhere; }
.read-exits .rf { color: var(--muted); }
#show-read { width: 100%; margin: 0 0 12px; }
#show-read[aria-pressed="true"] { border-color: var(--reading); box-shadow: inset 0 0 0 1.5px var(--reading); }
#read-zoom { margin: 12px 0 8px; font-size: 0.9rem; }
.read > p:last-child { margin: 0; font-size: 0.9rem; }
/* The second look: the sheets of numbered crops, and what came back for each. */
.look h4 { margin: 16px 0 4px; font-size: 1rem; }
.look > p { margin: 0 0 10px; font-size: 0.9rem; }
.look-sheets { list-style: none; margin: 0 0 12px; padding: 0; display: flex; flex-direction: column; gap: 14px; }
.look-sheet { display: grid; grid-template-columns: 128px minmax(0, 1fr); gap: 12px; align-items: start; }
.look-open { display: block; width: 128px; min-width: 44px; min-height: 44px; padding: 0; overflow: hidden; border-radius: 10px; background: #ffffff; }
.look-open img { display: block; width: 100%; height: auto; }
.look-pic { position: relative; display: block; }
.look-pt { position: absolute; width: 12px; height: 12px; border: 2.5px solid #0a7d3b; border-radius: 50%; transform: translate(-50%, -50%);
  box-shadow: 0 0 0 1.5px #ffffff, inset 0 0 0 1px #ffffff; pointer-events: none; }
.look-pt.unused { border-style: dashed; border-color: #b3261e; }
.look-view .look-pt { width: 30px; height: 30px; border-width: 3.5px; }
.look-key { display: inline-flex; align-items: center; gap: 6px; margin-right: 12px; white-space: nowrap; }
.look-key .look-pt { position: static; transform: none; flex: none; }
.look-open:hover { border-color: var(--reading); background: #ffffff; }
.look-crops { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; font-size: 0.9rem; }
.look-crops li { display: flex; align-items: flex-start; gap: 8px; overflow-wrap: anywhere; }
.look-crops .lk { flex: none; display: inline-flex; align-items: center; justify-content: center; min-width: 24px; height: 24px; padding: 0 4px;
  background: #ffffff; color: #000000; font-size: 0.8rem; font-weight: 800; }
.look-view { width: min(96vw, 760px); max-width: none; max-height: 94vh; padding: 0; border: 1px solid var(--line); border-radius: 22px;
  background: var(--card); color: var(--fg); }
.look-view::backdrop { background: rgb(0 0 0 / 0.7); }
.look-view-bar { position: sticky; top: 0; z-index: 1; display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 8px 8px 8px 16px; background: var(--card); border-bottom: 1px solid var(--line); }
.look-view-bar h3 { margin: 0; font-size: 1rem; }
.look-view-pic { padding: 12px 12px 0; }
.look-view-pic .look-pic { width: fit-content; max-width: 100%; margin: 0 auto; }
#look-view-img { display: block; max-width: 100%; max-height: 66vh; width: auto; height: auto; background: #ffffff; }
.look-view .look-crops { padding: 12px 16px 16px; }
.read-legend { display: none; }
.result.reading .read-legend { display: flex; }
.result.reading #legend, .result.reading .now-card { display: none; }
.read-legend i { background-color: #ffffff; box-shadow: 0 0 0 2px #ffffff; }
.sw-rbox { height: 12px !important; background: #ffffff !important; outline: 2px dashed #6a1b9a; outline-offset: -2px; }
.sw-rpt { width: 14px !important; height: 14px !important; border-radius: 50% !important; border: 3px solid #6a1b9a; }
.sw-rzoom { height: 4px !important; background-image: linear-gradient(#6a1b9a, #6a1b9a); }
.sw-rcode { height: 3px !important; background-image: repeating-linear-gradient(90deg, #111111 0 6px, transparent 6px 10px); }
.sw-rdrop { width: 14px !important; height: 14px !important; border-radius: 50% !important; border: 3px solid #5f6368; }

/* The language of the plan card (i18n.js). */
.lang-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.lang-row label { display: inline-flex; align-items: center; gap: 6px; color: var(--muted); font-size: 0.9rem; }
.lang-row label, .lang-row select { cursor: pointer; }
.lang-row select { min-height: 44px; min-width: 10em; padding: 6px 14px; border: 1px solid var(--line); border-radius: 999px; background: var(--card); color: var(--fg); font: inherit; }
.lang-row select:focus-visible { outline: 3px solid var(--fg); outline-offset: 2px; }

/* What the plan says: the words that Muse Spark read on the plan, each with its original. */
.words h3 { margin: 0 0 6px; }
.words h4 { font-size: 0.95rem; margin: 16px 0 6px; color: var(--muted); font-weight: 550; }
#words-lang { margin: 0 0 8px; }
.w-title { margin: 0 0 4px; font-weight: 650; font-size: 1.05rem; }
.w-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; }
.w-list li { padding: 8px 0; border-top: 1px solid var(--line); }
.w-text { display: block; overflow-wrap: anywhere; }
.w-orig { display: block; margin-top: 2px; font-size: 0.85rem; color: var(--muted); overflow-wrap: anywhere; }
.w-title .w-orig { font-weight: 400; }
#words-note { margin: 14px 0 0; font-size: 0.85rem; }

/* More samples: a faded row and one round chevron (house rule: more is a peek). */
.gallery li.peek { max-height: 96px; overflow: hidden; opacity: 0.4; -webkit-mask-image: linear-gradient(#000, transparent); mask-image: linear-gradient(#000, transparent); }
#gallery-more { display: flex; width: 52px; height: 52px; min-height: 0; padding: 0; margin: -28px auto 8px; position: relative; }
#gallery-more[hidden] { display: none; }
#gallery-more .ico { width: 24px; height: 24px; }
@media (max-width: 480px) {
  .stages { font-size: 0.74rem; }
}

/* Korean breaks lines between words, not inside them (judge 6). */
:lang(ko) { word-break: keep-all; overflow-wrap: anywhere; }
