/* ============================================================================
   APEC — THE GALLERY · STYLESHEET
   ============================================================================
   A sunlit museum hall. One framed album per event hangs on a curved
   wall; the wall sweeps past in an arc as you scroll sideways. Click an
   album and it comes off the wall, opens like a book, and shows its
   photographs as photobook spreads. Ink / warm cream / brass — the
   shared language of the APEC pages, with the lights turned up.
   Everything renders from data/gallery-data.js.

   Motion notes: the arc is driven by CSS scroll-driven animations
   (view-timeline). js/gallery.js drives the same math by hand in
   browsers without them, and html.flatfx turns the arc off entirely
   (reduced motion · ?static=1).
   ========================================================================== */

:root {
  /* the dark family tokens (dialogs, veil, chrome on dim) */
  --ink:        #0a0b0d;
  --ink-2:      #101217;
  --line:       rgba(237, 231, 216, 0.14);
  --cream:      #ede7d8;
  --cream-dim:  #b6afa0;
  --gold:       #c9a45c;
  --gold-hi:    #e6c581;
  --gold-dim:   rgba(201, 164, 92, 0.35);

  /* the lit room */
  --wall-hi:    #f6f1e4;
  --wall:       #efe9da;
  --wall-lo:    #ddd5c1;
  --paper:      #f6f0e1;
  --paper-2:    #efe8d5;
  --txt:        #201d16;
  --txt-soft:   #55503f;
  --txt-faint:  #8b8371;
  --brass:      #a37e33;
  --brass-deep: #8a692c;
  --frame:      #191510;
  --line-ink:   rgba(32, 29, 22, 0.14);

  --font-display: "Fraunces", Georgia, "Times New Roman", serif;
  --font-text:    "Instrument Sans", "Segoe UI", system-ui, sans-serif;
  --font-mono:    "IBM Plex Mono", Consolas, "Courier New", monospace;

  --pad: clamp(1.25rem, 4vw, 4rem);
  --head-h: 4.25rem;
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-swing: cubic-bezier(0.7, 0, 0.2, 1);

  /* hall geometry */
  --floor-y: 72svh;                              /* where wall meets floor   */
  --bay-w: clamp(20rem, 33vw, 32rem);            /* one album's stretch      */
  --bay-gap: clamp(2rem, 5vw, 4.5rem);
  --cv-top: 11.5svh;                             /* hanging height           */
  --cv-h: clamp(17rem, 55svh, 36rem);            /* the framed canvas height */
  --cv-drop: calc(var(--floor-y) - var(--cv-top) - var(--cv-h));  /* wall below the frame */
  --sweep: 44deg;                                /* how hard the wall curves */
  --recede: -8.5rem;
}

/* ---- Base ---------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

html { font-size: 125%; /* +25%: 16→20px base type scale, for PC legibility */ -webkit-text-size-adjust: 100%; }

body {
  background: var(--wall);
  color: var(--txt);
  font-family: var(--font-text);
  font-size: clamp(1rem, 0.95rem + 0.25vw, 1.125rem);
  line-height: 1.65;
  overflow: hidden;                     /* the hall is the page */
  height: 100svh;
}

img { max-width: 100%; height: auto; display: block; }

[hidden] { display: none !important; }

::selection { background: var(--gold); color: var(--ink); }

a { color: var(--brass-deep); text-decoration-color: var(--gold-dim); text-underline-offset: 3px; }

:focus-visible { outline: 2px solid var(--brass-deep); outline-offset: 3px; }

.skip-link {
  position: fixed; top: -4rem; left: 1rem; z-index: 300;
  background: var(--gold); color: var(--ink);
  padding: 0.6rem 1rem; font-family: var(--font-mono); font-size: 0.8rem;
  transition: top 0.2s;
}
.skip-link:focus { top: 1rem; }

/* ---- Boot veil: the lights come up ---------------------------------------- */
.veil {
  position: fixed; inset: 0; z-index: 260; background: var(--ink);
  pointer-events: none; opacity: 1; transition: opacity 1.1s var(--ease-out);
}
body.booted .veil { opacity: 0; }
/* passing through a doorway: the lights dip fast, then come back up
   on the next wall at the veil's own unhurried pace */
body.booted .veil.is-pass { opacity: 1; transition-duration: 0.4s; }
html.static .veil { display: none; }

/* ---- Custom cursor --------------------------------------------------------- */
.cursor-dot, .cursor-ring {
  position: fixed; top: 0; left: 0; z-index: 240;
  pointer-events: none; border-radius: 50%; opacity: 0;
}
.cursor-dot { width: 6px; height: 6px; background: var(--txt); margin: -3px 0 0 -3px; }
.cursor-ring {
  width: 44px; height: 44px; margin: -22px 0 0 -22px;
  border: 1px solid rgba(138, 105, 44, 0.7);
  display: grid; place-items: center;
  transition: width 0.3s var(--ease-out), height 0.3s var(--ease-out),
              margin 0.3s var(--ease-out), border-color 0.3s, background-color 0.3s;
}
.cursor-ring span {
  font-family: var(--font-mono); font-size: 0.55rem; letter-spacing: 0.22em;
  text-transform: uppercase; color: var(--ink); opacity: 0; transition: opacity 0.2s;
  user-select: none;
}
body.cursor-on { cursor: none; }
body.cursor-on a, body.cursor-on button, body.cursor-on [role="button"] { cursor: none; }
body.cursor-on .cursor-dot, body.cursor-on .cursor-ring { opacity: 1; }
.cursor-ring.is-link {
  width: 62px; height: 62px; margin: -31px 0 0 -31px;
  background: var(--gold-hi); border-color: var(--gold-hi);
}
.cursor-ring.is-link span { opacity: 1; }
.cursor-ring.is-down { width: 52px; height: 52px; margin: -26px 0 0 -26px; }

/* ---- Fixed chrome ----------------------------------------------------------- */
.site-head {
  position: fixed; inset: 0 0 auto 0; z-index: 200;
  height: var(--head-h);
  display: flex; align-items: center; justify-content: space-between;
  padding: 0 var(--pad);
  background: linear-gradient(180deg, rgba(246, 241, 228, 0.92), rgba(246, 241, 228, 0));
  border-bottom: 1px solid transparent;
  transition: border-color 0.4s;
}
.site-head.scrolled { border-bottom-color: transparent; }
.brand { display: flex; align-items: center; gap: 0.8rem; text-decoration: none; }
.brand__mark { width: 40px; height: auto; }
.brand__text { display: flex; flex-direction: column; line-height: 1.2; }
.brand__text strong {
  font-family: var(--font-display); font-weight: 600; font-size: 1.02rem;
  letter-spacing: 0.18em; color: var(--txt);
}
.brand__text small {
  font-family: var(--font-mono); font-size: 0.56rem; letter-spacing: 0.16em;
  text-transform: uppercase; color: var(--txt-faint);
}
.head-side { display: flex; align-items: center; gap: 1.4rem; }
.head-search {
  display: inline-flex; align-items: center; gap: 0.45rem;
  border: 0; background: none; cursor: pointer;
  font-family: var(--font-mono); font-size: 0.62rem; letter-spacing: 0.2em;
  text-transform: uppercase; color: var(--brass-deep);
  border-bottom: 1px solid var(--gold-dim); padding: 0 0 2px;
  transition: color 0.25s, border-color 0.25s;
}
.head-search:hover { color: var(--txt); border-color: var(--txt); }
.head-search svg { flex: none; }
.head-home {
  font-family: var(--font-mono); font-size: 0.62rem; letter-spacing: 0.2em;
  text-transform: uppercase; color: var(--brass-deep); text-decoration: none;
  border-bottom: 1px solid var(--gold-dim); padding-bottom: 2px;
  transition: color 0.25s, border-color 0.25s;
}
.head-home:hover { color: var(--txt); border-color: var(--txt); }
.head-note {
  font-family: var(--font-mono); font-size: 0.72rem; letter-spacing: 0.18em;
  text-transform: uppercase; color: var(--txt-faint);
}
@media (max-width: 640px) { .head-note { display: none; } }

/* ---- Walk progress hairline ------------------------------------------------- */
.progress { position: fixed; top: 0; left: 0; right: 0; height: 2px; z-index: 210; }
.progress span {
  display: block; height: 100%; width: 100%;
  background: linear-gradient(90deg, var(--brass), var(--gold-hi));
  transform: scaleX(0); transform-origin: 0 50%;
}

/* ============================================================================
   THE ROOM — plaster, skylight, the polished floor
   ========================================================================== */
