/* Chinatown Trails — grayscale interaction prototype. Wireframe only: no brand colour, typeface or illustration.
   Layout system (see DESIGN_NOTES.md "Type, size and spacing"):
   - Type scale: display 28 · title 22 · headline 18 · body 16 · callout 15 · label 14 · caption 13. Nothing on the phone is smaller than 13px.
   - Weights (Gill Sans): 300 Light for display titles and big numbers, 400 Regular for reading text and labels, 600 SemiBold for headings, buttons and emphasis. Bold/UltraBold are not used.
   - Touch: every tappable thing is at least 44×44px (Apple 44pt; WCAG 2.5.8 floor 24px). Main actions are 52px and sit at the bottom.
   - Spacing: 4px grid (4 · 8 · 12 · 16 · 24); screen side padding 16px.
   - Contrast: text colours are ≥4.5:1 on white; control borders ≥3:1 (WCAG 1.4.3 / 1.4.11).
   - Compact mode: when a screen is shorter than 600px (small phones, Chrome bars) the same layout tightens via a container query. */
:root {
  --ink: #1d1d1d;      /* 16.6:1 — headings, main text, primary fill */
  --ink-2: #474747;    /* 9.4:1 — reading text in stories, secondary text */
  --ink-3: #6b6b6b;    /* 5.3:1 — captions, meta, sources */
  --line-strong: #8c8c8c; /* 3.4:1 — borders of things you can tap */
  --line: #d4d4d4; --line-2: #e6e6e6; --fill: #f2f2f2; --paper: #fff; --page: #e9e9e9;
  --fs-display: 28px; --fs-title: 22px; --fs-headline: 18px; --fs-body: 16px; --fs-callout: 15px; --fs-label: 14px; --fs-caption: 13px;
  --tap: 44px; --tap-main: 52px;
  --s1: 4px; --s2: 8px; --s3: 12px; --s4: 16px; --s5: 24px;
  --r-s: 8px; --r: 12px; --r-l: 16px;
  --hud: 50px; /* boss 2026-11-02: top bar height (was 56, 48, then 42 — too tight) */
  /* Latin: Gill Sans (built into macOS / iOS; Gill Sans MT on Windows); CJK falls back to the system Chinese / Japanese / Korean fonts. */
  font-family: "Gill Sans", "Gill Sans MT", "Gill Sans Nova", "Lato", "Helvetica Neue", Arial, "PingFang TC", "Noto Sans TC", sans-serif;
  color: var(--ink);
}
* { box-sizing: border-box; }
body { margin: 0; background: var(--page); }
button, input { font: inherit; color: inherit; }
h1, h2, h3, p { margin: 0; }
:root:lang(zh-Hans) { font-family: "Gill Sans", "Gill Sans MT", "Gill Sans Nova", "Lato", "Helvetica Neue", Arial, "PingFang SC", "Noto Sans SC", sans-serif; }
:root:lang(ja) { font-family: "Gill Sans", "Gill Sans MT", "Gill Sans Nova", "Lato", "Helvetica Neue", Arial, "Hiragino Sans", "Noto Sans JP", sans-serif; }
:root:lang(ko) { font-family: "Gill Sans", "Gill Sans MT", "Gill Sans Nova", "Lato", "Helvetica Neue", Arial, "Apple SD Gothic Neo", "Noto Sans KR", sans-serif; }
:root:lang(ko) .pr-phone { word-break: keep-all; }

