/* skin.css — nadinerafael (Nadine & Rafael). Site 4: Modern dark & gold, an evening on a roof in BGC.
   Hero feature: the guest pass (lab/docs/SITE4-PLAN.md). The loud axes: a lift panel for navigation
   (the pages are floors), five pages with the weight in the pass and the night, a full-screen night
   city behind every page (the view from that page's floor), and a narrow centred column on a dark
   field with the pass and the programme set as tickets. Tokens and every visual rule for this site.
   Engine internals are never touched here.

   §0 type · §1 tokens · §2 base · §3 the city behind every page · §4 frame, type, buttons · §5 the car panel ·
   §6 the design-study tab · §7 the cover · §8 panels on the cover · §9 tickets · §10 the pass ·
   §11 the door view · §12 the night · §13 details and the lookbook · §14 the reply · §15 the band ·
   §16 page turn and footer · §17 motion, §17b riding between floors · §18 print · §19 the arrival (the lift doors) · §20 the living city ·
   §21 the pass, handled · §22 the night slider */

/* §0 · type. Bodoni Moda, self-hosted from demo/assets/type (the user, 2026-10-02: Android has no Didone,
   so the names fell back to Noto Serif there). One variable file, the latin subset, weights 400–900 and
   the optical-size axis: at the names' size the hairlines draw as fine as a Didone's should
   (font-optical-sizing is auto). No italic file: the ampersand is the upright one (§2). OFL 1.1, the
   licence beside it. The sans stays the system's. */
@font-face {
  font-family: "Bodoni Moda"; font-style: normal; font-weight: 400 900; font-display: swap;
  src: url("../assets/type/bodoni-moda-opsz.woff2") format("woff2");
}

/* §1 · tokens. Gold sits on lines and type only, never as a large flat field (SITE4-PLAN.md §6). */
[data-skin="nadinerafael"] {
  --night: #0b0a09;
  --char: #161412;          /* panels */
  --char-2: #201d19;        /* raised panels, the plate */
  --line: #3b352d;          /* rules on the dark */
  --gold: #cdae72;          /* champagne gold: 9:1 on --night */
  --gold-hi: #e9d09a;
  --gold-dim: #8c7650;      /* rings at rest, decorative rules */
  --ivory: #f2ebdd;
  --mute: #b4aa98;          /* 7:1 on --char */

  --bg: var(--night);
  --bg-raised: var(--char);
  --ink: var(--ivory);
  --muted: var(--mute);
  --rule: var(--line);
  --accent: var(--gold);
  --accent-soft: rgb(205 174 114 / .12);
  --on-accent: #1d160b;
  --field: #100e0c;

  --display: "Bodoni Moda", Didot, "Bodoni 72", "Bodoni MT", Georgia, "Noto Serif", serif;
  --body: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --ui: var(--body);

  --step--1: .8125rem;
  --step-0: 1rem;
  --step-1: 1.2rem;
  --step-2: clamp(1.45rem, 1.2rem + 1.1vw, 2rem);
  --step-3: clamp(1.9rem, 1.4rem + 2.3vw, 3.1rem);
  --step-4: clamp(2.6rem, 1.6rem + 4.6vw, 5.4rem);

  --radius: 2px;
  --radius-card: 6px;
  --margin: clamp(1rem, 5vw, 3rem);
  --measure: 40rem;
  --module: clamp(3.5rem, 8vw, 6.5rem);
  --motion-fast: 220ms;
  --ease: cubic-bezier(.22, .61, .36, 1);
  --ease-soft: cubic-bezier(.16, .84, .24, 1);
  --focus-w: 2px;
  --focus-off: 3px;

  --a-reveal-dur: 900ms;
  --a-reveal-ease: var(--ease-soft);
  --a-rise-y: 18px;

  /* the pass image's palette and faces (pass.js draws the PNG from these) */
  --pass-ground: #121110;
  --pass-ground-2: #1c1a17;
  --pass-ink: var(--ivory);
  --pass-muted: var(--mute);
  --pass-accent: var(--gold);
  --pass-notch: var(--night);   /* the PNG is opaque: the night under its notches (S5) */
  --pass-display: var(--display);
  --pass-ui: var(--body);
}

/* §2 · base. Both html and body clip sideways (DECISIONS.md, the iPhone stand-in). */
html[data-skin="nadinerafael"] { overflow-x: clip; background: var(--night); color-scheme: dark; }
[data-skin="nadinerafael"] body {
  background: var(--night);
  color: var(--ink);
  font: var(--step-0)/1.6 var(--body);
  -webkit-font-smoothing: antialiased;
  overflow-x: clip;
}
[data-skin="nadinerafael"] a { color: inherit; text-decoration-thickness: 1px; text-underline-offset: .24em; text-decoration-color: var(--gold-dim); }
[data-skin="nadinerafael"] a:hover { color: var(--gold-hi); text-decoration-color: currentColor; }
[data-skin="nadinerafael"] main img:not([class|="orn"]) { background: var(--char-2); }   /* an ornament (orn-*) is alpha: no backing */
.amp { font-family: var(--display); font-style: normal; color: var(--gold); }   /* upright: no italic file is loaded, and a synthesised slant is worse */
.nw { white-space: nowrap; }
.kicker, .label {
  font: 600 var(--step--1)/1.4 var(--ui);
  letter-spacing: .24em;
  text-transform: uppercase;
  color: var(--gold);
}
.label { color: var(--mute); letter-spacing: .18em; }
.lede { font-size: var(--step-1); line-height: 1.55; color: var(--ink); max-width: 34em; }
.hint { font-size: var(--step--1); line-height: 1.5; color: var(--mute); }
.prose { max-width: 34em; }
.prose p + p { margin-top: 1em; }

/* §3 · the city behind every page: the view from this page's floor (SITE4-PLAN.md §7a). A fixed
   layer, not background-attachment: fixed (which iOS ignores). The picture and the cover's lights are
   one box sized like object-fit: cover (container units), so a light's % lands on its window at
   every crop. 100lvh, so the layer never resizes when a phone's address bar moves. */
.city {
  position: fixed; inset: 0 0 auto 0; z-index: 0;
  height: 100vh; height: 100lvh;
  overflow: hidden; pointer-events: none;
  container-type: size;
  background: var(--night);
}
.city-stage {
  position: absolute; left: 50%; top: 50%;
  width: max(100cqw, 160cqh); aspect-ratio: 8 / 5;
  translate: -50% -50%;
}
.city-stage > img { width: 100%; height: 100%; object-fit: cover; }
/* the veil: heavy on interior pages, where text runs over the view; light on the cover's first screen */
.city::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(rgb(11 10 9 / .8), rgb(11 10 9 / .86));
}
[data-floor="l"] .city::after {
  background:
    linear-gradient(rgb(11 10 9 / .55), rgb(11 10 9 / .12) 46%, rgb(11 10 9 / .2) 70%, rgb(11 10 9 / .62));
  transition: background-color 600ms var(--ease);
}
/* once the cover has been scrolled past its first screen, the city dims behind the panels */
[data-floor="l"][data-scrolled] .city::after { background-color: rgb(11 10 9 / .5); }   /* .35 left the story's small text over bright windows (2026-10-06) */
main, .foot, .turn { position: relative; z-index: 1; }

/* the cover's lit windows (lights.js): one per invitation that has said yes, a soft glow over a real
   lit window of the photograph (site.js → lights, measured on floor-l.jpg; SITE4-PLAN.md §4). */
.city-lights { position: absolute; inset: 0; --wave: 26ms; }
/* the photograph's own windows, dimmed on the cover's first screen (S1, 2026-10-08): the towers' band is
   already full of lit windows, so the glows were lost in it. Under the glows (first in the mount), over the
   picture; it goes once the cover is scrolled, when the whole veil darkens anyway. */