.hall { position: relative; height: 100svh; }

.room { position: absolute; inset: 0; z-index: 1; overflow: hidden; }

.room__wall {
  position: absolute; inset: 0 0 calc(100svh - var(--floor-y)) 0;
  background:
    /* corner falloff, so the hall feels round */
    radial-gradient(130% 100% at 50% 34%, rgba(255, 253, 244, 0.7), rgba(0, 0, 0, 0) 58%),
    linear-gradient(105deg, rgba(58, 48, 30, 0.24), rgba(0, 0, 0, 0) 14% 86%, rgba(58, 48, 30, 0.26)),
    /* plaster: bright at eye height, real shadow up in the cove */
    linear-gradient(180deg, #b9ae92 0%, #d3c9ae 6%, #eae2cd 14%, var(--wall-hi) 36%, #f4eede 58%, #e6ddc8 86%, #d9cfb6 100%);
}
/* faint plaster striation */
.room__wall::after {
  content: ""; position: absolute; inset: 0;
  background: repeating-linear-gradient(180deg,
    rgba(120, 108, 82, 0.028) 0 1px, rgba(0, 0, 0, 0) 1px 7px);
}

/* the luminous skylight strip, with its slender mullions */
.room__ceiling {
  position: absolute; inset: 0 0 auto 0; height: 4.6svh;
  background:
    repeating-linear-gradient(90deg,
      rgba(0, 0, 0, 0) 0 6.8rem, rgba(96, 84, 58, 0.34) 6.8rem calc(6.8rem + 3px)),
    linear-gradient(180deg, #fffcf0 0%, #fdf6e2 55%, #ecdfc0 100%);
  box-shadow: 0 1px 0 rgba(96, 82, 52, 0.45), 0 10px 34px -6px rgba(255, 244, 214, 0.85);
}
/* the light it pours down the plaster */
.room__ceiling::after {
  content: ""; position: absolute; inset: 100% 0 auto 0; height: 34svh;
  background: radial-gradient(72% 100% at 50% 0%, rgba(255, 250, 230, 0.6), rgba(0, 0, 0, 0) 72%);
}

.room__floor {
  position: absolute; inset: var(--floor-y) 0 0 0;
  background:
    linear-gradient(105deg, rgba(44, 37, 24, 0.24), rgba(0, 0, 0, 0) 16% 84%, rgba(44, 37, 24, 0.26)),
    linear-gradient(180deg, #8e8571 0%, #b0a791 9%, #c9c2ae 32%, #c2bAA4 64%, #a49a83 100%);
}
/* long glossy sheen across the polish */
.room__sheen {
  position: absolute; inset: var(--floor-y) 0 0 0; pointer-events: none;
  background:
    linear-gradient(97deg, rgba(0, 0, 0, 0) 24%, rgba(255, 253, 246, 0.6) 41%, rgba(255, 253, 246, 0.1) 51%, rgba(0, 0, 0, 0) 60%),
    radial-gradient(62% 50% at 50% 0%, rgba(255, 252, 240, 0.55), rgba(0, 0, 0, 0) 76%);
}
/* the seam where wall meets floor, and the wall's soft cast onto it */
.room__seam {
  position: absolute; left: 0; right: 0; top: var(--floor-y); height: 4.5rem;
  background: linear-gradient(180deg, rgba(52, 44, 27, 0.3), rgba(52, 44, 27, 0.08) 30%, rgba(0, 0, 0, 0));
}
.room__seam::before {
  content: ""; position: absolute; inset: -1px 0 auto 0; height: 1px;
  background: rgba(64, 54, 33, 0.44);
}

/* ============================================================================
   THE RAIL — the curved wall of albums (a sideways scroller)
   ========================================================================== */
.rail {
  position: absolute; inset: 0; z-index: 10;
  display: flex; align-items: stretch;
  gap: var(--bay-gap);
  overflow-x: auto; overflow-y: hidden;
  padding-inline: calc(50vw - var(--bay-w) / 2);
  scrollbar-width: none;
  overscroll-behavior-x: contain;
  outline-offset: -6px;
  user-select: none; -webkit-user-select: none;
}
.rail::-webkit-scrollbar { display: none; }

.bay {
  position: relative;
  flex: 0 0 var(--bay-w);
  width: var(--bay-w); height: 100svh;
  view-timeline: --bay inline;
  transform: perspective(1200px);
  /* NO content-visibility here. It applies implicit PAINT containment
     (invisible in the `contain` computed value) that clips the wall label
     + ghost numeral where they overflow the bay into the gap — the centred
     album's label vanished behind its neighbour's frame. Exempting the
     centred bays dynamically was worse still (toggling content-visibility
     mid-scroll thrashes layout). The off-screen albums are left to render;
     the walk's cost is kept down by the cheaper shadows/shine/no-filter
     changes instead. */
}
/* the bay's contents ride one wrapper, so the arrival can fade them in
   without touching the arc transform on .bay itself */
.bay__in {
  width: 100%; height: 100%;
  display: grid; justify-items: center; align-content: start;
}
.bay--text .bay__in { align-content: center; }

/* — the arc: each bay sweeps a circle segment as it crosses the room —
   TRANSFORM ONLY: a z-index here would force the whole scroll-linked
   animation onto the main thread (z-index can't run on the compositor).
   The paint-order grade (centered bay above its receded neighbours'
   protruding labels) is written by gallery.js instead — cheap, and only
   when a bay's grade actually changes. */
@keyframes bay-sweep {
  /* literal values, NOT var(--sweep)/var(--recede): keyframes that need
     var() substitution are resolved per-element on the main thread every
     frame — literals let the sweep run on the compositor. Keep these in
     step with --sweep/--recede (a narrow-hall redefinition sits in the
     760px media block). */
  0%   { transform: perspective(1200px) rotateY(44deg) translateZ(-8.5rem); }
  50%  { transform: perspective(1200px) rotateY(0deg) translateZ(0); }
  100% { transform: perspective(1200px) rotateY(-44deg) translateZ(-8.5rem); }
}
@keyframes bay-shade {           /* side albums fall out of their spotlight */
  0%   { opacity: 0.38; }
  50%  { opacity: 0; }
  100% { opacity: 0.38; }
}
@keyframes bay-glow {            /* …and the centre one stands in it */
  0%   { opacity: 0.05; }
  50%  { opacity: 1; }
  100% { opacity: 0.05; }
}
@supports (animation-timeline: view()) and (animation-range: entry) {
  html:not(.flatfx) .bay {
    animation: bay-sweep auto linear both;
    animation-timeline: --bay;
  }
  html:not(.flatfx) .bay .cv__shade {
    animation: bay-shade auto linear both;
    animation-timeline: --bay;
  }
  html:not(.flatfx) .bay .bay__spot,
  html:not(.flatfx) .bay .cv__halo,
  html:not(.flatfx) .bay .cv__lume {
    animation: bay-glow auto linear both;
    animation-timeline: --bay;
  }
}

/* ---- The spotlight over each work ---------------------------------------- */
.bay__spot {
  position: absolute; top: 0; left: 50%; translate: -50% 0;
  width: calc(var(--cv-h) * 1.34); height: calc(var(--floor-y) - 6svh);
  pointer-events: none;
  /* a soft cone of warm light, widening as it falls — gradients only */
  background:
    radial-gradient(56% 110% at 50% -6%, rgba(255, 247, 218, 0.95), rgba(255, 247, 218, 0.3) 56%, rgba(255, 247, 218, 0) 74%),
    linear-gradient(180deg, rgba(255, 246, 214, 0.55), rgba(255, 246, 214, 0) 72%);
}
/* the pool it leaves on the polish */
.bay__spot::after {
  content: ""; position: absolute; left: 50%; translate: -50% 0;
  bottom: -10svh; width: 120%; height: 11svh;
  background: radial-gradient(50% 50% at 50% 50%, rgba(255, 246, 212, 0.5), rgba(255, 246, 212, 0) 72%);
}
/* the slender track light it hangs from */
.bay__lamp {
  position: absolute; top: 4.6svh; left: 50%; translate: -50% 0;
  width: 1.1rem; height: 0.42rem; border-radius: 0 0 40% 40% / 0 0 100% 100%;
  background: linear-gradient(180deg, #3a3329, #15110b);
  box-shadow: 0 1px 2px rgba(40, 32, 16, 0.4);
  pointer-events: none;
}
.bay__lamp::before {
  content: ""; position: absolute; inset: auto auto -0.3rem 50%; translate: -50% 0;
  width: 0.46rem; height: 0.3rem; border-radius: 50%;
  background: rgba(255, 244, 206, 0.98);
  box-shadow: 0 0 12px 4px rgba(255, 240, 192, 0.65);
}
.bay__lamp::after {   /* stem up to the skylight track */
  content: ""; position: absolute; inset: auto auto 100% 50%; translate: -50% 0;
  width: 1.5px; height: 4.6svh; background: linear-gradient(180deg, #57503f, #241f16);
}

/* ---- The numeral etched into the plaster behind each work ------------------ */
.bay__ghost {
  position: absolute; z-index: 1; pointer-events: none;
  top: calc(var(--cv-top) - 7svh);
  left: calc(50% - (var(--cv-h) * 5 / 7) / 2 - 9rem);
  font-family: var(--font-display); font-style: italic; font-weight: 300;
  font-size: clamp(10rem, 30svh, 17rem); line-height: 1;
  color: rgba(46, 40, 26, 0.06);
  text-shadow: 1px 1px 0 rgba(255, 253, 244, 0.5);
  user-select: none;
}

/* While an album or the lightbox is open (html.reading, set by gallery.js)
   the hall behind it holds still — no point nudging a scroll cue nobody
   can see behind the dim. */
html.reading .intro__hint::after { animation-play-state: paused; }

/* ---- The works arrive as the lights come up ---------------------------------
   Content is NEVER hidden by default (the boot veil covers the pre-boot
   moment); the arrival is an animation, so a script failure or a
   screenshot run can't leave an empty wall. html.shot skips theatrics. */
@keyframes bay-arrive {
  from { opacity: 0; translate: 0 1.6rem; }
  to   { opacity: 1; translate: 0 0; }
}
html:not(.flatfx):not(.shot) body.booted .bay__in {
  animation: bay-arrive 1s var(--ease-out) both;
  animation-delay: calc(0.15s + var(--bd, 0ms));
}

/* ---- The framed album on the wall ----------------------------------------- */
.cv {
  position: relative; z-index: 2; margin-top: var(--cv-top);
  border: 0; padding: 0; background: none; text-align: inherit;
  -webkit-tap-highlight-color: transparent;
}
/* the frame's soft cast on the plaster — a gradient, not a box-shadow:
   the old 54px/110px shadow blurs were the wall's single dearest raster
   cost (nine frames re-blurred through every sweep) */
.cv::before {
  content: ""; position: absolute; z-index: -1; pointer-events: none;
  inset: 4% -14% -10% -14%;
  background: radial-gradient(56% 58% at 50% 56%,
    rgba(42, 34, 16, 0.5), rgba(42, 34, 16, 0.16) 56%, rgba(42, 34, 16, 0) 76%);
  opacity: 0.9; transition: opacity 0.5s var(--ease-out);
}
.cv:hover::before, .cv:focus-visible::before { opacity: 1; }
.cv__frame {
  position: relative; display: block;
  height: var(--cv-h); aspect-ratio: 5 / 7;
  background: linear-gradient(168deg, #241e14 0%, var(--frame) 30% 70%, #0b0906 100%);
  padding: clamp(0.5rem, 1.1vw, 0.8rem);
  box-shadow:
    inset 0 1px 0 rgba(214, 190, 130, 0.28),
    0 2px 3px rgba(40, 32, 16, 0.45),
    0 10px 14px -8px rgba(42, 34, 16, 0.5);   /* big soft cast: .cv::before */
  transition: translate 0.5s var(--ease-out), box-shadow 0.5s var(--ease-out);
}
/* frame profile: a fine brass sight edge inside the walnut */
.cv__frame::before {
  content: ""; position: absolute; inset: clamp(0.3rem, 0.7vw, 0.5rem);
  border: 1px solid rgba(214, 178, 106, 0.55);
  pointer-events: none; z-index: 2;
}
.cv__frame img {
  width: 100%; height: 100%; object-fit: cover;
  /* no sepia/saturate filter here: a filter on a 3D-rotating image is
     re-applied to its re-projected raster every frame, and at 0.1 it was
     invisible anyway */
}
/* glass — and the glare that slides across it when you reach for the album */
.cv__frame::after {
  content: ""; position: absolute; inset: 0; z-index: 2; pointer-events: none;
  background: linear-gradient(112deg,
    rgba(255, 252, 240, 0) 12%, rgba(255, 252, 240, 0.17) 26%,
    rgba(255, 252, 240, 0.03) 40%, rgba(255, 252, 240, 0) 55%);
  background-size: 240% 100%; background-position: 88% 0;
  transition: background-position 0.9s var(--ease-out);
}
.cv:hover .cv__frame::after, .cv:focus-visible .cv__frame::after { background-position: 12% 0; }
/* the pages tucked behind the cover — this frame holds a whole album */
.cv__leaves, .cv__leaves::before {
  content: ""; position: absolute; z-index: -1;
  inset: 4% -1.1% 2% auto; width: 3%;
  background: linear-gradient(90deg, #efe8d4, #d9d0b6);
  box-shadow: 1px 2px 6px rgba(45, 36, 18, 0.35);
  transition: translate 0.5s var(--ease-out);
}
.cv__leaves::before { inset: 2% auto 4% auto; right: -46%; width: 46%; }
.cv:hover .cv__leaves { translate: 3px 0; }

/* the picture light's halo, blooming on the plaster behind the frame */
.cv__halo {
  position: absolute; z-index: -1; pointer-events: none;
  inset: -18% -34%;
  background: radial-gradient(50% 50% at 50% 46%, rgba(255, 245, 208, 0.62), rgba(255, 245, 208, 0.2) 54%, rgba(255, 245, 208, 0) 76%);
  opacity: 0;
}
/* the shine lifting the photograph itself. NO mix-blend-mode: a blend mode
   forces the whole 3D-rotating bay to be re-composited with backdrop
   readback on every frame of the walk — it was one of the two dearest
   costs. A plain warm overlay at trimmed alpha reads almost identically. */
.cv__lume {
  position: absolute; inset: 0; z-index: 2; pointer-events: none;
  background: radial-gradient(86% 66% at 50% 30%, rgba(255, 248, 222, 0.3), rgba(255, 248, 222, 0.04) 58%, rgba(255, 248, 222, 0) 78%);
  opacity: 0;
}
/* dimming shade for out-of-spotlight albums (animated by the arc) */
.cv__shade {
  position: absolute; inset: 0; z-index: 3; pointer-events: none;
  background: linear-gradient(180deg, rgba(24, 20, 12, 0.5), rgba(24, 20, 12, 0.34));
  opacity: 0;
}

.cv:hover .cv__frame, .cv:focus-visible .cv__frame {
  translate: 0 -6px;
  box-shadow:
    inset 0 1px 0 rgba(214, 190, 130, 0.28),
    0 3px 5px rgba(40, 32, 16, 0.4),
    0 14px 18px -9px rgba(45, 36, 18, 0.52);
}

/* ---- Its reflection in the polish (starting at the wall/floor seam) -------- */
.cv__mirror {
  position: absolute; top: calc(100% + var(--cv-drop)); left: 0; right: 0;
  height: calc(var(--cv-h) * 0.62); display: block;
  pointer-events: none;
  transform: scaleY(-1);
  /* colour ops only — blur() here re-blurred nine reflections on every
     re-raster of the sweep; the mask fade + low opacity keep it soft */
  opacity: 0.3; filter: saturate(0.75) brightness(1.06);
  -webkit-mask-image: linear-gradient(0deg, rgba(0, 0, 0, 0.85), rgba(0, 0, 0, 0) 88%);
          mask-image: linear-gradient(0deg, rgba(0, 0, 0, 0.85), rgba(0, 0, 0, 0) 88%);
}
.cv__mirror img { width: 100%; height: 100%; object-fit: cover; object-position: bottom; }
/* soft contact shadow pooling at the seam under the work */
.cv::after {
  content: ""; position: absolute; top: calc(100% + var(--cv-drop) - 0.9svh); left: 4%; right: 4%;
  height: 1.8svh; border-radius: 50%;
  background: radial-gradient(50% 50% at 50% 50%, rgba(50, 42, 24, 0.3), rgba(0, 0, 0, 0) 70%);
  pointer-events: none;
}

/* ---- The wall label: a fine card beside the work, at reading height -------- */
.bay__label {
  position: absolute; z-index: 4;
  top: calc(var(--cv-top) + var(--cv-h) * 0.6);
  left: calc(50% + (var(--cv-h) * 5 / 7) / 2 + 1.1rem);
  width: clamp(9.5rem, 12vw, 11.5rem);
  border: 0; text-align: left;
  background: linear-gradient(160deg, #fcf9f0, #f1ead8);
  padding: 0.9rem 0.95rem 0.8rem;
  box-shadow:
    0 1px 1px rgba(45, 36, 18, 0.3),
    0 12px 26px -12px rgba(45, 36, 18, 0.5);
  transition: translate 0.4s var(--ease-out), box-shadow 0.4s var(--ease-out);
}
.bay__label::before {   /* brass pin */
  content: ""; position: absolute; top: 0.5rem; right: 0.55rem;
  width: 0.28rem; height: 0.28rem; border-radius: 50%;
  background: radial-gradient(circle at 35% 30%, #ecd9a8, var(--brass) 65%, #6b5220);
}
.bay__label:hover { translate: 0 -3px; }
.bay__label__no {
  display: block;
  font-family: var(--font-mono); font-size: 0.52rem; letter-spacing: 0.3em;
  color: var(--brass-deep); text-transform: uppercase;
}
.bay__label__title {
  display: block; margin-top: 0.5rem;
  font-family: var(--font-display); font-weight: 480; font-style: normal;
  font-size: clamp(1rem, 1.2vw, 1.16rem); line-height: 1.2; color: var(--txt);
}
.bay__label__era {
  display: block; margin-top: 0.45rem;
  font-family: var(--font-mono); font-size: 0.54rem; letter-spacing: 0.13em;
  text-transform: uppercase; color: var(--txt-soft); line-height: 1.7;
}
.bay__label__n {
  display: block; margin-top: 0.6rem; padding-top: 0.5rem;
  border-top: 1px solid var(--line-ink);
  font-family: var(--font-mono); font-size: 0.52rem; letter-spacing: 0.2em;
  text-transform: uppercase; color: var(--txt-faint);
}
/* the LAST album's label would otherwise reach past the gap and straight
   into the colophon's text (nothing to its right holds it back) — pull
   the label in, and narrow+right-align the colophon panel by the same
   reach so the two can never collide, at any viewport. Right-aligning
   the grid item (rather than a margin under justify-items:center, which
   only moves the visible box by HALF a margin — centering splits it
   either side of the margin box) is what actually delivers the full
   clearance. Only applies while labels hang beside their frame (pairs
   with the 1100px flip below). */
@media (min-width: 1101px) {
  .bay[data-edge="end"] .bay__label { width: 8rem; }
  .bay[data-kind="colo"] .bay__in { justify-items: end; }
  .bay[data-kind="colo"] .bay__panel {
    /* the flat 2D estimate undershoots: the neighbour bay isn't sitting
       flat when colo is centred — it's a step into its own rotateY/
       translateZ arc, and perspective splays its near (right) edge
       further than a plain offset predicts. +3.5rem is empirical
       slack for that, checked against the rendered geometry directly
       rather than derived analytically. */
    --colo-clear: max(0px, calc(
      (var(--cv-h) * 5 / 14) + 12.6rem - (var(--bay-w) / 2) - var(--bay-gap)
    ));
    width: min(38rem, calc(var(--bay-w) - var(--colo-clear)), 92vw);
  }
}

/* narrower rooms: the card slips under the frame instead */
@media (max-width: 1100px) {
  .bay__label {
    top: calc(var(--cv-top) + var(--cv-h) + 2.4svh);
    left: 50%; translate: -50% 0; width: min(14rem, 70vw);
    text-align: center;
  }
  .bay__label:hover { translate: -50% -3px; }
  .bay__label::before { right: auto; left: 50%; margin-left: -0.14rem; }
  .bay__label__no { padding-left: 0; }
}

/* ---- The stanchion posts between works ------------------------------------- */
.bay__post {
  position: absolute; z-index: 5; pointer-events: none;
  left: calc(-0.5 * var(--bay-gap)); bottom: calc(100svh - var(--floor-y) - 12svh);
  width: 3px; height: 12svh;
  background: linear-gradient(90deg, #38312a, #7a7060 45%, #221d16);
}
.bay__post::before {   /* the brass cap */
  content: ""; position: absolute; top: -0.42rem; left: 50%; translate: -50% 0;
  width: 0.72rem; height: 0.72rem; border-radius: 50%;
  background: radial-gradient(circle at 34% 30%, #f2e2b2, var(--brass) 60%, #55420f);
  box-shadow: 0 1px 2px rgba(45, 36, 18, 0.55);
}
.bay__post::after {    /* base + its blurred reflection */
  content: ""; position: absolute; top: 100%; left: 50%; translate: -50% 0;
  width: 1.7rem; height: 0.44rem; border-radius: 50%;
  background: #2b2620;
  box-shadow: 0 0.5rem 0.55rem -0.22rem rgba(38, 33, 26, 0.45);
}

/* ============================================================================
   THE DOORWAY — an arched opening to the next wall (or back to the last).
   Drawn entirely in gradients: walnut casing, a lit passage beyond, the
   next room's plaster and floor. Clicking it walks you through.
   ========================================================================== */
.door {
  position: relative; z-index: 2; margin-top: var(--cv-top);
  height: var(--cv-h);                   /* the arch hangs in the same band */
  border: 0; padding: 0; background: none; cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
/* the casing's soft cast on the plaster, like the frames' */
.door::before {
  content: ""; position: absolute; z-index: -1; pointer-events: none;
  inset: 4% -18% -10% -18%;
  background: radial-gradient(56% 58% at 50% 56%,
    rgba(42, 34, 16, 0.42), rgba(42, 34, 16, 0.13) 56%, rgba(42, 34, 16, 0) 76%);
  opacity: 0.9; transition: opacity 0.5s var(--ease-out);
}
.door:hover::before, .door:focus-visible::before { opacity: 1; }
/* warm light spilling out of the passage, pooling at the threshold */
.door::after {
  content: ""; position: absolute; left: -12%; right: -12%;
  top: calc(100% + var(--cv-drop) - 1.4svh); height: 3svh;
  border-radius: 50%; pointer-events: none;
  background: radial-gradient(50% 50% at 50% 50%, rgba(255, 243, 202, 0.5), rgba(255, 243, 202, 0) 72%);
}
.door__arch {
  display: block; position: relative; height: 100%;
  width: calc(var(--cv-h) * 0.56);
  padding: clamp(0.5rem, 1.1vw, 0.8rem);
  background: linear-gradient(168deg, #241e14 0%, var(--frame) 30% 70%, #0b0906 100%);
  border-radius: 50% 50% 0 0 / 22% 22% 0 0;
  box-shadow:
    inset 0 1px 0 rgba(214, 190, 130, 0.28),
    0 2px 3px rgba(40, 32, 16, 0.45),
    0 10px 14px -8px rgba(42, 34, 16, 0.5);
  transition: translate 0.5s var(--ease-out);
}
/* the brass sight edge inside the casing */
.door__arch::before {
  content: ""; position: absolute; inset: clamp(0.3rem, 0.7vw, 0.5rem);
  border: 1px solid rgba(214, 178, 106, 0.55);
  border-radius: 50% 50% 0 0 / 21% 21% 0 0;
  pointer-events: none; z-index: 2;
}
.door:hover .door__arch, .door:focus-visible .door__arch { translate: 0 -6px; }
/* the passage: the next room glowing beyond the opening */
.door__deep {
  display: block; position: relative; height: 100%; overflow: hidden;
  border-radius: 48% 48% 0 0 / 20% 20% 0 0;
  background:
    /* skylight falling in the room beyond */
    radial-gradient(92% 58% at 50% 10%, rgba(255, 250, 228, 0.95), rgba(255, 250, 228, 0) 62%),
    /* its far plaster, the seam, the polished floor */
    linear-gradient(180deg, #f4eedd 0%, #ece4cf 52%, #d9d0b8 70%,
                    #978c74 71.5%, #b9ae94 78%, #d6cdb4 100%);
  box-shadow:
    inset 0 16px 26px -14px rgba(40, 32, 16, 0.6),
    inset 0 -8px 16px -10px rgba(40, 32, 16, 0.35);
}
/* the glow that answers the hand */
.door__glow {
  position: absolute; inset: 0;
  background: radial-gradient(70% 52% at 50% 42%, rgba(255, 244, 206, 0.55), rgba(255, 244, 206, 0) 72%);
  opacity: 0.45; transition: opacity 0.5s var(--ease-out);
}
.door:hover .door__glow, .door:focus-visible .door__glow { opacity: 0.95; }
/* the way-on arrow, floating in the opening */
.door__arrow {
  position: absolute; top: 44%; left: 50%; translate: -50% -50%;
  color: var(--brass-deep); font-size: 1.5rem; line-height: 1;
  text-shadow: 0 1px 0 rgba(255, 253, 244, 0.6);
  animation: hint-nudge 2.2s var(--ease-out) infinite;
}
html.flatfx .door__arrow { animation: none; }
/* the door's plaque — the wall-label card, centred beneath the arch */
.door__plate {
  position: absolute; top: calc(100% + 2.4svh); left: 50%; translate: -50% 0;
  width: min(13rem, 66vw); display: block; text-align: center;
  background: linear-gradient(160deg, #fcf9f0, #f1ead8);
  padding: 0.9rem 0.95rem 0.8rem;
  box-shadow:
    0 1px 1px rgba(45, 36, 18, 0.3),
    0 12px 26px -12px rgba(45, 36, 18, 0.5);
  transition: translate 0.4s var(--ease-out);
}
.door__plate::before {   /* brass pin */
  content: ""; position: absolute; top: 0.5rem; left: 50%; margin-left: -0.14rem;
  width: 0.28rem; height: 0.28rem; border-radius: 50%;
  background: radial-gradient(circle at 35% 30%, #ecd9a8, var(--brass) 65%, #6b5220);
}
.door:hover .door__plate { translate: -50% -3px; }
@media (max-height: 560px) { .door__plate { display: none; } }

/* ============================================================================
   ENTRANCE & COLOPHON — wall texts, set into the same arc
   ========================================================================== */
.bay--text .bay__panel {
  /* never wider than the bay itself — a grid item's default min-width:auto
     would otherwise let long unbroken text (the title, the mono counts)
     blow the box out past its own bay and into a neighbour's wall label */
  width: min(38rem, var(--bay-w), 92vw); min-width: 0;
  padding-bottom: 14svh;
  display: grid; justify-items: center; text-align: center;
}

.intro__kicker {
  font-family: var(--font-mono); font-size: 0.6rem; letter-spacing: 0.34em;
  text-transform: uppercase; color: var(--txt-soft);
}
.intro__title {
  margin-top: 1.2rem;
  font-family: var(--font-display); font-weight: 320;
  font-size: clamp(3rem, 6vw, 5.4rem); line-height: 0.98;
  letter-spacing: -0.015em; color: var(--txt);
  text-wrap: balance;
}
.intro__title em { font-style: italic; color: var(--brass); }
.intro__rule {
  margin-top: 1.6rem; width: 4rem; height: 1px; background: var(--brass);
  position: relative;
}
.intro__rule::before, .intro__rule::after {
  content: ""; position: absolute; top: -1.5px; width: 4px; height: 4px;
  rotate: 45deg; background: var(--brass);
}
.intro__rule::before { left: -0.7rem; }
.intro__rule::after { right: -0.7rem; }
.intro__sub { margin-top: 1.4rem; max-width: 34em; font-size: 0.95rem; color: var(--txt-soft); }
.intro__count {
  margin-top: 1.5rem;
  font-family: var(--font-mono); font-size: 0.58rem; letter-spacing: 0.28em;
  text-transform: uppercase; color: var(--brass-deep);
}
/* the entrance's own way into the catalogue, below the count line */
.intro__search {
  margin-top: 1.9rem;
  display: inline-flex; align-items: center; gap: 0.65rem;
  padding: 0.62rem 0.85rem 0.62rem 1rem;
  border: 1px solid var(--gold-dim); border-radius: 2rem;
  background: linear-gradient(160deg, #fcf9f0, #f1ead8);
  cursor: pointer;
  box-shadow: 0 1px 1px rgba(45, 36, 18, 0.22), 0 10px 22px -14px rgba(45, 36, 18, 0.5);
  transition: translate 0.3s var(--ease-out), border-color 0.3s, box-shadow 0.3s;
}
.intro__search:hover {
  translate: 0 -2px; border-color: var(--brass);
  box-shadow: 0 2px 3px rgba(45, 36, 18, 0.22), 0 16px 28px -14px rgba(45, 36, 18, 0.55);
}
.intro__search svg { flex: none; color: var(--brass-deep); }
.intro__search span {
  font-family: var(--font-text); font-size: 0.92rem; color: var(--txt-soft);
}
.intro__search kbd {
  font-family: var(--font-mono); font-size: 0.6rem; line-height: 1; color: var(--txt-faint);
  border: 1px solid var(--line-ink); border-radius: 4px; padding: 0.18rem 0.4rem;
  background: rgba(255, 253, 244, 0.6);
}
@media (pointer: coarse) { .intro__search kbd { display: none; } }

.intro__hint {
  margin-top: 2rem; display: flex; align-items: center; gap: 0.8rem;
  font-family: var(--font-mono); font-size: 0.58rem; letter-spacing: 0.22em;
  text-transform: uppercase; color: var(--txt-faint);
}
.intro__hint::after {
  content: "\2192"; color: var(--brass); font-size: 0.9rem;
  animation: hint-nudge 2.2s var(--ease-out) infinite;
}
@keyframes hint-nudge {
  0%, 100% { translate: 0 0; opacity: 0.7; }
  50%      { translate: 0.5rem 0; opacity: 1; }
}
html.flatfx .intro__hint::after { animation: none; }

.colo { text-align: center; display: grid; justify-items: center; }
.colo img { width: 64px; opacity: 0.92; }
.colo__org {
  margin-top: 1.1rem; font-family: var(--font-display);
  font-weight: 400; font-size: 1.1rem; color: var(--txt);
}
.colo__note { margin-top: 0.9rem; font-size: 0.88rem; color: var(--txt-soft); max-width: 30em; }
.colo__link {
  margin-top: 1.4rem; display: inline-block;
  font-family: var(--font-mono); font-size: 0.66rem; letter-spacing: 0.2em;
  text-transform: uppercase; color: var(--brass-deep); text-decoration: none;
  border-bottom: 1px solid var(--gold-dim); padding-bottom: 2px;
}
.colo__link:hover { color: var(--txt); border-color: var(--txt); }
.colo__social { margin-top: 1.4rem; display: flex; align-items: center; justify-content: center; gap: 0.8rem; }
.colo__social a {
  display: inline-flex; align-items: center; justify-content: center;
  width: 2.4rem; height: 2.4rem; border-radius: 50%;
  color: var(--brass-deep); border: 1px solid var(--gold-dim);
  transition: color .25s ease, border-color .25s ease, transform .25s ease;
}
.colo__social a:hover { color: var(--txt); border-color: var(--txt); transform: translateY(-2px); }
.colo__social svg { display: block; width: 1.1rem; height: 1.1rem; }

/* ============================================================================
   THE HOUSE LIGHTS — a fixed beam where you stand; dusk everywhere else.
   The wall slides through the light, so whichever album faces you is lit.
   ========================================================================== */
.dimmer {
  position: absolute; inset: 0; z-index: 20; pointer-events: none;
  background:
    radial-gradient(52vw 58svh at 50% 42%,
      rgba(0, 0, 0, 0) 34%,
      rgba(26, 21, 12, 0.13) 58%,
      rgba(25, 20, 11, 0.3) 82%,
      rgba(23, 18, 10, 0.42) 100%),
    linear-gradient(180deg, rgba(26, 21, 12, 0.16), rgba(0, 0, 0, 0) 18% 82%, rgba(26, 21, 12, 0.2));
}
@media (max-width: 760px) {
  .dimmer {
    background:
      radial-gradient(70vw 54svh at 50% 40%,
        rgba(0, 0, 0, 0) 36%,
        rgba(26, 21, 12, 0.13) 60%,
        rgba(25, 20, 11, 0.3) 84%,
        rgba(23, 18, 10, 0.4) 100%),
      linear-gradient(180deg, rgba(26, 21, 12, 0.14), rgba(0, 0, 0, 0) 16% 84%, rgba(26, 21, 12, 0.18));
  }
}

/* ============================================================================
   THE DOCK — where you stand, and every album by name
   ========================================================================== */
.dock {
  position: fixed; z-index: 30; left: 50%; bottom: clamp(0.8rem, 2.4svh, 1.6rem);
  translate: -50% 0;
  display: grid; justify-items: center; gap: 0.55rem;
  max-width: min(94vw, 46rem);
}
.dock__readout {
  font-family: var(--font-mono); font-size: 0.6rem; letter-spacing: 0.22em;
  text-transform: uppercase; color: #f0e9d6; text-align: center;
  text-shadow: 0 1px 2px rgba(30, 24, 14, 0.5);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 92vw;
}
.dock__row { display: flex; align-items: center; gap: 0.9rem; max-width: inherit; }
.dock__chips {
  display: flex; gap: 0.15rem; overflow-x: auto; scrollbar-width: none;
  padding: 2px;                       /* room for focus rings */
}
.dock__chips::-webkit-scrollbar { display: none; }
.dock__chip {
  position: relative; flex: none;
  padding: 0.4rem 0.65rem 0.75rem;
  background: none; border: 0; cursor: pointer;
  font-family: var(--font-mono); font-size: 0.62rem; letter-spacing: 0.12em;
  color: rgba(238, 230, 210, 0.66);
  text-shadow: 0 1px 2px rgba(30, 24, 14, 0.45);
  transition: color 0.25s;
}
/* each numeral stands on a small brass point */
.dock__chip::after {
  content: ""; position: absolute; left: 50%; bottom: 0.28rem; translate: -50% 0;
  width: 3px; height: 3px; rotate: 45deg;
  background: rgba(238, 230, 210, 0.3);
  transition: background-color 0.25s, scale 0.25s var(--ease-out);
}
.dock__chip:hover { color: #f5efdd; }
.dock__chip:hover::after { background: rgba(230, 197, 129, 0.75); }
.dock__chip.is-here { color: var(--gold-hi); }
.dock__chip.is-here::after { background: var(--gold-hi); scale: 1.5; }
.dock__arrow {
  flex: none; width: 2rem; height: 2rem; border-radius: 50%;
  border: 1px solid rgba(238, 230, 210, 0.32); background: none;
  color: rgba(238, 230, 210, 0.72); font-size: 1rem; line-height: 1; cursor: pointer;
  transition: border-color 0.25s, color 0.25s;
}
.dock__arrow:hover { border-color: var(--gold-hi); color: var(--gold-hi); }

/* ============================================================================
   THE TOME — an album taken off the wall and opened
   ========================================================================== */
.tome {
  border: 0; padding: 0; background: transparent; color: var(--cream);
  width: 100vw; height: 100svh; max-width: 100vw; max-height: 100svh;
  overflow: hidden; cursor: auto;
}
.tome::backdrop {
  /* a plain deep dim — backdrop-filter: blur() here re-blurred the whole
     screen continuously while the book was open */
  background: rgba(9, 9, 11, 0.84);
}

.tome__bar {
  position: absolute; inset: 0 0 auto 0; z-index: 40;
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  padding: 1.05rem var(--pad);
  background: linear-gradient(180deg, rgba(8, 8, 10, 0.55), rgba(8, 8, 10, 0));
  opacity: 0; transition: opacity 0.45s var(--ease-out);
  pointer-events: none;
}
.tome.is-open .tome__bar, .tome.is-opening .tome__bar { opacity: 1; pointer-events: auto; }
.tome__back {
  border: 0; background: none; cursor: pointer;
  font-family: var(--font-mono); font-size: 0.64rem; letter-spacing: 0.2em;
  text-transform: uppercase; color: var(--gold-hi);
  border-bottom: 1px solid var(--gold-dim); padding-bottom: 3px;
  transition: color 0.25s, border-color 0.25s;
}
.tome__back:hover { color: var(--cream); border-color: var(--cream); }
.tome__where {
  font-family: var(--font-mono); font-size: 0.6rem; letter-spacing: 0.2em;
  text-transform: uppercase; color: var(--cream-dim);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

.tome__scroller {
  position: absolute; inset: 0; overflow-y: auto; overscroll-behavior: contain;
  padding: calc(var(--head-h) + 2svh) 0 7svh;
  scrollbar-width: thin; scrollbar-color: rgba(201, 164, 92, 0.4) transparent;
  opacity: 0; transition: opacity 0.35s var(--ease-out);
}
.tome.is-hinge .tome__scroller, .tome.is-open .tome__scroller { opacity: 1; }
.tome.is-open .tome__scroller { overflow-y: auto; }
.tome.is-opening .tome__scroller { overflow-y: hidden; }

/* ---- The book ------------------------------------------------------------- */
.book {
  width: min(94vw, 72rem); margin-inline: auto;
  display: grid; justify-items: center; gap: clamp(1.6rem, 3.4svh, 2.6rem);
}

.leaf {
  position: relative;
  background:
    radial-gradient(120% 100% at 50% 0%, rgba(255, 253, 244, 0.6), rgba(0, 0, 0, 0) 60%),
    linear-gradient(160deg, var(--paper) 0%, var(--paper-2) 100%);
  box-shadow:
    0 2px 3px rgba(0, 0, 0, 0.45),
    0 3px 0 -1px #e9e1cb,          /* the pages stacked beneath */
    0 6px 0 -2px #dcd2b8,
    0 9px 0 -3px #cfc4a6,
    0 16px 22px -12px rgba(0, 0, 0, 0.75);  /* 80px blur was a raster hog */
  color: var(--txt);
}
/* paper tooth */
.leaf::after {
  content: ""; position: absolute; inset: 0; pointer-events: none; opacity: 0.5;
  background: repeating-linear-gradient(98deg, rgba(120, 105, 70, 0.02) 0 2px, rgba(0, 0, 0, 0) 2px 6px);
}

.leaf--title, .leaf--colo {
  width: min(88vw, 34rem);
  padding: clamp(2.4rem, 6svh, 4rem) clamp(1.6rem, 4vw, 3rem);
  text-align: center; display: grid; justify-items: center;
}
/* a letterpress hairline around the title and colophon pages */
.leaf--title::before, .leaf--colo::before {
  content: ""; position: absolute; inset: 0.9rem; pointer-events: none;
  border: 1px solid rgba(32, 29, 22, 0.14);
}
.leaf--title::after { display: none; }        /* keep the frame crisp */
.leaf__no {
  font-family: var(--font-display); font-style: italic; font-weight: 300;
  font-size: clamp(3rem, 8svh, 4.6rem); line-height: 1; color: var(--brass);
}
.leaf__rule { width: 3.2rem; height: 1px; background: var(--brass); margin-top: 1.4rem; opacity: 0.65; }
.leaf__title {
  margin-top: 1.3rem;
  font-family: var(--font-display); font-weight: 420;
  font-size: clamp(1.8rem, 3.4vw, 2.5rem); line-height: 1.12; color: var(--txt);
}
.leaf__era {
  margin-top: 0.9rem;
  font-family: var(--font-mono); font-size: 0.62rem; letter-spacing: 0.24em;
  text-transform: uppercase; color: var(--brass-deep);
}
.leaf__note { margin-top: 1.2rem; font-size: 0.92rem; color: var(--txt-soft); max-width: 26em; }
.leaf__count {
  margin-top: 1.6rem;
  font-family: var(--font-mono); font-size: 0.56rem; letter-spacing: 0.22em;
  text-transform: uppercase; color: var(--txt-faint);
}

/* ---- The spreads ----------------------------------------------------------- */
.leaf--spread {
  width: 100%;
  padding: clamp(1.4rem, 3.4vw, 3rem) clamp(1.2rem, 3.4vw, 3rem) clamp(2.2rem, 4vw, 3.2rem);
  /* long albums: leaves outside the scroller skip layout & paint entirely */
  content-visibility: auto;
  contain-intrinsic-size: auto 40rem;
}
.leaf--colo { content-visibility: auto; contain-intrinsic-size: auto 24rem; }
/* the gutter: two pages meeting in the middle */
.leaf--spread::before {
  content: ""; position: absolute; inset: 0; pointer-events: none; z-index: 2;
  background: linear-gradient(90deg,
    rgba(0, 0, 0, 0) 44%, rgba(84, 72, 44, 0.13) 49.7%,
    rgba(60, 50, 28, 0.22) 50%, rgba(84, 72, 44, 0.13) 50.3%, rgba(0, 0, 0, 0) 56%);
}
.leaf__head {
  display: flex; justify-content: space-between; gap: 1rem;
  margin-bottom: clamp(1.1rem, 2.4svh, 1.8rem);
  font-family: var(--font-mono); font-size: 0.54rem; letter-spacing: 0.24em;
  text-transform: uppercase; color: var(--txt-faint);
}
/* align-items:start so a print never stretches to match its neighbour's
   height — each keeps its own picture's proportions */
.leaf__grid { display: grid; gap: clamp(1rem, 2.6vw, 2rem); align-items: start; }
.leaf__grid--p3a { grid-template-columns: 1.55fr 1fr; grid-template-areas: "a b" "a c"; }
.leaf__grid--p3b { grid-template-columns: 1fr 1.55fr; grid-template-areas: "b a" "c a"; }
.leaf__grid--p2a { grid-template-columns: 1.35fr 1fr; grid-template-areas: "a b"; }
.leaf__grid--p2b { grid-template-columns: 1fr 1.35fr; grid-template-areas: "b a"; }
.leaf__grid--p1  { grid-template-columns: 1fr;        grid-template-areas: "a"; }
.leaf__grid > :nth-child(1) { grid-area: a; }
.leaf__grid > :nth-child(2) { grid-area: b; }
.leaf__grid > :nth-child(3) { grid-area: c; }
/* the small companions sit lower / higher, so nothing lines up too neatly */
.leaf__grid--p2a > :nth-child(2) { margin-top: clamp(1.6rem, 5svh, 3.4rem); }
.leaf__grid--p2b > :nth-child(2) { margin-bottom: clamp(1.6rem, 5svh, 3.4rem); align-self: end; }
.leaf__foot {
  margin-top: clamp(1.2rem, 2.6svh, 2rem);
  display: flex; justify-content: space-between;
  font-family: var(--font-mono); font-size: 0.54rem; letter-spacing: 0.22em;
  color: var(--txt-faint);
}

/* ---- A photograph in the book ---------------------------------------------- */
.ph { position: relative; display: grid; align-self: start; }
.ph__btn {
  border: 0; padding: 0.45rem 0.45rem 0; background: #fdfbf4; cursor: pointer;
  box-shadow: 0 1px 2px rgba(60, 50, 28, 0.35), 0 12px 26px -12px rgba(60, 50, 28, 0.5);
  transition: translate 0.4s var(--ease-out), box-shadow 0.4s var(--ease-out), rotate 0.4s var(--ease-out);
  rotate: var(--ph-rot, 0deg);
}
.ph__btn:hover {
  translate: 0 -4px; rotate: 0deg;
  box-shadow: 0 2px 4px rgba(60, 50, 28, 0.35), 0 22px 40px -14px rgba(60, 50, 28, 0.6);
}
/* the whole photograph, never cropped: the print takes the picture's own
   ratio (fills the cell's width, natural height) so nothing is cut off */
.ph__btn img { display: block; width: 100%; height: auto; }
.ph figcaption {
  padding: 0.5rem 0.55rem 0.55rem;
  background: #fdfbf4; margin-top: 0;
  font-family: var(--font-display); font-style: italic;
  font-size: 0.82rem; color: var(--txt-soft);
  box-shadow: 0 1px 2px rgba(60, 50, 28, 0.35), 0 12px 26px -12px rgba(60, 50, 28, 0.5);
  clip-path: inset(0 -40px -40px -40px);
  rotate: var(--ph-rot, 0deg);
}
.ph figcaption .num {
  font-family: var(--font-mono); font-style: normal; font-size: 0.54rem;
  letter-spacing: 0.2em; text-transform: uppercase; color: var(--txt-faint);
}
/* the whole print (button + caption strip) tilts together */
.ph--t1 { --ph-rot: -1.3deg; }
.ph--t2 { --ph-rot: 1.1deg; }
.ph--t3 { --ph-rot: -0.7deg; }
.ph:hover figcaption { rotate: 0deg; translate: 0 -4px; }
/* archival tape on some prints */
.ph--tape::before, .ph--tape::after {
  content: ""; position: absolute; z-index: 3; width: 3.4rem; height: 1.1rem;
  background: rgba(233, 222, 186, 0.72);
  box-shadow: 0 1px 2px rgba(60, 50, 28, 0.22);
  pointer-events: none;
}
.ph--tape::before { top: -0.45rem; left: -0.9rem; rotate: -42deg; }
.ph--tape::after  { top: -0.45rem; right: -0.9rem; rotate: 42deg; }
/* the full-page plate — the lone photo on a spread. Shown whole (its own
   ratio), centred, and capped in height so a portrait one can't run off
   the page. */
.ph--plate .ph__btn { padding: 0; background: none; text-align: center; }
.ph--plate .ph__btn img {
  width: auto; max-width: 100%; max-height: 74svh; margin-inline: auto;
}
.ph--plate figcaption {
  position: absolute; left: 1rem; bottom: 1rem; margin: 0;
  padding: 0.45rem 0.8rem; clip-path: none;
  background: rgba(253, 251, 244, 0.92);
}

/* ---- Colophon leaf --------------------------------------------------------- */
.leaf--colo img { width: 58px; opacity: 0.94; }
.leaf--colo .colo__org { color: var(--txt); }
.leaf--colo .leaf__fin {
  margin-top: 2rem; font-family: var(--font-mono); font-size: 0.56rem;
  letter-spacing: 0.3em; text-transform: uppercase; color: var(--txt-faint);
}

/* ---- The flyer: the cover that flies off the wall --------------------------- */
.flyer {
  position: fixed; z-index: 30; pointer-events: none;
  transform-origin: top left; will-change: transform;
  display: none;
}
.tome.is-opening .flyer, .tome.is-closing .flyer { display: block; }
.flyer__cover {
  position: absolute; inset: 0;
  transform-style: preserve-3d; transform: perspective(1600px) rotateY(0deg);
  transform-origin: left center;
  transition: transform 0.72s var(--ease-swing);
}
.tome.is-hinge .flyer__cover { transform: perspective(1600px) rotateY(-152deg); }
.flyer__front, .flyer__inside {
  position: absolute; inset: 0;
  backface-visibility: hidden; -webkit-backface-visibility: hidden;
}
.flyer__front {
  background: var(--frame); padding: clamp(0.5rem, 1.1vw, 0.8rem);
  box-shadow: 0 24px 60px -20px rgba(0, 0, 0, 0.85);
}
.flyer__front img { width: 100%; height: 100%; object-fit: cover; }
.flyer__inside {
  transform: rotateY(180deg);
  background: linear-gradient(200deg, var(--paper) 0%, var(--paper-2) 100%);
  box-shadow: 0 10px 40px -12px rgba(0, 0, 0, 0.6);
}

/* ============================================================================
   THE LIGHTBOX — a photograph, up close (over the open book)
   ========================================================================== */
.lightbox {
  border: 0; padding: 0; background: transparent; color: var(--cream);
  max-width: min(94vw, 74rem); max-height: 94svh;
  margin: auto; overflow: visible; cursor: auto;
}
.lightbox::backdrop {
  background: rgba(7, 8, 10, 0.92);
}
.lightbox__bar {
  display: flex; align-items: center; justify-content: space-between;
  padding: 0 0 0.7rem;
}
.lightbox__count {
  font-family: var(--font-mono); font-size: 0.62rem; letter-spacing: 0.22em;
  text-transform: uppercase; color: var(--cream-dim);
}
.lightbox__close {
  border: 1px solid var(--line); background: rgba(10, 11, 13, 0.5);
  color: var(--cream); width: 2.3rem; height: 2.3rem; border-radius: 50%;
  font-size: 0.85rem; cursor: pointer;
  transition: border-color 0.25s, color 0.25s, background-color 0.25s;
}
.lightbox__close:hover { border-color: var(--gold-hi); color: var(--gold-hi); }
.lightbox__body {
  background: var(--cream); padding: 0.7rem 0.7rem 0;
  box-shadow: 0 30px 80px -20px rgba(0, 0, 0, 0.9);
}
.lightbox__body img {
  max-height: min(74svh, 46rem); width: auto; max-width: 100%; margin-inline: auto;
}
.lightbox__body figcaption {
  font-family: var(--font-mono); font-size: 0.58rem; letter-spacing: 0.2em;
  text-transform: uppercase; color: #6f6858;
  padding: 0.6rem 0.2rem 0.65rem; text-align: center;
}
.lightbox__nav {
  position: absolute; top: 50%; translate: 0 -50%;
  border: 1px solid var(--line); background: rgba(10, 11, 13, 0.55);
  color: var(--cream); width: 2.6rem; height: 2.6rem; border-radius: 50%;
  font-size: 1.3rem; line-height: 1; cursor: pointer;
  transition: border-color 0.25s, color 0.25s;
}
.lightbox__nav:hover { border-color: var(--gold-hi); color: var(--gold-hi); }
.lightbox__nav--prev { left: -3.4rem; }
.lightbox__nav--next { right: -3.4rem; }
@media (max-width: 900px) {
  .lightbox__nav--prev { left: 0.5rem; }
  .lightbox__nav--next { right: 0.5rem; }
}

/* ============================================================================
   THE CATALOGUE — search across every wall (a paper card over the hall)
   ========================================================================== */
.cata {
  border: 0; padding: 0; background: transparent; color: var(--txt);
  width: min(94vw, 38rem); max-height: 82svh;
  margin: 9svh auto auto; overflow: visible; cursor: auto;
}
.cata::backdrop { background: rgba(9, 9, 11, 0.62); }

.cata__card {
  position: relative;
  display: grid; grid-template-rows: auto auto auto 1fr;
  max-height: 82svh;
  background:
    radial-gradient(120% 100% at 50% 0%, rgba(255, 253, 244, 0.6), rgba(0, 0, 0, 0) 60%),
    linear-gradient(160deg, var(--paper) 0%, var(--paper-2) 100%);
  box-shadow:
    0 2px 3px rgba(0, 0, 0, 0.45),
    0 24px 60px -18px rgba(0, 0, 0, 0.8);
  padding: 1.3rem 1.4rem 1.1rem;
}
/* the letterpress hairline the title/colophon leaves wear */
.cata__card::before {
  content: ""; position: absolute; inset: 0.6rem; pointer-events: none;
  border: 1px solid rgba(32, 29, 22, 0.14);
}
.cata__head { display: flex; align-items: center; justify-content: space-between; gap: 1rem; }
.cata__title {
  font-family: var(--font-display); font-weight: 460;
  font-size: 1.25rem; color: var(--txt);
}
.cata__close {
  border: 1px solid var(--line-ink); background: none; color: var(--txt-soft);
  width: 2rem; height: 2rem; border-radius: 50%; flex: none;
  font-size: 0.75rem; cursor: pointer;
  transition: border-color 0.25s, color 0.25s;
}
.cata__close:hover { border-color: var(--brass-deep); color: var(--brass-deep); }
.cata__field {
  margin-top: 0.9rem;
  display: flex; align-items: center; gap: 0.6rem;
  border-bottom: 1px solid var(--brass); padding-bottom: 0.45rem;
  color: var(--brass-deep);
}
.cata__field input {
  flex: 1; border: 0; background: none; outline: none;
  font-family: var(--font-text); font-size: 1rem; color: var(--txt);
}
.cata__field input::placeholder { color: var(--txt-faint); font-style: italic; }
.cata__field input::-webkit-search-cancel-button { -webkit-appearance: none; }
.cata__hint {
  margin-top: 0.55rem;
  font-family: var(--font-mono); font-size: 0.54rem; letter-spacing: 0.16em;
  text-transform: uppercase; color: var(--txt-faint);
}
.cata__results {
  margin-top: 0.8rem; overflow-y: auto; min-height: 6rem;
  scrollbar-width: thin; scrollbar-color: rgba(163, 126, 51, 0.4) transparent;
  padding: 2px 2px 0.4rem;               /* room for focus rings */
}
.cata__sect {
  margin: 0.9rem 0 0.35rem;
  font-family: var(--font-mono); font-size: 0.54rem; letter-spacing: 0.24em;
  text-transform: uppercase; color: var(--brass-deep);
}
.cata__sect:first-child { margin-top: 0.1rem; }
.cata__row {
  display: grid; grid-template-columns: auto 1fr auto; align-items: center;
  gap: 0.8rem; width: 100%; text-align: left;
  border: 0; background: none; cursor: pointer;
  padding: 0.5rem 0.4rem;
  border-bottom: 1px solid var(--line-ink);
  transition: background-color 0.2s;
}
.cata__row:hover { background: rgba(201, 164, 92, 0.13); }
.cata__row__no {
  font-family: var(--font-display); font-style: italic; font-weight: 300;
  font-size: 1.15rem; color: var(--brass); min-width: 2rem; text-align: center;
}
.cata__row__thumb {
  width: 3.1rem; height: 2.3rem; object-fit: cover; flex: none;
  background: #ddd5c1;
  box-shadow: 0 1px 2px rgba(60, 50, 28, 0.35);
}
.cata__row__body { min-width: 0; }
.cata__row__title {
  display: block; font-family: var(--font-display); font-weight: 450;
  font-size: 0.95rem; line-height: 1.25; color: var(--txt);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.cata__row--ph .cata__row__title { font-style: italic; font-weight: 400; font-size: 0.88rem; }
.cata__row__era {
  display: block; margin-top: 0.15rem;
  font-family: var(--font-mono); font-size: 0.52rem; letter-spacing: 0.13em;
  text-transform: uppercase; color: var(--txt-soft);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.cata__row__meta {
  font-family: var(--font-mono); font-size: 0.52rem; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--txt-faint); text-align: right; white-space: nowrap;
}
.cata__none, .cata__more {
  padding: 1.4rem 0.4rem; text-align: center;
  font-family: var(--font-display); font-style: italic;
  font-size: 0.95rem; color: var(--txt-soft);
}
.cata__more { padding: 0.7rem 0.4rem 0.3rem; font-size: 0.85rem; }
@media (max-width: 640px) {
  .cata { margin-top: 4svh; max-height: 88svh; }
  .cata__card { max-height: 88svh; padding: 1.05rem 1rem 0.9rem; }
  .cata__row__meta { display: none; }
}

/* ============================================================================
   NOSCRIPT · SMALL ROOMS · MOTION DISCIPLINE
   ========================================================================== */
.noscript-note {
  position: fixed; inset: 0; z-index: 150; display: grid; place-content: center;
  padding: var(--pad); text-align: center; color: var(--txt-soft);
  background: var(--wall);
}

/* narrower halls */
@media (max-width: 760px) {
  :root {
    --bay-w: min(80vw, 24rem);
    --cv-h: clamp(14rem, 42svh, 26rem);
    --sweep: 32deg;
    --recede: -4.5rem;
    --floor-y: 65svh;
    --cv-top: 10.5svh;
  }
  .bay__label { width: min(14rem, 72vw); }
  /* the gentler narrow-hall sweep — mirrors --sweep/--recede above */
  @keyframes bay-sweep {
    0%   { transform: perspective(1200px) rotateY(32deg) translateZ(-4.5rem); }
    50%  { transform: perspective(1200px) rotateY(0deg) translateZ(0); }
    100% { transform: perspective(1200px) rotateY(-32deg) translateZ(-4.5rem); }
  }
  .bay__ghost {
    font-size: clamp(6.5rem, 20svh, 10rem);
    left: calc(50% - (var(--cv-h) * 5 / 7) / 2 - 4.5rem);
    top: calc(var(--cv-top) - 5svh);
  }
  .cv__mirror { height: calc(var(--cv-h) * 0.4); opacity: 0.26; }
  .bay__post { display: none; }
  .dock { bottom: 0.7rem; }
  .dock__readout { max-width: 88vw; }
  .dock__arrow { display: none; }
  .leaf--spread::before { display: none; }        /* one page, no gutter */
  .leaf__grid--p3a, .leaf__grid--p3b, .leaf__grid--p2a, .leaf__grid--p2b {
    grid-template-columns: 1fr;
    grid-template-areas: "a" "b" "c";
  }
  .leaf__grid--p2a > :nth-child(2), .leaf__grid--p2b > :nth-child(2) { margin: 0; }
}
@media (max-height: 560px) {
  :root { --cv-h: clamp(11rem, 42svh, 16rem); }
  .bay__label { display: none; }
}

/* the still hall: reduced motion or ?static=1 — the wall hangs flat */
html.flatfx .bay { transform: none; }
html.flatfx .cv__shade { opacity: 0.12; }
html.flatfx .bay__spot { opacity: 0.85; }
html.flatfx .cv__halo { opacity: 0.55; }
html.flatfx .cv__lume { opacity: 0.5; }
html.flatfx .dimmer { opacity: 0.6; }
/* flat walls stack in plain order, so labels sit under the frame instead */
html.flatfx .bay__label {
  top: calc(var(--cv-top) + var(--cv-h) + 2.4svh);
  left: 50%; translate: -50% 0; width: min(14rem, 70vw);
  text-align: center;
}
html.flatfx .bay__label::before { right: auto; left: 50%; margin-left: -0.14rem; }

html.static *, html.static *::before, html.static *::after {
  animation: none !important; transition: none !important;
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001s !important; animation-iteration-count: 1 !important;
    transition-duration: 0.001s !important;
  }
}