/* ── Desktop shell: screen index | phone | interaction notes (designer view, not part of the product) ── */
.pr-shell { display: grid; grid-template-columns: 230px auto 320px; justify-content: center; align-items: start; gap: 28px; min-height: 100svh; padding: 28px 20px; }
.pr-index, .pr-notes-panel { position: sticky; top: 28px; max-height: calc(100svh - 56px); overflow-y: auto; padding: 16px; border: 1px solid var(--line); border-radius: var(--r); background: var(--paper); }
.pr-index-title { font-weight: 600; font-size: 15px; }
.pr-index-sub { margin-top: 2px; color: var(--ink-3); font-size: 12px; }
.pr-index-list { margin: 14px 0; padding: 0; list-style: none; display: grid; gap: 2px; }
.pr-index-list button { appearance: none; width: 100%; padding: 7px 8px; border: 0; border-radius: 6px; background: transparent; text-align: left; font-size: 13px; cursor: pointer; }
.pr-index-list button:hover { background: var(--fill); }
.pr-index-list button[aria-current="true"] { background: var(--ink); color: #fff; }
.pr-reset { appearance: none; width: 100%; min-height: 36px; border: 1px dashed var(--line-strong); border-radius: 8px; background: transparent; color: var(--ink-2); font-size: 12px; cursor: pointer; }
.pr-demo { display: grid; grid-template-columns: repeat(5, 1fr); gap: 4px; margin-bottom: 10px; }
.pr-demo .pr-index-sub { grid-column: 1 / -1; margin-bottom: 2px; }
.pr-demo .pr-reset { min-height: 30px; padding: 0; }
.pr-demo .pr-rescan, .pr-demo .pr-demo-span { grid-column: 1 / -1; margin-top: 4px; }
.pr-demo .pr-demo-half { grid-column: span 2; }
.pr-demo .pr-reset[aria-pressed="true"] { border-style: solid; border-color: var(--ink); color: var(--ink); font-weight: 600; }
.pr-notes-title { color: var(--ink-3); font-size: 11px; font-weight: 600; letter-spacing: .14em; }
.pr-notes-screen { margin: 4px 0 12px; font-size: 18px; }
.pr-notes-body h4 { margin: 14px 0 6px; font-size: 12px; color: var(--ink-3); letter-spacing: .08em; }
.pr-notes-body p, .pr-notes-body li { font-size: 13px; line-height: 1.6; color: var(--ink-2); }
.pr-notes-body ol, .pr-notes-body ul { margin: 0; padding-left: 18px; display: grid; gap: 4px; }
.pr-notes-body .q { padding: 8px 10px; border-left: 3px solid var(--ink); background: var(--fill); }

/* ── Device: real phone photo frame + mock Safari / Chrome bars (shared with cards.html) ── */
.pr-stage { display: grid; place-items: start center; gap: 14px; }
.device { position: relative; width: 430px; height: 876px; --chrome-top: 50px; --chrome-bottom: 124px; }
.device[data-browser="chrome"] { --chrome-top: 110px; --chrome-bottom: 88px; }
.device[data-browser="none"] { --chrome-top: 50px; --chrome-bottom: 26px; }
.device-frame { position: absolute; inset: 0; z-index: 4; width: 430px; height: 876px; mix-blend-mode: multiply; pointer-events: none; }
.browser-switch { display: inline-flex; padding: 3px; border: 1px solid #d3d1c7; border-radius: 999px; background: #f4f2ec; }
.browser-switch button { appearance: none; min-height: 36px; padding: 6px 14px; border: 0; border-radius: 999px; background: transparent; color: #5d665e; font-size: 13px; font-weight: 650; cursor: pointer; }
.browser-switch button[aria-pressed="true"] { background: #fff; color: var(--ink); box-shadow: 0 1px 3px rgba(0,0,0,.12); }
/* Status bar like a current iPhone Pro Max (the frame is 430pt wide, 1:1): time and icons sit level with the Dynamic Island
   (island 157–273 × 36–70 in the frame; the screen starts 23px from the frame's left and 22px from its top),
   time centred in the space left of the island, icons in the space right of it; time 17pt semibold. */
.prototype-status { position: absolute; z-index: 8; top: 0; left: 0; right: 0; height: 61px; display: grid; grid-template-columns: 134px 1fr 134px; align-items: center; justify-items: center; color: #000; font: 600 17px/1 -apple-system, BlinkMacSystemFont, "SF Pro Text", sans-serif; letter-spacing: -.02em; pointer-events: none; }
.prototype-status img { grid-column: 3; width: 78px; height: auto; }
.mock-chrome { position: absolute; left: 0; right: 0; z-index: 7; color: #1d1d1f; font: 500 14px/1 -apple-system, BlinkMacSystemFont, sans-serif; }
.mock-top { top: 56px; height: 54px; display: none; align-items: center; padding: 0 14px; background: #f1f3f4; border-bottom: 1px solid #dadce0; }
.device[data-browser="chrome"] .mock-top { display: flex; }
.mock-bottom { bottom: 0; height: var(--chrome-bottom); display: flex; flex-direction: column; justify-content: flex-start; gap: 4px; padding: 8px 14px 0; background: rgba(246, 246, 246, .96); border-top: 1px solid #d5d5d8; backdrop-filter: blur(14px); }
.device[data-browser="chrome"] .mock-bottom { background: #f1f3f4; border-top-color: #dadce0; padding-top: 4px; }
.device[data-browser="none"] .mock-bottom { background: transparent; border: 0; }
.device[data-browser="none"] .mock-tools, .device[data-browser="none"] .mock-url { display: none; }
.mock-url { display: flex; align-items: center; gap: 8px; height: 40px; padding: 0 14px; border-radius: 12px; background: #e3e3e6; }
.mock-top .mock-url { flex: 1; border-radius: 999px; background: #fff; box-shadow: inset 0 0 0 1px #dadce0; }
.mock-host { flex: 1; text-align: center; font-size: 14px; }
.mock-top .mock-host { text-align: left; }
.mock-aa { font-size: 13px; font-weight: 600; }
.mock-lock { font-size: 10px; opacity: .55; }
.mock-dots, .mock-reload { font-size: 16px; color: #3c3c43; }
.mock-tools { display: flex; align-items: center; justify-content: space-between; height: 44px; padding: 0 8px; }
.mock-tools svg { width: 24px; height: 24px; fill: none; stroke: #0a7aff; stroke-width: 1.9; stroke-linecap: round; stroke-linejoin: round; }
.device[data-browser="chrome"] .mock-tools svg { stroke: #3c4043; }
.device[data-browser="chrome"] .mock-tools circle { fill: #3c4043; stroke: none; }
.mock-tools svg.dim { opacity: .35; }
.device[data-browser="chrome"] .safari-only, .device:not([data-browser="chrome"]) .chrome-only { display: none; }
.mock-home { position: absolute; left: 50%; bottom: 9px; width: 134px; height: 5px; margin-left: -67px; border-radius: 3px; background: #111; }

/* ── Phone canvas and screens ── */
.pr-phone { position: absolute; left: 23px; top: 22px; z-index: 1; width: 384px; height: 835px; overflow: hidden; border-radius: 43px; background: var(--paper); }
.pr-screen { position: absolute; inset: var(--chrome-top) 0 var(--chrome-bottom); container-type: size; display: flex; flex-direction: column; gap: var(--s3); padding: var(--s4) var(--s4) var(--s4); overflow: hidden; animation: pr-in .3s ease-out; }
.pr-screen[hidden] { display: none; }
.pr-phone.has-hud .pr-screen { top: calc(var(--chrome-top) + var(--hud)); padding-top: var(--s3); }
@keyframes pr-in { from { opacity: 0; transform: translateX(18px); } to { opacity: 1; transform: none; } }

/* Type roles */
.pr-screen h1 { font-size: var(--fs-title); line-height: 1.3; font-weight: 600; }
.pr-screen h2 { font-size: var(--fs-headline); line-height: 1.4; font-weight: 600; }
.pr-kicker { color: var(--ink-3); font-size: var(--fs-caption); font-weight: 400; letter-spacing: .06em; }
.pr-note { color: var(--ink-3); font-size: var(--fs-caption); line-height: 1.5; }

/* Placeholders: grey box with a cross and a label (to be replaced by real art) */
.ph { display: grid; place-items: center; min-height: 44px; padding: 8px; border: 1px dashed #a8a8a8; border-radius: var(--r); color: var(--ink-3); font-size: var(--fs-caption); line-height: 1.4; text-align: center;
  background: linear-gradient(to top right, transparent calc(50% - .5px), #d8d8d8 50%, transparent calc(50% + .5px)), linear-gradient(to bottom right, transparent calc(50% - .5px), #d8d8d8 50%, transparent calc(50% + .5px)), var(--fill); }
.ph-emblem, .ph-stamp { width: 140px; height: 140px; border-radius: 50%; margin: 0 auto; }
.ph-wide { width: 100%; height: 140px; }
.ph-photo { width: 100%; aspect-ratio: 16 / 9; flex: none; }
.ph-object { flex: 1; min-height: 72px; }
.ph-avatar { width: 40px; height: 40px; min-height: 0; padding: 0; border-radius: 50%; font-size: 11px; }
.ph-guide { flex: none; width: 52px; height: 52px; min-height: 0; padding: 0; border-radius: 50%; font-size: 12px; }
.ph-plaque { height: 140px; }

/* ── Buttons and links ── */
.pr-btn { appearance: none; flex: none; display: flex; align-items: center; justify-content: center; gap: 6px; width: 100%; min-height: var(--tap-main); padding: 0 var(--s4); border-radius: var(--r); font-size: var(--fs-body); font-weight: 600; line-height: 1.25; text-align: center; cursor: pointer; }
.pr-btn-primary { border: 0; background: var(--ink); color: #fff; }
.pr-btn-dark { border: 2px solid var(--ink); background: var(--paper); color: var(--ink); }
.pr-btn:disabled { opacity: .4; cursor: default; }
.pr-btn[hidden], .pr-next[hidden] { display: none; }
.pr-link { appearance: none; flex: none; align-self: center; min-height: var(--tap); padding: 0 var(--s3); border: 0; background: transparent; color: var(--ink-2); font-size: var(--fs-callout); font-weight: 400; text-decoration: underline; text-underline-offset: 3px; cursor: pointer; }
.pr-link[hidden] { display: none; }
.pr-inline { display: inline-flex; align-items: center; min-height: var(--tap); margin-left: var(--s1); padding: 0 var(--s1); font-size: var(--fs-caption); vertical-align: middle; }
.pr-back { appearance: none; flex: none; align-self: flex-start; display: inline-flex; align-items: center; min-width: var(--tap); min-height: var(--tap); margin-left: calc(var(--s2) * -1); padding: 0 var(--s2); border: 0; background: transparent; color: var(--ink-2); font-size: var(--fs-callout); font-weight: 400; cursor: pointer; }
.pr-chip { display: inline-flex; align-items: center; min-height: 36px; padding: 0 var(--s3); border: 1px solid var(--ink); border-radius: 999px; background: var(--paper); font-size: var(--fs-label); font-weight: 600; white-space: nowrap; }
/* Small pills keep a 36px look but get a 44px hit area. */
.pr-lang, .pr-hud-badges { appearance: none; position: relative; flex: none; display: inline-flex; align-items: center; gap: 4px; min-height: 36px; padding: 0 var(--s3); border: 1px solid var(--line-strong); border-radius: 999px; background: var(--paper); color: var(--ink); font-size: var(--fs-label); font-weight: 600; cursor: pointer; }
.pr-lang::before, .pr-hud-badges::before { content: ""; position: absolute; inset: -4px -2px; }
.pr-hud-badges { border-color: var(--ink); }

/* ── Player bar (every screen except the first-time intro) ── */
.pr-hud { position: absolute; z-index: 6; left: 0; right: 0; top: var(--chrome-top); height: var(--hud); display: flex; align-items: center; gap: var(--s2); padding: 0 var(--s4); border-bottom: 1px solid var(--line-2); background: var(--paper); }
.pr-hud[hidden] { display: none; }
.pr-hud-main { flex: 1; min-width: 0; }
.pr-hud-level { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; font-size: var(--fs-caption); color: var(--ink-2); }
.pr-hud-level b { color: var(--ink); font-size: var(--fs-label); }
.pr-meter { height: 6px; margin-top: 6px; border-radius: 3px; background: var(--line-2); overflow: hidden; }
.pr-meter span { display: block; height: 100%; width: 0; background: var(--ink); transition: width .6s; }

/* ── Intro ── */
.pr-toprow { display: flex; align-items: center; justify-content: space-between; gap: var(--s2); }
.pr-carousel { flex: 1; min-height: 0; display: flex; flex-direction: column; }
.pr-slides { flex: 1; min-height: 0; display: flex; overflow-x: auto; scroll-snap-type: x mandatory; scrollbar-width: none; }
.pr-slides::-webkit-scrollbar { display: none; }
.pr-slide { flex: 0 0 100%; display: flex; flex-direction: column; justify-content: center; gap: var(--s4); text-align: center; scroll-snap-align: start; }
.pr-slide h1 { font-size: var(--fs-display); line-height: 1.2; font-weight: 300; }
.pr-slide p { color: var(--ink-2); font-size: var(--fs-body); line-height: 1.65; }
.pr-bars { display: flex; gap: var(--s2); }
.pr-bars button { appearance: none; position: relative; flex: 1; height: var(--tap); padding: 0; border: 0; background: transparent; cursor: pointer; }
.pr-bars button::before, .pr-bars button::after { content: ""; position: absolute; left: 0; right: 0; top: 20px; height: 4px; border-radius: 2px; background: var(--line-2); }
.pr-bars button::after { right: auto; width: 0; background: var(--ink); }
.pr-bars button.is-done::after, .pr-bars button[aria-current="true"]::after { width: 100%; }
.pr-carousel.is-playing .pr-bars button[aria-current="true"]::after { width: 0; animation: pr-fill var(--auto, 3500ms) linear forwards; }
@keyframes pr-fill { to { width: 100%; } }

/* ── Stop page (brief) ── */
.pr-guide { display: flex; align-items: flex-start; gap: var(--s3); }
.pr-bubble { padding: var(--s3); border: 1px solid var(--line); border-radius: var(--r); font-size: var(--fs-callout); line-height: 1.55; color: var(--ink); }
.pr-mission { display: flex; flex-wrap: wrap; gap: var(--s2); margin: 0; padding: 0; list-style: none; }
.pr-mission li { padding: 4px 10px; border: 1px solid var(--line); border-radius: 999px; font-size: var(--fs-caption); color: var(--ink-2); }
.pr-earn { padding: var(--s3); border: 2px solid var(--ink); border-radius: var(--r); font-size: var(--fs-callout); font-weight: 400; text-align: center; }
.pr-earn b { font-size: var(--fs-headline); font-weight: 600; }
.pr-loc { font-size: var(--fs-caption); line-height: 1.45; color: var(--ink-2); }
.pr-loc.is-off { padding: var(--s2) var(--s3); border: 1px dashed var(--ink-2); border-radius: var(--r-s); }
/* Stop page (boss 2026-11-02): the picture takes all the space above, the text sits at the bottom, no "welcome back" line. */
[data-screen="brief"] .pr-photo { flex: 1 1 0; min-height: 96px; aspect-ratio: auto; }
[data-screen="brief"] .pr-photo { position: relative; }
[data-screen="brief"] .pr-photo.is-art img { object-position: center; padding-top: 52px; }
/* The reward sits on the picture's top-left corner as a label, like the puzzle label (boss 2026-11-02). */
.pr-photo .pr-earn { position: absolute; left: var(--s3); top: var(--s3); margin: 0; padding: 6px 10px; border: 1px solid var(--line-strong); border-radius: var(--r-s); background: var(--paper); font-size: 15px; line-height: 1.2; text-align: left; }

/* ── Puzzles: object card front, story back ── */
/* Puzzle tag (boss 2026-11-02): plain "Puzzle 1 / 5" text on the picture's top-right corner, no box and no progress dots.
   No back button: the phone's own back steps through the puzzles (see go() in proto.js). */
.pr-qtag { position: absolute; z-index: 1; left: var(--s3); right: var(--s3); top: var(--s3); display: flex; justify-content: flex-end; align-items: flex-start; pointer-events: none; }
.pr-qtag-step { margin: 0; min-height: 36px; display: flex; align-items: center; font-size: 13px; font-weight: 600; color: var(--ink); }
.pr-dots { display: flex; gap: 4px; }
.pr-dots i { width: 18px; height: 6px; border-radius: 3px; background: var(--line-2); }
.pr-dots i.on { background: var(--ink); }
.pr-dots i.done { background: #9a9a9a; }
/* Question and story share one area; the story fades in over the question (no card flip, boss 2026-11-02). */
.pr-flip { position: relative; flex: 1; min-height: 0; }
.pr-face { position: absolute; inset: 0; display: flex; flex-direction: column; gap: var(--s3); transition: opacity .25s ease-out; }
.pr-back-face { opacity: 0; gap: 0; border: 1px solid var(--line); border-radius: var(--r); background: var(--paper); overflow: hidden; }
.pr-flip.is-flipped .pr-front { opacity: 0; }
/* Full-width puzzle page (boss 2026-11-02, chosen over the framed card): the picture runs edge to edge under the top bar,
   the question and options sit below it with the screen's side margin and no frame, and the button keeps that same margin. */
.pr-puzzle { padding-inline: 0; }
.pr-front, .pr-back-face { border: 0; border-radius: 0; background: var(--paper-grain, none), var(--paper); } /* the textured grey paper, like every other screen (boss 2026-11-02) */
.pr-front > :not(.pr-object) { margin-inline: var(--s4); }
/* The puzzle picture is a postage stamp (boss 2026-11-02): inset like the text, a white paper margin with the app's paper grain,
   a perforated edge all round, and a soft shadow on the outer
   wrapper — a mask would cut away a shadow on the stamp itself. Each puzzle is a stamp; the answer is stamped on. */
/* fixed 5:4 landscape, the same in every language (boss 2026-11-02); the stamp sits at least 16px under the top bar. Spare
   height in shorter languages (Chinese, Korean) is split one third above the stamp, two thirds between stamp and question,
   by two empty spacers (their negative margin cancels the column gap they would add); never a taller stamp. Only where even
   5:4 does not fit does it get a little flatter. */
.pr-front { padding-top: var(--s4); }
.pr-front::before, .pr-front::after { content: ""; margin-bottom: calc(var(--s3) * -1); }
.pr-front::before { order: 0; flex: 1 1 0; }
.pr-front > .pr-stamp-wrap { order: 1; }
.pr-front::after { order: 2; flex: 2 1 0; }
.pr-front > :not(.pr-stamp-wrap) { order: 3; }
.pr-front > .pr-stamp-wrap { flex: 0 1 auto; aspect-ratio: 5 / 4; min-height: 72px; display: flex; flex-direction: column; margin: 0 var(--s4);
  filter: drop-shadow(0 1px 1px rgba(38, 50, 56, .28)) drop-shadow(0 4px 8px rgba(38, 50, 56, .14)); }
.pr-stamp-wrap > .pr-object { --perf: 5px; --margin: 12px; flex: 1; min-height: 0; margin: 0; border-radius: 0; box-shadow: none;
  -webkit-mask: radial-gradient(circle var(--perf) at 50% 50%, #0000 96%, #000) repeat calc(var(--perf-w, 15px) / -2) calc(var(--perf-h, 15px) / -2) / var(--perf-w, 15px) var(--perf-h, 15px),
    linear-gradient(#000 0 0) no-repeat 50% / calc(100% - var(--perf) * 3) calc(100% - var(--perf) * 3);
  mask: radial-gradient(circle var(--perf) at 50% 50%, #0000 96%, #000) repeat calc(var(--perf-w, 15px) / -2) calc(var(--perf-h, 15px) / -2) / var(--perf-w, 15px) var(--perf-h, 15px),
    linear-gradient(#000 0 0) no-repeat 50% / calc(100% - var(--perf) * 3) calc(100% - var(--perf) * 3); }
/* The perforation mask above is only a stand-in until proto.js draws each stamp's exact outline (an SVG with round holes at
   the stamp's real size, set inline); tiled CSS patterns are stretched differently by each browser and gave ovals on iPhone. */
/* the paper margin (a frame: the middle is cut out so the picture shows): near white, clearly lighter than the grey page,
   with only a hint of grain under a white veil (boss 2026-11-02) */
.pr-stamp-wrap > .pr-object::after { content: ""; position: absolute; inset: 0; padding: var(--margin); background: linear-gradient(rgba(255, 255, 255, .8), rgba(255, 255, 255, .8)), var(--paper-grain, none), #fff; pointer-events: none;
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0); -webkit-mask-composite: xor; mask: linear-gradient(#000 0 0) content-box exclude, linear-gradient(#000 0 0); }
/* a faint grain over the picture only (not the margin), so the image reads as printed on paper */
.pr-stamp-wrap > .pr-object::before { content: ""; position: absolute; z-index: 1; inset: var(--margin); background: var(--paper-grain, none); mix-blend-mode: multiply; opacity: .45; pointer-events: none; }
.pr-stamp-wrap > .pr-object .pr-qtag { z-index: 2; top: calc(var(--margin) + 6px); right: calc(var(--margin) + 8px); left: calc(var(--margin) + 8px); }
.pr-stamp-wrap > .pr-object .pr-tag { z-index: 2; right: calc(var(--margin) + 6px); bottom: calc(var(--margin) + 6px); }
/* Stamp lettering (boss 2026-11-02): a stamp issued today, so it uses the app's own Gill Sans throughout (not a period face);
   hierarchy from size, weight and letter-spacing only; a hairline frame
   inside the paper margin; face value top-left (the puzzle number, the biggest figure); the series — the building's name — over
   the place of issue top-right; caption (the object) bottom-left; year of issue, tiny, bottom-right. All inside the picture,
   never on the perforated margin; all English. "Puzzle n / 5" stays for screen readers only. */
.pr-stamp-wrap > .pr-object .pr-stamp-text { inset: calc(var(--margin) + 8px) calc(var(--margin) + 10px); display: block; color: var(--ink); font-family: var(--text); }
.pr-stamp-text::before { content: ""; position: absolute; inset: -4px -6px; border: 1px solid rgba(38, 50, 56, .45); pointer-events: none; }
.pr-sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.pr-stamp-value { position: absolute; left: 0; top: 2px; font-size: 38px; font-weight: 600; line-height: .8; }
.pr-stamp-value small { margin-left: 1px; font-size: 15px; color: var(--ink-2); }
.pr-stamp-issuer { position: absolute; right: 0; top: 3px; text-align: right; font-size: 9px; font-weight: 400; letter-spacing: .16em; line-height: 1.5; text-transform: uppercase; }
.pr-stamp-issuer b { display: block; margin-bottom: 4px; font-size: 12px; font-weight: 600; letter-spacing: .12em; line-height: 1.15; }
.pr-stamp-caption { position: absolute; left: 0; bottom: 1px; font-size: 11px; font-weight: 600; letter-spacing: .1em; line-height: 1.3; text-transform: uppercase; } /* a long caption may break onto two lines to keep clear of the object */
.pr-stamp-year { position: absolute; right: 0; bottom: 2px; font-size: 9px; letter-spacing: .12em; color: var(--ink-2); }
.pr-puzzle > .pr-qfoot { margin-inline: var(--s4); }
.pr-flip.is-flipped .pr-back-face { opacity: 1; }
/* Only the side being shown takes taps, so a tap during the fade never lands on the side fading out. */
.pr-flip.is-flipped .pr-front, .pr-flip:not(.is-flipped) .pr-back-face { pointer-events: none; }
.pr-object { position: relative; flex: 1; min-height: 72px; border-radius: var(--r); background: var(--fill); overflow: hidden; }
.pr-object img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; filter: grayscale(1); }
.pr-tag { position: absolute; right: var(--s2); bottom: var(--s2); padding: 2px 8px; border: 1px solid var(--line-strong); border-radius: 999px; background: var(--paper); color: var(--ink-2); font-size: var(--fs-caption); }
.pr-front h2 { flex: none; }
.pr-options { display: grid; gap: var(--s2); flex: none; }
.pr-opt { appearance: none; min-height: 48px; padding: 10px var(--s3); border: 1px solid var(--line-strong); border-radius: var(--r); background: var(--paper); text-align: left; font-size: var(--fs-body); line-height: 1.35; cursor: pointer; }
.pr-opt:disabled { cursor: default; }
/* Right / wrong: a round rubber stamp pressed over the right end of the option, slightly tilted (boss 2026-11-02):
   tick or cross in a double ring, Hawaiian words around it (img/stamps/*.svg, with a worn-ink texture), drawn as a mask in the answer colour.
   It takes no room, so the text never wraps because of it. It is taller than an option row, so it sits above the neighbouring rows
   (z-index) and the question area does not clip it — the stamp is always a whole circle.
   A wrong pick also turns light grey with a line through it. Nothing else on the page changes. */
.pr-opt { position: relative; }
.pr-options.is-done .pr-opt[data-correct]::after, .pr-opt.is-miss::after { content: ""; position: absolute; z-index: 1; right: 0; top: 50%; width: 52px; height: 52px; transform: translate(var(--stamp-x, 0px), calc(-50% + var(--stamp-y, 0px))) rotate(var(--stamp-turn, -12deg)); pointer-events: none; background: currentColor; -webkit-mask: var(--mark) center / contain no-repeat; mask: var(--mark) center / contain no-repeat; }
.pr-options.is-done .pr-opt[data-correct]::after { --mark: url("img/stamps/stamp-right.svg?v=3"); color: #009944; }
.pr-opt.is-miss::after { --mark: url("img/stamps/stamp-wrong.svg?v=3"); color: #9ea4a7; }
/* Each row is stamped a little differently — shifted and turned by hand, never lined up (boss 2026-11-02). */
.pr-opt:nth-child(1) { --stamp-x: -4px; --stamp-y: 1px; --stamp-turn: -14deg; }
.pr-opt:nth-child(2) { --stamp-x: -18px; --stamp-y: -3px; --stamp-turn: 9deg; }
.pr-opt:nth-child(3) { --stamp-x: -8px; --stamp-y: 3px; --stamp-turn: -24deg; }
/* Wrong pick: crossed out and locked; the other options stay open for another try. */
.pr-opt.is-miss { color: #9ea4a7; text-decoration: line-through; text-decoration-thickness: 1px; }
.pr-read { appearance: none; flex: none; min-height: var(--tap); border: 1px dashed var(--ink-2); border-radius: var(--r); background: var(--paper); font-size: var(--fs-callout); font-weight: 600; cursor: pointer; }
.pr-read[hidden] { display: none; }
.pr-feedback { flex: none; padding: var(--s3); border-left: 4px solid var(--ink); background: var(--fill); font-size: var(--fs-label); line-height: 1.5; color: var(--ink-2); }
.pr-feedback[hidden] { display: none; }
.pr-feedback b { display: block; margin-bottom: 2px; color: var(--ink); font-size: var(--fs-headline); }
.pr-notes { flex: 1; min-height: 0; overflow-y: auto; display: grid; grid-auto-rows: max-content; align-content: start; gap: var(--s3); padding: var(--s4); }
.pr-notes h3 { font-size: var(--fs-title); line-height: 1.3; }
.pr-notes p { font-size: var(--fs-body); line-height: 1.7; color: var(--ink-2); }
.pr-clue { background: linear-gradient(transparent 55%, #d9d9d9 55%); color: var(--ink); font-weight: 600; }
.pr-fig { appearance: none; position: relative; display: block; width: 100%; padding: 0; border: 0; border-radius: var(--r-s); background: var(--fill); overflow: hidden; cursor: zoom-in; }
.pr-fig img { display: block; width: 100%; max-height: 210px; object-fit: cover; filter: grayscale(1); }
.pr-fig-zoom { position: absolute; right: var(--s2); bottom: var(--s2); display: grid; place-items: center; width: 36px; height: 36px; border-radius: 50%; background: rgba(0,0,0,.65); color: #fff; font-size: 16px; }
.pr-notes .pr-figcap { margin-top: calc(var(--s1) * -1); font-size: var(--fs-caption); line-height: 1.5; color: var(--ink-3); }
.pr-notes .pr-onsite { padding: var(--s3); border: 1px dashed var(--line-strong); border-radius: var(--r-s); font-size: var(--fs-callout); line-height: 1.55; color: var(--ink); }
.pr-notes .pr-src { font-size: var(--fs-caption); line-height: 1.5; color: var(--ink-3); }
/* One button under the card: "read the story" on the question side, "back to the question" on the story side. */
.pr-qfoot .pr-unflip { flex: 1; min-width: 0; min-height: var(--tap); }
.pr-puzzle:not(:has(.pr-flip.is-flipped)) .pr-qfoot .pr-unflip, .pr-puzzle:has(.pr-flip.is-flipped) .pr-qfoot .pr-read { display: none; }

/* ── Done ── */
.pr-done { align-items: center; justify-content: center; text-align: center; }
.pr-done h1 { font-size: var(--fs-display); font-weight: 300; }
.pr-stamp-slot { display: grid; place-items: center; width: 168px; height: 168px; flex: none; border: 2px dashed var(--line); border-radius: 50%; }
.pr-done .ph-stamp { opacity: 0; transform: scale(2.2) rotate(-18deg); }
.pr-done.is-stamped .ph-stamp { animation: pr-slam .5s cubic-bezier(.2, .9, .3, 1) .3s forwards; }
@keyframes pr-slam { 60% { opacity: 1; transform: scale(.92) rotate(2deg); } to { opacity: 1; transform: none; } }
.pr-summary { display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--s2); width: 100%; }
.pr-summary div { padding: var(--s3) var(--s1); border: 1px solid var(--line); border-radius: var(--r); }
.pr-summary b { display: block; font-size: var(--fs-title); font-weight: 300; line-height: 1.2; }
.pr-summary > div > span { color: var(--ink-3); font-size: var(--fs-caption); }
.pr-pts-note { width: 100%; padding: var(--s2) var(--s3); border: 1px dashed var(--ink-2); border-radius: var(--r-s); font-size: var(--fs-caption); line-height: 1.5; color: var(--ink-2); }
.pr-pts-note[hidden] { display: none; }
.pr-goal { width: 100%; display: flex; justify-content: space-between; align-items: center; gap: var(--s2); padding: var(--s3); border: 1px dashed var(--line-strong); border-radius: var(--r); font-size: var(--fs-label); color: var(--ink-2); }
.pr-goal b { color: var(--ink); font-size: var(--fs-callout); }

/* ── Lists: stops, badge wall, coupons ── */
.pr-title-row { display: flex; justify-content: space-between; align-items: baseline; gap: var(--s2); flex: none; }
.pr-title-row p { color: var(--ink-3); font-size: var(--fs-label); font-weight: 400; white-space: nowrap; }
.pr-stops, .pr-rewards, .pr-stamps { flex: 1; min-height: 0; overflow-y: auto; margin: 0; padding: 0; list-style: none; display: grid; align-content: start; }
.pr-stops { gap: var(--s2); }
.pr-stop { appearance: none; width: 100%; min-height: 80px; display: grid; grid-template-columns: 56px 1fr 16px; align-items: center; gap: var(--s3); padding: var(--s3); border: 1px solid var(--line-strong); border-radius: var(--r); background: var(--paper); text-align: left; cursor: pointer; }
/* Badge (= the building's QR sign) with its points underneath. */
.pr-stop-reward { display: grid; justify-items: center; gap: var(--s1); }
.pr-stop-plaque { display: grid; place-items: center; align-content: center; width: 48px; height: 52px; border: 1.5px dashed var(--ink-3); border-radius: 8px; background: var(--fill); color: var(--ink-3); font-size: 12px; line-height: 1.2; }
.pr-stop-plaque b { color: var(--ink); font-size: var(--fs-label); }
.pr-stop-pts { font-size: var(--fs-caption); font-weight: 600; line-height: 1.2; white-space: nowrap; }
.pr-stop-text { min-width: 0; }
.pr-stop-name { display: block; font-size: var(--fs-body); font-weight: 600; line-height: 1.3; }
.pr-stop small { display: block; margin-top: 4px; color: var(--ink-3); font-size: var(--fs-caption); line-height: 1.4; }
.pr-stop-go { color: var(--ink-3); font-size: 22px; line-height: 1; }
.pr-empty { padding: var(--s5); text-align: center; color: var(--ink-3); font-size: var(--fs-label); }
.pr-level-card { flex: none; display: grid; gap: var(--s1); padding: var(--s3); border: 1px solid var(--line); border-radius: var(--r); }
.pr-level-card > p:first-child { font-size: var(--fs-label); color: var(--ink-2); }
.pr-level-card > p:first-child b { color: var(--ink); font-size: var(--fs-headline); }
.pr-stamps { grid-template-columns: repeat(3, 1fr); gap: var(--s4) var(--s2); }
.pr-stamp { appearance: none; display: grid; justify-items: center; gap: var(--s1); min-width: 0; padding: 0; border: 0; background: transparent; color: var(--ink-3); font: inherit; text-align: center; cursor: pointer; }
.pr-stamp i { display: grid; place-items: center; width: 84px; height: 84px; border: 1.5px dashed var(--line-strong); border-radius: 50%; font-style: normal; font-size: var(--fs-caption); font-weight: 600; line-height: 1.2; }
.pr-stamp.is-done i { border: 3px double var(--ink); color: var(--ink); font-size: var(--fs-caption); }
.pr-stamp span { width: 100%; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; font-size: var(--fs-caption); }
.pr-points { flex: none; display: flex; justify-content: space-between; align-items: center; padding: var(--s3) var(--s4); border: 2px solid var(--ink); border-radius: var(--r); font-size: var(--fs-callout); font-weight: 400; }
.pr-points b { font-size: var(--fs-title); font-weight: 300; }
.pr-rewards { gap: var(--s2); }
.pr-reward { display: grid; grid-template-columns: 52px 1fr auto; align-items: center; gap: var(--s3); padding: var(--s3); border: 1px dashed var(--line-strong); border-radius: var(--r); font-size: var(--fs-callout); font-weight: 400; line-height: 1.35; }
.pr-reward.is-open { border-style: solid; border-color: var(--ink); }
.pr-reward.is-used { opacity: .6; }
.pr-reward > b { display: grid; place-items: center; align-content: center; width: 52px; height: 52px; border: 1px solid var(--line-strong); border-radius: 50%; font-size: var(--fs-headline); font-weight: 600; line-height: 1.05; }
.pr-reward > b small { display: block; color: var(--ink-3); font-size: 12px; font-weight: 400; }
.pr-reward small { display: block; margin-top: 2px; color: var(--ink-3); font-size: var(--fs-caption); font-weight: 400; }
.pr-reward > small { margin: 0; text-align: right; }
.pr-reward button { appearance: none; min-height: var(--tap); padding: 0 var(--s3); border: 1px solid var(--ink); border-radius: var(--r-s); background: var(--paper); font-size: var(--fs-label); font-weight: 600; cursor: pointer; }
.pr-reward button:disabled { border-color: var(--line-strong); color: var(--ink-3); cursor: default; }
.pr-expiry { flex: none; }

/* ── Redeem ── */
.pr-code-card { flex: none; display: grid; gap: var(--s1); justify-items: center; padding: var(--s4); border: 2px solid var(--ink); border-radius: var(--r-l); text-align: center; }
.pr-code-card[hidden] { display: none; }
.pr-code-name { font-size: var(--fs-headline); font-weight: 600; line-height: 1.35; }
.pr-code-cost { color: var(--ink-2); font-size: var(--fs-label); }
.pr-swipe-step { display: flex; flex-direction: column; gap: var(--s3); flex: 1; min-height: 0; }
.pr-swipe-step[hidden] { display: none; }
/* Swipe track: the knob must travel to the end; the track fills behind it. */
.pr-swipe { --fill: 0px; position: relative; flex: none; margin-top: auto; height: 60px; padding: 4px; border-radius: 999px; background: var(--fill); box-shadow: inset 0 0 0 1px var(--line-strong); overflow: hidden; touch-action: none; }
.pr-swipe::before { content: ""; position: absolute; left: 4px; top: 4px; bottom: 4px; width: calc(var(--fill) + 52px); border-radius: 999px; background: #d0d0d0; }
.pr-swipe-label { position: absolute; inset: 0; display: grid; place-items: center; padding-left: 40px; color: var(--ink-2); font-size: var(--fs-body); font-weight: 600; pointer-events: none; }
.pr-swipe-knob { appearance: none; position: relative; z-index: 1; width: 52px; height: 52px; border: 0; border-radius: 50%; background: var(--ink); color: #fff; font-size: 22px; font-weight: 600; cursor: grab; touch-action: none; }
.pr-swipe-knob:active { cursor: grabbing; }
/* Live voucher: ticking clock + moving band + shop name — a screenshot would be frozen. */
.pr-voucher { flex: none; display: grid; gap: var(--s1); justify-items: center; padding: 0 0 var(--s3); border: 2px solid var(--ink); border-radius: var(--r-l); text-align: center; overflow: hidden; }
.pr-voucher[hidden] { display: none; }
.pr-voucher-band { justify-self: stretch; height: 18px; background: repeating-linear-gradient(var(--band-angle, 45deg), var(--ink) 0 10px, var(--paper) 10px 20px); background-size: 200% 100%; animation: pr-band 1.6s linear infinite; }
.pr-voucher-band:last-child { margin-top: var(--s2); animation-direction: reverse; }
@keyframes pr-band { to { background-position: -56px 0; } }
.pr-voucher-ok { margin-top: var(--s3); font-size: var(--fs-display); font-weight: 300; }
.pr-voucher .pr-code-name { padding: 0 var(--s3); }
.pr-voucher-clock { font-size: 40px; font-weight: 300; letter-spacing: .04em; font-variant-numeric: tabular-nums; }
.pr-voucher-date { color: var(--ink-2); font-size: var(--fs-label); }
.pr-voucher-hint[hidden] { display: none; }
.pr-redeemed { flex: none; padding: var(--s3); border: 2px solid var(--ink); border-radius: var(--r); text-align: center; font-size: var(--fs-callout); font-weight: 600; }
.pr-redeemed[hidden] { display: none; }

/* ── Bottom tabs ── */
/* Lists run right up to the tab bar: the bar cancels the screen's flex gap above it. */
.pr-tabs { flex: none; display: grid; grid-template-columns: repeat(3, 1fr); margin: calc(var(--s3) * -1) calc(var(--s4) * -1) calc(var(--s4) * -1); border-top: 1px solid var(--line); }
.pr-tabs button { appearance: none; min-height: var(--tap); padding: 0 var(--s1); border: 0; background: var(--paper); color: var(--ink-3); font-size: var(--fs-label); font-weight: 600; line-height: 1.2; cursor: pointer; }
/* Current tab: an underline under its label, in the tab's own colour (--tab-color; ink in the wireframe). */
.pr-tabs button.is-on { color: var(--ink); text-decoration: underline 3px var(--tab-color, var(--ink)); text-underline-offset: 8px; }
/* Short dividers between tabs, as tall as the labels. */
.pr-tabs button { position: relative; }
.pr-tabs button + button::before { content: ""; position: absolute; left: 0; top: 50%; width: 1px; height: 1.1em; background: var(--line); transform: translateY(-50%); }

/* ── Sheets and overlays (find the sign, confirm, rules, language) ── */
.pr-plaque, .pr-confirm, .pr-rules, .pr-langsheet { position: absolute; z-index: 10; inset: var(--chrome-top) 0 var(--chrome-bottom); display: flex; align-items: flex-end; background: rgba(0,0,0,.45); }
.pr-langsheet { z-index: 11; }
.pr-plaque[hidden], .pr-confirm[hidden], .pr-rules[hidden], .pr-langsheet[hidden] { display: none; }
.pr-plaque-card, .pr-langsheet-card { width: 100%; max-height: 100%; overflow-y: auto; display: grid; gap: var(--s3); padding: var(--s5) var(--s4) var(--s4); border-radius: var(--r-l) var(--r-l) 0 0; background: var(--paper); }
.pr-plaque-card h2, .pr-langsheet-card h2 { font-size: 20px; line-height: 1.3; }
.pr-plaque-addr { margin-top: calc(var(--s2) * -1); color: var(--ink-3); font-size: var(--fs-caption); }
.pr-plaque-earn { font-size: var(--fs-callout); font-weight: 600; }
.pr-plaque-earn:empty { display: none; }
.pr-plaque-where { font-size: var(--fs-callout); line-height: 1.55; color: var(--ink); }
.pr-plaque-actions { display: grid; grid-template-columns: 1fr 1.4fr; gap: var(--s2); }
.pr-confirm-sum { padding: var(--s3); border: 2px solid var(--ink); border-radius: var(--r); font-size: var(--fs-callout); font-weight: 600; line-height: 1.45; }
.pr-rules-list { margin: 0; padding-left: 20px; display: grid; gap: var(--s2); font-size: var(--fs-callout); line-height: 1.5; color: var(--ink); }
.pr-langsheet-list { display: grid; gap: var(--s2); }
.pr-langsheet-list button { appearance: none; min-height: var(--tap-main); padding: 0 var(--s4); border: 1px solid var(--line-strong); border-radius: var(--r); background: var(--paper); text-align: left; font-size: var(--fs-body); cursor: pointer; }
.pr-langsheet-list button[aria-pressed="true"] { border: 2px solid var(--ink); font-weight: 600; }
.pr-langsheet-list button[aria-pressed="true"]::after { content: "  ✓"; }
.pr-lightbox { position: absolute; z-index: 10; inset: var(--chrome-top) 0 var(--chrome-bottom); display: flex; flex-direction: column; gap: var(--s3); padding: 60px var(--s4) var(--s4); background: rgba(20, 20, 20, .96); color: #fff; }
.pr-lightbox[hidden] { display: none; }
.pr-lb-close { appearance: none; position: absolute; top: var(--s2); right: var(--s2); display: grid; place-items: center; width: var(--tap); height: var(--tap); padding: 0; border: 0; background: transparent; color: #fff; font-size: 14px; line-height: 1; cursor: pointer; }
.pr-lb-view { flex: 1; min-height: 0; overflow: auto; display: grid; place-items: center; scrollbar-width: none; }
.pr-lb-view img { max-width: 100%; max-height: 100%; filter: grayscale(1); cursor: zoom-in; }
.pr-lb-view.is-zoomed { place-items: start; }
.pr-lb-view.is-zoomed img { max-width: none; max-height: none; width: 260%; cursor: zoom-out; }
.pr-lb-cap { font-size: var(--fs-label); line-height: 1.55; color: #e6e6e6; }
.pr-lb-hint { font-size: var(--fs-caption); color: #b5b5b5; }

/* Toast (+XP and short messages) sits just above the bottom actions. */
.pr-toast { position: absolute; z-index: 12; left: 50%; bottom: calc(var(--chrome-bottom) + 76px); max-width: calc(100% - 32px); padding: 10px 18px; border-radius: 999px; background: var(--ink); color: #fff; font-size: var(--fs-callout); font-weight: 600; text-align: center; transform: translateX(-50%); animation: pr-toast 1.4s ease-out forwards; }
.pr-toast[hidden] { display: none; }
@keyframes pr-toast { 0% { opacity: 0; transform: translate(-50%, 12px) scale(.9); } 15%, 75% { opacity: 1; transform: translate(-50%, 0) scale(1); } 100% { opacity: 0; transform: translate(-50%, -16px); } }

/* ── Compact: screens shorter than 600px tighten spacing and let pictures give up height first. Text never goes below 13px and taps never below 44px. ── */
@container (max-height: 600px) {
  .pr-slide { gap: var(--s3); }
  .pr-slide h1 { font-size: 24px; }
  .ph-emblem { width: 112px; height: 112px; }
  .ph-wide { height: 104px; }
  .ph-photo { aspect-ratio: 5 / 2; }
  .pr-guide .ph-guide { width: 44px; height: 44px; }
  .pr-bubble { padding: var(--s2) var(--s3); font-size: var(--fs-label); }
  .pr-mission { display: none; }
  .pr-front { gap: var(--s2); }
  .pr-front::before, .pr-front::after { margin-bottom: calc(var(--s2) * -1); }
  .pr-front h2 { font-size: 17px; line-height: 1.35; }
  .pr-options { gap: 6px; }
  .pr-opt { min-height: var(--tap); padding: 8px var(--s3); font-size: var(--fs-callout); }
  .ph-object, .pr-object { min-height: 48px; }
  .pr-feedback { padding: var(--s2) var(--s3); font-size: var(--fs-caption); }
  .pr-feedback b { font-size: var(--fs-callout); }
  .pr-done { gap: var(--s2); }
  .pr-stamp-slot { width: 124px; height: 124px; }
  .pr-done .ph-stamp { width: 104px; height: 104px; }
  .pr-done h1 { font-size: 24px; }
  .pr-summary div { padding: var(--s2) var(--s1); }
  .pr-summary b { font-size: var(--fs-headline); }
  .pr-code-card { padding: var(--s3); }
  .pr-voucher-ok { margin-top: var(--s2); font-size: 24px; }
  .pr-voucher-clock { font-size: 34px; }
  .pr-stop { min-height: 72px; padding: var(--s2) var(--s3); }
}
@container (max-height: 520px) {
  .pr-front h2 { font-size: var(--fs-callout); }
  .pr-opt { font-size: var(--fs-label); }
  .ph-object, .pr-object { min-height: 40px; }
  .pr-summary > div > span { font-size: 12px; }
}

/* ── Responsive shell ── */
@media (max-width: 1100px) { .pr-shell { grid-template-columns: auto 300px; } .pr-index { display: none; } }
@media (max-width: 760px) { .pr-shell { grid-template-columns: auto; } .pr-notes-panel { display: none; } }
@media (max-width: 480px) {
  body { background: var(--paper); }
  .pr-shell { display: block; padding: 0; }
  .device, .device[data-browser] { width: 100%; height: 100svh; --chrome-top: 0px; --chrome-bottom: 0px; }
  .pr-phone { left: 0; top: 0; width: 100%; height: 100%; border-radius: 0; }
  .device-frame, .prototype-status, .mock-chrome, .browser-switch { display: none !important; }
  .pr-screen { inset: 0; padding-top: max(var(--s4), env(safe-area-inset-top)); }
  .pr-phone.has-hud .pr-screen { top: var(--hud); padding-top: var(--s3); }
  .pr-hud { top: 0; }
}
@media (max-height: 640px) { :root { --hud: 46px; } }
@media (prefers-reduced-motion: reduce) { *, *::before, *::after { animation: none !important; transition: none !important; } .pr-done .ph-stamp { opacity: 1; transform: none; } }
[data-screen="redeem"] .pr-tabs { margin-top: auto; }

/* ⓘ info toggle: explanations stay folded so lists keep their room. */
.pr-title-row h1 { flex: none; }
.pr-title-row p { margin-left: auto; }
.pr-info { appearance: none; position: relative; flex: none; align-self: center; display: grid; place-items: center; width: 26px; height: 26px; padding: 0; border: 1.5px solid var(--ink-2); border-radius: 50%; background: var(--paper); color: var(--ink-2); font: italic 700 15px/1 Georgia, "Times New Roman", serif; cursor: pointer; }
.pr-info::before { content: ""; position: absolute; inset: -9px; }
.pr-info[aria-expanded="true"] { background: var(--ink); border-color: var(--ink); color: #fff; }
/* "?" explanation popover: dims the screen (tab bar included) until closed. */
.pr-info-body { position: absolute; z-index: 9; inset: 0; display: flex; align-items: flex-start; padding: 64px var(--s4) var(--s4); background: rgba(0, 0, 0, .35); }
.pr-info-card { position: relative; width: 100%; display: grid; gap: var(--s2); padding: var(--s4) 48px var(--s4) var(--s4); border-radius: var(--r); background: var(--paper); box-shadow: 0 10px 30px rgba(0, 0, 0, .22); }
/* Every close is the same ✕ icon in the card's top-right corner (boss 2026-11-02). */
.pr-plaque-card, .pr-langsheet-card { position: relative; }
.pr-plaque-card > .pr-sheet-close ~ .pr-kicker, .pr-plaque-card > .pr-sheet-close ~ h2, .pr-langsheet-card > h2 { padding-right: 40px; }
.pr-badge-card > .pr-sheet-close ~ .pr-kicker, .pr-badge-card > .pr-sheet-close ~ h2 { padding-inline: 40px; }
.pr-plaque-actions:has(> :only-child) { grid-template-columns: 1fr; }
.pr-badge-card .pr-plaque-actions:has([data-badge-where][hidden]) { display: none; }
.pr-info-close, .pr-sheet-close { appearance: none; position: absolute; top: 2px; right: 2px; display: grid; place-items: center; width: var(--tap); height: var(--tap); padding: 0; border: 0; background: transparent; color: var(--ink); font-size: 14px; line-height: 1; cursor: pointer; }
/* Close = × inside a 30px circle (like the top-bar circles); the button itself stays a 44px target. */
.pr-info-close::before, .pr-sheet-close::before, .pr-lb-close::before { content: ""; position: absolute; inset: 7px; border: 1px solid currentColor; border-radius: 50%; }
.pr-info-body[hidden] { display: none; }
.pr-info-body .pr-note { color: var(--ink-2); }
/* About page */
.pr-about { flex: 1; min-height: 0; overflow-y: auto; margin: 0; display: grid; align-content: start; gap: var(--s2); }
.pr-about > div { display: grid; gap: 2px; padding: var(--s3) 0; border-bottom: 1px solid var(--line-2); }
.pr-about dt { color: var(--ink-3); font-size: var(--fs-caption); font-weight: 400; }
.pr-about dd { margin: 0; font-size: var(--fs-callout); line-height: 1.55; }
.ph-sponsors { display: grid; height: 64px; margin-top: var(--s1); }
/* About button at the right end of the player bar. */
.pr-hud-about { appearance: none; position: relative; flex: none; display: grid; place-items: center; width: 36px; height: 36px; padding: 0; border: 1px solid var(--line-strong); border-radius: 50%; background: var(--paper); color: var(--ink); font: italic 700 17px/1 Georgia, "Times New Roman", serif; cursor: pointer; }
.pr-hud-about::before { content: ""; position: absolute; inset: -4px; }
.pr-hud { gap: 6px; }
/* Narrow phones: the language pill shows only the globe. */
/* In the bar the language button shows a one-glyph short name (繁 简 EN 日 한); the sheet lists full names. No flags. */
.pr-hud .pr-lang { width: 36px; padding: 0; justify-content: center; font-size: var(--fs-callout); font-weight: 600; }
.pr-hud-level { white-space: normal; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; line-height: 1.2; }
@media (max-width: 360px) { .pr-hud { gap: 4px; padding: 0 var(--s3); } .pr-hud .ph-avatar { width: 32px; height: 32px; font-size: 10px; } }
.pr-hud .pr-lang::before { inset: -4px; }
/* Level name + medal count is one tap target that opens My achievements. */
.pr-hud-main { appearance: none; flex: 1; min-width: 0; min-height: var(--tap); display: flex; flex-direction: column; justify-content: center; padding: 0; border: 0; background: transparent; text-align: left; cursor: pointer; }
.pr-hud-level { display: flex; align-items: baseline; flex-wrap: wrap; gap: 0 6px; overflow: visible; white-space: normal; -webkit-line-clamp: unset; }
.pr-hud-medal { white-space: nowrap; font-size: var(--fs-label); font-weight: 600; color: var(--ink); }
.pr-hud-medal b { margin-left: 2px; }
.pr-hud .pr-meter { display: block; width: 100%; }
.pr-hud .pr-meter > span { display: block; }
/* Level card: the avatar that belongs to the current title sits on the left. */
.pr-level-card { grid-template-columns: auto 1fr; column-gap: var(--s3); align-items: center; }
.pr-level-card > * { grid-column: 2; }
.pr-level-card > .ph-avatar { grid-column: 1; grid-row: 1 / span 3; width: 56px; height: 56px; font-size: 11px; }
/* Scrolling: no native scrollbar inside the phone; a 3px colour bar floats at the right edge while a list moves (see proto.js). */
.pr-phone :is(.pr-stops, .pr-rewards, .pr-stamps, .pr-about, .pr-notes, .pr-plaque-card, .pr-langsheet-card) { scrollbar-width: none; overscroll-behavior: contain; } /* a list that reaches its end stops there; it never drags the page or phone along */
.pr-phone { overscroll-behavior: contain; }
@media (max-width: 480px) { html, body { overscroll-behavior: none; } }
.pr-phone :is(.pr-stops, .pr-rewards, .pr-stamps, .pr-about, .pr-notes, .pr-plaque-card, .pr-langsheet-card)::-webkit-scrollbar { display: none; }
.pr-scrollbar { position: absolute; z-index: 13; right: 2px; top: 0; width: 3px; height: 0; border-radius: 2px; background: var(--bar, var(--accent, var(--ink-3))); opacity: 0; transition: opacity .35s; pointer-events: none; }
.pr-scrollbar.is-on { opacity: 1; transition-duration: .1s; }
/* Top bar: language and About circles at 30px (boss 2026-11-02: 36 looked too big); hit area stays 44px. */
.pr-hud .pr-lang, .pr-hud-about { width: 30px; height: 30px; min-height: 30px; font-size: var(--fs-caption); }
.pr-hud .pr-lang::before, .pr-hud-about::before { inset: -8px; }
/* Switching tabs: the new screen appears at once (no slide), so only the content area seems to change. */
.pr-screen.is-instant { animation: none; }
/* Top bar = the game's name "Chinatown Trails" as plain text (boss 2026-11-02; same in every language), then language and About. */
.pr-wordmark { position: absolute; left: 50%; transform: translateX(-50%); font-size: 18px; font-weight: 600; color: var(--ink); white-space: nowrap; } /* centred in the bar (boss 2026-11-02) */
.pr-hud .pr-lang { margin-left: auto; }
/* Badge card (tap a badge on the wall): same sheet as the sign card, with the badge large on top. */
.pr-badgesheet { position: absolute; z-index: 10; inset: var(--chrome-top) 0 var(--chrome-bottom); display: flex; align-items: flex-end; background: rgba(0, 0, 0, .45); }
.pr-badgesheet[hidden] { display: none; }
.pr-badge-card { justify-items: center; text-align: center; }
.pr-badge-card .pr-plaque-actions { width: 100%; }
.pr-badge-big { width: 140px; height: 140px; border-radius: 50%; opacity: .55; }
.pr-badge-big.is-done { opacity: 1; }
/* Desktop preview: the page itself never scrolls (scrolling the pink background moved the whole phone).
   The phone scales to fit the window height (--fit from proto.js); side panels scroll inside themselves. */
@media (min-width: 861px) {
  html, body { height: 100%; overflow: hidden; overscroll-behavior: none; }
  .device { transform: scale(var(--fit, 1)); transform-origin: top center; margin-bottom: calc(876px * (var(--fit, 1) - 1)); }
}
/* Answer options carry a letter (A B C) in front; the letter column keeps wrapped lines aligned. */
.pr-options { counter-reset: opt; }
.pr-opt { counter-increment: opt; display: flex; align-items: baseline; gap: 10px; }
.pr-opt::before { content: counter(opt, upper-alpha); flex: none; width: 1em; font-weight: 600; color: var(--ink-2); }
/* Question footer: the pink story line, with Next beside it once the answer is right (same height, so nothing moves). */
.pr-qfoot { flex: none; display: flex; gap: var(--s2); }
.pr-qfoot .pr-read { flex: 1; min-width: 0; }
.pr-qfoot .pr-next { flex: none; width: auto; min-height: var(--tap); padding: 0 var(--s4); }
/* Lower chrome (boss 2026-11-02): less space under the top bar. */
.pr-phone.has-hud .pr-screen { padding-top: var(--s2); }
/* Question screens: the picture starts right under the top bar's line (no gap); 8px above and below the pink button. */
.pr-phone.has-hud .pr-puzzle { gap: var(--s2); padding-top: 0; padding-bottom: var(--s4); } /* button lifted: 16px below it (boss 2026-11-02) */
/* Stop page, like the puzzle pages (boss 2026-11-02): the building picture runs edge to edge right under the top bar's line;
   the text and button below keep the 16px side margin. */
.pr-phone.has-hud [data-screen="brief"] { padding-top: 0; padding-inline: 0; }
[data-screen="brief"] > :not(.pr-photo) { margin-inline: var(--s4); }
[data-screen="brief"] > .pr-btn { width: auto; }
/* Stop page: the building's own photo fills the 16:9 (compact 5:2) frame, cropped from the centre. */
.pr-photo { overflow: hidden; background: var(--fill); }
.pr-photo img { display: block; width: 100%; height: 100%; object-fit: cover; object-position: center; }
.pr-photo.is-art img { object-fit: contain; padding: var(--s2) var(--s2) 0; object-position: center bottom; }


/* 3D badge (viewer.html?embed in an iframe) */
.pr-badge3d { display: block; width: 100%; height: 100%; border: 0; background: transparent; color-scheme: normal; }
.pr-stamp-slot.has-badge { width: 100%; height: 200px; border: 0; border-radius: 0; }
.pr-stamp-slot.has-badge .pr-badge3d { height: 200px; pointer-events: none; opacity: 0; transform: scale(1.6) rotate(-8deg); }
.pr-done.is-stamped .pr-stamp-slot.has-badge .pr-badge3d { animation: pr-slam .5s cubic-bezier(.2, .9, .3, 1) .3s forwards; }
/* badge wall: two per row, so a 3D badge shows whole and large */
.pr-stamps { grid-template-columns: repeat(2, 1fr); gap: var(--s5) var(--s3); }
.pr-stamp i { width: 116px; height: 116px; }
.pr-stamp.is-done i.has-badge { width: 100%; height: 116px; border: 0; border-radius: 0; background: transparent; overflow: visible; }   /* never clip the magnet shadow */
.pr-stamp i.has-badge .pr-badge3d { pointer-events: none; height: 116px; }   /* magnet shadow is drawn inside the viewer (?magnet), on the badge's own outline */   /* explicit: % height does not resolve inside the grid tile */   /* the tap goes to the button: opens the full-screen card */
/* earned 3D badge: the card fills the screen and the badge takes most of it */
/* full-screen badge: solid dark brand colour, all text white */
.pr-badgesheet.is-full { align-items: stretch; color: #fff; background: transparent; }
.pr-badgesheet.is-full::before { content: ""; position: absolute; inset: 0; transition: opacity .8s ease; background: #263238; }   /* solid ink, the darkest colour of the brand palette */
.pr-badgesheet.is-full .pr-badge-card { position: relative; z-index: 1; }
.pr-badgesheet.is-full .pr-badge-card, .pr-badgesheet.is-full .pr-badge-card :is(h2, p, .pr-kicker, .pr-plaque-addr, .pr-plaque-where, .pr-badge-spin) { color: #fff; }
.pr-badgesheet.is-full .pr-badge-card :is(.pr-plaque-addr, .pr-badge-spin) { color: rgba(255, 255, 255, .72); }
.pr-badgesheet.is-full .pr-sheet-close { color: #fff; border-color: rgba(255, 255, 255, .7); }
/* full-screen badge shows only three lines under it: name, address, earned date (boss 2026-11-02) */
.pr-badgesheet.is-full :is([data-badge-kicker], [data-badge-spin]) { display: none; }
.pr-badgesheet.is-full .pr-badge-card { background: transparent; }
.pr-badgesheet.is-full .pr-badge-card { height: 100%; max-height: none; border-radius: 0; grid-template-rows: none; align-content: center; padding-top: var(--s3); }   /* badge + three lines as one block, centred */
.pr-badge-stage { width: 100%; min-height: 0; height: 300px; margin-bottom: calc(var(--s3) * -1); }   /* text sits right under the badge */
.pr-badgesheet.is-full .pr-sheet-close { top: var(--s2); right: var(--s2); z-index: 1; }
.pr-badge-spin { margin: 0; color: var(--ink-3); font-size: var(--fs-caption); }
@media (prefers-reduced-motion: reduce) { .pr-stamp-slot.has-badge .pr-badge3d { opacity: 1; transform: none; } }

/* opening animation of the full-screen badge: page and text fade in while the badge grows from its tile */
.pr-badgesheet.is-full .pr-badge-card > :not([data-badge-art]) { transition: opacity .5s ease .7s; }
.pr-badgesheet.is-full.is-opening::before { opacity: 0; transition: none; }
.pr-badgesheet.is-full.is-opening .pr-badge-card > :not([data-badge-art]) { opacity: 0; transition: none; }
.pr-badge-stage { transform-origin: 50% 50%; position: relative; z-index: 1; }
@media (prefers-reduced-motion: reduce) { .pr-badge-stage { transition: none !important; } }

/* Surfaces (boss 2026-11-02): top bar and bottom tabs in a very light grey; everything between sits on paper.
   Paper = the light grey ground plus a fine, irregular grain (SVG noise, tiled) and faint larger mottling. */
:root {
  --bar: #f3f3f5;
  --paper-grain: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='240' height='240'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.75' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 .32  0 0 0 0 .30  0 0 0 0 .27  0 0 0 .38 0'/%3E%3C/filter%3E%3Crect width='240' height='240' filter='url(%23n)'/%3E%3C/svg%3E"),
                 url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='600' height='600'%3E%3Cfilter id='m'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.02' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 .45  0 0 0 0 .43  0 0 0 0 .4  0 0 0 .2 0'/%3E%3C/filter%3E%3Crect width='600' height='600' filter='url(%23m)'/%3E%3C/svg%3E");
}
.pr-phone { background: var(--paper-grain), var(--paper); }
.pr-plaque-card, .pr-langsheet-card { background-image: var(--paper-grain); }
/* status bar, top bar, its two round buttons and the tab bar: one flat very light grey, no paper grain */
.pr-hud, .pr-tabs { background: var(--bar); }
/* the status bar overlaps the top bar by 11px and sits above it: paint only the part above the top bar,
   or it covers the tops of the EN and i buttons */
.pr-phone:not(.tour-cam-on) .prototype-status { background: linear-gradient(var(--bar), var(--bar)) top / 100% 50px no-repeat; }
.pr-hud .pr-lang, .pr-hud .pr-hud-about { background: var(--bar); }

/* not-yet-earned badges: the grey badge, number on it; same size as an earned one */
.pr-stamp i.has-badge.is-locked { position: relative; display: block; width: 100%; height: 116px; border: 0; border-radius: 0; background: transparent; }
.pr-stamp i.is-locked b { position: absolute; left: 50%; top: 46%; transform: translate(-50%, -50%); padding: 2px 8px; border-radius: 999px; background: rgba(236, 236, 238, .92); color: var(--ink-3, #6b7080); font-size: 13px; font-weight: 600; letter-spacing: .04em; }
.pr-badge-locked { width: 78%; margin: 0 auto; }
.pr-badge-locked img { width: 100%; height: auto; display: block; }

/* Blender stills with the shadow baked in (640×437, badge = 79.7% of the image width, centred).
   Wall: badge 90% of the tile, centre at 46% of its height. The negative margin is half the image height (a % of width). */
.pr-stamp i.has-badge { position: relative; }
.pr-badge-shot { position: absolute; left: -6.5%; top: 46%; width: 113%; max-width: none; height: auto; margin-top: -38.6%; pointer-events: none; }
.pr-stamp-slot.has-badge { position: relative; }
/* end-of-stop slot: sized by height so the badge (≈170px tall) stays inside the 200px slot */
.pr-stamp-slot.has-badge .pr-badge-shot { left: 50%; top: 50%; width: auto; height: 240px; margin: 0; opacity: 0; transform: translate(-50%, -50%) scale(1.6) rotate(-8deg); }
.pr-done.is-stamped .pr-stamp-slot.has-badge .pr-badge-shot { animation: pr-slam-shot .5s cubic-bezier(.2, .9, .3, 1) .3s forwards; }
@keyframes pr-slam-shot { 60% { opacity: 1; transform: translate(-50%, -50%) scale(.92) rotate(2deg); } to { opacity: 1; transform: translate(-50%, -50%); } }
@media (prefers-reduced-motion: reduce) { .pr-stamp-slot.has-badge .pr-badge-shot { opacity: 1; transform: translate(-50%, -50%); } }
/* unearned: flat grey outline, same size and centre as an earned badge (90% of the tile, centre at 46%) */
.pr-badge-sil { position: absolute; left: 5%; top: 46%; width: 90%; height: auto; margin-top: -27.5%; pointer-events: none; mix-blend-mode: multiply; }   /* multiplied into the paper: reads as a shadow with the grain showing through */
/* light sweep over the gold of the badge stills, as in the 3D view: one slow pass, then a pause (3.2 s of a 7 s cycle) */
.pr-badge-sheen { aspect-ratio: 640 / 437; height: auto; -webkit-mask-size: 100% 100%; mask-size: 100% 100%;
  background: linear-gradient(110deg, transparent 38%, rgba(255, 255, 255, .95) 50%, transparent 62%) 160% 0 / 300% 100% no-repeat;
  mix-blend-mode: soft-light; animation: pr-sheen 7s ease-in-out infinite; }
@keyframes pr-sheen { 0% { background-position: 160% 0; } 46%, 100% { background-position: -60% 0; } }
.pr-done.is-stamped .pr-stamp-slot.has-badge .pr-badge-sheen { animation: pr-slam-shot .5s cubic-bezier(.2, .9, .3, 1) .3s forwards, pr-sheen 7s ease-in-out 1s infinite; }
@media (prefers-reduced-motion: reduce) { .pr-badge-sheen { display: none; } }
/* closing the full badge card: the badge flies back to its tile (proto.js) while the card and its text fade out */
.pr-badgesheet.is-full.is-closing { pointer-events: none; }
.pr-badgesheet.is-full.is-closing::before { opacity: 0; transition: opacity .55s ease; }
.pr-badgesheet.is-full.is-closing :is(.pr-badge-card > :not([data-badge-art]), .pr-sheet-close) { opacity: 0; transition: opacity .25s ease; }
/* About page: a close button right of the title (not a back link) */
.pr-about-head { display: flex; align-items: center; justify-content: space-between; gap: var(--s2); flex: none; }
.pr-about-head h1 { min-width: 0; }
.pr-about-close { position: relative; top: auto; right: auto; flex: none; margin-right: -7px; }
/* level card: just the avatar, the title and a "?" (boss 2026-11-02); progress and the rules live in the popover */
.pr-level-card { grid-template-columns: auto 1fr auto; padding: var(--s2) 0; }
.pr-level-card > * { grid-column: auto; }
.pr-level-card > .ph-avatar { grid-column: 1; grid-row: 1; width: 44px; height: 44px; font-size: 10px; }
.pr-level-card > p:first-child { grid-column: 2; grid-row: 1; }
.pr-level-card > .pr-info { grid-column: 3; grid-row: 1; }
.pr-level-rules-title { margin: 0; font-size: var(--fs-title, 20px); font-weight: 400; }
.pr-level-rules { margin: 0; padding: 0; list-style: none; display: grid; gap: 0; }
.pr-level-rules li { display: flex; justify-content: space-between; gap: var(--s2); padding: 6px 0; border-bottom: 1px solid var(--line); color: var(--ink-2); font-size: var(--fs-caption); }
.pr-level-rules li.is-now { color: var(--ink); font-weight: 600; }
/* Tab screens (boss 2026-11-02): only two layers — the fixed bars and one scrolling area. Each tab's header
   (title, level card, points) is a floating card at the top of that area and scrolls away with the list. */
.pr-scroll { flex: 1; min-height: 0; overflow-y: auto; display: flex; flex-direction: column; margin-inline: calc(var(--s4) * -1); padding: var(--s3) var(--s4) var(--s4); scrollbar-width: none; overscroll-behavior: contain; }
.pr-scroll::-webkit-scrollbar { display: none; }
.pr-scroll > :is(.pr-stops, .pr-rewards, .pr-stamps) { flex: none; min-height: auto; overflow: visible; border-top: 0; }
.pr-head-card { flex: none; display: grid; gap: var(--s3); margin-bottom: var(--s3); padding: var(--s3) var(--s4); background: rgba(255, 255, 255, .6); box-shadow: 0 1px 2px rgba(38, 50, 56, .08), 0 8px 20px rgba(38, 50, 56, .08); }
.pr-head-card .pr-title-row { margin: 0; }
/* status card stays inset with the 16px side margin, not an edge-to-edge band (boss 2026-11-02) */
.pr-level-card.pr-head-card { display: grid; padding: var(--s2) var(--s3); }
/* redeem confirm: where, what you get, then the points; the rules fold into "Good to know" */
.pr-confirm-facts { margin: 0; display: grid; gap: var(--s2); }
.pr-confirm-facts > div { display: grid; gap: 2px; }
.pr-confirm-facts dt { color: var(--ink-3); font-size: var(--fs-caption); letter-spacing: .04em; }
.pr-confirm-facts dd { margin: 0; display: flex; align-items: baseline; justify-content: space-between; gap: var(--s2); font-size: var(--fs-callout); line-height: 1.45; }
.pr-confirm-facts dd .pr-link { flex: none; }
.pr-confirm-sum { font-size: var(--fs-caption); font-weight: 400; padding: var(--s2) var(--s3); }
.pr-confirm-rules summary { cursor: pointer; color: var(--ink-2); font-size: var(--fs-caption); list-style: none; }
.pr-confirm-rules summary::-webkit-details-marker { display: none; }
.pr-confirm-rules summary::after { content: " ＋"; }
.pr-confirm-rules[open] summary::after { content: " －"; }
.pr-confirm-rules .pr-rules-list { margin-top: var(--s2); font-size: var(--fs-caption); color: var(--ink-2); gap: 4px; }
/* confirm sheet v2: taller, scrolls inside, buttons stay at the bottom; big "what you get", then Shop and Points blocks */
.pr-confirm .pr-plaque-card { min-height: 82%; max-height: 100%; overflow-y: auto; align-content: start; gap: var(--s3); scrollbar-width: none; }
.pr-confirm .pr-plaque-card::-webkit-scrollbar { display: none; }
.pr-confirm h2[data-confirm-get] { font-size: 24px; line-height: 1.3; }
.pr-confirm-offer { margin: -6px 0 0; color: var(--ink-3); font-size: var(--fs-caption); }
.pr-confirm-block { display: grid; gap: 4px; padding-top: var(--s3); border-top: 1px solid var(--line); }
.pr-confirm-block h3 { margin: 0 0 4px; color: var(--ink-3); font: 600 12px/1.3 var(--sans, inherit); letter-spacing: .08em; text-transform: uppercase; }
.pr-confirm-shop { margin: 0; font-size: 18px; }
.pr-confirm-line { margin: 0; color: var(--ink-2); font-size: var(--fs-callout); line-height: 1.45; }
.pr-confirm-map { justify-self: start; margin-top: var(--s2); min-height: 40px; padding-inline: var(--s4); }
.pr-confirm-pts { margin: 0; display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--s2); }
.pr-confirm-pts > div { display: grid; gap: 2px; padding: var(--s2); border: 1px solid var(--line-strong, var(--ink)); }
.pr-confirm-pts dt { color: var(--ink-3); font-size: 11px; line-height: 1.3; }
.pr-confirm-pts dd { margin: 0; font-size: 24px; font-weight: 300; line-height: 1.1; }
.pr-confirm .pr-confirm-rules { padding-top: var(--s3); border-top: 1px solid var(--line); }
.pr-confirm .pr-plaque-actions { position: sticky; bottom: calc(var(--s4) * -1); margin-top: auto; padding-block: var(--s3) var(--s4); background: inherit; }
/* personal status card at the top of every tab: avatar + title + ?, then badges / points / to go */
.pr-status { grid-template-columns: auto 1fr auto; align-items: center; column-gap: var(--s3); row-gap: var(--s3); padding: var(--s3) var(--s4); }
.pr-status > .ph-avatar { width: 48px; height: 48px; font-size: 10px; }
.pr-status-title { margin: 0; }
.pr-status-title b { font-family: var(--text); font-weight: 400; font-size: 22px; }
.pr-status-stats { grid-column: 1 / -1; margin: 0; padding-top: var(--s3); border-top: 1px solid var(--line); display: grid; grid-template-columns: repeat(3, 1fr); }
.pr-status-stats > div { display: grid; gap: 2px; }
.pr-status-stats > div + div { padding-left: var(--s3); border-left: 1px solid var(--line); }
.pr-status-stats dt { color: var(--ink-3); font-size: 11px; letter-spacing: .06em; }
.pr-status-stats dd { margin: 0; font-family: var(--text); font-size: 26px; font-weight: 300; line-height: 1.1; color: var(--ink); }
.pr-status-stats dd small { font-size: 13px; color: var(--ink-3); }
.pr-scroll > .pr-title-row { margin: var(--s2) 0 var(--s2); }
/* all-buildings list: a finished building keeps its place, its box turns ink with a check */
.pr-stop.is-done .pr-stop-plaque { background: var(--ink); color: #fff; border-color: var(--ink); }
.pr-stop.is-done .pr-stop-plaque i { font-style: normal; font-size: 14px; line-height: 1; }
.pr-stop.is-done .pr-stop-plaque b { color: #fff; }
.pr-stop.is-done .pr-stop-pts { color: var(--ink-3); font-weight: 400; }
/* status card avatar: the level's medal (design/avatar-studies/make_medal.py); thick-card effect rolled back (boss 2026-11-02) */
.pr-status > .ph-avatar { width: 56px; height: 56px; padding: 0; border: 0; background: none; overflow: visible; }
.pr-status > .ph-avatar img { width: 100%; height: 100%; display: block; }
/* boss 2026-11-02: header cards flat — one solid light colour, no paper grain showing through, no shadow */
.pr-head-card { background: #F7F7F8; box-shadow: none; }
/* boss 2026-11-02: shorter status card — the title row takes less room */
.pr-status { row-gap: var(--s2); padding: var(--s2) var(--s3); }
.pr-status > .ph-avatar { width: 40px; height: 40px; min-height: 0; margin: -4px 0; }
.pr-status-title b { font-size: 18px; }
.pr-status > .pr-info { width: 24px; height: 24px; font-size: 13px; }
.pr-status-stats { padding-top: var(--s2); }
.pr-status-stats dd { font-size: 22px; }
/* Explore grouped by area: jump buttons under the status card, a heading per area that stays pinned while scrolling */
.pr-areas { flex: none; display: flex; flex-wrap: wrap; gap: 6px; margin: 0 0 var(--s2); }
.pr-areas button { appearance: none; min-height: 32px; padding: 0 12px; border: 1px solid var(--ink); border-radius: 999px; background: transparent; color: var(--ink); font: 400 13px/1 var(--text, inherit); cursor: pointer; }
.pr-area { display: block; }
.pr-area > ul { margin: 0; padding: 0; list-style: none; display: grid; }
.pr-area + .pr-area { margin-top: var(--s3); }
.pr-area-head { position: sticky; top: calc(var(--s3) * -1); z-index: 2; display: flex; align-items: baseline; justify-content: space-between; margin: 0 calc(var(--s4) * -1); padding: var(--s2) var(--s4) 6px; background: #ECECEE; border-bottom: 1px solid var(--ink); }
.pr-area-head h2 { margin: 0; font-family: var(--text); font-size: 17px; font-weight: 400; }
.pr-area-head span { color: var(--ink-3); font-size: var(--fs-caption); }
/* Explore v3 (boss 2026-11-02): area = plain bold heading; buildings = mock QR door plaques, three per row */
.pr-scroll > .pr-stops { gap: 0; }
.pr-area + .pr-area { margin-top: var(--s4); }
.pr-area-title { display: flex; align-items: baseline; justify-content: space-between; margin: 0 0 var(--s2); font-family: var(--text); font-size: 20px; font-weight: 600; letter-spacing: 0; color: var(--ink); }
.pr-area-title span { color: var(--ink-3); font-size: 13px; font-weight: 400; }
.pr-plaque-grid { margin: 0; padding: 0; list-style: none; display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--s2); }
.pr-plaque-tile { appearance: none; width: 100%; display: grid; grid-template-rows: auto 1fr; padding: 0; border: 0; background: #fff; color: var(--ink); text-align: left; cursor: pointer; box-shadow: 0 1px 2px rgba(38, 50, 56, .18); }
.pr-pt-top { position: relative; display: flex; align-items: flex-end; justify-content: space-between; height: 46px; padding: 4px 8px; background: var(--street); color: #fff; }
.pr-pt-top b { font-family: var(--text); font-size: 34px; font-weight: 300; line-height: .9; letter-spacing: -.02em; }
.pr-pt-top i { font-style: normal; font-size: 13px; line-height: 1; align-self: flex-start; display: grid; place-items: center; width: 20px; height: 20px; border-radius: 50%; background: #fff; color: var(--street); font-weight: 700; }
.pr-pt-body { display: grid; grid-template-columns: 28px 1fr; grid-template-rows: auto 1fr; column-gap: 6px; padding: 6px 6px 7px; min-height: 64px; }
.pr-pt-body svg { grid-row: 1 / span 2; width: 28px; height: 28px; fill: var(--ink); }
.pr-pt-name { font-size: 11px; line-height: 1.25; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
.pr-pt-body small { grid-column: 1 / -1; align-self: end; margin-top: 4px; color: var(--ink-3); font-size: 10px; letter-spacing: .04em; }
.pr-plaque-tile.is-done .pr-pt-body small { color: var(--ink); font-weight: 600; }
/* plaque v2 (boss 2026-11-02): no QR; the name is the biggest thing, the number small */
.pr-plaque-tile { grid-template-rows: 1fr auto; }
.pr-pt-top { display: grid; grid-template-columns: 1fr auto; grid-template-rows: auto 1fr; align-items: start; height: auto; min-height: 92px; padding: 6px 8px 8px; }
.pr-pt-top small { font-size: 11px; letter-spacing: .04em; opacity: .85; }
.pr-pt-top i { grid-column: 2; grid-row: 1; }
.pr-pt-top .pr-pt-name { grid-column: 1 / -1; grid-row: 2; align-self: end; margin-top: 6px; color: #fff; font-family: var(--text); font-size: 15px; font-weight: 600; line-height: 1.15; -webkit-line-clamp: 3; }
.pr-pt-foot { padding: 5px 8px 6px; color: var(--ink-3); font-size: 10px; letter-spacing: .04em; }
.pr-plaque-tile.is-done .pr-pt-foot { color: var(--ink); font-weight: 600; }
/* boss 2026-11-02: every plaque exactly the same size; a bit more space between them */
.pr-plaque-grid { gap: 12px; }
.pr-plaque-tile { height: 124px; grid-template-rows: 98px 26px; overflow: hidden; }
.pr-pt-top { height: 98px; min-height: 0; overflow: hidden; }
.pr-pt-top .pr-pt-name { font-size: 14px; }
.pr-pt-foot { height: 26px; display: flex; align-items: center; padding-block: 0; }
/* no building numbers for visitors (boss 2026-11-02): an empty kicker takes no room */
.pr-kicker:empty { display: none; }
.pr-pt-top i { grid-column: 2; }
/* a finished plaque must read as done at a glance (boss 2026-11-02): a tilted round stamp on the colour block,
   and the strip under it turns ink with "✓ done" in white */
.pr-pt-top .pr-pt-stamp { position: absolute; top: 8px; right: 6px; width: 56px; height: 56px; display: grid; place-content: center; justify-items: center; gap: 1px;
  border: 2px solid #fff; border-radius: 50%; background: transparent; color: #fff; font-style: normal; font-size: 10px; font-weight: 700; letter-spacing: .06em; line-height: 1;
  transform: rotate(-14deg); box-shadow: inset 0 0 0 3px var(--street), inset 0 0 0 4px rgba(255, 255, 255, .85); }
.pr-pt-top .pr-pt-stamp b { font-size: 20px; line-height: 1; }
.pr-plaque-tile.is-done .pr-pt-foot { background: var(--ink); color: #fff; font-weight: 600; }
/* find-the-plaque card v2 (boss 2026-11-02): taller, layered — street, name, address, what the plaque looks like,
   where it is, what you get; the navigate button stays at the bottom */
.pr-plaque .pr-plaque-card { min-height: 82%; max-height: 100%; overflow-y: auto; align-content: start; gap: var(--s3); scrollbar-width: none; }
.pr-plaque .pr-plaque-card::-webkit-scrollbar { display: none; }
.pr-plaque-street { display: flex; align-items: center; gap: 6px; }
.pr-plaque-street i { width: 10px; height: 10px; border-radius: 50%; background: var(--street); }
.pr-plaque .pr-plaque-addr { margin-top: -8px; }
.pr-plaque-preview { margin: 0; display: grid; gap: 6px; }
.pr-plaque-mock { position: relative; display: grid; align-content: end; gap: 6px; min-height: 150px; padding: 14px 16px 16px; background: var(--street); color: #fff; }
.pr-plaque-mock b { max-width: 70%; font-family: var(--text); font-size: 26px; font-weight: 600; line-height: 1.1; }
.pr-plaque-mock span { font-size: 11px; letter-spacing: .06em; opacity: .9; }
.pr-plaque-mock i { position: absolute; top: 14px; right: 14px; width: 56px; height: 56px; background:
  repeating-linear-gradient(90deg, #fff 0 4px, transparent 4px 7px), repeating-linear-gradient(0deg, #fff 0 4px, transparent 4px 7px); outline: 6px solid #fff; outline-offset: -6px; opacity: .95; }
.pr-plaque-preview figcaption { color: var(--ink-3); font-size: 11px; }
.pr-plaque-gets { grid-template-columns: 1fr 1fr; }
.pr-plaque-gets dd img { width: 64px; height: auto; display: block; }
.pr-plaque .pr-plaque-actions { position: sticky; bottom: calc(var(--s4) * -1); margin-top: auto; padding-block: var(--s3) var(--s4); background: inherit; }
/* opening the 3D badge: keep its view invisible until the model reports ready (no half-loaded frame) */
.pr-badge-stage.is-loading { visibility: hidden; }
/* full-screen badge card on the app's own grey paper (boss 2026-11-02), dark text instead of white on ink */
.pr-badgesheet.is-full::before { background: var(--paper-grain), var(--paper); }
.pr-badgesheet.is-full .pr-badge-card, .pr-badgesheet.is-full .pr-badge-card :is(h2, p, .pr-kicker, .pr-plaque-addr, .pr-plaque-where, .pr-badge-spin) { color: var(--ink); }
.pr-badgesheet.is-full .pr-badge-card :is(.pr-plaque-addr, .pr-badge-spin) { color: var(--ink-3); }
.pr-badgesheet.is-full .pr-sheet-close { color: var(--ink); border-color: var(--ink); }
/* full-screen badge card keeps the top bar (Chinatown Trails · language · i) visible above it (boss 2026-11-02) */
.pr-badgesheet.is-full { top: calc(var(--chrome-top) + var(--hud)); }
/* full badge card text (boss 2026-11-02): name small, then a story line, which badge this is, and a next-stop button;
   the address and earned date are on the badge's back, so they are not repeated here */
.pr-badgesheet.is-full [data-badge-name] { font-size: 17px; }
.pr-badgesheet.is-full :is([data-badge-addr], [data-badge-state]) { display: none; }
.pr-badge-story, .pr-badge-nth { display: none; }
.pr-badgesheet.is-full .pr-badge-story { display: block; max-width: 30ch; margin: var(--s2) auto 0; font-family: var(--text); font-size: 17px; line-height: 1.5; text-align: center; color: var(--ink); }
.pr-badgesheet.is-full .pr-badge-nth { display: block; margin: var(--s3) 0 0; text-align: center; color: var(--ink-3); font-size: 13px; letter-spacing: .02em; }
.pr-badgesheet.is-full .pr-plaque-actions { margin-top: var(--s4); }
/* the actions row hides when "where is the plaque" is hidden; keep it when the next-stop button is showing */
.pr-badgesheet.is-full .pr-badge-card .pr-plaque-actions:has([data-badge-next]:not([hidden])) { display: grid; grid-template-columns: 1fr; }
/* boss 2026-11-02: the name bigger, the story line shorter and quieter */
.pr-badgesheet.is-full [data-badge-name] { font-size: 26px; }
.pr-badgesheet.is-full .pr-badge-story { font-size: 15px; max-width: 28ch; color: var(--ink-2); }
/* boss 2026-11-02: no next-stop button on the badge card; the whole block sits a little lower */
.pr-badgesheet.is-full [data-badge-next] { display: none; }
.pr-badgesheet.is-full .pr-badge-card .pr-plaque-actions { display: none; }
.pr-badgesheet.is-full .pr-badge-card { padding-top: 48px; }