[data-floor="l"] .city-lights::before {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(transparent 12%, rgb(11 10 9 / .42) 24%, rgb(11 10 9 / .46) 58%, transparent 70%);
  transition: opacity 600ms var(--ease);
}
[data-floor="l"][data-scrolled] .city-lights::before { opacity: 0; }
/* 1.4× and warmer than the photograph's windows (S1): `scale`, so each glow stays centred on its window */
.light {
  position: absolute; left: var(--x); top: var(--y); width: var(--w); height: var(--h);
  border-radius: 50%;
  background: radial-gradient(closest-side, #ffe7b4, rgb(255 198 112 / .82) 45%, rgb(255 178 90 / 0));
  box-shadow: 0 0 .7rem .15rem rgb(255 186 96 / .36);
}
.light:not([data-yours]) { scale: 1.4; }
.light-tag { display: none; }
.light[data-yours] {
  z-index: 1;
  background: radial-gradient(closest-side, #fffaf0, rgb(255 228 170 / .9) 50%, rgb(255 210 140 / 0));
  box-shadow: 0 0 .5rem .2rem rgb(255 220 150 / .85), 0 0 2.2rem .6rem rgb(255 196 110 / .35);
}
/* the tag hangs BELOW the window, in the dark of the palms: above it, it met the cover's words and Look
   closer on a laptop (2026-10-06) */
.light[data-yours] .light-tag {
  display: block; position: absolute; left: 50%; top: calc(100% + 1.6rem); translate: -50% 0;
  font: 600 .75rem/1 var(--ui); letter-spacing: .24em; text-transform: uppercase; color: var(--gold-hi);
  white-space: nowrap; text-shadow: 0 1px 8px rgb(0 0 0 / .9);
}
.light[data-yours] .light-tag::after {
  content: ""; position: absolute; left: 50%; bottom: calc(100% + .35rem); width: 1px; height: 1.05rem; background: var(--gold-hi);
}

/* §4 · the frame: one narrow centred column on the dark field */
.wrap { width: 100%; max-width: calc(var(--measure) + 2 * var(--margin)); margin-inline: auto; padding-inline: var(--margin); }
.wrap--wide { max-width: calc(64rem + 2 * var(--margin)); }
.section { padding-block: var(--module); }
.head { padding-top: clamp(5.5rem, 13vh, 8.5rem); padding-bottom: calc(var(--module) / 2); display: grid; gap: .9rem; }
.head-floor { display: flex; align-items: center; gap: .9rem; }
.head-floor b { font: 400 var(--step-2)/1 var(--display); color: var(--gold); }
.head-title { font: 400 var(--step-4)/.98 var(--display); letter-spacing: -.01em; text-wrap: balance; }
.band-head { display: grid; gap: .6rem; margin-bottom: 2rem; }
.band-title { font: 400 var(--step-3)/1.05 var(--display); }
.band-head--gap { margin-top: var(--module); }
/* the gold rule between sections (orn-rule.webp); a plain hairline under it, so a missing file is a rule */
.rule { position: relative; height: 2.5rem; }
.rule::before { content: ""; position: absolute; left: 22%; right: 22%; top: 50%; border-top: 1px solid var(--gold-dim); opacity: .5; }
/* the ornament (orn-rule.webp) only once reveal.js has seen the rule: a background below the first
   screen would otherwise download at once (DECISIONS.md, the page-weight budget) */
.rule[data-seen]::after {
  content: ""; position: absolute; left: 50%; top: 50%; translate: -50% -50%;
  width: min(24rem, 70%); aspect-ratio: 10 / 1;
  background: url("../assets/nadinerafael/orn-rule.webp") center / contain no-repeat;
}

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: .6rem;
  min-height: 48px; padding: 0 1.7rem;
  border: 1px solid var(--gold); border-radius: var(--radius);
  background: transparent; color: var(--gold-hi);
  font: 600 var(--step--1)/1 var(--ui); letter-spacing: .2em; text-transform: uppercase; text-decoration: none;
  transition: background var(--motion-fast) var(--ease), color var(--motion-fast) var(--ease), border-color var(--motion-fast) var(--ease);
}
[data-skin="nadinerafael"] a.btn { color: var(--gold-hi); text-decoration: none; }
.btn:hover, [data-skin="nadinerafael"] a.btn:hover { background: var(--gold); border-color: var(--gold); color: var(--on-accent); }
.btn--solid { background: var(--gold); color: var(--on-accent); }
[data-skin="nadinerafael"] a.btn--solid { color: var(--on-accent); }
.btn--solid:hover, [data-skin="nadinerafael"] a.btn--solid:hover { background: var(--gold-hi); border-color: var(--gold-hi); }
.btn--quiet { border-color: var(--line); color: var(--ivory); min-height: 44px; padding: 0 1.2rem; }
.btn:disabled { opacity: .45; cursor: not-allowed; }
.btn:disabled:hover { background: transparent; color: var(--gold-hi); border-color: var(--gold); }
.more { font-weight: 600; text-decoration: none; border-bottom: 1px solid var(--gold-dim); padding-bottom: .15rem; color: var(--gold-hi); }
.more::after { content: " →"; }
.panel { background: rgb(22 20 18 / .94); border: 1px solid var(--line); border-radius: var(--radius-card); padding: clamp(1.4rem, 4vw, 2.4rem); }

/* §5 · the car panel (the user's pick, A: lab/share/nadinerafael-lift-nav.html). The pages are floors.
   Desktop, from 80em: a charcoal plate fixed at mid-height on the right, a lit display at its head
   and a brass-ringed button per floor, its name engraved beside it. Below 80em: a call button bottom
   right that raises the plate within thumb reach. Behaviour is chrome.js as it is (toggle, Escape,
   outside tap, any link) plus its floor display (data-wsd-el="travel"). DOM order is L → R, so tab
   order goes up the building; the plate shows R at the top. Gold on the rings and lettering only. */
.car { position: fixed; z-index: 40; right: 0; bottom: 0; }
.plate {
  display: none;
  position: fixed; right: max(1rem, env(safe-area-inset-right)); bottom: calc(5.6rem + env(safe-area-inset-bottom));
  width: 15.5rem; padding: 1rem 1rem 1.15rem;
  background: linear-gradient(90deg, #1a1816, #262320 48%, #1a1816);
  border: 1px solid var(--gold-dim); border-radius: 10px;
  box-shadow: 0 24px 60px rgb(0 0 0 / .6), inset 0 1px 0 rgb(255 255 255 / .05);
}
.plate[data-open] { display: grid; gap: .8rem; }
.plate-disp {
  justify-self: end;
  display: flex; align-items: center; justify-content: center; gap: .35rem;
  min-width: 3.9rem; height: 2.6rem; padding: 0 .55rem;
  border-radius: 4px; background: #070706; border: 1px solid #3d362b;
  color: var(--gold); font: 500 1.3rem/1 ui-monospace, "Cascadia Mono", Consolas, monospace;
  text-shadow: 0 0 9px rgb(201 169 106 / .65);
}
.plate-arrow { font-size: .62rem; opacity: .85; min-width: .7rem; }
.plate-arrow::before { content: "\25B2"; }
.car[data-dir="down"] .plate-arrow::before { content: "\25BC"; }
.plate-list { display: flex; flex-direction: column-reverse; gap: .55rem; }
.floor {
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  min-height: 48px; text-decoration: none; color: var(--mute);
}
[data-skin="nadinerafael"] .floor { text-decoration: none; }
.floor-name { font: 600 .75rem/1.2 var(--ui); letter-spacing: .2em; text-transform: uppercase; white-space: nowrap; }
.floor-ring {
  flex: none; width: 46px; height: 46px; border-radius: 50%;
  display: grid; place-items: center;
  border: 1.5px solid var(--gold-dim); color: var(--ivory);
  font: 500 .95rem/1 var(--ui);
  background: radial-gradient(circle at 50% 35%, #2e2a25, #161412);
  transition: box-shadow var(--motion-fast) var(--ease), border-color var(--motion-fast) var(--ease), color var(--motion-fast) var(--ease);
}
.floor:hover .floor-ring { border-color: var(--gold); }
.floor:hover .floor-name, .floor[aria-current="page"] .floor-name { color: var(--ivory); }
.floor[aria-current="page"] .floor-ring {
  border-color: var(--gold); color: var(--gold);
  box-shadow: 0 0 0 4px rgb(201 169 106 / .13), 0 0 16px rgb(201 169 106 / .5);
}
/* the story as a ride (A1, 2026-10-08): as Going up scrolls, the display counts with the story's floors
   and the floor it is passing lights, a little less than the one you are on */
.floor[data-wsd-passing] .floor-ring {
  border-color: var(--gold); color: var(--gold-hi);
  box-shadow: 0 0 12px rgb(201 169 106 / .45);
}
.floor[data-wsd-passing] .floor-name { color: var(--ivory); }
.floor:focus-visible { outline: none; }
.floor:focus-visible .floor-ring { outline: 2px solid var(--ivory); outline-offset: 3px; }
.car-call {
  position: fixed; right: max(1rem, env(safe-area-inset-right)); bottom: calc(1.25rem + env(safe-area-inset-bottom));
  display: flex; align-items: center; gap: .75rem;
  height: 60px; padding: 0 6px 0 1.2rem;
  border-radius: 30px; border: 1px solid var(--gold-dim);
  background: var(--char); color: var(--ivory);
  font: 600 .75rem/1 var(--ui); letter-spacing: .2em; text-transform: uppercase;
  box-shadow: 0 10px 30px rgb(0 0 0 / .55);
}
.car-call .floor-ring { border-color: var(--gold); color: var(--gold); font-family: ui-monospace, "Cascadia Mono", Consolas, monospace; }
.car-call .say-close { display: none; }
.car-call[aria-expanded="true"] .say-open { display: none; }
.car-call[aria-expanded="true"] .say-close { display: inline; }
@media (min-width: 80em) {
  .car-call { display: none; }
  .plate, .plate[data-open] {
    display: grid; gap: .85rem; justify-items: center;
    right: 2.5rem; top: 50%; bottom: auto; translate: 0 -50%;
    width: auto; padding: 1rem 1rem 1.2rem;
  }
  .plate-disp { justify-self: center; }
  .floor { position: relative; justify-content: center; }
  /* the names sit beside the buttons, like the plates engraved beside real ones */
  .floor-name { position: absolute; right: calc(100% + 1.6rem); top: 50%; translate: 0 -50%; text-align: right; text-shadow: 0 1px 10px rgb(0 0 0 / .9); }
}
@media (prefers-reduced-motion: no-preference) {
  .plate[data-open] { animation: nr-rise 300ms var(--ease-soft) both; }
  .car[data-travel] .plate-arrow { animation: nr-blink 640ms steps(2, jump-none) infinite; }
}
@media (min-width: 80em) and (prefers-reduced-motion: no-preference) { .plate[data-open] { animation: none; } }

/* §6 · the design-study tab: always readable, top left on every page; its panel drops beneath */
.study { position: fixed; z-index: 41; left: max(1rem, env(safe-area-inset-left)); top: 1rem; }
.study-tab, .demo-btn {
  display: inline-flex; align-items: center; gap: .55rem;
  min-height: 44px; padding: 0 1rem;
  border: 1px solid var(--line); border-radius: 22px;
  background: rgb(22 20 18 / .9); color: var(--ivory);
  font: 600 .75rem/1 var(--ui); letter-spacing: .18em; text-transform: uppercase;
  -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
}
.study-tab:hover, .demo-btn:hover { border-color: var(--gold); color: var(--gold-hi); }
.study-dot { width: .5rem; height: .5rem; border-radius: 50%; background: var(--gold); box-shadow: 0 0 8px rgb(205 174 114 / .8); }
.study-panel {
  position: absolute; top: calc(100% + .6rem); left: 0; z-index: 2;
  width: min(23rem, calc(100vw - 2rem));
  padding: 1.2rem; display: grid; gap: .85rem;
  background: var(--char-2); border: 1px solid var(--gold-dim); border-radius: var(--radius-card);
  box-shadow: 0 20px 50px rgb(0 0 0 / .6);
}
.study-panel p { font-size: var(--step--1); line-height: 1.55; }
.study-ctl { display: flex; flex-wrap: wrap; gap: .5rem; }
.demo-btn { background: transparent; border-radius: var(--radius); }

/* §7 · the cover. The city from the lobby fills the screen; the names are set in gold in the sky
   above the towers; the windows light as the guests say yes (§3), the visitor's own last. */
.cover {
  min-height: 100svh;
  display: grid; align-content: start; justify-items: center; text-align: center; gap: .55rem;
  padding: clamp(4.6rem, 11svh, 8rem) var(--margin) calc(5.5rem + env(safe-area-inset-bottom));
}
/* the Floors button sits bottom right below 80em: the note about the windows rests above it */
@media (min-width: 80em) { .cover { padding-bottom: 2.5rem; } }
/* the Deco fan (orn-fan.webp) rises behind the names, out of the flow: a missing file leaves nothing */
.names { position: relative; isolation: isolate; }
.names::before {
  content: ""; position: absolute; z-index: -1; left: 50%; bottom: 62%; translate: -50% 0;
  width: min(30rem, 86vw); aspect-ratio: 2 / 1;
  background: url("../assets/nadinerafael/orn-fan.webp") center bottom / contain no-repeat;
  opacity: .3;   /* the delivered fan is solid rays, not fine lines: at .55 it out-shone the kicker and the names (2026-10-06) */
}
/* on a phone the names stack, so a fan 86vw wide ran off the top of the screen and under the study tab */
@media (max-width: 40em) { .names::before { width: 60vw; } }
/* from 834 the fan's top was cut off by the screen (S14, 2026-10-08): the words come down and the fan
   scales with the screen's height, so its top shows with air above it. The gaps tighten to give the drop
   back, because your window (y 65.5%) sits just under the note about the windows on a laptop. */
@media (min-width: 52em) {
  .cover { padding-top: clamp(6rem, 14svh, 10rem); gap: .35rem; }
  .cover .cover-cta { margin-top: .45rem; }
  .names::before { width: min(26rem, 86vw, 36svh); }
}
/* a short laptop screen (S15, 2026-10-09): under the reply the note about the windows ended below your window
   (504 / 484px at 1280 × 720), so it sits beside the reply instead. Two columns for that one row only; after the
   wedding, with the reply gone, it goes back to the middle. */
@media (min-width: 52em) and (max-height: 48em) {
  .cover { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); column-gap: 1.5rem; }
  .cover > * { grid-column: 1 / -1; }
  .cover > .cover-cta { grid-column: 1; justify-self: end; align-self: center; }
  .cover > .cover-lights { grid-column: 2; justify-self: start; align-self: center; margin-top: .45rem; max-width: 24em; text-align: left; }
  [data-phase="after"] .cover > .cover-lights { grid-column: 1 / -1; justify-self: center; text-align: center; }
}
.cover .kicker { text-shadow: 0 1px 12px rgb(0 0 0 / .8); }
.names {
  font: 400 clamp(3rem, 1.6rem + 7vw, 7.4rem)/.92 var(--display);
  letter-spacing: -.01em; color: var(--gold-hi);
  text-shadow: 0 2px 30px rgb(0 0 0 / .65);
  text-wrap: balance;
}
.names .amp { display: block; font-size: .5em; line-height: 1.1; color: var(--gold); }
@media (min-width: 40em) { .names .amp { display: inline; font-size: .62em; } }
.cover-date, .cover-place, .cover-lights { text-wrap: balance; }
.cover-date { font: 400 var(--step-1)/1.4 var(--display); color: var(--ivory); text-shadow: 0 1px 14px rgb(0 0 0 / .9); }
.cover-place { font-size: var(--step--1); letter-spacing: .14em; text-transform: uppercase; color: var(--ivory); text-shadow: 0 1px 12px rgb(0 0 0 / .95); }
.cover-cta { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: .6rem 1rem; margin-top: .7rem; }
.cover-cta--start { justify-content: flex-start; }
/* after a yes (guests.js → <html data-reply>), the cover's Reply becomes Your pass, up on 28 (S3) */
.cta-pass, [data-reply="yes"] .cover-cta :is(.cta-reply, .hint) { display: none; }
[data-reply="yes"] .cover-cta .cta-pass { display: inline-flex; }
/* its own small ground: lit windows sit behind it on a phone (pixcontrast p10 2.8 without it) */
.cover-cta .hint { color: var(--ivory); padding: .25rem .6rem; border-radius: 3px; background: rgb(11 10 9 / .62); }
.count { font: 400 var(--step-0)/1.4 var(--display); color: var(--ivory); text-shadow: 0 1px 12px rgb(0 0 0 / .9); }
.count b { font-weight: 400; font-variant-numeric: lining-nums tabular-nums; color: var(--gold-hi); }
.count-after { display: none; }
[data-phase="after"] .count-before { display: none; }
[data-phase="after"] .count-after { display: inline; }
[data-phase="after"] .cover-cta { display: none; }
/* on the night (A3, 2026-10-08): the countdown gives way to now and next from the running order, so the
   first screen is the useful one. Shown only while schedule.js says the night is on. */
.cover-live { display: none; font: 400 var(--step-1)/1.4 var(--display); color: var(--ivory); text-shadow: 0 1px 12px rgb(0 0 0 / .9); text-wrap: balance; }
.cover-live[data-live="night"] { display: block; }
.cover:has(.cover-live[data-live="night"]) .count { display: none; }
.cl-label { font: 600 .75rem/1 var(--ui); letter-spacing: .3em; text-transform: uppercase; color: var(--gold); vertical-align: .15em; }
.cover-live [data-wsd-field="title"] { color: var(--gold-hi); }
.cl-next { color: var(--ivory); }

/* the line about the windows sits low on the first screen, over the city, on its own small ground */
.cover-lights {
  align-self: end; margin-top: auto;
  max-width: 30em; padding: .7rem 1rem;
  background: rgb(11 10 9 / .62); border: 1px solid rgb(205 174 114 / .25); border-radius: var(--radius-card);
  font-size: var(--step--1); line-height: 1.5; color: var(--ivory);
}
.cover-lights b { font-weight: 600; color: var(--gold-hi); font-variant-numeric: lining-nums; }

/* §8 · the panels under the first screen: the invitation, the story by floor, the pass */
.invite { display: grid; gap: 1.1rem; text-align: center; justify-items: center; }
.invite-say { font: 400 var(--step-3)/1.18 var(--display); max-width: 20em; text-wrap: balance; }
.invite-links { display: flex; flex-wrap: wrap; justify-content: center; gap: .5rem 1.6rem; }
.invite-links a { min-height: 44px; display: inline-flex; align-items: center; }
.going { display: grid; gap: 1.6rem; }
.going-shot { margin: 0; }
.going-shot img { width: 100%; height: auto; border-radius: var(--radius-card); }
.going-list { display: grid; border-top: 1px solid var(--line); }
.going-list li { display: grid; grid-template-columns: 3.2rem minmax(0, 1fr); gap: 1rem; padding-block: 1rem; border-bottom: 1px solid var(--line); }
.going-floor {
  width: 2.6rem; height: 2.6rem; border-radius: 50%; display: grid; place-items: center;
  border: 1.5px solid var(--gold-dim); color: var(--gold); font: 500 .85rem/1 var(--ui);
}
.going-list b { display: block; font: 400 var(--step-1)/1.3 var(--display); color: var(--ivory); margin-bottom: .2rem; }
.going-list p { color: var(--mute); }
/* a still from that floor of their story (story-01…03, the user, 2026-10-06): small, under the words */
.going-still { margin: .9rem 0 .2rem; max-width: 30rem; }
.going-still img { width: 100%; height: auto; aspect-ratio: 3 / 2; object-fit: cover; border-radius: var(--radius-card); }
@media (min-width: 56em) {
  .going { grid-template-columns: minmax(0, 5fr) minmax(0, 6fr); align-items: start; column-gap: 3rem; }
}
/* the photograph stays beside the floors as they scroll (S13, 2026-10-08): once it scrolled past, the left
   half was bare city for two screens. A grid item, so it travels within its row; phones unchanged. */
@media (min-width: 64em) {
  .going-shot { position: sticky; top: clamp(1.5rem, 10vh, 6rem); }
}
.teaser { display: grid; gap: 1rem; justify-items: start; }

/* §9 · tickets: the pass and the programme. A charcoal panel with a tear line across it and a notch
   cut at each end (a mask, so the city shows through the notches), and Deco corners (orn-corner). */
.ticket {
  --notch: 13px; --tear: 70%;
  position: relative;
  background: linear-gradient(180deg, var(--char-2), var(--char) 40%, var(--char));
  border: 1px solid var(--gold-dim); border-radius: var(--radius-card);
  -webkit-mask:
    radial-gradient(circle at left var(--tear), transparent var(--notch), #000 calc(var(--notch) + .5px)) left / 51% 100% no-repeat,
    radial-gradient(circle at right var(--tear), transparent var(--notch), #000 calc(var(--notch) + .5px)) right / 51% 100% no-repeat;
  mask:
    radial-gradient(circle at left var(--tear), transparent var(--notch), #000 calc(var(--notch) + .5px)) left / 51% 100% no-repeat,
    radial-gradient(circle at right var(--tear), transparent var(--notch), #000 calc(var(--notch) + .5px)) right / 51% 100% no-repeat;
}
.ticket::after {
  content: ""; position: absolute; left: calc(var(--notch) + .6rem); right: calc(var(--notch) + .6rem); top: var(--tear);
  border-top: 2px dotted var(--gold-dim); pointer-events: none;
}
/* the Deco corners (orn-corner.webp): backgrounds, so a missing file leaves nothing */
.corners i {
  position: absolute; width: clamp(3rem, 9vw, 4.6rem); aspect-ratio: 1; pointer-events: none; opacity: .9;
  background: url("../assets/nadinerafael/orn-corner.webp") 0 0 / contain no-repeat;
}
.c-tl { top: .5rem; left: .5rem; }
.c-tr { top: .5rem; right: .5rem; transform: scaleX(-1); }
.c-bl { bottom: .5rem; left: .5rem; transform: scaleY(-1); }
.c-br { bottom: .5rem; right: .5rem; transform: scale(-1, -1); }

/* §10 · the pass (pass.js). The card on screen is this markup; the saved PNG is the engine's drawing
   in the tokens above, its words read from data-wsd-print. Sample before a reply, yours after one. */
.pass-page { display: grid; gap: 1.6rem; justify-items: center; padding-bottom: var(--module); }
.pass-side { display: grid; gap: 1.2rem; justify-items: center; width: 100%; }
@media (min-width: 56em) {
  .pass-page { grid-template-columns: minmax(0, 25rem) minmax(0, 1fr); align-items: center; column-gap: clamp(2rem, 5vw, 4rem); justify-items: stretch; }
  .pass-side { justify-items: start; }
  .pass-side .pass-say, .pass-side .pass-said { text-align: left; justify-items: start; }
  [data-pass] .pass-side .pass-say > * { justify-items: start; }
  .pass-side .pass-actions { grid-template-columns: 1fr; width: min(100%, 18rem); }
}
.pass-wrap { position: relative; width: min(100%, 25rem); }
.pass { --tear: 74%; padding: 2.4rem 1.6rem 1.6rem; display: grid; gap: 1.2rem; text-align: center; }
.pass-head { display: grid; gap: .45rem; justify-items: center; }
.pass-names { font: 600 .78rem/1.2 var(--ui); letter-spacing: .32em; text-transform: uppercase; color: var(--gold); }
/* the fan between the names and "Admit": a background in a reserved band, so a missing file is a gap */
.pass-head::before { content: ""; order: 1; width: 7rem; aspect-ratio: 2 / 1; background: url("../assets/nadinerafael/orn-fan.webp") center bottom / contain no-repeat; }
.pass-names { order: 0; }
.pass-kicker, .pass-name, .pass-party { order: 2; }
.pass-kicker { font: 600 .75rem/1 var(--ui); letter-spacing: .32em; text-transform: uppercase; color: var(--mute); margin-top: .4rem; }
.pass-name { font: 400 clamp(2rem, 1.4rem + 3vw, 2.8rem)/1.02 var(--display); color: var(--ivory); overflow-wrap: anywhere; }
.pass-party { min-height: 1.4em; color: var(--mute); }
.pass-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem .8rem; padding-top: 1rem; border-top: 1px solid var(--line); }
.pass-grid div { display: grid; gap: .25rem; }
.pass-grid dt { font: 600 .7rem/1.2 var(--ui); letter-spacing: .22em; text-transform: uppercase; color: var(--mute); }
.pass-grid dd { margin: 0; font: 400 1.15rem/1.25 var(--display); color: var(--ivory); }
.pass-dress { font-size: var(--step--1); letter-spacing: .08em; color: var(--gold); padding-bottom: 1.4rem; }
.pass-stub { display: grid; gap: .55rem; justify-items: center; padding-top: .8rem; }
/* the drawn code: rays made from the name (the engine stamps --i --n --v on each mark). An ornament,
   never a scannable code, and the card says so. */
.pass-code { position: relative; width: 9.6rem; aspect-ratio: 1; --r0: 2.35rem; }
.pass-code::before { content: ""; position: absolute; inset: calc(50% - 2.05rem); border: 1px solid var(--gold-dim); border-radius: 50%; }
.mark {
  position: absolute; left: 50%; top: 50%;
  width: 3px; height: calc(.8rem + var(--v) * 1.85rem); margin-left: -1.5px;
  border-radius: 2px; background: var(--gold);
  opacity: calc(.45 + var(--v) * .55);
  transform-origin: 50% 0;
  transform: rotate(calc(var(--i) / var(--n) * 1turn + .5turn)) translateY(var(--r0));
}
.pass-initials { position: absolute; inset: 0; display: grid; place-items: center; font: 400 1.6rem/1 var(--display); color: var(--gold-hi); }
.pass-number { font: 600 .75rem/1 var(--ui); letter-spacing: .26em; text-transform: uppercase; color: var(--mute); }
.pass-number span { color: var(--gold-hi); }
.pass-note { font-size: .75rem; color: var(--mute); }
.pass-stamp {
  /* in the band reserved for the fan, between the names and "Admit", so it lies over no words */
  position: absolute; top: 6.5rem; left: 50%; translate: -50% -50%; rotate: -8deg;
  padding: .35rem 1rem; border: 2px solid var(--gold); border-radius: 3px;
  font: 600 .95rem/1 var(--ui); letter-spacing: .4em; text-transform: uppercase; color: var(--gold);
  background: rgb(11 10 9 / .6); pointer-events: none;
}
[data-pass="yours"] .pass-stamp { display: none; }
[data-pass="regrets"] .pass-wrap { opacity: .4; }
.pass-say { text-align: center; max-width: 30em; display: grid; gap: .5rem; justify-items: center; }
.pass-say > * { display: none; }
[data-pass="sample"] .say-sample, [data-pass="yours"] .say-yours, [data-pass="regrets"] .say-regrets { display: grid; gap: .6rem; justify-items: center; }
.pass-actions { display: grid; gap: .6rem; width: min(100%, 25rem); }
/* three across only where each label fits on one line (at 30em they were 127px and every label wrapped) */
@media (min-width: 40em) { .pass-actions { width: min(100%, 36rem); grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.pass-actions .btn { padding: 0 .9rem; letter-spacing: .14em; }
[data-pass="sample"] .pass-actions, [data-pass="regrets"] .pass-actions { display: none; }
[data-phase="after"] [data-wsd-el="calendar"] { display: none; }
.pass-said { text-align: center; color: var(--gold-hi); }
.pass-how { display: grid; gap: 1rem; }
.pass-how ol { display: grid; gap: .8rem; counter-reset: step; }
.pass-how li { display: grid; grid-template-columns: 2.4rem minmax(0, 1fr); gap: .8rem; counter-increment: step; }
.pass-how li::before {
  content: counter(step); width: 2.1rem; height: 2.1rem; border-radius: 50%; display: grid; place-items: center;
  border: 1.5px solid var(--gold-dim); color: var(--gold); font: 500 .85rem/1 var(--ui);
}
/* the reveal: gold leaf falls once over a pass seen for the first time (orn-fleck-01…03; a drawn
   speck under each, so a missing file still falls as gold) */
.flecks { position: absolute; inset: -2rem -1rem 0; pointer-events: none; overflow: hidden; z-index: 2; }
.flecks i {
  position: absolute; top: -10%; left: var(--fx); width: var(--fs, 18px); aspect-ratio: 1; opacity: 0;
  background: center / contain no-repeat;
}
.flecks i::before {
  content: ""; position: absolute; inset: 22%; z-index: -1; border-radius: 50%;
  background: radial-gradient(closest-side, var(--gold-hi), rgb(205 174 114 / .6) 55%, transparent);
}
/* nine pieces of leaf: where each starts, how big, when, how far it drifts and turns */
.flecks i:nth-child(1) { --fx: 8%; --fs: 16px; --fdel: .15s; --fd: 2.4s; --drift: 1.4rem; --spin: 300deg; }
.flecks i:nth-child(2) { --fx: 21%; --fs: 22px; --fdel: .5s; --fd: 2.9s; --drift: -.8rem; --spin: -220deg; }
.flecks i:nth-child(3) { --fx: 34%; --fs: 14px; --fdel: .05s; --fd: 2.2s; --drift: 2rem; --spin: 180deg; }
.flecks i:nth-child(4) { --fx: 46%; --fs: 20px; --fdel: .7s; --fd: 3.1s; --drift: -1.6rem; --spin: 340deg; }
.flecks i:nth-child(5) { --fx: 57%; --fs: 13px; --fdel: .3s; --fd: 2.5s; --drift: 1rem; --spin: -260deg; }
.flecks i:nth-child(6) { --fx: 66%; --fs: 24px; --fdel: .9s; --fd: 3.3s; --drift: -1.1rem; --spin: 200deg; }
.flecks i:nth-child(7) { --fx: 76%; --fs: 15px; --fdel: .2s; --fd: 2.3s; --drift: 1.8rem; --spin: -320deg; }
.flecks i:nth-child(8) { --fx: 86%; --fs: 19px; --fdel: .6s; --fd: 2.8s; --drift: -.6rem; --spin: 240deg; }
.flecks i:nth-child(9) { --fx: 93%; --fs: 12px; --fdel: 1s; --fd: 2.6s; --drift: -1.4rem; --spin: -180deg; }
.flecks i:nth-child(3n+1) { background-image: url("../assets/nadinerafael/orn-fleck-01.webp"); }
.flecks i:nth-child(3n+2) { background-image: url("../assets/nadinerafael/orn-fleck-02.webp"); }
.flecks i:nth-child(3n) { background-image: url("../assets/nadinerafael/orn-fleck-03.webp"); }

/* §11 · the door view: full screen, gold on black, the name as large as the screen allows. Outside
   <main> on purpose (a transformed main would trap a fixed overlay). */
.door {
  position: fixed; inset: 0; z-index: 60;
  display: grid; place-items: center; overflow-y: auto;
  padding: 1.5rem var(--margin) 2rem;
  background: #000; color: var(--gold-hi); text-align: center;
}
.door-in { display: grid; gap: 1rem; justify-items: center; width: min(100%, 34rem); }
.door-names { font: 600 .8rem/1.2 var(--ui); letter-spacing: .32em; text-transform: uppercase; color: var(--gold); }
.door-name { font: 400 clamp(2.6rem, 1.6rem + 7vw, 5.4rem)/1 var(--display); color: #fff3d6; overflow-wrap: anywhere; }
.door-party { font-size: var(--step-1); color: var(--gold); }
.door .pass-code { width: min(15rem, 60vw); --r0: min(3.6rem, 14.5vw); }
.door .mark { height: calc(1.1rem + var(--v) * min(2.8rem, 10vw)); width: 4px; margin-left: -2px; background: var(--gold-hi); }
.door .pass-code::before { inset: calc(50% - min(3.15rem, 12.7vw)); }
.door .pass-initials { font-size: clamp(2rem, 6vw, 2.6rem); }
.door-number { font: 600 1rem/1 var(--ui); letter-spacing: .3em; text-transform: uppercase; color: var(--gold); }
.door-note { font-size: var(--step--1); color: #c9bda3; max-width: 26em; }
.door-close { margin-top: .5rem; }
html[data-door] { overflow: hidden; }
html[data-door] .car, html[data-door] .study { visibility: hidden; }

/* §12 · the night (schedule.js, live): now and next on a ticket, the programme below it */
/* the pass card's inner spacing (S8, 2026-10-08): at 1.8rem / 1.4rem the corners sat about 8px from the
   first line. --pad-x is read by the tear line and its notches below. */
.live { --tear: 58%; --pad-x: 1.6rem; padding: 2.6rem var(--pad-x) 1.6rem; display: grid; gap: 1.6rem; }
.live-now, .live-next { display: grid; gap: .3rem; }
.nn-label { font: 600 .72rem/1 var(--ui); letter-spacing: .3em; text-transform: uppercase; color: var(--gold); }
.nn-label + .nn-time { margin-top: .35rem; }   /* NEXT sat right on the time */
.nn-time { font: 400 var(--step-2)/1 var(--display); color: var(--gold-hi); font-variant-numeric: lining-nums; }
.nn-title { font: 400 var(--step-3)/1.05 var(--display); color: var(--ivory); }
.live-next .nn-title { font-size: var(--step-2); }
.nn-note { color: var(--mute); }
.nn-left { font-size: var(--step--1); letter-spacing: .08em; color: var(--gold); }
.live-before { display: none; color: var(--mute); }
[data-live="before"] .live-before, [data-live="after"] .live-over { display: block; }
.live-over { display: none; font: 400 var(--step-2)/1.2 var(--display); }
[data-live="before"] .nn-label-next::after { content: ""; }
.live-skip { display: flex; flex-wrap: wrap; align-items: center; gap: .7rem 1rem; padding-top: 1.4rem; }
/* this ticket's content changes height through the evening (now, next, Back to today), so its tear follows
   the content, at the top of .live-skip, not a % of the ticket: at 58% it crossed "… days to the night" at
   every width (2026-10-06). The notches are two discs in the page's night, not the mask's cut. */
.live { -webkit-mask: none; mask: none; }
.live::after { display: none; }
.live-skip { position: relative; }
.live-skip::before {
  content: ""; position: absolute; top: -1px; left: calc(var(--notch) + .6rem - var(--pad-x)); right: calc(var(--notch) + .6rem - var(--pad-x));
  border-top: 2px dotted var(--gold-dim); pointer-events: none;
}
/* only the halves inside the ticket: whole discs put a dark bump over the city outside each edge (2026-10-07) */
.live-skip::after {
  content: ""; position: absolute; top: calc(-1 * var(--notch)); left: calc(-1 * var(--pad-x) - 1px); right: calc(-1 * var(--pad-x) - 1px);
  height: calc(2 * var(--notch)); pointer-events: none;
  background:
    radial-gradient(circle at 0 50%, var(--night) var(--notch), transparent calc(var(--notch) + .5px)),
    radial-gradient(circle at 100% 50%, var(--night) var(--notch), transparent calc(var(--notch) + .5px));
}
.skip-said { font: 400 var(--step-1)/1.2 var(--display); color: var(--ivory); }
.skip-said b { font-weight: 400; font-variant-numeric: lining-nums tabular-nums; color: var(--gold-hi); }
/* before the night the cover's countdown, after that the said line (S7): never both */
[data-live="before"] .skip-on, [data-wsd="schedule"]:not([data-live="before"]) .skip-count { display: none; }
/* "simulated" belongs to the slider, not to the count (S7, 2026-10-08) */
.skip-sim { font: 600 .72rem/1 var(--ui); letter-spacing: .2em; text-transform: uppercase; color: var(--gold); }
.scrub-label .skip-sim { font-size: inherit; letter-spacing: inherit; }
.live-skip .hint { flex-basis: 100%; }
.prog { display: grid; border-top: 1px solid var(--gold-dim); }
.prog-item { display: grid; grid-template-columns: 5.6rem minmax(0, 1fr); gap: 1rem; padding: 1rem 0; border-bottom: 1px solid var(--line); }
.prog-time { font: 400 var(--step-1)/1.2 var(--display); color: var(--gold); font-variant-numeric: lining-nums; }
.prog-title { font: 600 var(--step-0)/1.3 var(--body); color: var(--ivory); }
.prog-note { color: var(--mute); font-size: .95rem; }
.prog-item[data-state="past"] { opacity: .5; }
.prog-item[data-state="now"] { background: linear-gradient(90deg, rgb(205 174 114 / .14), transparent 80%); box-shadow: inset 2px 0 0 var(--gold); padding-left: .8rem; }
.prog-item[data-state="now"] .prog-title::after {
  content: ""; display: inline-block; width: .5rem; height: .5rem; margin-left: .6rem; vertical-align: .1em;
  border-radius: 50%; background: var(--gold-hi); box-shadow: 0 0 8px var(--gold);
}

/* §13 · details: the roof, getting there, and the dress code as a lookbook with a colour check */
.venue { display: grid; gap: 1.2rem; }
.venue figure { margin: 0; }
.venue img { width: 100%; height: auto; border-radius: var(--radius-card); }
.venue-name { font: 400 var(--step-3)/1.05 var(--display); }
.qa { display: grid; border-top: 1px solid var(--gold-dim); }
.qa-row { display: grid; gap: .35rem; padding-block: 1.1rem; border-bottom: 1px solid var(--line); }
.qa dt { font: 400 var(--step-2)/1.1 var(--display); color: var(--ivory); }
.qa dd { margin: 0; color: var(--mute); max-width: 36em; }
.looks { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1.4rem 1rem; }
@media (min-width: 56em) { .looks { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 2rem 1.4rem; } }
.look { margin: 0; display: grid; gap: .6rem; align-content: start; }
.look img { width: 100%; height: auto; aspect-ratio: 2 / 3; object-fit: cover; border-radius: var(--radius-card); }
.look figcaption { display: grid; gap: .15rem; }
.look b { font: 400 var(--step-1)/1.2 var(--display); color: var(--ivory); }
.look span { font-size: .9rem; color: var(--mute); }
/* check this look (A5, 2026-10-08): asks Check my colour about the look's colours (colours.js) */
.look-check {
  justify-self: start; min-height: 44px; padding: 0; border: 0; background: none; cursor: pointer;
  color: var(--gold); font: 600 .7rem/1.2 var(--ui); letter-spacing: .2em; text-transform: uppercase; text-align: left;
  text-decoration: underline; text-decoration-color: var(--gold-dim); text-underline-offset: .45em;
}
.look-check:hover { color: var(--gold-hi); }
.look-check:focus-visible { outline: 2px solid var(--ivory); outline-offset: 3px; }
.check { display: grid; gap: 1.2rem; }
.swatches { display: flex; flex-wrap: wrap; gap: .6rem; }
.swatch {
  display: inline-flex; align-items: center; gap: .55rem;
  min-height: 44px; padding: 0 .9rem 0 .5rem;
  border: 1px solid var(--line); border-radius: 22px; background: var(--char);
  color: var(--ivory); font: 500 .875rem/1 var(--ui);
}
.swatch::before { content: ""; width: 1.6rem; height: 1.6rem; border-radius: 50%; background: var(--swatch); box-shadow: inset 0 0 0 1px rgb(255 255 255 / .22); }
.swatch:hover { border-color: var(--gold-dim); }
.swatch[aria-pressed="true"] { border-color: var(--gold); box-shadow: 0 0 0 1px var(--gold); }
/* a tap brings the answer into view (colours.js, S9); the margins keep it off the Floors button and the
   study tab. A look asks about several colours, one verdict each (A5). */
.answer { min-height: 5.5rem; display: grid; gap: .6rem; scroll-margin: 5rem 0 6.5rem; }
@media (min-width: 80em) { .answer { scroll-margin-bottom: 2rem; } }
.verdict {
  display: grid; grid-template-columns: 3rem minmax(0, 1fr); gap: .3rem 1rem; align-items: center;
  padding: 1rem 1.1rem; border-radius: var(--radius-card); border: 1px solid var(--line); background: var(--char);
}
.verdict::before { content: ""; grid-row: span 2; width: 3rem; height: 3rem; border-radius: 50%; background: var(--swatch); box-shadow: inset 0 0 0 1px rgb(255 255 255 / .25); }
.verdict-head { font: 600 .78rem/1.2 var(--ui); letter-spacing: .2em; text-transform: uppercase; }
.verdict-say { color: var(--ivory); }
.verdict[data-verdict="motif"] { border-color: var(--gold); }
.verdict[data-verdict="motif"] .verdict-head { color: var(--gold-hi); }
.verdict[data-verdict="fine"] .verdict-head { color: var(--mute); }
.verdict[data-verdict="avoid"] { border-color: #b8786c; }
.verdict[data-verdict="avoid"] .verdict-head { color: #f0a594; }

/* §14 · the reply (rsvp-simple.js), and the hand-off up to the pass */
.reply { display: grid; gap: 2rem; }
@media (min-width: 56em) { .reply { grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); align-items: start; column-gap: 3rem; } }
.reply-shot { margin: 0; order: -1; }
.reply-shot img { width: 100%; height: auto; border-radius: var(--radius-card); }
@media (min-width: 56em) { .reply-shot { order: 2; position: relative; } }
.reply-body { display: grid; gap: 1.5rem; }
.reply-form { display: grid; gap: 1.4rem; }
.field { display: grid; gap: .45rem; }
.field label, .reply-q { font-weight: 600; color: var(--ivory); }
.field input, .field textarea {
  width: 100%; min-height: 48px; padding: .7rem .9rem;
  border: 1px solid var(--line); border-radius: var(--radius); background: var(--field); color: var(--ivory);
}
.field input:focus, .field textarea:focus { border-color: var(--gold); outline: none; box-shadow: 0 0 0 1px var(--gold); }
.reply-ask { display: grid; gap: .6rem; }
.choices { display: grid; gap: .5rem; }
@media (min-width: 30em) { .choices { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.choice {
  display: flex; align-items: center; gap: .7rem; min-height: 52px; padding: .6rem 1rem;
  border: 1px solid var(--line); border-radius: var(--radius); background: var(--field); cursor: pointer;
}
.choice input { width: 1.15rem; height: 1.15rem; accent-color: var(--gold); }
.choice:has(input:checked) { border-color: var(--gold); background: var(--accent-soft); }
.choice:has(input:focus-visible) { outline: 2px solid var(--ivory); outline-offset: 2px; }
.plus { display: grid; gap: .6rem; }
.stepper { display: flex; align-items: center; gap: .75rem; }
.step-btn { width: 44px; height: 44px; border-radius: 50%; border: 1px solid var(--gold-dim); background: var(--field); color: var(--gold-hi); font-size: 1.25rem; line-height: 1; }
.step-btn:disabled { opacity: .35; }
.step-out { font: 400 var(--step-2)/1 var(--display); min-width: 1.5ch; text-align: center; color: var(--gold-hi); }
.step-label { color: var(--mute); }
.plus-names { display: grid; gap: .8rem; }
.error { padding: .75rem 1rem; border-radius: var(--radius); background: rgb(184 120 108 / .14); border: 1px solid #b8786c; color: #f6c3b7; }
.confirm { display: grid; gap: .9rem; }
.confirm h2 { font: 400 var(--step-3)/1.05 var(--display); color: var(--gold-hi); }
.confirm-up { display: grid; gap: .7rem; justify-items: start; padding: 1.1rem 1.2rem; border: 1px solid var(--gold-dim); border-radius: var(--radius-card); background: rgb(205 174 114 / .07); }
.summary { display: grid; gap: .3rem; }
.summary-row { display: flex; justify-content: space-between; gap: 1rem; padding-block: .4rem; border-bottom: 1px solid var(--line); }
.answer-word { color: var(--mute); }
.stats { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; padding-top: 1.4rem; border-top: 1px solid var(--line); }
@media (min-width: 40em) { .stats { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
.stat { display: grid; gap: .15rem; }
.stat b { font: 400 var(--step-3)/1 var(--display); font-weight: 400; color: var(--gold-hi); font-variant-numeric: lining-nums; }
.stat span { font-size: var(--step--1); color: var(--mute); }

/* §15 · a photograph full-bleed between the panels */
.band { margin: 0; position: relative; }
.band img { width: 100%; height: clamp(18rem, 62svh, 40rem); object-fit: cover; object-position: 50% 50%; border-radius: 0; }
.band figcaption { position: absolute; left: var(--margin); bottom: 1rem; font-size: var(--step--1); color: var(--ivory); text-shadow: 0 1px 10px rgb(0 0 0 / .9); }

/* §16 · the page turn (a lift ride: down and up) and the footer */
.turn { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 1.5rem; padding-block: var(--module); border-top: 1px solid var(--line); }
.turn a { display: grid; gap: .3rem; text-decoration: none; min-height: 44px; }
[data-skin="nadinerafael"] .turn a { text-decoration: none; }
.turn-next { text-align: right; margin-left: auto; }
.turn-say { font: 400 var(--step-2)/1.1 var(--display); color: var(--ivory); }
.turn a:hover .turn-say { color: var(--gold-hi); }
.foot {
  display: grid; gap: .6rem; padding-block: 2.5rem calc(6.5rem + env(safe-area-inset-bottom));
  border-top: 1px solid var(--gold-dim); font-size: var(--step--1); color: var(--mute);
  background: rgb(11 10 9 / .92);
}
@media (min-width: 80em) { .foot { padding-bottom: 3rem; } }
.foot-names { font: 400 var(--step-2)/1.1 var(--display); color: var(--gold-hi); }
.foot-mark { max-width: 44em; color: var(--ivory); }
.wsd-mark { display: flex; align-items: center; gap: .5rem; }
.wsd-mark i { width: .55rem; height: .55rem; border-radius: 50%; background: var(--gold); }
[data-skin="nadinerafael"] .wsd-skip { background: var(--gold); color: var(--on-accent); padding: .75rem 1rem; border-radius: 0 0 6px 0; z-index: 70; }

/* §17 · motion. Two ambient surfaces at most per page: the cover's windows coming on and flickering
   faintly, and nothing continuous anywhere else. Everything else is a one-time entrance. */
@media (prefers-reduced-motion: no-preference) {
  .city-lights[data-ready] .light { animation: nr-on 900ms calc(var(--i) * var(--wave) + 500ms) var(--ease) both; }
  .city-lights[data-ready] .light:nth-child(9n+4) { animation: nr-on 900ms calc(var(--i) * var(--wave) + 500ms) var(--ease) both, nr-flicker 11s calc(var(--i) * 170ms + 4s) ease-in-out infinite; }
  .city-lights[data-ready] .light[data-yours] { animation: nr-on 900ms calc(var(--i) * var(--wave) + 900ms) var(--ease) both, nr-yours 2.6s calc(var(--i) * var(--wave) + 1.8s) ease-in-out 2; }
  .light[data-yours] .light-tag { animation: nr-fade 900ms calc(var(--i) * var(--wave) + 1.6s) var(--ease) both; }
  [data-fresh] .flecks i { animation: nr-fleck var(--fd, 2.6s) var(--fdel, 0s) cubic-bezier(.3, .1, .5, 1) both; }
  [data-fresh] .pass { animation: nr-develop 1.4s var(--ease-soft) both; }
}
@keyframes nr-on { from { opacity: 0; } 35% { opacity: 1; filter: brightness(1.6); } to { opacity: 1; filter: none; } }
@keyframes nr-flicker { 0%, 100% { opacity: 1; } 46% { opacity: 1; } 50% { opacity: .35; } 54% { opacity: .9; } 58% { opacity: .5; } 64% { opacity: 1; } }
@keyframes nr-yours { 0%, 100% { box-shadow: 0 0 .5rem .2rem rgb(255 220 150 / .85), 0 0 2.2rem .6rem rgb(255 196 110 / .35); } 50% { box-shadow: 0 0 .8rem .35rem rgb(255 230 170 / 1), 0 0 3.2rem 1rem rgb(255 196 110 / .5); } }
@keyframes nr-fade { from { opacity: 0; } to { opacity: 1; } }
@keyframes nr-rise { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: none; } }
@keyframes nr-blink { 0% { opacity: .2; } 100% { opacity: 1; } }
@keyframes nr-fleck {
  0% { opacity: 0; transform: translateY(0) rotate(0deg); }
  10% { opacity: 1; }
  80% { opacity: 1; }
  100% { opacity: 0; transform: translateY(calc(var(--fall, 30rem))) translateX(var(--drift, 1rem)) rotate(var(--spin, 260deg)); }
}
@keyframes nr-develop { from { opacity: 0; transform: translateY(16px) scale(.985); filter: brightness(1.6) saturate(.4); } to { opacity: 1; transform: none; filter: none; } }

/* §17b · riding between floors (the user, 2026-10-02). A page change is a ride: the car panel stays put
   while its display counts (chrome.js), and the city outside slides by the floors travelled, sinking
   as you go up and rising as you go down. Built on the engine's departure/arrival pair (motion.js'
   data-leaving, chrome.js' data-ride and --wsd-travel), never @view-transition: the demos open from a
   file path (atelier.css). The body does not fade here, as it does on other sites: the city and the
   panel are the lift, and they never go dark between floors; the words go and come instead. */
@media (prefers-reduced-motion: no-preference) {
  html[data-skin="nadinerafael"][data-atelier~="motion"] body,
  html[data-skin="nadinerafael"][data-leaving] body { animation: none; }
  html[data-leaving] :is(.foot, .turn) { animation: a-page-fade-out 260ms var(--ease) both; }
  html[data-leaving] .city-stage { animation: nr-ride-leave 260ms cubic-bezier(.5, 0, .75, 0) both; }
  html[data-leaving="fwd"] .city-stage { --ride-to: 5vh; }
  html[data-leaving="back"] .city-stage { --ride-to: -5vh; }
  html[data-ride] .city-stage {
    animation: nr-ride-arrive calc(420ms + var(--wsd-travel, 1) * 130ms) var(--ease-soft) both;
  }
  html[data-ride="up"] .city-stage { --ride-from: calc(-1 * (2vh + var(--wsd-travel, 1) * 2.5vh)); }
  html[data-ride="down"] .city-stage { --ride-from: calc(2vh + var(--wsd-travel, 1) * 2.5vh); }
}
/* transform, not translate: the stage is centred with `translate` (§3), and the two compose. The scale
   keeps the picture's edge off screen for most of the ride. */
@keyframes nr-ride-leave { to { transform: translateY(var(--ride-to, 0)) scale(1.04); filter: brightness(.55); } }
@keyframes nr-ride-arrive {
  from { transform: translateY(var(--ride-from, 0)) scale(1.06); filter: brightness(.55); }
  to { transform: none; filter: none; }
}

/* §18 · print: the page as a document; the pass prints on its own */
@media print {
  .city, .car, .study, .turn, .wsd-skip, .flecks, .door { display: none !important; }
  [data-skin="nadinerafael"] body { background: #fff; color: #000; }
  .head, .cover { padding-top: 0; min-height: 0; }
}

/* §19 · the arrival: the lift comes down for you (atelier §Y, the doors route; the user's pick,
   2026-10-02, after lab/share/nadinerafael-arrival.html). The display counts down from R, the car
   stalls between twenty and nineteen in a brownout, the line is read by the emergency lamp, the lift's
   power comes back, and the doors part on a city still dark; the line rises to where the names land,
   then the city comes back and the names take its place. Charcoal doors, brushed: gold on the lines
   and the engraving only, never a brass field (SITE4-PLAN.md §6). Silent. */
.a-arrival--doors {
  --amber: #ffb54a;
  --a-doors-head: 7.5rem;
  --a-doors-head-bg: linear-gradient(#0e0d0c, #141210);
  --a-doors-leaf-l: repeating-linear-gradient(90deg, rgb(255 255 255 / .02) 0 1px, transparent 1px 4px), linear-gradient(90deg, #191715, #25221e 55%, #1c1a17);
  --a-doors-leaf-r: repeating-linear-gradient(90deg, rgb(255 255 255 / .02) 0 1px, transparent 1px 4px), linear-gradient(90deg, #1c1a17, #25221e 45%, #191715);
  --a-doors-seam: var(--gold-dim);
  --a-doors-line-at: 67%;
  --a-doors-line-to: calc(clamp(4.6rem, 11svh, 8rem) + 3rem);   /* where the cover's names sit (§7) */
  --a-doors-call-at: 7.25rem;
  --lift-name: clamp(2.3rem, 1rem + 5vw, 5.25rem);
  --a-arr-exit: 1700ms;
}
/* After a full ride the line lingers in the sky while the city comes back, and fades as the names
   switch on (§17's html[data-arrived]); a Skip leaves at once. */
.a-arrival--doors[data-leaving]:has(.a-doors[data-stage="parted"]) { --a-doors-fade-delay: 700ms; }
@media (max-width: 39.99em) {
  .a-arrival--doors { --a-doors-head: 6rem; --a-doors-line-at: 60%; }
}
@media (min-width: 52em) { .a-arrival--doors { --a-doors-line-to: calc(clamp(6rem, 14svh, 10rem) + 3rem); } }   /* the cover's drop (S14) */
.a-doors-head { border-bottom: 1px solid var(--gold-dim); }
.a-arrival--doors .a-arrival-note { color: var(--mute); }

/* the display over the doors, and the emergency lamp */
.lift-disp {
  display: flex; align-items: center; justify-content: center; gap: .6rem; margin: 0;
  width: 9.4rem; height: 4rem; border-radius: 5px; background: #050504; border: 1px solid #3d362b;
  font: 500 2.1rem/1 ui-monospace, "Cascadia Mono", Consolas, monospace; color: var(--gold-hi);
  text-shadow: 0 0 12px rgb(233 208 154 / .75);
}
.lift-arrow { font-size: .45em; min-width: 1ch; opacity: 0; }
.lift-floor { min-width: 2ch; text-align: center; font-variant-numeric: tabular-nums; }
.a-doors:is([data-stage="travel"], [data-stage="restore"]) .lift-arrow { opacity: .85; }
.a-doors[data-stage="dark"] .lift-disp { color: #1d1a15; text-shadow: none; }
.lift-lamp {
  position: absolute; right: 2.5rem; top: 50%; translate: 0 -50%;
  width: 2.9rem; height: 1.1rem; border-radius: .55rem; background: #221f1b; border: 1px solid #3d362b;
}
.a-doors:is([data-stage="stall"], [data-stage="dark"]) .lift-lamp {
  background: var(--amber);
  box-shadow: 0 0 18px 6px rgb(255 181 74 / .45), 0 0 120px 40px rgb(255 160 60 / .12);
  transition: background 200ms 480ms, box-shadow 200ms 480ms;
}
@media (max-width: 39.99em) {
  .lift-disp { width: 7.4rem; height: 3.25rem; font-size: 1.7rem; }
  .lift-lamp { right: 1.4rem; width: 2.1rem; height: .9rem; }
}

/* the doors: two framed panels each, the names engraved across the seam, "& Rafael" a line lower */
.a-doors-leaf::before, .a-doors-leaf::after { content: ""; position: absolute; }
.a-doors-leaf::before { inset: 9% 13%; border: 1px solid rgb(140 118 80 / .45); }
.a-doors-leaf::after { inset: calc(9% + 10px) calc(13% + 10px); border: 1px solid rgb(140 118 80 / .18); }
.a-doors-leaf--l::before, .a-doors-leaf--l::after { right: 0; border-right: 0; }
.a-doors-leaf--r::before, .a-doors-leaf--r::after { left: 0; border-left: 0; }
.a-doors-leaf--r { border-left: 1px solid #070606; }
.lift-eng {
  position: absolute; top: 31%; z-index: 1; margin: 0;
  display: flex; flex-direction: column;
  font: 400 var(--lift-name)/1 var(--display); color: var(--gold-hi); white-space: nowrap;
  text-shadow: 0 1px 0 rgb(0 0 0 / .7), 0 -1px 0 rgb(255 240 210 / .08);
}
.a-doors-leaf--l .lift-eng { right: clamp(.75rem, 1.5vw, 1.4rem); align-items: flex-end; }
.a-doors-leaf--r .lift-eng { left: clamp(.75rem, 1.5vw, 1.4rem); align-items: flex-start; }
.a-doors-leaf--r .lift-name { padding-top: .95em; }
/* as the doors part the engraving dims, so the line climbs past nothing on its way to the sky */
.a-doors[data-stage="parted"] .lift-eng { opacity: 0; transition: opacity 500ms var(--ease); }
.lift-name .amp { font-size: .75em; }
.lift-kick {
  margin-bottom: clamp(1.1rem, .8rem + 1vw, 1.6rem);
  font: 600 .75rem/1 var(--ui); letter-spacing: .3em; text-transform: uppercase; color: var(--gold);
  text-shadow: none;
}

/* the line, read by the lamp, then in the sky over the dark city */
/* the halo: once the power is back the line sits over the photographed doors' gold fan, whose rays ran
   through its words (2026-10-07). Not in the dark, where it would dim the lamp's pool behind the words. */
.a-doors-line { font: 400 clamp(1.3rem, 1rem + 1vw, 1.65rem)/1.45 var(--display); color: #f3dcb6;
  transition: text-shadow 700ms var(--ease); }
.a-doors:is([data-stage="restore"], [data-stage="arrived"], [data-stage="parted"]) .a-doors-line {
  text-shadow: 0 0 .35em #0b0a09, 0 0 .9em rgb(11 10 9 / .95), 0 0 1.8em rgb(11 10 9 / .8);
}
.lift-when { margin-bottom: .9rem; font: 600 .7rem/1 var(--ui); letter-spacing: .3em; text-transform: uppercase; color: var(--amber); }

/* the call button */
.lift-call {
  display: grid; justify-items: center; gap: .75rem; padding: 0; border: 0; background: none; cursor: pointer;
  font: 600 .7rem/1 var(--ui); letter-spacing: .24em; text-transform: uppercase; color: var(--ivory);
}
.lift-ring {
  display: grid; place-items: center; width: 4.1rem; height: 4.1rem; border-radius: 50%;
  border: 1.5px solid var(--gold); color: var(--gold); font-size: 1.1rem;
  background: radial-gradient(circle at 50% 35%, #2e2a25, #161412);
}
.lift-call:hover .lift-ring { box-shadow: 0 0 0 5px rgb(205 174 114 / .16), 0 0 22px rgb(205 174 114 / .55); }
.lift-call:focus-visible { outline: none; }
.lift-call:focus-visible .lift-ring { outline: 2px solid var(--ivory); outline-offset: 4px; }

/* the page under the doors: the city in the brownout, the cover's words and the panel not yet there.
   The doors' own note carries the design-study mark meanwhile. */
html[data-arrival] .city-stage > img { filter: brightness(.14) saturate(.5); }
html[data-arrival] .city .city-lights .light[data-light] { opacity: 0; animation: none; }   /* out-ranks §17 and §20 */
html[data-arrival] :is(.cover > *, .car, .study) { opacity: 0; }

@media (prefers-reduced-motion: no-preference) {
  .lift-ring { animation: nr-breathe 2.8s ease-in-out infinite; }
  .a-doors[data-stage="stall"] .lift-disp { animation: nr-disp-die 480ms linear both; }
  .a-doors[data-stage="arrived"] .lift-disp { animation: nr-ding 700ms var(--ease); }
  /* then the city comes back, the lights in their wave (§17), the names like a sign switching on */
  html[data-arrived] .city-stage > img { animation: nr-power 1300ms linear both; }
  html[data-arrived] .names { animation: nr-neon 1600ms 900ms linear both; }
  html[data-arrived] :is(.cover > :not(.names), .car, .study) { animation: nr-fade 900ms 2100ms var(--ease) both; }
  html[data-arrived] .cover > .kicker { animation-delay: 1500ms; }
}
@keyframes nr-breathe { 0%, 100% { box-shadow: 0 0 0 0 rgb(205 174 114 / 0); } 50% { box-shadow: 0 0 0 6px rgb(205 174 114 / .1), 0 0 18px rgb(205 174 114 / .35); } }
@keyframes nr-disp-die {
  0%, 24%, 50%, 69%, 84% { color: #ffcf8a; text-shadow: 0 0 10px rgb(255 190 110 / .7), 0 0 26px rgb(255 160 70 / .3); }
  25%, 49%, 70%, 83%, 100% { color: #1d1a15; text-shadow: none; }
}
@keyframes nr-ding { 30% { color: #fff3d6; text-shadow: 0 0 26px rgb(255 236 190 / 1), 0 0 4px #fff; } }
@keyframes nr-power {
  0% { filter: brightness(.14) saturate(.5); } 22% { filter: brightness(.75); } 30% { filter: brightness(.22) saturate(.6); }
  48% { filter: brightness(1); } 54% { filter: brightness(.6); } 70%, 100% { filter: none; }
}
@keyframes nr-neon { 0% { opacity: 0; } 12% { opacity: .8; } 16% { opacity: .1; } 26% { opacity: .9; } 30% { opacity: .35; } 48%, 100% { opacity: 1; } }

/* §19b · the arrival, filmed (the user, 2026-10-06: "a cinematic elegant feel … a bit cartoonish right now").
   The doors are a photograph (lift-doors.webp, split down its seam, each leaf sliding with its half; the drawn
   doors stay underneath, so a missing file is the old doors), letterbox bars that draw back as the doors
   part, a slow push-in, fine grain and a vignette, the emergency lamp as a warm pool of light from above,
   the display as amber numerals behind smoked glass, and a brass call button. */
.a-arrival--doors {
  --bar: clamp(1.5rem, 5svh, 3rem);
  --a-doors-head: calc(7.5rem + var(--bar));
  /* the doors photograph's width, sized like object-fit: cover over both leaves (it is 3:2) */
  --dw: max(100vw, calc((100svh - var(--a-doors-head)) * 1.5));
  /* the photograph's brass stile: its outer lines stand 4.73% of its width either side of the seam
     (measured, 2026-10-06), so the names start past it, and on a phone shrink to fit what is left of the
     leaf ("& Rafael" is about 3.9em) */
  --stile: calc(var(--dw) * .0473);
  --lift-name: min(clamp(2.3rem, 1rem + 5vw, 5.25rem), calc((50vw - var(--stile) - 2.25rem) / 3.9));
}
/* the photograph carries its own frames and its own seam: the drawn ones go */
.a-arrival--doors .a-doors-leaf::before, .a-arrival--doors .a-doors-leaf::after { content: none; }
.a-arrival--doors .a-doors-leaf { border-color: transparent; }
.a-arrival--doors .a-doors-leaf--l .lift-eng { right: calc(var(--stile) + clamp(.75rem, 1.5vw, 1.4rem)); }
.a-arrival--doors .a-doors-leaf--r .lift-eng { left: calc(var(--stile) + clamp(.75rem, 1.5vw, 1.4rem)); }
@media (max-width: 39.99em) { .a-arrival--doors { --a-doors-head: calc(6rem + var(--bar)); } }
.a-arrival--doors .a-doors-head { padding-top: var(--bar); }
.a-arrival--doors .a-doors-leaf--l {
  background: url("../assets/nadinerafael/lift-doors.webp") calc(50vw - var(--dw) / 2) 50% / var(--dw) auto no-repeat,
    var(--a-doors-leaf-l);
}
.a-arrival--doors .a-doors-leaf--r {
  background: url("../assets/nadinerafael/lift-doors.webp") calc(var(--dw) / -2) 50% / var(--dw) auto no-repeat,
    var(--a-doors-leaf-r);
}
/* the letterbox: over everything but Skip and the note, which read as a subtitle in the bottom bar */
.a-arrival.a-arrival--doors::before, .a-arrival.a-arrival--doors::after {
  content: ""; position: absolute; left: 0; right: 0; z-index: 6; height: var(--bar);
  background: #000; pointer-events: none;
  transition: translate 1300ms cubic-bezier(.65, 0, .25, 1) 200ms;
}
.a-arrival.a-arrival--doors::before { top: 0; }
.a-arrival.a-arrival--doors::after { bottom: 0; }
.a-arrival--doors:has(.a-doors[data-stage="parted"])::before { translate: 0 -100%; }
.a-arrival--doors:has(.a-doors[data-stage="parted"])::after { translate: 0 100%; }
.a-arrival--doors :is(.a-arrival-skip, .a-arrival-note) { z-index: 7; }
.a-arrival--doors .a-arrival-skip { bottom: calc(var(--bar) + .7rem); background: var(--night); }   /* the seam no longer runs through it */
.a-arrival--doors .a-arrival-note { bottom: calc((var(--bar) - 1.4em) / 2); margin: 0; line-height: 1.4; }
/* grain and a vignette, over the doors and the line; still in reduced motion */
.a-arrival--doors .a-doors::after {
  content: ""; position: absolute; inset: 0; z-index: 5; pointer-events: none;
  background:
    url("../assets/nadinerafael/grain.webp") 0 0 / 192px 192px,
    radial-gradient(ellipse 75% 70% at 50% 46%, transparent 52%, rgb(0 0 0 / .62) 100%);
}

/* the emergency lamp: a warm pool from above, flickering on in the dark (the pill is gone) */
.lift-lamp { display: none; }
.a-arrival--doors .a-doors::before {
  content: ""; position: absolute; inset: 0; z-index: 3; pointer-events: none; opacity: 0;
  background: radial-gradient(ellipse 48% 62% at 50% 38%, rgb(255 178 96 / .4), rgb(255 150 60 / .13) 48%, transparent 74%);
  mix-blend-mode: screen;
  transition: opacity 500ms linear;
}
.a-doors[data-stage="dark"]::before { opacity: 1; }
/* the display: amber numerals in the display face, behind smoked glass in a bronze bezel */
.a-arrival--doors .lift-disp {
  position: relative;
  background: linear-gradient(180deg, #140e08, #060403);
  border: 1px solid #4a3d2a;
  box-shadow: inset 0 0 18px rgb(0 0 0 / .9), 0 0 0 4px #0c0a08, 0 0 0 5px rgb(140 118 80 / .35);
  font: 400 2.5rem/1 var(--display); font-variant-numeric: lining-nums tabular-nums;
  color: #ffcf8a; text-shadow: 0 0 10px rgb(255 190 110 / .7), 0 0 26px rgb(255 160 70 / .3);
}
.a-arrival--doors .lift-disp::after {
  content: ""; position: absolute; inset: 0; border-radius: inherit; pointer-events: none;
  background: linear-gradient(162deg, rgb(255 255 255 / .08), transparent 42%);
}
@media (max-width: 39.99em) { .a-arrival--doors .lift-disp { font-size: 2rem; } }
/* the call button: a brass push on a blackened plate */
.a-arrival--doors .lift-ring {
  width: 4.4rem; height: 4.4rem; border: 0; color: #2a1f10; font-size: .95rem;
  background: radial-gradient(circle at 38% 30%, #fff1cc, #d9b878 30%, #9a7a43 62%, #5c4524 92%);
  box-shadow: 0 0 0 7px #120f0c, 0 0 0 8px rgb(140 118 80 / .5), 0 6px 18px rgb(0 0 0 / .7), inset 0 -3px 6px rgb(60 40 15 / .55);
}
.a-arrival--doors .lift-call { gap: 1.1rem; font: 400 .95rem/1 var(--display); letter-spacing: .14em; text-transform: none; color: #e9dcc4; }
.a-arrival--doors .lift-call:hover .lift-ring { box-shadow: 0 0 0 7px #120f0c, 0 0 0 8px var(--gold), 0 0 26px rgb(255 205 130 / .5), inset 0 -3px 6px rgb(60 40 15 / .55); }
/* Android Chrome laid its blue tap highlight over the button and turned the brass teal (the user, 2026-10-09):
   off, and the button presses in like a real one instead, so a tap still answers */
.lift-call { -webkit-tap-highlight-color: transparent; }
.a-arrival--doors .lift-call:active .lift-ring {
  scale: .95; animation: none;   /* the breathing glow would hold its own shadow over the press */
  background: radial-gradient(circle at 42% 36%, #f6dfa6, #c9a663 32%, #876a38 64%, #4e3b1f 92%);
  box-shadow: 0 0 0 7px #120f0c, 0 0 0 8px var(--gold), 0 0 22px rgb(255 205 130 / .55), inset 0 3px 8px rgb(40 26 8 / .7);
}

@media (prefers-reduced-motion: no-preference) {
  /* the push-in: each leaf grows from the seam, so the seam never opens; the line and the names' hand-off
     are not scaled */
  .a-doors-leaf--l { transform-origin: 100% 50%; }
  .a-doors-leaf--r { transform-origin: 0 50%; }
  .a-arrival--doors .a-doors-leaf { animation: nr-dolly 16s cubic-bezier(.2, .5, .3, 1) both; }
  .a-arrival--doors .a-doors::after { animation: nr-grain 1s steps(6) infinite; }
  .a-doors[data-stage="dark"]::before { animation: nr-lamp 1.5s linear both; }
  .a-arrival--doors .lift-ring { animation: nr-call 2.8s ease-in-out infinite; }
}
@keyframes nr-dolly { from { scale: 1; } to { scale: 1.07; } }
@keyframes nr-grain {
  0% { background-position: 0 0, center; } 17% { background-position: -61px 37px, center; } 33% { background-position: 88px -24px, center; }
  50% { background-position: -17px -93px, center; } 67% { background-position: 45px 71px, center; } 83% { background-position: -102px 12px, center; }
}
@keyframes nr-lamp { 0% { opacity: 0; } 8% { opacity: .85; } 12% { opacity: .15; } 21% { opacity: 1; } 27% { opacity: .5; } 40%, 100% { opacity: 1; } }
@keyframes nr-call {
  0%, 100% { box-shadow: 0 0 0 7px #120f0c, 0 0 0 8px rgb(140 118 80 / .5), 0 6px 18px rgb(0 0 0 / .7), inset 0 -3px 6px rgb(60 40 15 / .55); }
  50% { box-shadow: 0 0 0 7px #120f0c, 0 0 0 8px rgb(205 174 114 / .8), 0 0 24px rgb(255 205 130 / .35), inset 0 -3px 6px rgb(60 40 15 / .55); }
}

/* §20 · the living city (the user, 2026-10-02): the cover's city rises as it is scrolled, the visitor's
   own window switches on once after their yes, and Look closer makes the lit windows browsable, each
   with a line (lights.js). */

/* the rise: the camera goes up as the cover scrolls, so the city sinks. A wrapper, so it never fights
   the stage's centring (translate) or the ride between floors (transform, §17b). CSS only, where
   scroll-linked animation exists; elsewhere the city simply stays. It grows from its foot as it sinks
   (1.09 × the layer's height covers the 9vh), so the top of the screen never opens onto the bare layer:
   a plain translate left a black strip over the top 9vh of every scrolled screen (2026-10-07). Its own
   name: as `nr-rise` it overrode §17's keyframes of that name and pushed the open Floors plate 9vh down. */
.city-rise { position: absolute; inset: 0; transform-origin: 50% 100%; }
@supports (animation-timeline: scroll()) {
  @media (prefers-reduced-motion: no-preference) {
    [data-floor="l"] .city-rise {
      animation: nr-sink linear both;
      animation-timeline: scroll(root block);
      animation-range: 0 100vh;
    }
  }
}
@keyframes nr-sink { to { transform: translateY(9vh) scale(1.09); } }

/* your window, the first time: after the whole wave, a pause, then it switches on like a light that
   catches, and the tag comes after (data-fresh, set once by lights.js). The wave runs in about 1.2 s
   instead of 2.2 s on that visit (S2, 2026-10-08), so yours catches near 2 s and its tag is up near 3 s:
   a guest back from the pass had often scrolled on before the 5 s it took. Other visits keep the pace. */
.city-lights:has(.light[data-fresh]) { --wave: 14ms; }
@media (prefers-reduced-motion: no-preference) {
  .city-lights[data-ready] .light[data-yours][data-fresh] {
    animation: nr-switch 1300ms calc(var(--i) * var(--wave) + 400ms) linear both, nr-yours 2.6s calc(var(--i) * var(--wave) + 1800ms) ease-in-out 2;
  }
  .light[data-yours][data-fresh] .light-tag { animation: nr-fade 900ms calc(var(--i) * var(--wave) + 1600ms) var(--ease) both; }
}
@keyframes nr-switch {
  0%, 38% { opacity: 0; }
  42% { opacity: 1; filter: brightness(2.2); }
  47% { opacity: .15; }
  55% { opacity: 1; filter: brightness(1.8); }
  100% { opacity: 1; filter: none; }
}

/* Look closer: the words go, the note stays and changes, the veil lifts, the windows answer */
.lights-look-say, .say-done { display: none; }
html[data-looking] .lights-say, html[data-looking] .say-look { display: none; }
html[data-looking] .lights-look-say, html[data-looking] .say-done { display: inline; }
.lights-look {
  display: flex; align-items: center; justify-content: center; min-height: 44px; margin: .6rem auto 0; padding: 0 1.2rem;
  border: 1px solid var(--gold-dim); border-radius: 22px; background: rgb(11 10 9 / .5); color: var(--gold-hi); cursor: pointer;
  font: 600 .7rem/1 var(--ui); letter-spacing: .22em; text-transform: uppercase;
  transition: border-color var(--motion-fast) var(--ease), background var(--motion-fast) var(--ease);
}
.lights-look:hover { border-color: var(--gold); }
.lights-look[aria-pressed="true"] { background: var(--gold); color: var(--on-accent); border-color: var(--gold); }
.cover > * { transition: opacity 400ms var(--ease); }
html[data-looking] .cover > :not(.cover-lights) { opacity: 0; }
html[data-looking] main, html[data-looking] .foot { pointer-events: none; }
/* the note goes up into the empty sky, so no window hides behind it (fixed: <main>'s entrance has ended
   by the time anyone presses Look closer, so no transform holds it) */
html[data-looking] .cover-lights {
  pointer-events: auto; position: fixed; z-index: 2; left: 50%; top: clamp(4.6rem, 11svh, 8rem); translate: -50% 0;
  width: min(30em, calc(100vw - 2 * var(--margin)));
}
html[data-looking] .city::after { background: linear-gradient(rgb(11 10 9 / .25), rgb(11 10 9 / 0) 40%, rgb(11 10 9 / .1) 70%, rgb(11 10 9 / .5)); }

/* the layer: the same height as <main> and earlier in the page, so the note (and Done) stay on top.
   ⚠ By its attribute, never `.look`: the lookbook's figures are `.look` too (details/), and a bare `.look`
   here fixed all six full-screen over the page from 2026-10-02 until the photographs showed it (2026-10-06). */
[data-lights-layer] { position: fixed; inset: 0; z-index: 1; pointer-events: none; }
/* a full 44px target (lights.js never lets two overlap); the ring is drawn window-sized inside it */
.look-spot {
  position: absolute; left: var(--sx); top: var(--sy); translate: -50% -50%;
  width: 44px; height: 44px; padding: 0; border: 0; border-radius: 50%; background: none;
  pointer-events: auto; cursor: pointer;
}
.look-spot::before { content: ""; position: absolute; inset: 9px; border-radius: 50%; }
.look-spot:hover::before { box-shadow: 0 0 0 1px rgb(233 208 154 / .5); }
.look-spot[aria-current]::before { box-shadow: 0 0 0 1.5px var(--gold-hi), 0 0 16px rgb(255 214 150 / .45); }
.look-spot:focus-visible { outline: none; }
.look-spot:focus-visible::before { outline: 2px solid var(--ivory); outline-offset: 4px; }
.look-card {
  position: absolute; left: var(--cx); top: var(--cy); margin: 0;
  translate: -50% calc(-100% - 22px);
  padding: .55rem .85rem; border: 1px solid rgb(205 174 114 / .4); border-radius: 4px;
  background: rgb(11 10 9 / .88); color: var(--ivory); white-space: nowrap;
  font: 400 var(--step--1)/1.3 var(--body); pointer-events: none;
}
.look-card[data-place="below"] { translate: -50% 22px; }

/* §21 · the pass, handled (the user, 2026-10-02): a foil that follows the pointer or a finger, Turn over
   to the back (the running order, the code large), and the stub torn at the door (pass.js). */

/* the foil: a warm, narrow shine (screen: color-dodge turned the charcoal olive); nothing moves
   unless a pointer does. touch-action: pan-y keeps a vertical drag scrolling the page. */
.pass[data-wsd-el="card"] { touch-action: pan-y; }
.pass[data-wsd-el="card"]::before {
  content: ""; position: absolute; inset: 0; z-index: 1; border-radius: inherit; pointer-events: none;
  background:
    radial-gradient(38% 26% at calc(var(--foil-x, .5) * 100%) calc(var(--foil-y, .3) * 100%), rgb(255 226 170 / .13), transparent 72%),
    linear-gradient(115deg, transparent calc(var(--foil-x, .5) * 100% - 16%), rgb(255 234 196 / .09) calc(var(--foil-x, .5) * 100%), transparent calc(var(--foil-x, .5) * 100% + 16%));
  mix-blend-mode: screen; opacity: 0; transition: opacity 450ms var(--ease);
}
.pass[data-wsd-el="card"][data-foil]::before { opacity: 1; }

/* turn over: both faces in one grid cell, the away face hidden by its back */
.pass-wrap { display: grid; perspective: 1600px; }
/* the face turned away is hidden once the turn has finished (visibility, delayed by the turn), so it is
   neither read nor measured under the other; the face coming round is visible at once */
.pass-wrap > .pass { grid-area: 1 / 1; backface-visibility: hidden; transition: rotate 750ms var(--ease-soft), visibility 0s 0s; }
.pass-back { rotate: y -180deg; --tear: 82%; align-content: start; visibility: hidden; transition: rotate 750ms var(--ease-soft), visibility 0s 750ms; }
[data-turned] .pass-wrap > .pass[data-wsd-el="card"] { rotate: y 180deg; visibility: hidden; transition: rotate 750ms var(--ease-soft), visibility 0s 750ms; }
[data-turned] .pass-back { rotate: y 0deg; visibility: visible; transition: rotate 750ms var(--ease-soft), visibility 0s 0s; }
.pass-back-head { display: grid; gap: .45rem; justify-items: center; padding-top: .6rem; }
.pass-night { list-style: none; margin: 0; padding: 1rem 0 0; border-top: 1px solid var(--line); display: grid; gap: .5rem; text-align: left; }
.pass-night li { display: grid; grid-template-columns: 5rem minmax(0, 1fr); gap: .6rem; align-items: baseline; font: 400 1.05rem/1.3 var(--display); color: var(--ivory); }
.pass-night-time { font: 600 .7rem/1.2 var(--ui); letter-spacing: .14em; text-transform: uppercase; color: var(--gold); font-variant-numeric: tabular-nums; }
.pass-back .pass-dress { padding-bottom: 1.6rem; }
/* your window on your pass (A2, 2026-10-08): the cover's photograph cut at your light (site.js → lights.yours,
   its centre at 51.87% / 65.9% of floor-l.jpg), four times the box's width in a 3:1 box, so the position
   centres it: x (0.5 − 0.5187 × 4) / (1 − 4) = 52.49%, y with the picture's 8:5 = 68.35%. The photograph
   loads only once the pass is turned (it is the cover's, 576 KB). Yours only: a sample has no window. */
.pass-view { margin: 0; display: grid; gap: .5rem; justify-items: center; }
.pass-view-img {
  position: relative; width: 100%; aspect-ratio: 3 / 1; overflow: hidden;
  border: 1px solid var(--gold-dim); border-radius: 4px; background: var(--night);
}
[data-turned] .pass-view-img { background: url("../assets/nadinerafael/floor-l.jpg") 52.49% 68.35% / 400% auto no-repeat, var(--night); }
.pass-view-img::before {
  content: ""; position: absolute; left: 50%; top: 50%; width: 9px; height: 9px; translate: -50% -50%; border-radius: 50%;
  background: radial-gradient(closest-side, #fffaf0, rgb(255 228 170 / .9) 50%, rgb(255 210 140 / 0));
  box-shadow: 0 0 .5rem .2rem rgb(255 220 150 / .85), 0 0 1.6rem .5rem rgb(255 196 110 / .35);
}
.pass-view-img::after {
  content: ""; position: absolute; left: 50%; top: 50%; width: 26px; height: 26px; translate: -50% -50%;
  border: 1px solid var(--gold-hi); border-radius: 50%;
}
.pass-view figcaption { font: 600 .68rem/1.2 var(--ui); letter-spacing: .22em; text-transform: uppercase; color: var(--mute); }
[data-pass]:not([data-pass="yours"]) .pass-view { display: none; }
.pass-turn {
  grid-area: 2 / 1; justify-self: center; margin-top: .6rem; min-height: 44px; padding: 0 1rem;
  border: 0; background: none; color: var(--gold); cursor: pointer;
  font: 600 .72rem/1 var(--ui); letter-spacing: .24em; text-transform: uppercase;
  text-decoration: underline; text-decoration-color: var(--gold-dim); text-underline-offset: .45em;
}
.pass-turn:hover { color: var(--gold-hi); }
.pass-turn .say-back, [data-turned] .pass-turn .say-front { display: none; }
[data-turned] .pass-turn .say-back { display: inline; }

/* the stub at the door: drag across it to tear it off along the dashed line, or press the button */
.door-stub {
  display: flex; justify-content: space-between; gap: 1rem; width: min(100%, 20rem);
  padding: .9rem 1.1rem; border: 1px solid var(--gold-dim); border-top: 2px dashed var(--gold); border-radius: 0 0 6px 6px;
  background: #0d0c0b; color: var(--gold-hi); font: 600 .8rem/1 var(--ui); letter-spacing: .3em; text-transform: uppercase;
  touch-action: pan-y; user-select: none; cursor: grab;
  transform-origin: 0 0; transform: translateY(calc(var(--tear, 0) * 12px)) rotate(calc(var(--tear, 0) * 6deg));
}
.door-stub:not([data-tearing]) { transition: transform 300ms var(--ease); }
.door-stub[data-tearing] { cursor: grabbing; }
.door-torn { min-height: 1.5em; color: var(--gold-hi); max-width: 26em; }
.door-torn:empty { display: none; }
[data-torn] .door-stub:not([data-fresh]) { visibility: hidden; }
@media (prefers-reduced-motion: no-preference) {
  [data-torn] .door-stub[data-fresh] { animation: nr-stub-off 900ms var(--ease) both; pointer-events: none; }
}
@media (prefers-reduced-motion: reduce) {
  .pass-wrap > .pass { transition: none; }
  [data-torn] .door-stub { visibility: hidden; }
}
@keyframes nr-stub-off { to { transform: translate(2.5rem, 8rem) rotate(20deg); opacity: 0; visibility: hidden; } }

/* §22 · the night slider (the user, 2026-10-02): drag through the evening in place of the skip button.
   schedule.js moves the clock as it is dragged and, while the night is on, puts --wsd-night-at (minutes
   since the doors at 4:45) on <html>. The roof at dusk (floor-r-dusk.jpg, the user's pick of two
   photographs over a CSS grade; drawn for now) fades into the night view: all dusk to sunset (6:00,
   75 min), all night by 7:00 (135 min), dinner. Before the night and after it, the night view. */
.city-dusk { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; opacity: 0; transition: opacity 500ms var(--ease); }
html[data-night] .city-dusk { opacity: clamp(0, calc((135 - var(--wsd-night-at, 999)) / 60), 1); }
/* the veil eases off in the middle of the night page while the evening is on, so the sky can be seen
   between the head (on the darker top) and the ticket (its own ground) */
html[data-night][data-floor="r"] .city::after { background: linear-gradient(rgb(11 10 9 / .82), rgb(11 10 9 / .6) 45%, rgb(11 10 9 / .86)); }

/* the city fills as the evening goes (A4, 2026-10-08): lights.js lights the roof's windows (site.js →
   nightLights) from sunset (75 min) to dinner (135 min) as the slider moves. Each batch comes on together,
   a little staggered (--k), and never again while it stays on; no wave from the page's load. */
/* under the night page's veil (.6–.86) the cover's glows were lost: larger and stronger here */
[data-floor="r"] .light:not([data-yours]) {
  scale: 2.4;
  background: radial-gradient(closest-side, #fff4d6, rgb(255 206 120 / .95) 45%, rgb(255 180 90 / 0));
  box-shadow: 0 0 .6rem .2rem rgb(255 196 110 / .55), 0 0 1.6rem .4rem rgb(255 170 80 / .22);
}
@media (prefers-reduced-motion: no-preference) {
  [data-floor="r"] .city-lights[data-ready] .light:nth-child(n) { animation: nr-on 700ms calc(var(--k, 0) * 70ms) var(--ease) both; }
}

.scrub-row { flex-basis: 100%; display: grid; gap: .3rem; }
.scrub-label { font: 600 .72rem/1 var(--ui); letter-spacing: .2em; text-transform: uppercase; color: var(--mute); }
.scrub { width: 100%; height: 44px; margin: 0; background: none; cursor: pointer; -webkit-appearance: none; appearance: none; touch-action: pan-y; }
.scrub::-webkit-slider-runnable-track { height: 2px; background: var(--gold-dim); }
.scrub::-moz-range-track { height: 2px; background: var(--gold-dim); }
.scrub::-webkit-slider-thumb {
  -webkit-appearance: none; width: 24px; height: 24px; margin-top: -11px; border-radius: 50%;
  background: var(--gold); border: 4px solid var(--night); box-shadow: 0 0 0 1px var(--gold), 0 0 14px rgb(205 174 114 / .5);
}
.scrub::-moz-range-thumb { width: 16px; height: 16px; border-radius: 50%; background: var(--gold); border: 4px solid var(--night); box-shadow: 0 0 0 1px var(--gold); }
.scrub:focus-visible { outline: 2px solid var(--ivory); outline-offset: 4px; }
.scrub-ends { display: flex; justify-content: space-between; font: 600 .68rem/1 var(--ui); letter-spacing: .18em; text-transform: uppercase; color: var(--mute); }
@media (prefers-reduced-motion: reduce) { .city-dusk { transition: none; } }
