/* Thank-you site for the Faculty of Science, Batch 23.1.
   Phone first: every rule below is written for a 390 px screen, then widened. */

:root {
  --sc-canvas: #040A10;   /* one ground at every edge: Safari's bars take this colour on an iPhone */
  --sc-surface: #0D1C17;
  --sc-ink: #F1F6F2;
  --sc-ink-soft: #A9BFB4;
  --sc-accent: #A9CDB6;
  --sc-accent-ink: #06100D;
  --sc-font-display: "Cormorant Garamond", "Iowan Old Style", Georgia, serif;
  --sc-font-text: "Cormorant Garamond", "Iowan Old Style", Georgia, serif;

  --label: "Big Shoulders Display", "Arial Narrow", sans-serif;
  --script: "Pinyon Script", "Snell Roundhand", cursive;
  --hand: "Caveat", "Bradley Hand", cursive;

  --life: #A9CDB6;
  --life-deep: #1F4134;
  --health: #A9C2E0;
  --health-deep: #1D3A57;
  --night: #040A10;
  --line: color-mix(in oklab, var(--sc-ink) 16%, transparent);
  --line-strong: color-mix(in oklab, var(--sc-ink) 30%, transparent);
  --glass: color-mix(in oklab, #0B1B16 78%, transparent);
  --ease: cubic-bezier(0.23, 1, 0.32, 1);
  --safe-b: env(safe-area-inset-bottom, 0px);
  --edge: #040A10;   /* html's colour: Safari paints the status bar band with it */
  --under: 0px;      /* how far the cover runs on under a phone's bottom bar */
}
@media (hover: none) and (pointer: coarse) { :root { --under: 120px; } }

html { background: var(--edge); }
body {
  background: var(--edge);         /* Safari paints the status bar band with the body's colour */
  color: var(--sc-ink);
  font-family: var(--sc-font-text);
  font-size: 1.125rem;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}
body.is-locked { overflow: hidden; touch-action: none; }
/* Nothing may make the page wider than the screen: an iPhone lets a page that is even a
   little too wide slide left and right under the thumb (the gallery's wall lights did, by
   45 px). Clip, not hidden: it makes no scroll box, so nothing inside stops pinning. */
main, .card, .viewer { overflow-x: clip; }
button { font: inherit; color: inherit; }
img { max-width: 100%; }

/* ------------------------------------------------------------- chrome -- */
/* iPhone Safari 26+ reads the background colour of fixed and sticky elements near
   its bars and paints the status bar and toolbar solid with it, which stops the page
   showing under the Dynamic Island and the toolbar (and can stick until a reload).
   So no fixed element here carries a colour of its own: each one is transparent and
   wears its colour on a pseudo-element, which Safari does not read. None of them
   moves across a screen edge either. */
.mark { /* back to the start, once the cover is behind us */
  position: fixed; z-index: 40; top: calc(10px + env(safe-area-inset-top, 0px)); left: 12px;
  display: inline-flex; align-items: center; gap: 8px; height: 34px; padding: 0 14px 0 10px;
  border: 1px solid var(--line); border-radius: 999px; isolation: isolate;
  font-family: var(--label); font-weight: 700; font-size: 0.78rem; letter-spacing: 0.2em;
  text-transform: uppercase; color: var(--sc-accent); text-decoration: none;
  opacity: 0; transform: translateY(-4px); pointer-events: none;
  transition: opacity 0.35s var(--ease), transform 0.35s var(--ease);
}
.mark::after { content: ""; position: absolute; inset: 0; z-index: -1; border-radius: inherit; background: var(--glass); }
.mark::before { /* an arrow up */
  content: ""; width: 9px; height: 9px; border-left: 2px solid currentColor; border-top: 2px solid currentColor;
  transform: translateY(2px) rotate(45deg);
}
body.is-past-cover .mark { opacity: 0.94; transform: none; pointer-events: auto; }
/* Back to start and the strip step aside while the zoom flies and while the visitor reads on
   down the page (like Safari's own bars), and come back on the way up (nav.js). The close
   has its own buttons. They only fade: nothing fixed crosses a screen edge. */
body.is-flying .mark, body.is-flying .protocol,
body.is-past-cover.is-reading .mark, body.is-past-cover.is-reading .protocol,
body.is-past-cover.is-at-close .protocol, body.is-past-cover.is-at-close .mark, body.is-indoors .mark { opacity: 0; pointer-events: none; }
.mark span { display: none; }
/* Full-screen fixed layers exist only while they work, and keep their colour on a pseudo-element. */
.cut { position: fixed; inset: 0; z-index: 55; opacity: 0; display: none; pointer-events: none; transition: opacity 0.32s var(--ease); }
.cut::before { content: ""; position: absolute; inset: 0; background: var(--night); }
.cut.is-on { display: block; pointer-events: auto; }
.cut.is-shown { opacity: 1; }
.mark:hover { opacity: 1; }

.protocol {
  position: fixed; z-index: 40; left: 50%; bottom: calc(12px + var(--safe-b));
  transform: translate(-50%, 0);
  display: flex; align-items: center; gap: 10px;
  padding: 6px 6px 6px 14px;
  border: 1px solid var(--line); border-radius: 999px; isolation: isolate;
  transition: opacity 0.4s var(--ease);
}
.protocol::before {
  content: ""; position: absolute; inset: 0; z-index: -1; border-radius: inherit; background: var(--glass);
  box-shadow: 0 10px 30px -12px rgba(0, 0, 0, 0.6), inset 0 1px 0 rgba(255, 255, 255, 0.06);
}
/* the strip belongs to the journey, not the cover: hidden until the cover is behind us,
   and again whenever the visitor scrolls back up to it */
body:not(.is-past-cover) .protocol { opacity: 0; pointer-events: none; }
/* The grain is a fixed layer, and Safari clips fixed layers to the area between its
   bars: it lightened the page by a few levels there but not under the bars, which
   showed as a line at the edge of each bar. Phones go without it. */
@media (hover: none) and (pointer: coarse) { .sc-grain { display: none; } }
/* an open card is a page of its own: the rest of the site steps aside */
body.is-carded main, body.is-carded .mark, body.is-carded .protocol, body.is-carded .cut { display: none; }
.protocol__steps { display: flex; gap: 2px; list-style: none; margin: 0; padding: 0; }
.protocol__steps a { display: grid; place-items: center; width: 22px; height: 40px; text-decoration: none; -webkit-tap-highlight-color: transparent; }
.protocol__dot {
  width: 8px; height: 8px; border-radius: 50%;
  border: 1.5px solid var(--sc-ink-soft); background: transparent;
  transition: background 0.3s var(--ease), border-color 0.3s var(--ease), transform 0.3s var(--ease);
}
.protocol__steps a.is-done .protocol__dot { background: var(--sc-accent); border-color: var(--sc-accent); }
.protocol__steps a.is-here .protocol__dot { transform: scale(1.45); border-color: var(--sc-ink); }
.protocol__label {
  position: absolute; bottom: 46px; left: 50%; transform: translateX(-50%);
  white-space: nowrap; padding: 4px 10px; border-radius: 6px; background: var(--sc-surface);
  font-family: var(--label); font-weight: 600; font-size: 0.78rem; letter-spacing: 0.12em; text-transform: uppercase;
  opacity: 0; pointer-events: none; transition: opacity 0.15s var(--ease);
}
.protocol__steps li { position: relative; }
@media (hover: hover) and (pointer: fine) {
  .protocol__steps a:hover .protocol__label, .protocol__steps a:focus-visible .protocol__label { opacity: 1; }
}
.protocol__find {
  border: 0; border-radius: 999px; padding: 10px 14px; cursor: pointer; white-space: nowrap;
  background: var(--sc-accent); color: var(--sc-accent-ink);
  font-family: var(--label); font-weight: 800; font-size: 0.8rem; letter-spacing: 0.1em; text-transform: uppercase;
  transition: transform 0.12s var(--ease), background 0.15s var(--ease);
}
.protocol__find:hover { background: #C3E0CD; }
.protocol__find:active { transform: scale(0.97); }

:focus-visible { outline: 2px solid var(--sc-accent); outline-offset: 3px; border-radius: 6px; }

.station { position: relative; }

/* ------------------------------------------------------------ 1 · drop -- */
/* On a phone the cover runs on under Safari's bottom bar (--under), so the bar
   floats over the bench instead of over a black band; its top fades into
   --edge, the colour Safari paints behind the status bar. */
.drop { height: calc(100svh + var(--under)); min-height: 560px; overflow: hidden; isolation: isolate; background: var(--edge); }
/* Once the journey begins the cover steps aside: the journey is a page of its own, and
   scrolling up from the Milky Way never comes back here (Back to start does). */
body.is-past-cover .drop { display: none; }
.drop__stage { position: absolute; inset: 0; z-index: 0; }
/* on a phone the scene sits a little higher, so the words below have room to breathe */
.drop__frame { position: absolute; top: -60px; right: 0; bottom: 60px; left: 0; }
.drop__frame img, .drop__frame video {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: 50% 32%;
  max-width: none;
}
.drop__release { opacity: 0; }
.drop.is-releasing .drop__release { opacity: 1; }
.drop.is-releasing .drop__idle { opacity: 0; transition: opacity 0.12s linear; }
.drop__frame::after { /* the top melts into the status bar, the bottom darkens for the words */
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background:
    linear-gradient(to bottom, var(--edge) 0%, color-mix(in oklab, var(--edge) 0%, transparent) 14%),
    linear-gradient(to top, var(--edge) 0%, var(--edge) calc(var(--under) * 0.6), color-mix(in oklab, var(--edge) 0%, transparent) 52%);
}

.drop__copy {
  position: absolute; z-index: 2; left: 0; right: 0; bottom: calc(var(--under) + 58px + var(--safe-b));
  padding: 0 22px; text-align: center; display: grid; justify-items: center;
}
.drop__eyebrow, .drop__crest {
  margin: 0; font-family: var(--label); font-weight: 600; font-size: 0.76rem;
  letter-spacing: 0.24em; text-transform: uppercase; color: var(--sc-accent);
}
/* on a phone the university's name rides at the top, clear of the dish */
.drop__eyebrow { display: none; }
.drop__crest { position: absolute; z-index: 2; left: 0; right: 0; top: calc(16px + env(safe-area-inset-top, 0px)); text-align: center; font-size: 0.84rem; letter-spacing: 0.22em; opacity: 0.92; }
.drop__title {
  margin: 0; font-family: var(--script); font-weight: 400; line-height: 1.05;
  font-size: clamp(3.6rem, 17vw, 7.5rem); letter-spacing: 0;
  text-shadow: 0 6px 30px rgba(0, 0, 0, 0.45);
}
.drop__lede {
  margin: 10px auto 0; max-width: 32ch; font-style: italic; font-weight: 500; text-wrap: balance;
  font-size: clamp(1.3rem, 5.6vw, 1.65rem); line-height: 1.3; color: color-mix(in oklab, var(--sc-ink) 88%, var(--sc-accent));
}
.begin {
  margin-top: 28px; display: inline-flex; align-items: center; gap: 10px; min-height: 52px; padding: 0 26px 0 20px;
  border: 0; border-radius: 999px; cursor: pointer; background: var(--sc-accent); color: var(--sc-accent-ink);
  font-family: var(--label); font-weight: 800; font-size: 0.92rem; letter-spacing: 0.14em; text-transform: uppercase;
  box-shadow: 0 16px 34px -14px rgba(0, 0, 0, 0.8), 0 0 0 6px color-mix(in oklab, var(--sc-accent) 16%, transparent);
  -webkit-tap-highlight-color: transparent; transition: transform 0.14s var(--ease), background 0.15s var(--ease);
}
.begin:hover { background: #C3E0CD; }
.begin:active { transform: scale(0.97); }
.begin__drop { /* a small falling drop */
  width: 12px; height: 16px; background: var(--sc-accent-ink); border-radius: 50% 50% 50% 50% / 62% 62% 38% 38%;
  transform: rotate(180deg); animation: begin-drop 2.4s var(--ease) infinite;
}
@keyframes begin-drop { 0%, 55% { transform: rotate(180deg) translateY(0); opacity: 1; } 80% { transform: rotate(180deg) translateY(-5px); opacity: 0.2; } 100% { transform: rotate(180deg) translateY(0); opacity: 1; } }
.drop.is-releasing .begin { opacity: 0; transform: translateY(8px); pointer-events: none; transition: opacity 0.3s var(--ease), transform 0.3s var(--ease); }

/* The dish version (Oct 21): the words step aside as the camera rises over the dish; then the
   cover lies over the journey's first screen (body.is-morphing) while cover.js lays the dish on
   the zoom's lens, darkens the bench around it like the lens's own night, and fades. */
.drop--dish.is-releasing .drop__copy, .drop--dish.is-releasing .drop__crest { opacity: 0; transition: opacity 0.6s var(--ease) 1.5s; }
.drop--dish .drop__frame::after { transition: opacity 1.2s var(--ease) 1.6s; }
.drop--dish.is-releasing .drop__frame::after { opacity: 0; }
.drop__night {
  position: absolute; inset: 0; z-index: 1; pointer-events: none; opacity: 0;
  background: radial-gradient(circle at var(--nx, 50%) var(--ny, 50%), transparent 0, transparent calc(var(--nr, 0px) - 3px),
    rgba(4, 10, 16, 0.86) calc(var(--nr, 0px) + 1px), rgba(4, 10, 16, 0.94) calc(var(--nr, 0px) + 60px), var(--night) 100%);
}
body.is-morphing .drop { position: absolute; top: 0; left: 0; right: 0; z-index: 30; }
.drop__veil { position: fixed; inset: 0; z-index: 60; pointer-events: none; opacity: 0; display: none; }
.drop__veil::before { content: ""; position: absolute; inset: 0; background: radial-gradient(circle at 50% 50%, #0A1C2A 0%, var(--night) 70%); }
.drop__veil.is-on { display: block; pointer-events: auto; }
.drop__stars { position: relative; width: 100%; height: 100%; display: block; }

/* ------------------------------------------------------------ 2 · zoom -- */
.zoom { background: var(--night); }
/* Pinned stages stay transparent and their section carries the colour: Safari 26+
   turns a sticky element's own background into solid bars over the Dynamic Island
   and the bottom toolbar, and keeps them until a reload (tested in the iOS 27 simulator). */
/* Like the cover, the zoom runs on under a phone's bottom bar (--under), so nothing of the
   next station shows through the bar while it flies; everything that matters stays in the
   small screen above it (zoom.js measures without it, the floor ends above it). */
.zoom__stage { position: relative; height: calc(100svh + var(--under)); overflow: hidden; }
.zoom__stage::after { /* imagery melts into the ground at the top and bottom, where Safari's bars sit */
  content: ""; position: absolute; inset: 0; z-index: 3; pointer-events: none;
  background: linear-gradient(to bottom, var(--night) 0, transparent 72px, transparent calc(100% - 96px), var(--night) 100%);
}
.zoom__stars { position: absolute; inset: 0; width: 100%; height: 100%; }
.zoom__layers { position: absolute; inset: 0; }
/* the place being visited (zoom.js, Oct 22): its pin and name over the building, as the view arrives */
.zoom__here {
  position: absolute; left: var(--lx, 50%); top: var(--ly, 50%); z-index: 3; display: grid; justify-items: center; gap: 10px;
  transform: translate(-50%, -7px); opacity: 0; transition: opacity 0.3s ease; pointer-events: none;
}
.zoom__here.is-on { opacity: 1; transition: opacity 0.45s ease 1.1s; }
.zoom__here-dot { width: 14px; height: 14px; border-radius: 50%; background: var(--sc-accent); box-shadow: 0 0 0 4px rgba(169, 205, 182, 0.35), 0 0 18px rgba(169, 205, 182, 0.7); }
.zoom__here-name {
  padding: 6px 12px; border-radius: 999px; background: rgba(4, 10, 16, 0.72); color: var(--sc-ink); white-space: nowrap;
  font-family: var(--label); font-weight: 700; font-size: 0.8rem; letter-spacing: 0.14em; text-transform: uppercase;
}
.zoom__layer {
  position: absolute; left: var(--lx, 50%); top: var(--ly, 50%); width: var(--zs, 100vmin); height: var(--zs, 100vmin);
  margin: calc(var(--zs, 100vmin) / -2) 0 0 calc(var(--zs, 100vmin) / -2);
  transform-origin: 50% 50%; will-change: transform, opacity; opacity: 0;
  max-width: none; pointer-events: none; user-select: none;
}
/* the lens: night everywhere except a round window, with a thin glass rim */
.zoom__lens {
  position: absolute; inset: 0; z-index: 3; pointer-events: none; --open: 0;
  background: radial-gradient(circle at var(--lx) var(--ly),
    transparent 0, transparent calc(var(--lr) - 3px),
    rgba(4, 10, 16, 0.86) calc(var(--lr) + 1px), rgba(4, 10, 16, 0.94) calc(var(--lr) + 60px), var(--night) 100%);
}
.zoom__rim {
  position: absolute; left: calc(var(--lx) - var(--lr) - 3px); top: calc(var(--ly) - var(--lr) - 3px);
  width: calc(var(--lr) * 2 + 6px); height: calc(var(--lr) * 2 + 6px); border-radius: 50%;
  border: 1.5px solid rgba(214, 240, 226, 0.34);
  box-shadow: 0 0 0 1px rgba(214, 240, 226, 0.06), 0 0 40px rgba(169, 205, 182, 0.12), inset 0 0 30px rgba(0, 0, 0, 0.45);
}
.zoom__readout {
  position: absolute; z-index: 4; left: 18px; top: calc(56px + env(safe-area-inset-top, 0px));
  font-family: var(--label); text-shadow: 0 2px 12px rgba(0, 0, 0, 0.6);
}
.zoom__size { margin: 0; font-weight: 800; font-size: 2.1rem; line-height: 1; letter-spacing: 0.02em; font-variant-numeric: tabular-nums; }
.zoom__exp { font-size: 0.55em; vertical-align: 0.9em; margin-left: 1px; }
.zoom__unit { font-weight: 600; font-size: 0.7em; color: var(--sc-ink-soft); }
.zoom__what { margin: 6px 0 0; font-weight: 600; font-size: 0.86rem; letter-spacing: 0.18em; text-transform: uppercase; color: var(--sc-accent); }
/* Google's credit, on the imagery itself while it shows */
.zoom__credit {
  position: absolute; z-index: 4; left: calc(var(--lx) - var(--lr)); width: calc(var(--lr) * 2); top: calc(var(--ly) + var(--lr) * 0.8);
  margin: 0; text-align: center; pointer-events: none; opacity: 0;
  font-family: system-ui, -apple-system, "Helvetica Neue", Arial, sans-serif; font-style: normal; font-weight: 500;
  font-size: 0.5rem; letter-spacing: 0.02em;   /* Google asks for its credit while its imagery shows: kept tiny and faint (user, Oct 21) */
  color: rgba(255, 255, 255, 0.5); text-shadow: 0 1px 2px rgba(0, 0, 0, 0.8);
}
/* the film the idea comes from, small, at the foot of the screen while the view flies */
.zoom__film {
  position: absolute; z-index: 4; left: 20px; right: 20px; bottom: calc(var(--under) + 16px + var(--safe-b)); margin: 0 auto; max-width: 34ch;
  text-align: center; text-wrap: balance; pointer-events: none;
  font-style: italic; font-size: 0.92rem; line-height: 1.3; color: var(--sc-ink-soft); opacity: 0; transition: opacity 0.6s var(--ease);
}
.zoom.is-touring .zoom__film { opacity: 0.9; }   /* only while the view flies down (user, Oct 21) */
.zoom__film cite { font-style: normal; font-family: var(--label); font-weight: 700; font-size: 0.86em; letter-spacing: 0.14em; text-transform: uppercase; color: var(--sc-ink); }
/* the captions hang under the lens; zoom.js leaves them room for three lines */
.zoom__captions { position: absolute; z-index: 4; left: 20px; right: 20px; top: calc(var(--ly) + var(--lr) + 22px); text-align: center; pointer-events: none; }
.zoom__caption {
  position: absolute; left: 0; right: 0; top: 0; margin: 0 auto; max-width: 26ch; text-wrap: balance;
  font-style: italic; font-weight: 500; font-size: clamp(1.25rem, 5.2vw, 1.75rem); line-height: 1.3;
  text-shadow: 0 2px 18px rgba(0, 0, 0, 0.75); opacity: 0;
}

/* the end of the zoom: the places over the campus, and the cabins' floor plan */
.floor { position: absolute; inset: 0 0 var(--under) 0; z-index: 5; pointer-events: none; }
.floor__kicker { margin: 0; font-family: var(--label); font-weight: 600; font-size: 0.78rem; letter-spacing: 0.24em; text-transform: uppercase; color: var(--sc-accent); }
.floor__title { margin: 2px 0 0; font-weight: 500; font-style: italic; font-size: clamp(1.7rem, 7vw, 2.6rem); line-height: 1.05; }
.floor__note { margin: 2px 0 0; font-size: 0.95rem; color: var(--sc-ink-soft); }
/* "Tap your name", lit like a button and gently pulsing, so nobody misses it (user, Oct 21:
   "they never understand that, surely"); tapping it opens Find your name */
.tap-hint {
  position: relative; display: inline-flex; align-items: center; gap: 10px; margin: 10px auto 0; min-height: 40px; padding: 0 18px 0 14px;
  border: 0; border-radius: 999px; background: var(--sc-accent); color: var(--sc-accent-ink); cursor: pointer;
  font-family: var(--label); font-weight: 800; font-size: 0.9rem; letter-spacing: 0.14em; text-transform: uppercase;
  box-shadow: 0 12px 26px -12px rgba(0, 0, 0, 0.9); -webkit-tap-highlight-color: transparent; text-shadow: none;
  transition: transform 0.12s var(--ease), background 0.15s var(--ease);
}
.tap-hint::before { /* a ring that keeps breathing out from the button */
  content: ""; position: absolute; inset: -3px; border-radius: inherit; border: 2px solid var(--sc-accent); pointer-events: none;
  animation: hintRing 2s var(--ease) infinite;
}
.tap-hint__dot { position: relative; width: 9px; height: 9px; border-radius: 50%; background: var(--sc-accent-ink); flex: none; }
.tap-hint__dot::after { content: ""; position: absolute; inset: -6px; border-radius: 50%; border: 2px solid var(--sc-accent-ink); animation: tapRing 2s var(--ease) infinite; }
.tap-hint:hover { background: #C3E0CD; }
.tap-hint:active { transform: scale(0.96); }
@keyframes hintRing { 0% { transform: scale(1); opacity: 0.85; } 70%, 100% { transform: scale(1.18, 1.5); opacity: 0; } }
@keyframes tapRing { 0% { transform: scale(0.35); opacity: 1; } 65%, 100% { transform: scale(1.25); opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .tap-hint::before, .tap-hint__dot::after { animation: none; opacity: 0; } }
.floor__swipe { margin: 8px 0 0; font-family: var(--label); font-weight: 600; font-size: 0.7rem; letter-spacing: 0.16em; text-transform: uppercase; color: var(--sc-ink-soft); }

/* the map: a label for each place over its pin, a fine line between them */
.places { position: absolute; inset: 0; opacity: 0; transition: opacity 0.6s var(--ease); }
.places.is-shown { opacity: 1; }
.places__head { position: absolute; left: 14px; right: 14px; top: calc(52px + env(safe-area-inset-top, 0px)); text-align: center; text-shadow: 0 2px 14px rgba(0, 0, 0, 0.85); }
.places__lines { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; pointer-events: none; }
.places__lines line { stroke: rgba(241, 246, 242, 0.78); stroke-width: 1; }
.places__marks { position: absolute; inset: 0; }
.pin { position: absolute; left: 0; top: 0; width: 0; height: 0; pointer-events: none; }
.pin__dot {
  position: absolute; left: -6px; top: -6px; width: 12px; height: 12px; border-radius: 50%; background: #F4FBF6;
  box-shadow: 0 0 0 3px rgba(169, 205, 182, 0.5), 0 2px 10px rgba(0, 0, 0, 0.7);
}
.pin::after { /* a slow ring, so the eye finds each place */
  content: ""; position: absolute; left: -6px; top: -6px; width: 12px; height: 12px; border-radius: 50%;
  border: 1.5px solid rgba(214, 240, 226, 0.8); opacity: 0;
}
.places.is-shown .pin::after { animation: pinRing 2.8s 0.6s var(--ease) infinite; }
@keyframes pinRing { from { transform: scale(1); opacity: 0.85; } to { transform: scale(3.4); opacity: 0; } }
.place {
  position: absolute; left: 0; top: 0; display: grid; justify-items: stretch; gap: 6px; padding: 8px 9px 9px;
  border: 1px solid rgba(241, 246, 242, 0.26); border-radius: 13px; text-align: left; color: #fff;
  background: rgba(4, 10, 16, 0.9); box-shadow: 0 12px 28px -12px rgba(0, 0, 0, 0.95);
  font-family: var(--label); -webkit-tap-highlight-color: transparent; pointer-events: none;
}
.places.is-shown .place { pointer-events: auto; }
button.place { cursor: pointer; }
.place__kicker { padding: 0 2px; font-weight: 700; font-size: 0.62rem; letter-spacing: 0.2em; text-transform: uppercase; color: var(--sc-accent); }
/* every name is a button that looks like one: a lit row with an arrow (user, Oct 21: "they are
   not tech guys") */
.place__name, .place__who, .place__open {
  display: flex; align-items: center; justify-content: space-between; gap: 10px; box-sizing: border-box; width: 100%;
  min-height: 38px; margin: 0; padding: 6px 9px 6px 10px; border: 1px solid rgba(241, 246, 242, 0.26); border-radius: 9px;
  background: rgba(241, 246, 242, 0.08); color: #fff; text-align: left; cursor: pointer;
  font-family: var(--label); font-weight: 800; font-size: 0.9rem; letter-spacing: 0.05em; line-height: 1.12; text-transform: uppercase;
  -webkit-tap-highlight-color: transparent; transition: background 0.18s var(--ease), border-color 0.18s var(--ease), transform 0.12s var(--ease);
}
.place__name::after, .place__who::after, .place__open::after {
  content: "\203A"; flex: none; font-size: 1.5em; line-height: 0.8; font-weight: 700; color: var(--sc-accent);
}
.place--cabins .place__open { border-color: color-mix(in oklab, var(--sc-accent) 60%, transparent); background: color-mix(in oklab, var(--sc-accent) 16%, transparent); }
@media (hover: hover) and (pointer: fine) {
  button.place:hover .place__name, button.place:hover .place__open, .place__who:hover { background: rgba(241, 246, 242, 0.16); border-color: var(--sc-accent); }
}
button.place:active .place__name, button.place:active .place__open, .place__who:active { transform: scale(0.98); background: rgba(169, 205, 182, 0.24); }
button.place.is-visited .place__full::after, .place__who.is-visited .place__full::after { content: " \2713"; color: var(--sc-accent); }
@media (max-width: 699px) {
  .place { padding: 7px 7px 8px; gap: 5px; }
  .place__name, .place__who, .place__open { min-height: 36px; padding: 5px 7px 5px 8px; gap: 6px; font-size: 0.8rem; }
}
/* the sixth place: the four who taught us and have left, no pin; their names two by two */
.place--away { justify-items: center; text-align: center; }
.place__list { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; width: 100%; }
.place--away .place__who { font-size: 0.78rem; }
@media (min-width: 900px) {
  .place { padding: 9px 10px 10px; }
  .place__kicker { font-size: 0.7rem; }
  .place__name, .place__who, .place__open { font-size: 1.02rem; min-height: 40px; }
  .place--away { padding: 11px 14px 12px; }
  .place--away .place__who { font-size: 0.96rem; }
  .place__list { gap: 8px; }
}
/* a wide screen: the two professors side by side, the four who left in one row (places.js) */
.places--wide .place--professors { grid-template-columns: 1fr 1fr; column-gap: 8px; }
.places--wide .place--professors .place__kicker { grid-column: 1 / -1; }
.places--wide .place__list { grid-template-columns: repeat(4, auto); }
/* a short screen: everything a little smaller, so the pins keep room between the label rows */
.places--tight .place { padding: 6px 7px 7px; gap: 4px; }
.places--tight .place__name, .places--tight .place__who, .places--tight .place__open { min-height: 32px; padding-top: 4px; padding-bottom: 4px; font-size: 0.88rem; }
.places--tight .place--away .place__who { font-size: 0.82rem; }
.places--tight .places__head .floor__title { font-size: clamp(1.5rem, 6vw, 2.1rem); }
.places--tight .places__head .tap-hint { margin-top: 6px; min-height: 34px; }
.places--tighter .place__kicker { font-size: 0.56rem; }
.places--tighter .place__name, .places--tighter .place__who, .places--tighter .place__open { min-height: 28px; font-size: 0.74rem; }
.places--tighter .place--away .place__who { font-size: 0.7rem; }
.places--tighter .places__head .floor__kicker { display: none; }
@media (max-width: 699px) { .places--tight .place__name, .places--tight .place__who, .places--tight .place__open { font-size: 0.76rem; } }
.place__more { display: none; }
.places--tightest .place--away { padding: 6px; }
.places--tightest .place--away .place__kicker, .places--tightest .place__list { display: none; }
.places--tightest .place__more {
  display: flex; align-items: center; justify-content: space-between; gap: 8px; width: 100%; min-height: 34px; margin: 0; padding: 4px 10px;
  border: 1px solid color-mix(in oklab, var(--sc-accent) 55%, transparent); border-radius: 9px; background: color-mix(in oklab, var(--sc-accent) 14%, transparent);
  color: #fff; cursor: pointer; font-family: var(--label); font-weight: 800; font-size: 0.8rem; letter-spacing: 0.08em; text-transform: uppercase;
}
.places--tightest .place__more::after { content: "\203A"; font-size: 1.5em; line-height: 0.8; color: var(--sc-accent); }
/* Google's credit sits in a corner of the map */
.zoom.is-map .zoom__credit { left: auto; right: 10px; width: auto; top: calc(8px + env(safe-area-inset-top, 0px)); text-align: right; }

/* the cabins: the floor plan, with the way back to the map */
.cabins {
  position: absolute; inset: 0; display: grid; grid-template-rows: auto 1fr auto;
  padding: calc(52px + env(safe-area-inset-top, 0px)) 14px calc(76px + var(--safe-b));
}
.cabins .floor__head, .floor__legend, .floor__back { opacity: 0; transform: translateY(8px); transition: opacity 0.5s var(--ease), transform 0.5s var(--ease); }
.floor.is-cabins .cabins { pointer-events: auto; }
.floor.is-cabins .cabins .floor__head, .floor.is-cabins .floor__legend, .floor.is-cabins .floor__back { opacity: 1; transform: none; }
.floor:not(.is-cabins) .seat, .floor:not(.is-cabins) .floor__back { pointer-events: none; }
.cabins .floor__head { text-align: center; }
@media (max-width: 699px) {
  .cabins { padding-left: 8px; padding-right: 8px; padding-top: calc(48px + env(safe-area-inset-top, 0px)); }
  .floor__note { font-size: 0.9rem; margin-top: 0; }
  .cabins .floor__title { font-size: 1.75rem; }
  .floor__plan { margin-top: 10px; }
  .floor__legend { margin-top: 10px; }
}
.floor__back {
  position: absolute; z-index: 2; top: calc(10px + env(safe-area-inset-top, 0px)); right: 12px;
  display: inline-flex; align-items: center; gap: 8px; height: 34px; padding: 0 14px 0 12px;
  border: 1px solid var(--line-strong); border-radius: 999px; background: rgba(4, 10, 16, 0.6); cursor: pointer;
  font-family: var(--label); font-weight: 700; font-size: 0.74rem; letter-spacing: 0.16em; text-transform: uppercase; color: var(--sc-ink);
}
.floor__back::before { content: ""; width: 8px; height: 8px; border-left: 2px solid currentColor; border-bottom: 2px solid currentColor; transform: translateX(2px) rotate(45deg); }
.floor__plan { position: relative; margin: 12px 0 0; width: 100%; height: 100%; min-height: 0; transform-origin: 50% 50%; will-change: transform, opacity; opacity: 0; }
.floor__legend {
  margin: 12px 0 0; text-align: center; font-family: var(--label); font-weight: 600; font-size: 0.74rem;
  letter-spacing: 0.14em; text-transform: uppercase; color: var(--sc-ink-soft);
}
.floor__key { display: inline-block; width: 10px; height: 10px; border-radius: 2px; margin: 0 6px 0 12px; vertical-align: -1px; }
.floor__key--life { background: var(--life); }
.floor__key--health { background: var(--health); }

/* the plan, drawn like an architect's (floor.js draws it in screen pixels): the building's
   footprint, its thick outer wall, every room's walls with a gap and a swing for its door, the
   halls open, the way in dotted from the entrance, and a name tag at every desk */
.plan { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); --wall: rgba(226, 236, 230, 0.6); }
.plan__lines { position: absolute; inset: 0; overflow: visible; pointer-events: none; }
.plan__ground { fill: rgba(4, 10, 16, 0.86); }
.plan__hall { fill: rgba(241, 246, 242, 0.015); }
.plan__room { fill: rgba(241, 246, 242, 0.055); }
.plan__wall { fill: none; stroke: var(--wall); stroke-width: 1.5; }
.plan__outer { fill: none; stroke: rgba(236, 244, 239, 0.86); stroke-width: 3.5; stroke-linejoin: miter; }
.plan__gap { stroke: #0A1316; stroke-width: 4; }
.plan__gap--outer { stroke-width: 6; }
.plan__leaf { stroke: color-mix(in oklab, var(--sc-accent) 85%, transparent); stroke-width: 1.4; }
.plan__swing { fill: none; stroke: color-mix(in oklab, var(--sc-accent) 55%, transparent); stroke-width: 1; stroke-dasharray: 2 2; }
.plan__path { fill: none; stroke: color-mix(in oklab, var(--sc-accent) 55%, transparent); stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; stroke-dasharray: 0.1 7; }
.plan--narrow .plan__path { stroke-dasharray: 0.1 5.5; }
.plan__arrow { fill: none; stroke: var(--sc-accent); stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.plan__room-label, .plan__entrance {
  position: absolute; display: grid; place-items: center; text-align: center; pointer-events: none;
  font-family: var(--label); font-weight: 700; text-transform: uppercase; color: var(--sc-ink-soft); line-height: 1.05;
}
.plan__room-label { font-size: 0.7rem; letter-spacing: 0.22em; padding: 0 6px; }
.plan__entrance { font-size: 0.74rem; letter-spacing: 0.22em; color: var(--sc-accent); }
.plan--narrow .plan__room-label { font-size: 0.52rem; letter-spacing: 0.12em; padding: 0 3px; }
.plan--narrow .plan__entrance { font-size: 0.58rem; letter-spacing: 0.16em; }
/* a desk: the whole desk is the button, the tag on it carries the name */
.seat {
  position: absolute; display: grid; place-items: center; margin: 0; padding: 0; border: 0; border-radius: 6px;
  background: transparent; cursor: pointer; -webkit-tap-highlight-color: transparent;
}
.seat--life { --tint: var(--life); }
.seat--health { --tint: var(--health); }
.seat__tag {
  position: relative; display: grid; justify-items: center; max-width: 100%; padding: 4px 6px; border-radius: 6px;
  /* lit like a button, in the department's colour (user, Oct 21: "they think this is just a name,
     so they never tap it") */
  background: var(--tint); color: #06120E;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.45), 0 0 0 1px rgba(255, 255, 255, 0.18), 0 4px 12px -4px rgba(0, 0, 0, 0.85), 0 0 18px -6px var(--tint);
  font-family: var(--label); font-weight: 800; font-size: 12px; line-height: 1.06; letter-spacing: 0.04em; text-transform: uppercase;
  white-space: nowrap; transition: background 0.18s var(--ease), transform 0.12s var(--ease);
}
.seat__title { font-size: 0.8em; letter-spacing: 0.14em; color: rgba(6, 18, 14, 0.72); }
.seat:hover .seat__tag, .seat:focus-visible .seat__tag { background: color-mix(in oklab, var(--tint) 78%, #fff); }
.seat:active .seat__tag { transform: scale(0.95); background: color-mix(in oklab, var(--tint) 70%, #fff); }
/* seen: a small tick on the tag's corner, which never makes the tag wider */
.seat.is-visited .seat__tag::after {
  content: "\2713"; position: absolute; top: -6px; right: -6px; width: 15px; height: 15px; border-radius: 50%;
  display: grid; place-items: center; font-size: 9px; line-height: 1; letter-spacing: 0; color: var(--tint); background: #06120E;
  box-shadow: 0 0 0 1.5px var(--tint);
}
.seat:focus-visible { outline: none; }
/* the tags light up one after another as the plan opens, so the eye knows they are there to tap */
.floor.is-cabins .seat__tag { animation: tagIn 0.5s var(--ease) both; animation-delay: calc(0.12s + var(--i, 0) * 22ms); }
@keyframes tagIn { from { opacity: 0; transform: scale(0.82); } 60% { opacity: 1; transform: scale(1.06); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .floor.is-cabins .seat__tag { animation: none; } }
.plan--narrow .seat__tag { padding: 3px 4px; border-radius: 5px; }

/* --------------------------------------------------------------- card -- */
.card {
  position: relative; min-height: 100lvh; color: var(--sc-ink);
  background:
    radial-gradient(80% 46% at 50% 14%, color-mix(in oklab, var(--tint, var(--life)) 16%, transparent), transparent 70%),
    linear-gradient(180deg, var(--night) 0%, #0A1915 18%, #07120F 82%, var(--night) 100%);
}
.card.card--health {
  background:
    radial-gradient(80% 46% at 50% 14%, color-mix(in oklab, var(--health) 16%, transparent), transparent 70%),
    linear-gradient(180deg, var(--night) 0%, #0A1522 18%, #070F17 82%, var(--night) 100%);
}
/* a wide screen: the glow spans the whole width, so the colour is even to both edges */
@media (min-width: 900px) {
  .card {
    background:
      radial-gradient(160% 62% at 50% 10%, color-mix(in oklab, var(--tint, var(--life)) 17%, transparent), transparent 78%),
      linear-gradient(180deg, #08130F 0%, #0B1B16 30%, #08140F 85%, var(--night) 100%);
  }
  .card.card--health {
    background:
      radial-gradient(160% 62% at 50% 10%, color-mix(in oklab, var(--health) 17%, transparent), transparent 78%),
      linear-gradient(180deg, #08101A 0%, #0B1724 30%, #08111A 85%, var(--night) 100%);
  }
}
.card[hidden] { display: none; }
.card__body {
  position: relative; min-height: 100lvh;
  padding: calc(18px + env(safe-area-inset-top, 0px)) 18px calc(28px + var(--safe-b));
}
.card__top { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin: 0 0 14px; }
.card__swipe { margin: 0; font-family: var(--label); font-weight: 600; font-size: 0.72rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--sc-ink-soft); }
/* the swipe hints are for fingers */
.swipe-hint { display: none; }
@media (hover: none) and (pointer: coarse) { .swipe-hint { display: inline; } .card__swipe, p.swipe-hint { display: block; } }
.card__close {
  display: block; margin: 0 0 0 auto; padding: 8px 14px; border: 1px solid var(--line-strong); border-radius: 999px;
  background: transparent; cursor: pointer;
  font-family: var(--label); font-weight: 700; font-size: 0.78rem; letter-spacing: 0.14em; text-transform: uppercase;
}
.card__portrait {
  margin: 0 auto; width: min(62vw, 300px); aspect-ratio: 4 / 5; border-radius: 22px; overflow: hidden;
  box-shadow: 0 24px 50px -24px rgba(0, 0, 0, 0.9), 0 0 0 1px color-mix(in oklab, var(--tint, var(--life)) 40%, transparent);
}
.card__portrait img { width: 100%; height: 100%; object-fit: cover; display: block; }
.card__text { text-align: center; margin-top: 16px; }
.card__dept { margin: 0; font-family: var(--label); font-weight: 600; font-size: 0.76rem; letter-spacing: 0.22em; text-transform: uppercase; color: var(--tint, var(--life)); }
.card__name { margin: 4px 0 0; font-family: var(--label); font-weight: 800; font-size: clamp(1.5rem, 6.6vw, 2.2rem); letter-spacing: 0.06em; line-height: 1.05; text-transform: uppercase; text-wrap: balance; }
.card__role { margin: 8px 0 0; font-family: var(--label); font-weight: 700; font-size: min(0.84rem, 3.5vw); letter-spacing: 0.16em; line-height: 1.4; text-transform: uppercase; color: var(--tint, var(--life)); white-space: pre; }   /* one role a line, never wrapped (user, Oct 22): a small phone gets it a little smaller */
.card__role[hidden] { display: none; }
.card__from { margin: 10px 0 0; font-style: italic; font-size: 1.15rem; color: var(--sc-ink-soft); }
/* The notes hang on a felt board in the department's colour; on a phone it runs edge to edge.
   Each note image is the paper rendered with its own shadow: the paper fills the middle 80%,
   so the image is 125% of the note's box, offset by 12.5%. A pin image is 2.4 cm across a
   7.6 cm note (31.6%), centred where its needle goes in. */
.card__notes {
  list-style: none; margin: 22px -18px 0; padding: 30px 0 46px; overflow: hidden;
  display: flex; flex-direction: column;
  background:
    radial-gradient(130% 70% at 50% 0%, rgba(255, 255, 255, 0.07), transparent 60%),
    radial-gradient(140% 100% at 50% 50%, transparent 52%, rgba(0, 0, 0, 0.36) 100%),
    url(../assets/notes/felt-life.webp) 0 0 / 256px 256px,
    #2B5646;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.07), inset 0 -1px 0 rgba(0, 0, 0, 0.4), inset 0 14px 26px -16px rgba(0, 0, 0, 0.6);
}
.card--health .card__notes {
  background:
    radial-gradient(130% 70% at 50% 0%, rgba(255, 255, 255, 0.07), transparent 60%),
    radial-gradient(140% 100% at 50% 50%, transparent 52%, rgba(0, 0, 0, 0.36) 100%),
    url(../assets/notes/felt-health.webp) 0 0 / 256px 256px,
    #294A6C;
}
.note { position: relative; flex: none; width: min(86%, 380px); aspect-ratio: 1; }
.note:nth-child(odd) { align-self: flex-start; margin-left: 4%; }
.note:nth-child(even) { align-self: flex-end; margin-right: 4%; }
.note + .note { margin-top: -10px; }
.note--free + .note { margin-top: 30px; }   /* the note below stays clear of the free place */
.card__notes.is-single .note { align-self: center; margin: 0; }   /* their own note alone on the board */
.note__sheet { position: absolute; inset: 0; transform: rotate(var(--tilt)); transform-origin: var(--pin-x) 5.5%; transition: transform 0.45s var(--ease); }
.note__paper {
  position: absolute; left: -12.5%; top: -12.5%; width: 125%; height: 125%; max-width: none; display: block;
  pointer-events: none; user-select: none; -webkit-user-select: none; -webkit-touch-callout: none;
}
.note__pin { position: absolute; z-index: 1; left: var(--pin-x); top: 5.5%; width: 31.6%; height: auto; max-width: none; transform: translate(-50%, -50%); pointer-events: none; }
.note[tabindex] { cursor: zoom-in; -webkit-tap-highlight-color: transparent; }
.note:focus-visible { outline: none; }
.note:focus-visible .note__sheet { outline: 2px solid var(--tint, var(--life)); outline-offset: 4px; }
.note.is-open { z-index: 3; cursor: zoom-out; }
.note.is-open .note__sheet { transform: rotate(0deg) scale(1.07); }
.note--free .note__sheet { transform: none; }
.note__slot {
  position: absolute; inset: 0; margin: 0; display: grid; place-items: center; padding: 22% 16% 14%;
  border: 1.5px dashed rgba(255, 255, 255, 0.32); border-radius: 4px; background: rgba(255, 255, 255, 0.03);
  text-align: center; font-style: italic; font-size: 1.05rem; line-height: 1.35; color: rgba(241, 246, 242, 0.72);
}
/* pinned as it comes into view: the pin goes in, the paper swings and settles */
.note.is-arriving .note__pin { animation: pinIn 0.42s cubic-bezier(0.3, 0.7, 0.2, 1) both; }
.note.is-arriving .note__sheet { animation: noteSwing 2.1s 0.16s both; }
@keyframes pinIn {
  from { transform: translate(-50%, -50%) scale(1.45); opacity: 0; }
  55% { opacity: 1; }
  to { transform: translate(-50%, -50%) scale(1); opacity: 1; }
}
@keyframes noteSwing {
  0% { transform: rotate(calc(var(--tilt) + 6deg)); animation-timing-function: cubic-bezier(0.45, 0, 0.55, 1); }
  27% { transform: rotate(calc(var(--tilt) - 3.2deg)); animation-timing-function: cubic-bezier(0.45, 0, 0.55, 1); }
  52% { transform: rotate(calc(var(--tilt) + 1.5deg)); animation-timing-function: cubic-bezier(0.45, 0, 0.55, 1); }
  75% { transform: rotate(calc(var(--tilt) - 0.6deg)); animation-timing-function: cubic-bezier(0.45, 0, 0.55, 1); }
  100% { transform: rotate(var(--tilt)); }
}
.note--free.is-arriving .note__sheet { animation: none; }
@media (min-width: 900px) {
  .card__notes {
    margin: 26px auto 0; max-width: 1060px; padding: 54px 44px 64px; border-radius: 18px; overflow: visible;
    flex-direction: row; justify-content: center; align-items: flex-start; gap: 32px;
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.07), inset 0 -1px 0 rgba(0, 0, 0, 0.4), inset 0 14px 26px -16px rgba(0, 0, 0, 0.6), 0 30px 60px -30px rgba(0, 0, 0, 0.9);
  }
  .note, .note:nth-child(odd), .note:nth-child(even) { width: calc((100% - 64px) / 3); margin: 0; align-self: flex-start; }
  .note:nth-child(2) { margin-top: 34px; }
  .note:nth-child(3) { margin-top: 12px; }
  .note.is-open .note__sheet { transform: rotate(0deg) scale(1.35); }
}
.card__nav { display: flex; justify-content: space-between; gap: 10px; max-width: 560px; margin: 22px auto 0; }
.card__nav button { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0;
  flex: 1; padding: 12px 10px; border: 1px solid var(--line-strong); border-radius: 12px; background: rgba(255, 255, 255, 0.03); cursor: pointer;
  font-family: var(--label); font-weight: 700; font-size: 0.8rem; letter-spacing: 0.14em; text-transform: uppercase;
}
.card__nav button:hover { border-color: var(--tint, var(--life)); }
.card__doors { position: absolute; top: 0; left: 0; right: 0; height: 100lvh; z-index: 3; pointer-events: none; display: flex; }   /* the first screen of the card */
.card__door {
  flex: 1; background: linear-gradient(90deg, #13261F, #0B1914); border: 1px solid var(--line);
  transform-origin: left center; transition: transform 0.9s var(--ease), opacity 0.9s var(--ease);
}
.card__door--r { transform-origin: right center; background: linear-gradient(270deg, #13261F, #0B1914); }
.card.is-opening .card__door--l { transform: perspective(1200px) rotateY(-86deg); opacity: 0; }
.card.is-opening .card__door--r { transform: perspective(1200px) rotateY(86deg); opacity: 0; }
.card.is-opening .card__body { animation: cardIn 0.9s var(--ease) both; }
@keyframes cardIn { from { opacity: 0; transform: scale(0.97); } to { opacity: 1; transform: none; } }

/* ----------------------------------------------------- 4 · practical -- */
.practical { padding: calc(36px + env(safe-area-inset-top, 0px)) 14px 96px; background: linear-gradient(180deg, var(--night) 0%, #071512 30%, #071512 70%, var(--night) 100%); }
.practical__inner { max-width: 1080px; margin: 0 auto; }
.practical__head { text-align: center; margin: 0 auto 14px; max-width: 23rem; }
.practical__kicker { margin: 0; font-family: var(--label); font-weight: 600; font-size: 0.8rem; letter-spacing: 0.24em; text-transform: uppercase; color: var(--sc-accent); }
/* the instruction is the heading, addressed to the lecturer */
.practical__title { margin: 0; font-weight: 500; font-style: italic; font-size: clamp(1.75rem, 7.4vw, 2.9rem); line-height: 1.14; text-wrap: balance; }
.practical__dear { display: block; color: var(--sc-accent); }
/* sized so the title, the gel and its buttons fit one phone screen above the bottom bar */
.gel { position: relative; margin: 0 auto; width: min(100%, 520px, calc((100svh - 356px) * 0.75)); aspect-ratio: 3 / 4; border-radius: 22px; overflow: hidden; background: #050D0B; box-shadow: 0 30px 60px -30px rgba(0, 0, 0, 0.9), inset 0 0 0 1px var(--line); }
.gel__canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; touch-action: manipulation; }
.gel__readout {
  position: absolute; top: 12px; right: 12px; display: flex; gap: 10px; align-items: baseline;
  padding: 6px 10px; border-radius: 8px; background: rgba(0, 0, 0, 0.55);
  font-family: var(--label); font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase; font-size: 0.78rem;
}
.gel__volts { font-variant-numeric: tabular-nums; color: #FF9B7A; font-size: 1rem; min-width: 4.2ch; text-align: right; }
.gel__status { color: var(--sc-ink-soft); }
.gel__message {
  position: absolute; left: 14px; right: 14px; bottom: 14px; margin: 0 auto; max-width: 34ch;
  padding: 12px 14px; border-radius: 14px; background: rgba(6, 16, 13, 0.82); box-shadow: 0 12px 30px -10px rgba(0, 0, 0, 0.7);
  font-style: italic; font-size: 1.15rem; line-height: 1.3; text-align: center;
  opacity: 0; transform: translateY(8px); transition: opacity 0.25s var(--ease), transform 0.25s var(--ease); pointer-events: none;
}
.gel__message.is-on { opacity: 1; transform: none; }
.gel__controls { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; width: min(100%, 520px); margin: 12px auto 0; }
.gel__btn {
  padding: 12px 6px; border-radius: 14px; line-height: 1.15; border: 1px solid var(--line-strong); background: rgba(255, 255, 255, 0.03); cursor: pointer;
  font-family: var(--label); font-weight: 800; font-size: 0.86rem; letter-spacing: 0.1em; text-transform: uppercase;
  transition: background 0.15s var(--ease), border-color 0.15s var(--ease), opacity 0.2s var(--ease), transform 0.12s var(--ease);
}
.gel__btn:not(:disabled):hover { border-color: var(--sc-accent); }
.gel__btn:active:not(:disabled) { transform: scale(0.98); }
.gel__btn.is-next { background: var(--sc-accent); color: var(--sc-accent-ink); border-color: var(--sc-accent); }
.gel__btn:disabled { opacity: 0.38; cursor: default; }
.gel__btn.is-done { opacity: 0.55; }
.gel__btn--again { grid-column: 1 / -1; }

/* ------------------------------------------------------------ frames -- */
/* A picture frame: a walnut moulding round a cream mat. Each side of the moulding has its
   own shade (the light comes from above), so the corners mitre like a real frame; the
   moulding's shadow falls on the top of the mat. The gallery and the cells' photo share it. */
:root { --mw: 9px; --mat: 11px; }
@media (min-width: 720px) { :root { --mw: 13px; --mat: 22px; } }
.moulding {
  display: block; position: relative; box-sizing: border-box;
  border: var(--mw) solid; border-color: #5E412B #3F2A1B #26180F #4C3323;
  background: linear-gradient(180deg, #F5F1E8 0%, #EAE4D8 100%);
  box-shadow:
    inset 0 3px 7px -2px rgba(0, 0, 0, 0.34), inset 0 0 0 1px rgba(0, 0, 0, 0.16),
    0 0 0 1px rgba(0, 0, 0, 0.55), 0 26px 40px -22px rgba(0, 0, 0, 0.95), 0 8px 16px -8px rgba(0, 0, 0, 0.7);
}
.moulding::before { /* a fine light lip along the outer edge */
  content: ""; position: absolute; inset: calc(-1 * var(--mw)); pointer-events: none;
  box-shadow: inset 0 1px 0 rgba(255, 236, 210, 0.18), inset 1px 0 0 rgba(255, 236, 210, 0.08);
}
/* the mat's bevel round the photo: a white core and a little shade */
.bevel { position: relative; }
.bevel::after { content: ""; position: absolute; inset: 0; pointer-events: none; box-shadow: 0 0 0 1.5px #FBF9F3, inset 1px 1.5px 3px rgba(0, 0, 0, 0.35); }

/* --------------------------------------------------------- 5 · cells -- */
/* One screen. The film is square and shows the photo, at its end, in a 16:10 rectangle in
   its middle (film.json: rect); --film-k is the square's width over the rectangle's. The
   sharp photo and its frame sit exactly on that rectangle, so when the film ends the photo
   takes over without a pixel moving. The film's outer band fades into the ground. */
/* Like the zoom, the stage runs on under a phone's bottom bar (--under), so the next station
   does not show through the bar while the film plays; --cy, the photo's middle, is 46% down
   the screen above the bar. */
.cells { background: var(--sc-canvas); --ch: calc(var(--mw) + var(--mat)); --pw: min(calc(92vw - 2 * var(--ch)), 1040px, calc((100svh - 370px) * 1.6)); --film-k: 1.125; --cy: calc(100svh * 0.46); }
.cells__stage { position: relative; height: calc(100svh + var(--under)); overflow: hidden; }
.cells__film {
  position: absolute; z-index: 2; left: 50%; top: var(--cy); width: calc(var(--pw) * var(--film-k)); height: auto; aspect-ratio: 1;
  transform: translate(-50%, -50%); max-width: none; pointer-events: none; background: var(--sc-canvas);
  -webkit-mask-image: linear-gradient(to right, transparent 0, #000 4.5%, #000 95.5%, transparent 100%), linear-gradient(to bottom, transparent 0, #000 4.5%, #000 95.5%, transparent 100%);
  -webkit-mask-composite: source-in; mask-image: linear-gradient(to right, transparent 0, #000 4.5%, #000 95.5%, transparent 100%), linear-gradient(to bottom, transparent 0, #000 4.5%, #000 95.5%, transparent 100%);
  mask-composite: intersect;
}
.cells__photo {
  position: absolute; z-index: 3; left: calc(50% - var(--pw) / 2); top: calc(var(--cy) - var(--pw) / 3.2);
  width: var(--pw); aspect-ratio: 16 / 10; margin: 0; padding: 0; border: 0; border-radius: 0; background: #2A2A28;
  opacity: 0; pointer-events: none; cursor: zoom-in; -webkit-tap-highlight-color: transparent; transition: opacity 0.5s var(--ease);
}
.cells__photo img { display: block; width: 100%; height: 100%; object-fit: cover; }
.cells__frame {
  position: absolute; z-index: 1; left: calc(50% - var(--pw) / 2 - var(--ch)); top: calc(var(--cy) - var(--pw) / 3.2 - var(--ch));
  width: calc(var(--pw) + 2 * var(--ch)); height: calc(var(--pw) / 1.6 + 2 * var(--ch)); opacity: 0; transition: opacity 0.9s var(--ease) 0.15s;
}
/* the end: the photo, in its frame; the film steps back */
.cells.is-framed .cells__photo { opacity: 1; pointer-events: auto; }
.cells.is-framed .cells__frame { opacity: 1; }
.cells.is-framed .cells__film { opacity: 0; transition: opacity 0.6s var(--ease) 0.5s; }
/* the words hang just under the photo's frame; the lines share one place, each with its
   part of the film, and the last one stays */
.cells__words {
  position: absolute; z-index: 4; left: 20px; right: 20px; top: calc(var(--cy) + var(--pw) / 3.2 + var(--ch) + 18px);
  display: grid; justify-items: center; row-gap: 16px; pointer-events: none;
}
.cells__lines { display: grid; width: 100%; }
.cells__line {
  grid-area: 1 / 1; margin: 0 auto; max-width: 24ch; text-align: center;
  font-style: italic; font-weight: 500; font-size: clamp(1.45rem, 6vw, 2.2rem); line-height: 1.25; text-shadow: 0 2px 20px rgba(0, 0, 0, 0.8); text-wrap: balance;
  opacity: 0; transform: translateY(8px); transition: opacity 0.6s var(--ease), transform 0.6s var(--ease);
}
.cells__line.is-on { opacity: 1; transform: none; }
.cells__again {
  display: inline-flex; align-items: center; gap: 8px; padding: 10px 18px; border: 1px solid var(--line-strong); border-radius: 999px;
  background: transparent; cursor: pointer; font-family: var(--label); font-weight: 700; font-size: 0.8rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--sc-ink);
  opacity: 0; transform: translateY(6px); transition: opacity 0.5s var(--ease) 0.5s, transform 0.5s var(--ease) 0.5s, border-color 0.15s var(--ease);
}
.cells__again::before { content: "\21BB"; font-size: 1.15em; letter-spacing: 0; color: var(--sc-accent); }
.cells__again:hover { border-color: var(--sc-accent); }
.cells.is-framed .cells__again { opacity: 1; transform: none; pointer-events: auto; }
/* framed, the station ends just under the button: no empty screen before the gallery (user, Oct 21) */
.cells__stage { transition: height 0.6s var(--ease); }
.cells.is-framed .cells__stage { height: min(calc(100svh + var(--under)), calc(var(--cy) + var(--pw) / 3.2 + var(--ch) + 210px)); }

/* ------------------------------------------------------- 6 · gallery -- */
/* A small exhibition: the frames hang one under another on the dark wall, each under its
   own picture light, which comes on as the frame comes into view. gallery.js decides the
   rows (on a phone a landscape photo hangs alone, two portraits share a row); in a row every
   photo is the same height, because each frame grows by its photo's shape (flex-grow = its
   aspect ratio, from a basis of the frame's own width). A row never grows taller than --maxh. */
.gallery {
  background: var(--sc-canvas); --gap: 14px; --maxh: min(64svh, 600px); --chrome: calc(2 * (var(--mw) + var(--mat)));
  padding: 40px 20px 88px;
}
.gallery__head { max-width: 30rem; margin: 0 auto 78px; text-align: center; }
.gallery__kicker { margin: 0; font-family: var(--label); font-weight: 600; font-size: 0.8rem; letter-spacing: 0.24em; text-transform: uppercase; color: var(--sc-accent); }
.gallery__title { margin: 0; font-weight: 500; font-style: italic; font-size: clamp(3.1rem, 13.6vw, 5.4rem); line-height: 1.02; text-wrap: balance; }
.gallery__lede { margin: 14px auto 0; max-width: 30ch; color: var(--sc-ink-soft); font-size: 1.15rem; line-height: 1.45; text-wrap: balance; }
/* the stack brings its own hint, right under the prints */
.gallery--stack .gallery__hint { display: none; }
.gallery--stack .gallery__head { margin-bottom: 30px; }
.gallery__hint { margin: 16px 0 0; font-family: var(--label); font-weight: 600; font-size: 0.74rem; letter-spacing: 0.18em; text-transform: uppercase; color: var(--sc-ink-soft); }
.gallery__wall { display: grid; row-gap: 76px; max-width: 1180px; margin: 0 auto; }
.wall__row {
  display: flex; align-items: flex-end; justify-content: center; gap: var(--gap); width: 100%; margin: 0 auto;
  max-width: calc(var(--maxh) * var(--sum) + var(--n) * var(--chrome) + (var(--n) - 1) * var(--gap));
}
.frame { position: relative; isolation: isolate; margin: 0; min-width: 0; flex: var(--ar) 1 var(--chrome); }
.frame__open { display: block; width: 100%; margin: 0; padding: 0; border: 0; border-radius: 0; background: none; color: inherit; cursor: zoom-in; -webkit-tap-highlight-color: transparent; }
.frame__open:focus-visible { outline-offset: 6px; }
.frame__mould { padding: var(--mat) var(--mat) calc(var(--mat) * 1.3); }
.frame__photo { display: block; aspect-ratio: var(--ar); background: center / cover no-repeat; }
.frame__photo img { display: block; width: 100%; height: 100%; object-fit: cover; opacity: 0; transition: opacity 0.6s var(--ease); }
.frame.is-loaded .frame__photo img { opacity: 1; }
/* the picture light: a small brass lamp on an arm above the frame */
.frame__lamp {
  position: absolute; z-index: 1; left: 50%; top: -21px; width: clamp(54px, 32%, 168px); height: 7px; transform: translateX(-50%);
  border-radius: 4px 4px 3px 3px; background: linear-gradient(180deg, #E8D3A2, #A8854D 55%, #67502F); box-shadow: 0 1px 0 rgba(0, 0, 0, 0.6);
}
.frame__lamp::before { content: ""; position: absolute; left: 50%; top: 7px; width: 3px; height: 14px; transform: translateX(-50%); background: linear-gradient(90deg, #5A4528, #C2A26A, #5A4528); }
.frame__lamp::after { /* the bulb's glow under the shade */
  content: ""; position: absolute; left: -12%; right: -12%; top: 3px; height: 14px; border-radius: 50%;
  background: radial-gradient(closest-side, rgba(255, 224, 176, 0.75), rgba(255, 224, 176, 0)); opacity: 0;
}
/* the light it throws on the wall, behind the frame */
.frame::before {
  content: ""; position: absolute; z-index: -1; left: -18%; right: -18%; top: -70px; bottom: 25%; pointer-events: none;
  background: radial-gradient(58% 56% at 50% 9%, rgba(255, 214, 166, 0.2), rgba(255, 214, 166, 0.05) 56%, rgba(255, 214, 166, 0) 78%);
  opacity: 0;
}
/* the dark before the lamp comes on */
.frame::after { content: ""; position: absolute; z-index: 2; inset: 0; pointer-events: none; background: rgba(4, 10, 16, 0.58); opacity: 0; }
.gallery--hung .frame { transform: translateY(12px); transition: transform 1s var(--ease); }
.gallery--hung .frame::after { opacity: 1; transition: opacity 0.8s var(--ease) 0.12s; }
.gallery--hung .frame::before, .gallery--hung .frame__lamp::after { transition: opacity 0.9s var(--ease); }
.gallery--hung .frame.is-lit { transform: none; }
.gallery--hung .frame.is-lit::after { opacity: 0; }
.gallery--hung .frame.is-lit::before, .gallery--hung .frame.is-lit .frame__lamp::after { opacity: 1; }
@media (min-width: 720px) {
  .gallery { --gap: 30px; --maxh: min(60svh, 560px); padding-left: 40px; padding-right: 40px; }
  .gallery__wall { row-gap: 100px; }
}
@media (prefers-reduced-motion: reduce) {
  .gallery--hung .frame, .gallery--hung .frame::after, .gallery--hung .frame::before, .gallery--hung .frame__lamp::after, .frame__photo img { transition: none; }
}

/* -------------------------------------------------------------- viewer -- */
/* Every photo full screen, side by side in a strip that snaps; swipe to the next. A page
   of its own while open (body.is-viewing sets the rest aside): nothing fixed, no colour at
   the edges but the page's own, so on an iPhone it runs under the island and the toolbar. */
body.is-viewing main, body.is-viewing .mark, body.is-viewing .protocol, body.is-viewing .cut { display: none; }
.viewer { position: relative; height: 100svh; overflow: hidden; opacity: 0; transition: opacity 0.3s var(--ease); }
.viewer.is-open { opacity: 1; }
.viewer__bar {
  position: absolute; z-index: 2; top: calc(12px + env(safe-area-inset-top, 0px)); left: 14px; right: 16px;
  display: flex; align-items: center; justify-content: space-between; gap: 12px; pointer-events: none;
}
.viewer__close {
  pointer-events: auto; display: inline-flex; align-items: center; gap: 8px; padding: 8px 15px 8px 12px;
  border: 1px solid var(--line-strong); border-radius: 999px; background: transparent; cursor: pointer;
  font-family: var(--label); font-weight: 700; font-size: 0.8rem; letter-spacing: 0.16em; text-transform: uppercase;
}
.viewer__close::before { content: ""; width: 8px; height: 8px; border-left: 2px solid currentColor; border-bottom: 2px solid currentColor; transform: translateX(2px) rotate(45deg); }
.viewer__count { margin: 0; font-family: var(--label); font-weight: 600; font-size: 0.84rem; letter-spacing: 0.16em; color: var(--sc-ink-soft); font-variant-numeric: tabular-nums; }
.viewer__strip {
  display: flex; height: 100%; margin: 0; padding: 0; list-style: none;
  overflow-x: auto; overflow-y: hidden; scroll-snap-type: x mandatory; overscroll-behavior-x: contain; scrollbar-width: none;
}
.viewer__strip::-webkit-scrollbar { display: none; }
/* on a phone a photo runs edge to edge */
.viewer__slide {
  flex: 0 0 100%; min-width: 0; display: grid; place-items: center; scroll-snap-align: center; scroll-snap-stop: always;
  padding: calc(66px + env(safe-area-inset-top, 0px)) 0 calc(84px + var(--safe-b));
}
.viewer__slide img {
  display: block; max-width: 100%; max-height: 100%; width: auto; height: auto;
  background: center / cover no-repeat; box-shadow: 0 30px 60px -30px rgba(0, 0, 0, 0.9);
}
@media (min-width: 720px) { .viewer__slide { padding-left: 24px; padding-right: 24px; } .viewer__slide img { border-radius: 3px; } }
.viewer__step { display: none; }
@media (hover: hover) and (pointer: fine) {
  .viewer__step {
    display: grid; place-items: center; position: absolute; z-index: 2; top: 50%; width: 52px; height: 52px; margin-top: -26px;
    border: 1px solid var(--line-strong); border-radius: 50%; background: transparent; cursor: pointer;
  }
  .viewer__step:hover { border-color: var(--sc-accent); }
  .viewer__step--prev { left: 20px; }
  .viewer__step--next { right: 20px; }
  .viewer__step::before { content: ""; width: 11px; height: 11px; border-left: 2px solid currentColor; border-top: 2px solid currentColor; }
  .viewer__step--prev::before { transform: translateX(3px) rotate(-45deg); }
  .viewer__step--next::before { transform: translateX(-3px) rotate(135deg); }
  .viewer__slide { padding-left: 96px; padding-right: 96px; }
}

/* --------------------------------------------------------- 7 · close -- */
.close { background: var(--sc-canvas); isolation: isolate; }
/* One screen of its own (user, Oct 21: "the last thank-you scene into one section"): the words
   spread through the middle, the credits at its foot, and the page ends with it. At the end of
   the page Safari's bar sits just under the last pixel (measured in the iOS 27 simulator), so
   no room is kept under the bar here; 100lvh fills the screen whether the bar is full or small. */
.close__stage {
  position: relative; display: grid; grid-template-rows: 1fr auto; justify-items: center; text-align: center;
  min-height: 100lvh;
  padding: 44px 20px calc(16px + var(--safe-b));
}
.close__stage::before { content: ""; position: absolute; inset: 0; z-index: -1; background: radial-gradient(74% 44% at 50% 46%, #10251E 0%, var(--sc-canvas) 74%); }
.close__inner { align-self: center; width: 100%; max-width: 46rem; }   /* wide enough for the title at desktop size, so it stays centred */
/* the helix that unzips into a heart, above the last words (js/helix.js; user, Oct 22). It takes the
   free space above the words as a row of its own, so its size comes from 100lvh and never changes when
   Safari's bar comes and goes; the dots sit at its foot, next to the words (helix.js). It runs from edge
   to edge of the screen, and a finger on it plays with the dots instead of scrolling. Without WebGL it
   is hidden and the close keeps its old layout. */
.close__stage:has(> .close__helix:not([hidden])) { grid-template-rows: minmax(72px, 1fr) auto minmax(0px, 0.4fr) auto; }
.close__stage:has(> .close__helix:not([hidden])) .close__inner { grid-row: 2; }
.close__stage:has(> .close__helix:not([hidden])) .close__foot { grid-row: 4; }
.close__helix {
  grid-row: 1; justify-self: stretch; position: relative; margin: 0 -20px 12px;
  touch-action: none; -webkit-user-select: none; user-select: none; -webkit-tap-highlight-color: transparent;
}
.close__helix[hidden] { display: none; }
.close__helix canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; pointer-events: none; }
/* desktop: the words are bigger, so the dots also use the stage's top margin (no island there);
   a short window has no room for them at all, and the close keeps its old layout */
@media (hover: hover) and (pointer: fine) {
  .close__stage:has(> .close__helix:not([hidden])) { grid-template-rows: minmax(100px, 1fr) auto minmax(0px, 0.4fr) auto; }
  .close__helix canvas { top: -44px; height: calc(100% + 44px); }
}
@media (hover: hover) and (pointer: fine) and (max-height: 780px), (max-height: 640px) {   /* 640: small phones (both of Safari's heights are under it, so it never flips) and landscape */
  .close__helix { display: none; }
  .close__stage:has(> .close__helix:not([hidden])) { grid-template-rows: 1fr auto; }
  .close__stage:has(> .close__helix:not([hidden])) .close__inner,
  .close__stage:has(> .close__helix:not([hidden])) .close__foot { grid-row: auto; }
}
.close__lead { margin: 0 auto 40px; max-width: 22ch; font-style: italic; font-size: clamp(1.35rem, 5.6vw, 1.85rem); line-height: 1.3; color: var(--sc-ink-soft); text-wrap: balance; }
.close__title { margin: 0; font-family: var(--script); font-size: clamp(4.4rem, 20.5vw, 8.6rem); line-height: 1.1; white-space: nowrap; }
.close__note { margin: 14px auto 0; max-width: 22ch; font-style: italic; font-size: clamp(1.35rem, 5.6vw, 1.85rem); line-height: 1.3; text-wrap: balance; }
.close__sign { margin: 36px 0 0; font-family: var(--label); font-weight: 800; letter-spacing: 0.22em; text-transform: uppercase; color: var(--sc-accent); font-size: 1.02rem; }
.close__links { margin: 46px 0 0; display: flex; gap: 14px; justify-content: center; flex-wrap: wrap; }
.close__links button, .close__links a {
  display: inline-flex; align-items: center; min-height: 52px; padding: 0 22px; border-radius: 999px; border: 1px solid var(--line-strong);
  background: transparent; cursor: pointer; text-decoration: none;
  font-family: var(--label); font-weight: 700; font-size: 0.92rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--sc-ink);
}
.close__links button { background: var(--sc-accent); color: var(--sc-accent-ink); border-color: var(--sc-accent); }
/* the credits, small, at the very foot of the screen (user, Oct 21) */
.close__foot { margin-top: 24px; font-size: 0.86rem; line-height: 1.35; color: var(--sc-ink-soft); }
.close__foot p { margin: 2px 0; }
.close__credit { margin-top: 4px !important; font-size: 0.8rem; color: color-mix(in oklab, var(--sc-ink-soft) 85%, transparent); }
.close__credit a { color: var(--sc-ink); text-decoration: underline; text-decoration-color: color-mix(in oklab, var(--sc-accent) 60%, transparent); text-underline-offset: 3px; }
.close__credit a:hover { color: var(--sc-accent); }

/* -------------------------------------------------------------- finder -- */
.finder { width: min(100%, 560px); max-height: 86svh; margin: auto auto 0; padding: 0; border: 0; border-radius: 22px 22px 0 0; background: linear-gradient(180deg, #0C1B16 0%, #0A1714 70%, var(--night) 100%); color: var(--sc-ink); overscroll-behavior: contain; }
/* on a phone the list starts near the top, so more names show at once (user, Oct 21) */
@media (max-width: 899px) { .finder { height: calc(100dvh - 54px - env(safe-area-inset-top, 0px)); max-height: none; } }
.finder__swipe { margin: 4px 0 0; font-family: var(--label); font-weight: 600; font-size: 0.68rem; letter-spacing: 0.16em; text-transform: uppercase; color: var(--sc-ink-soft); }
.finder::backdrop { background: rgba(3, 8, 7, 0.7); }
.finder__body { position: relative; padding: 20px 18px calc(24px + var(--safe-b)); }
.finder__title { margin: 0; font-weight: 500; font-style: italic; font-size: 2rem; }
.finder__close { position: absolute; top: 18px; right: 16px; padding: 7px 12px; border: 1px solid var(--line-strong); border-radius: 999px; background: transparent; cursor: pointer; font-family: var(--label); font-weight: 700; font-size: 0.74rem; letter-spacing: 0.14em; text-transform: uppercase; }
.finder__group { margin-top: 16px; }
.finder__group h3 { margin: 0 0 6px; font-family: var(--label); font-weight: 700; font-size: 0.78rem; letter-spacing: 0.2em; text-transform: uppercase; color: var(--sc-accent); }
.finder__group--health h3 { color: var(--health); }
.finder__list { list-style: none; margin: 0; padding: 0; columns: 1; }
.finder__list button { display: block; width: 100%; padding: 9px 4px; border: 0; border-bottom: 1px solid var(--line); background: transparent; text-align: left; cursor: pointer; font-size: 1.2rem; }
.finder__list button:hover { color: var(--sc-accent); }

/* ------------------------------------------------------------ desktop -- */
@media (min-width: 900px) {
  .drop__frame { left: auto; right: 6vw; top: 5vh; bottom: 5vh; width: calc(90vh * 9 / 16); border-radius: 28px; overflow: hidden;
    box-shadow: 0 50px 120px -40px rgba(0, 0, 0, 0.9), 0 0 0 1px var(--line); }
  .drop__frame::after { background: linear-gradient(to top, rgba(4, 10, 16, 0.35), transparent 30%); }
  /* the dish version fills the whole screen behind the words (user, Oct 21), its own wide renders */
  .drop--dish .drop__frame { left: 0; right: 0; top: 0; bottom: 0; width: auto; border-radius: 0; box-shadow: none; }
  .drop--dish .drop__frame img, .drop--dish .drop__frame video { object-position: 50% 50%; }
  .drop--dish .drop__frame::after {
    background:
      linear-gradient(to right, rgba(4, 10, 16, 0.9) 0%, rgba(4, 10, 16, 0.62) 30%, rgba(4, 10, 16, 0) 56%),
      linear-gradient(to bottom, var(--edge) 0%, rgba(4, 10, 16, 0) 14%),
      linear-gradient(to top, var(--edge) 0%, rgba(4, 10, 16, 0) 18%);
  }
  .drop__copy { left: 7vw; right: auto; top: 50%; bottom: auto; transform: translateY(-50%); text-align: left; padding: 0; max-width: 560px; justify-items: start; }
  .drop__title { font-size: clamp(6rem, 9vw, 9rem); }
  .drop__lede { margin-left: 0; max-width: 24ch; }
  .drop__eyebrow { display: block; font-size: 1.08rem; letter-spacing: 0.22em; margin-bottom: 34px; }   /* clear of the script's tall letters (user, Oct 21) */
  .drop__lede { margin-top: 26px; }
  .drop__crest { display: none; }
  .begin { margin-top: 30px; }
  .zoom__readout { left: 40px; top: 72px; }
  .zoom__film { left: auto; right: 36px; bottom: 26px; margin: 0; max-width: 32ch; text-align: right; }
  .zoom__captions { left: calc(var(--lx) + var(--lr) + 56px); right: 48px; top: calc(var(--ly) - 30px); bottom: auto; text-align: left; }
  .zoom__caption { top: 0; bottom: auto; margin: 0; max-width: 20ch; }
  .zoom__size { font-size: 3rem; }
  .card__body { min-height: 100lvh; margin: 0 auto; max-width: 1120px; display: grid; grid-template-columns: 300px 1fr; grid-template-rows: auto auto auto auto; align-content: start; column-gap: 44px; padding: calc(4vh + 24px) 40px 7vh; }
  .card__top { grid-column: 1 / -1; }
  .card__portrait { grid-row: 2; width: 300px; height: 375px; }   /* sized outright: it alone sets the row's height */
  .card__text { grid-row: 2; align-self: center; text-align: left; margin-top: 0; }
  .card__notes { grid-column: 1 / -1; margin: 30px 0 0; }   /* the board runs the card's full width */
  /* a grid item with auto margins shrinks to its words (the names broke onto two lines): full width, centred */
  .card__nav { grid-column: 1 / -1; justify-self: center; width: 100%; max-width: 720px; margin: 32px auto 0; gap: 16px; }
  .card__nav button { padding: 15px 22px; font-size: 0.92rem; }
  .practical { padding: 64px 14px 132px; }
  .practical__inner { display: grid; grid-template-columns: 1fr 520px; column-gap: 60px; align-items: center; }
  .practical__head { text-align: left; margin: 0; grid-row: 1 / 3; }
  .gel { grid-column: 2; }
  .gel__controls { grid-column: 2; }
  .finder { margin: auto; border-radius: 22px; }
  .finder__list { columns: 2; column-gap: 24px; }
}

@media (prefers-reduced-motion: reduce) {
  .card__door, .card.is-opening .card__body { transition: none; animation: none; }
}

/* ------------------------------------------- pinned stages on a phone -- */
/* Safari on an iPhone (26 and later) paints its status bar and toolbar solid once a
   sticky element holding pictures reaches a screen edge, and keeps them that way
   until a reload, so the page stops running under the Dynamic Island. Muro's phone
   page simply has no sticky elements. Here the stages keep their pinned acts but are
   held still by a scroll-driven transform instead of position: sticky: while the act
   covers the screen, the stage moves down exactly as far as the page scrolls, which
   is what sticky did, and Safari sees ordinary page content. main.js switches this on
   after the engine has checked its stages (it warns about a stage that is not sticky
   at start-up). Desktops keep sticky. */
@media (hover: none) and (pointer: coarse) {
  @supports (animation-timeline: view()) {
    html.pin-free .sc-act--pinned { container-type: size; view-timeline: --sc-act block; }
    html.pin-free .sc-act--pinned > .sc-stage {
      position: absolute; top: 0; left: 0; right: 0;
      animation: sc-hold linear both;
      animation-timeline: --sc-act;
      animation-range: contain 0% contain 100%;
    }
  }
}
/* 100cqh is the act's height, 100dvh the screen's: the act's travel under the screen */
@keyframes sc-hold { from { transform: translate3d(0, 0, 0); } to { transform: translate3d(0, calc(100cqh - 100dvh), 0); } }
