/* ==========================================================================
   ogcz — Home only: the intro scene and the video-style showcase
   ========================================================================== */

/* ==========================================================================
   INTRO — the hero from the design guide → "Portfolio" → card deck,
   all in one sticky scene. Everything that moves here is transform or
   opacity only, so scrolling stays on the GPU.
   ========================================================================== */
.intro { position: relative; height: 320vh; }
.intro__stage {
  position: sticky;
  top: 0;
  height: 100vh;
  height: 100svh; /* keeps "Portfolio" above the phone/tablet browser bar */
  overflow: hidden;
  isolation: isolate;
  background: #000;
}

/* The guide's light beams and dust, baked into one image (assets/hero-beams.webp).
   Re-render it if the guide changes; cover + center keeps the beam
   crossing the wordmark on every screen shape. */
.hero-bg {
  position: absolute;
  inset: 0;
  z-index: -2;
  pointer-events: none;
  will-change: opacity;
}
.hero-bg img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 50%;
}
.intro__fade {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(to top, rgba(0, 0, 0, 0.85) 0%, transparent 55%);
}

/* Home: the nav logo starts hidden (the big "ogcz" is the logo here) and is
   shown by js/home.js once the wordmark has docked into it */
body[data-page="home"] .nav__brand { opacity: 0; pointer-events: none; }

/* The wordmark. The guide sets it at 189px in a ~1260×756 frame; the
   background scales with that frame (cover), so the text scales with it
   too, capped by width AND height so zooming or short windows never crop it.
   Phones use the guide's 25vw. */
.mark {
  position: absolute;
  left: 50%;
  top: 50%;
  z-index: 4;
  font-family: var(--f-mark);
  font-weight: 400;
  font-size: min(max(12.75vw, 21.25svh), 25.5vw, 36svh);
  line-height: 1;
  white-space: nowrap;
  transform: translate(-50%, -57.14%);
  will-change: transform, opacity;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.mark:focus-visible { outline: none; }
.mark__text {
  position: relative;
  display: block;
  color: transparent; /* the real text only sizes the box; the image paints it */
}
/* "ogcz" with the guide's dust, pre-rendered in gold and in red (assets/ogcz-mark*.webp) */
.mark__text img {
  position: absolute;
  left: -0.05em;
  top: -0.1em;
  width: 2.1104em;
  height: 1.45em;
  max-width: none;
  pointer-events: none;
  transition: opacity 0.5s var(--ease);
}
.mark__text .mark__red { opacity: 0; }
:root[data-accent="red"] .mark__text .mark__gold { opacity: 0; }
:root[data-accent="red"] .mark__text .mark__red { opacity: 1; }
/* the guide's cast shadow, pre-rendered (assets/ogcz-shadow.webp), placed in em */
.mark__shadow {
  position: absolute;
  left: 1.512em;
  top: 1.412em;
  width: 1.376em;
  height: 0.614em;
  z-index: -1;
  pointer-events: none;
}
.mark__shadow img { display: block; width: 100%; height: 100%; max-width: none; }

/* "Welcome to my / Portfolio": hidden on the title card, it fades in and
   grows as the wordmark docks. Laid out at its final (big) size and
   scaled down at the start, so growing it never re-lays-out the page */
.welcome {
  position: absolute;
  left: clamp(16px, 2.5rem, 4vw);
  bottom: clamp(28px, 4rem, 9svh);
  z-index: 3;
  opacity: 0; /* fades in on scroll, as the wordmark docks (js/home.js) */
  will-change: opacity;
}
.welcome__small,
.welcome__big {
  display: block;
  transform-origin: 0 100%;
  will-change: transform;
  white-space: nowrap;
}
.welcome__small {
  position: absolute;
  left: 0.05em;
  bottom: 100%;
  font-size: var(--small-end, 1.5rem);
  line-height: 1.3;
  color: rgba(150, 150, 150, 0.8);
  letter-spacing: 0.01em;
}
.welcome__big {
  font-family: var(--f-display);
  font-weight: 600;
  font-size: var(--big-end, 12vw);
  line-height: 0.9;
  letter-spacing: -0.03em;
  /* room for the last "o" (tight tracking pushes it past the box, and the
     gradient is clipped to the box) */
  padding: 0 0.12em 0.06em 0;
  margin-right: -0.12em;
  background: linear-gradient(180deg, #cfcac0 0%, #6e6a64 100%);
  -webkit-background-clip: text;
          background-clip: text;
  color: transparent;
}

@media (max-width: 640px) {
  .mark { font-size: min(21vw, 36svh); }
}

/* ---------- deck: a fan of cards that slides in from the right ---------- */
.deck__cards {
  position: absolute;
  z-index: 1; /* under the wordmark, which stays in front as the cards arrive */
  left: 50%;
  top: var(--deck-y, 36%);
  width: 0;
  height: 0;
  perspective: 1400px;
  transform-style: preserve-3d;
}
.dcard {
  --w: clamp(120px, min(25vw, 40vh), 420px); /* big poster cards */
  position: absolute;
  left: calc(var(--w) / -2);
  top: calc(var(--w) * -0.625); /* centred: half of 5/4 */
  width: var(--w);
  aspect-ratio: 4 / 5; /* banner cards: 4:5 portrait posters (e.g. 1080 × 1350) */
  border-radius: 14px;
  overflow: hidden;
  opacity: 0;
  box-shadow: 0 24px 48px -18px rgba(0, 0, 0, 0.9), 0 0 0 1px rgba(236, 231, 220, 0.08);
  will-change: transform, opacity;
  cursor: pointer;
  transition: box-shadow 0.4s;
}
.dcard .ph { border-radius: 14px; }
.dcard:hover,
.dcard:focus-visible { box-shadow: 0 30px 60px -18px rgba(0, 0, 0, 0.95), 0 0 0 1px var(--gold); }

/* About: ONE gold piece, the original tab size (34 × 128). Closed, it's
   tucked left so only its right end shows: the "About Me" strip. Clicking
   slides the whole piece out, revealing the text, with "About Me" staying
   on its end. Clicking again slides it back. */
.about {
  --tab: 34px;
  position: absolute;
  left: 0;
  top: 22%;
  z-index: 6;
  display: flex;
  width: min(340px, calc(100vw - 24px));
  height: 128px;
  background: var(--gold);
  color: var(--on-accent);
  border-radius: 0 10px 10px 0;
  cursor: pointer; /* no glow around the tab (owner) */
  transform: translate3d(calc(-100% + var(--tab)), 0, 0);
  transition: transform 0.6s var(--ease);
  will-change: transform;
  -webkit-tap-highlight-color: transparent;
}
.about.is-open { transform: none; }
.about:focus-visible { outline: none; }
.about:focus-visible .about__label { text-decoration: underline; }
.about__content {
  flex: 1;
  display: flex;
  align-items: center;
  padding: 0 14px 0 24px;
  opacity: 0;
  transition: opacity 0.25s var(--ease);
}
.about.is-open .about__content { opacity: 1; transition: opacity 0.4s var(--ease) 0.15s; }
.about__body p { color: var(--on-accent); opacity: 0.88; font-size: 14.5px; line-height: 1.5; }
.about__body p + p { margin-top: 8px; }
.about__label {
  flex: none;
  width: var(--tab);
  display: grid;
  place-items: center;
  writing-mode: vertical-rl;
  transform: rotate(180deg);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

/* ==========================================================================
   Section caption (shared)
   ========================================================================== */
.caption { max-width: 340px; }
.caption__num {
  display: block;
  font-size: 11px;
  letter-spacing: 0.3em;
  color: var(--muted);
  margin-bottom: 12px;
}
.caption__title {
  font-family: var(--f-display);
  font-weight: 500;
  font-size: clamp(28px, 3vw, 44px);
  line-height: 1.02;
  letter-spacing: -0.015em;
  color: var(--gold);
  margin-bottom: 14px;
}
.caption__blurb { color: #a9a397; font-size: 15px; }
.caption__list { margin-top: 16px; display: grid; gap: 4px; }
.caption__list li { display: flex; align-items: baseline; gap: 0.6em; font-size: 14px; color: var(--muted); }
.caption__list li::before {
  content: "";
  flex: none;
  width: 0.36em;
  height: 0.36em;
  border-radius: 50%;
  background: currentColor; /* same color as the text */
  transform: translateY(-0.12em);
}

/* ==========================================================================
   SERVICES — "Some of what I do"
   ========================================================================== */
.services {
  min-height: 100vh;
  display: grid;
  place-content: center;
  justify-items: center;
  gap: 36px;
  padding: 120px var(--gutter);
}
.services__title {
  font-family: var(--f-display);
  font-style: italic;
  font-weight: 400;
  font-size: clamp(20px, 2vw, 28px);
  color: var(--gold);
}
.services__grid {
  display: grid;
  grid-template-columns: repeat(3, clamp(96px, 13vw, 160px));
  gap: clamp(12px, 1.6vw, 22px);
  perspective: 1000px;
}
.tile {
  aspect-ratio: 1;
  border: 2px solid var(--gold); /* v1.4.2: the hover border, always on, 2px */
  border-radius: 18px;
  display: grid;
  place-items: center;
  padding: 10px;
  text-align: center;
  white-space: pre-line;
  font-size: clamp(11px, 1vw, 14px);
  line-height: 1.25;
  color: #cfc9bc;
  background: rgba(255, 255, 255, 0.01);
  opacity: 0;
  transform: rotateX(72deg) translateY(60px) rotateZ(var(--rz, 0deg));
  transition:
    opacity 0.9s var(--ease) var(--d, 0s),
    transform 1.1s var(--ease) var(--d, 0s),
    border-color 0.35s, background 0.35s, color 0.35s, box-shadow 0.35s;
}
.services.is-in .tile { opacity: 1; transform: rotateZ(var(--rz, 0deg)); }
.services.is-in .tile:hover,
.services.is-in .tile:focus-visible {
  transition-delay: 0s;
  transform: translateY(-8px) rotateZ(calc(var(--rz, 0deg) * -1.4)) scale(1.04);
  border-color: var(--gold);
  color: var(--gold-hi);
  background: rgba(var(--accent-rgb), 0.06);
  box-shadow: var(--hover-glow-strong);
}

/* ==========================================================================
   01 FLOW — coverflow carousel
   ========================================================================== */
.flow { position: relative; }
.flow__stage {
  position: sticky;
  top: 0;
  height: 100vh;
  overflow: hidden;
}
.flow__track {
  position: absolute;
  left: 38%;
  top: 50%;
  width: 0;
  height: 0;
  perspective: 1600px;
  transform-style: preserve-3d;
}
.fcard {
  --w: clamp(200px, 23vw, 340px);
  position: absolute;
  left: calc(var(--w) / -2);
  top: calc(var(--w) * -0.7);
  width: var(--w);
  aspect-ratio: 3 / 4.2;
  border-radius: 18px;
  overflow: hidden;
  box-shadow: 0 40px 80px -30px rgba(0, 0, 0, 0.95), 0 0 0 1px rgba(236, 231, 220, 0.08);
  will-change: transform, opacity, filter;
}
.fcard .ph { border-radius: 18px; }
/* "And many more…" uses the same Software colour as the Archives cards (toneFor("Software") in home.js) */
.fmore__big { position: relative; margin-bottom: 14px; font-family: var(--f-display); font-style: italic; font-weight: 300; font-size: clamp(34px, 3.4vw, 54px); line-height: 0.95; color: var(--gold-hi); }
.fcard__dim {
  position: absolute;
  inset: 0;
  background: #000;
  opacity: 0;
  pointer-events: none;
}
.flow .caption {
  position: absolute;
  right: var(--gutter);
  top: 50%;
  transform: translateY(-50%);
  width: min(300px, 26vw);
}
.flow__current {
  margin-top: 22px; /* no divider line above the current project */
  display: grid;
  gap: 4px;
}
.flow__current-title { font-family: var(--f-display); font-size: 18px; }
.flow__current-tag { color: var(--muted); font-size: 13px; line-height: 1.5; }

/* ==========================================================================
   02 BENTO — perspective grid
   ========================================================================== */
.bento {
  display: grid;
  grid-template-columns: minmax(220px, 1fr) 3fr;
  gap: clamp(24px, 4vw, 64px);
  padding: 18vh var(--gutter);
  align-items: start;
}
.caption--sticky { position: sticky; top: 30vh; }
.bento__persp { perspective: 1400px; }
.bento__grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-auto-rows: auto; /* row height comes from the 16:9 cells */
  grid-auto-flow: row dense; /* v1.5.3 mosaic: fill every gap */
  gap: clamp(10px, 1.2vw, 18px);
  transform-origin: 50% 0%;
  will-change: transform;
}
.bcell {
  position: relative;
  border-radius: 16px;
  overflow: hidden;
  box-shadow: 0 0 0 1px rgba(236, 231, 220, 0.08);
  transition: transform 0.6s var(--ease), box-shadow 0.4s;
}
.bcell .ph { border-radius: 16px; }
.bcell:hover { transform: translateY(-6px); box-shadow: 0 0 0 1px var(--line), 0 30px 60px -20px rgba(0, 0, 0, 0.9); }
.bcell { aspect-ratio: 16 / 9; }                       /* normal cell: 16:9 */
.bcell--wide { grid-column: span 2; aspect-ratio: 32 / 9; } /* two columns: 32:9 */
.bcell--tall { grid-row: span 2; aspect-ratio: auto; height: 100%; } /* two rows: stretches to the bottom of the second row */
.bcell--big { grid-column: span 2; grid-row: span 2; aspect-ratio: 16 / 9; } /* 2×2: 16:9 (e.g. 1600 × 900) */
.bcell--full { grid-column: 1 / -1; aspect-ratio: 16 / 9; } /* feature: full grid width, 16:9 */

/* ==========================================================================
   03 BOOKS — floating covers
   ========================================================================== */
.books {
  display: grid;
  grid-template-columns: minmax(220px, 1fr) 3fr;
  gap: clamp(24px, 4vw, 64px);
  align-items: center;
  padding: 14vh var(--gutter);
  min-height: 100vh;
}
.books__shelf {
  position: relative;
  height: min(76vh, 720px);
  perspective: 1600px;
}
.book3d {
  --w: clamp(150px, 16vw, 250px);
  --d: 26px;
  position: absolute;
  width: var(--w);
  aspect-ratio: 3 / 4.2;
  transform-style: preserve-3d;
  cursor: pointer;
  animation: bob 7s var(--ease-io) infinite alternate;
  animation-delay: var(--delay, 0s);
}
.book3d__body {
  position: absolute;
  inset: 0;
  transform-style: preserve-3d;
  transform: rotateX(var(--rx)) rotateY(var(--ry)) rotateZ(var(--rz));
  transition: transform 0.9s var(--ease);
}
.book3d:hover .book3d__body,
.book3d:focus-visible .book3d__body { transform: rotateX(4deg) rotateY(-14deg) rotateZ(0deg) translateZ(60px); }
.book3d__face {
  position: absolute;
  inset: 0;
  border-radius: 3px 10px 10px 3px;
  overflow: hidden;
  backface-visibility: hidden;
}
.book3d__front { transform: translateZ(calc(var(--d) / 2)); box-shadow: inset 6px 0 10px -4px rgba(0, 0, 0, 0.6); }
.book3d__back { transform: rotateY(180deg) translateZ(calc(var(--d) / 2)); background: #0d0b08; }
.book3d__spine {
  position: absolute;
  top: 0;
  left: calc(var(--d) / -2);
  width: var(--d);
  height: 100%;
  transform: rotateY(-90deg);
  background: linear-gradient(90deg, #1a1804, #3a3509 50%, #1a1804);
  backface-visibility: hidden;
}
.book3d__pages {
  position: absolute;
  top: 3px;
  right: calc(var(--d) / -2);
  width: var(--d);
  height: calc(100% - 6px);
  transform: rotateY(90deg);
  background: repeating-linear-gradient(90deg, #d9d1bf 0 1px, #b5ac98 1px 2px);
  backface-visibility: hidden;
}
.book3d .ph { border-radius: 3px 10px 10px 3px; }
.book3d__label {
  position: absolute;
  left: 0;
  bottom: -34px;
  font-size: 12px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
  transition: color 0.3s;
}
.book3d:hover .book3d__label { color: var(--gold); }
@keyframes bob {
  from { transform: translate3d(0, -10px, 0); }
  to { transform: translate3d(0, 12px, 0); }
}
.books__hint {
  position: absolute;
  right: 0;
  bottom: 0;
  font-size: 12px;
  color: var(--muted);
  letter-spacing: 0.1em;
}

/* ---------- flip-book modal ---------- */
.book-modal {
  position: fixed;
  inset: 0;
  z-index: 80;
  display: grid;
  place-items: center;
  grid-template-rows: 1fr auto;
  padding: 80px var(--gutter) 32px;
  background: rgba(0, 0, 0, 0.94);
  opacity: 0;
  transition: opacity 0.5s var(--ease);
}
.book-modal[hidden] { display: none; }
.book-modal.is-open { opacity: 1; }
.book-modal__close {
  position: absolute;
  top: 24px;
  right: var(--gutter);
  font-size: 13px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--muted);
  padding: 8px 0;
}
.book-modal__close:hover { color: var(--gold); }
.flip {
  width: min(92vw, calc((100vh - 200px) * 1.43), 1100px);
  aspect-ratio: 2 / 1.4;
  perspective: 2600px;
}
.flip__book {
  position: relative;
  width: 100%;
  height: 100%;
  transform-style: preserve-3d;
  transition: transform 0.9s var(--ease);
  transform: translateX(var(--shift, 0%)) scale(0.9) rotateX(8deg);
}
.book-modal.is-open .flip__book { transform: translateX(var(--shift, 0%)) scale(1) rotateX(0deg); }
.leaf {
  position: absolute;
  left: 50%;
  top: 0;
  width: 50%;
  height: 100%;
  transform-origin: left center;
  transform-style: preserve-3d;
  transition: transform 0.55s var(--ease-io); /* page turn */
  cursor: pointer;
}
.leaf.is-flipped { transform: rotateY(-180deg); }
.leaf__face {
  position: absolute;
  inset: 0;
  overflow: hidden;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  border-radius: 0 8px 8px 0;
  box-shadow: 0 30px 60px -20px rgba(0, 0, 0, 0.9);
}
.leaf__face--back { transform: rotateY(180deg); border-radius: 8px 0 0 8px; }
.leaf__face::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(90deg, rgba(0, 0, 0, 0.28), transparent 12%);
}
.leaf__face--back::after { background: linear-gradient(270deg, rgba(0, 0, 0, 0.28), transparent 12%); }
.leaf__face .ph { border-radius: inherit; }
.leaf__face--blank { visibility: hidden; }
.page-ph {
  width: 100%;
  height: 100%;
  display: grid;
  place-content: center;
  justify-items: center;
  gap: 8px;
  background: #e7e0d0;
  color: #6e6554;
  font-size: 12px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
}
.page-ph b {
  font-family: var(--f-display);
  font-weight: 300;
  font-style: italic;
  font-size: clamp(36px, 5vw, 72px);
  letter-spacing: 0;
  color: #b6a883;
}
.flip__controls {
  display: flex;
  align-items: center;
  gap: 24px;
  margin-top: 22px;
  font-size: 12px;
  letter-spacing: 0.2em;
  color: var(--muted);
}
.flip__controls button {
  width: 44px;
  height: 44px;
  border-radius: 50%;
  border: 1px solid var(--line);
  color: var(--gold);
  transition: background 0.3s, color 0.3s;
}
.flip__controls button:hover:not(:disabled) { background: var(--gold); color: var(--on-accent); }
.flip__controls button:disabled { opacity: 0.3; cursor: default; }

/* ==========================================================================
   04 REEL — presentation viewer
   ========================================================================== */
.reel {
  display: grid;
  grid-template-columns: minmax(220px, 1fr) 3fr;
  gap: clamp(24px, 4vw, 64px);
  align-items: center;
  padding: 14vh var(--gutter);
  min-height: 100vh;
}
.reel__viewer {
  perspective: 1400px;
}
.reel__screen {
  position: relative;
  aspect-ratio: 16 / 9;
  border-radius: 16px;
  overflow: hidden;
  background: #000;
  box-shadow: 0 0 0 1px rgba(236, 231, 220, 0.1), 0 50px 100px -30px rgba(0, 0, 0, 0.95);
  transform-origin: 50% 100%;
  will-change: transform;
}
.reel__slide {
  position: absolute;
  inset: 0;
  opacity: 0;
  transform: scale(1.04);
  transition: opacity 0.7s var(--ease), transform 1.2s var(--ease);
}
.reel__slide.is-on { opacity: 1; transform: none; }
.reel__slide iframe, .reel__slide video { width: 100%; height: 100%; border: 0; object-fit: cover; }
.reel__slide .ph { border-radius: 0; }
.reel__play {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 72px;
  height: 72px;
  margin: -36px 0 0 -36px;
  border-radius: 50%;
  border: 1px solid var(--line);
  display: grid;
  place-items: center;
  color: var(--gold);
  font-size: 18px;
  background: rgba(0, 0, 0, 0.5);
}
.reel__thumbs {
  display: flex;
  justify-content: center;
  gap: 10px;
  margin-top: 18px;
  flex-wrap: wrap;
}
.reel__thumb {
  width: clamp(56px, 7vw, 96px);
  aspect-ratio: 16 / 9;
  border-radius: 6px;
  overflow: hidden;
  opacity: 0.45;
  box-shadow: 0 0 0 1px rgba(236, 231, 220, 0.1);
  transition: opacity 0.3s, box-shadow 0.3s, transform 0.4s var(--ease);
}
.reel__thumb .ph { padding: 6px; }
.reel__thumb .ph::before { inset: 3px; }
.reel__thumb .ph__num { font-size: 20px; }
.reel__thumb:hover { opacity: 0.8; transform: translateY(-3px); }
.reel__thumb.is-on { opacity: 1; box-shadow: 0 0 0 1.5px var(--gold); }

/* ---------- Video & Presentations: own videos ---------- */
.reel__video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; background: #000; }
.reel__screen { transition: width 0.5s var(--ease); }
.reel__qsel {
  font: inherit;
  font-size: 11px;
  color: var(--ink);
  background: rgba(0, 0, 0, 0.6);
  border: 1px solid rgba(var(--accent-rgb), 0.6);
  border-radius: 6px;
  padding: 3px 6px;
  cursor: pointer;
}
.reel__qsel[hidden] { display: none; }
.reel__msg {
  position: absolute;
  inset: auto 16px 16px;
  z-index: 5;
  margin: 0;
  padding: 10px 14px;
  border-radius: 10px;
  background: rgba(0, 0, 0, 0.8);
  box-shadow: 0 0 0 1px var(--line);
  color: var(--ink);
  font-size: 13px;
  text-align: center;
}

/* ---------- Video & Presentations: the PPT view (only when there are presentations) ---------- */
.reel__viewer[hidden], .ppt[hidden] { display: none; }
.ppt__screen {
  position: relative;
  aspect-ratio: 16 / 9;
  border-radius: 16px;
  overflow: hidden;
  background: #000;
  cursor: pointer;
  box-shadow: 0 0 0 2px var(--gold), 0 24px 48px -18px rgba(0, 0, 0, 0.9);
}
.ppt__slide { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; }
.ppt__nav {
  position: absolute;
  top: 50%;
  width: 44px;
  height: 44px;
  margin-top: -22px;
  border-radius: 50%;
  color: var(--ink);
  background: rgba(0, 0, 0, 0.55);
  box-shadow: 0 0 0 1px rgba(var(--accent-rgb), 0.7);
  cursor: pointer;
  transition: color 0.3s, box-shadow 0.3s;
}
.ppt__prev { left: 14px; }
.ppt__next { right: 14px; }
.ppt__nav:hover { color: var(--gold-hi); box-shadow: 0 0 0 2px var(--gold); }
.ppt__count {
  position: absolute;
  left: 50%;
  bottom: 12px;
  transform: translateX(-50%);
  padding: 4px 10px;
  border-radius: 99px;
  background: rgba(0, 0, 0, 0.6);
  font-size: 11px;
  letter-spacing: 0.08em;
  color: var(--ink);
  white-space: nowrap;
}
.reel__views { margin-top: 24px; }

/* ---------- Video & Presentations: our player around YouTube ---------- */
.reel__label {
  position: absolute;
  left: 18px;
  bottom: 16px;
  z-index: 3;
  display: flex;
  align-items: baseline;
  gap: 10px;
  font-family: var(--f-display);
  font-size: clamp(15px, 1.4vw, 20px);
  color: var(--ink);
  text-shadow: 0 2px 12px rgba(0, 0, 0, 0.8);
  pointer-events: none;
  transition: opacity 0.4s var(--ease);
}
.reel__num { font-family: var(--f-body); font-size: 12px; letter-spacing: 0.2em; color: var(--gold-hi); }
.reel__slide::after { /* soft shade so the title reads on any poster */
  content: "";
  position: absolute;
  inset: 55% 0 0;
  z-index: 1;
  background: linear-gradient(to top, rgba(0, 0, 0, 0.75), transparent);
  pointer-events: none;
  transition: opacity 0.4s var(--ease);
}
.reel__play { z-index: 3; cursor: pointer; transition: transform 0.3s var(--ease), background 0.3s, color 0.3s; }
.reel__play:hover { transform: scale(1.08); background: var(--gold); color: var(--on-accent); }
.reel__poster { z-index: 1; }
/* the YouTube frame: laid out big (see fitFrame in home.js) and scaled to fit, never cropped */
.reel__yt { position: absolute; inset: 0; z-index: 0; overflow: hidden; background: #000; }
.reel__yt iframe { position: absolute; left: 50%; top: 50%; border: 0; pointer-events: none; }
.reel__shield { position: absolute; inset: 0; z-index: 2; cursor: pointer; }
/* while it plays (or is paused mid-way) the poster, title and big play button step aside */
.reel__slide.is-started .reel__poster,
.reel__slide.is-started .reel__play,
.reel__slide.is-started .reel__label,
.reel__slide.is-started::after { opacity: 0; pointer-events: none; }
.reel__slide.is-loading .reel__play { animation: reelPulse 1s ease-in-out infinite alternate; }
@keyframes reelPulse { to { opacity: 0.4; } }
.reel__ui {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 4;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 26px 16px 12px;
  background: linear-gradient(to top, rgba(0, 0, 0, 0.85), transparent);
  font-size: 12px;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
  opacity: 0;
  transform: translateY(6px);
  transition: opacity 0.3s var(--ease), transform 0.3s var(--ease);
}
.reel__slide.is-started:hover .reel__ui,
.reel__slide.is-paused .reel__ui,
.reel__slide:fullscreen .reel__ui:hover,
.reel__ui:focus-within { opacity: 1; transform: none; }
.reel__slide:not(.is-started) .reel__ui { display: none; }
.reel__btn { width: 30px; height: 30px; display: grid; place-items: center; color: var(--ink); cursor: pointer; transition: color 0.2s; }
.reel__btn:hover { color: var(--gold-hi); }
.reel__btn svg { width: 20px; height: 20px; fill: currentColor; }
.reel__seek, .reel__vol {
  --p: 0%;
  appearance: none;
  -webkit-appearance: none;
  height: 4px;
  border-radius: 4px;
  background: linear-gradient(to right, var(--gold) var(--p), rgba(236, 231, 220, 0.25) var(--p));
  cursor: pointer;
}
.reel__seek { flex: 1; min-width: 60px; }
.reel__vol { --p: 100%; width: 72px; }
.reel__seek::-webkit-slider-thumb, .reel__vol::-webkit-slider-thumb { -webkit-appearance: none; width: 12px; height: 12px; border-radius: 50%; background: var(--gold-hi); }
.reel__seek::-moz-range-thumb, .reel__vol::-moz-range-thumb { width: 12px; height: 12px; border: 0; border-radius: 50%; background: var(--gold-hi); }
.reel__slide:fullscreen { background: #000; }
.reel__slide:fullscreen, .reel__slide.is-fullscreen { opacity: 1; transform: none; border-radius: 0; }
.reel__slide.is-fullscreen .reel__ui { padding-bottom: 20px; }
.reel__q { font-size: 11px; letter-spacing: 0.08em; color: var(--muted); }
.reel__q.is-hd { color: var(--gold-hi); }
@media (max-width: 600px) { .reel__vol { display: none; } .reel__ui { gap: 8px; padding-inline: 10px; } }

/* ==========================================================================
   05 ARCHIVE
   ========================================================================== */
.archive { padding: 14vh var(--gutter); }
.archive__head {
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  gap: 24px;
  flex-wrap: wrap;
  margin-bottom: 40px;
}
.archive__filters { display: flex; gap: 8px; flex-wrap: wrap; }
.chip {
  padding: 8px 16px;
  border-radius: 999px;
  border: 1px solid var(--line-soft);
  font-size: 13px;
  color: var(--muted);
  transition: border-color 0.3s, color 0.3s, background 0.3s;
}
.chip:hover { border-color: var(--line); color: var(--ink); }
.chip.is-active { border-color: var(--gold); color: var(--gold); background: rgba(var(--accent-rgb), 0.06); }
.archive__grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
  gap: clamp(10px, 1.2vw, 16px);
}
.acell {
  position: relative;
  display: block;
  aspect-ratio: 4 / 5;
  border-radius: 14px;
  overflow: hidden;
  box-shadow: 0 0 0 1px rgba(236, 231, 220, 0.08);
  transition: opacity 0.5s var(--ease), transform 0.6s var(--ease);
}
.acell.is-hidden { display: none; }
.archive__empty { padding: 2.5rem 0; color: var(--muted); font-size: 0.95rem; }
.archive__empty[hidden] { display: none; }
.archive__more { margin-top: 36px; display: flex; justify-content: center; }
.acell .ph { border-radius: 14px; }
/* the default card is the whole card here, so its words need to read clearly */
.acell .ph__top { font-size: 11px; opacity: 0.9; }
.acell .ph__title { font-size: clamp(15px, 1.35vw, 21px); line-height: 1.18; overflow-wrap: break-word; }
.acell--long .ph__title { font-size: clamp(13px, 1.12vw, 17px); } /* a very long word still fits the card */
/* hover: every card fills with the accent and shows its tagline (like Digital Graphics) */
.acell__info {
  position: absolute;
  inset: 0;
  z-index: 2;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  gap: 8px;
  padding: 18px;
  border-radius: 14px;
  background: var(--gold);
  color: var(--on-accent);
  opacity: 0;
  transition: opacity 0.35s var(--ease);
  pointer-events: none;
}
.acell__cat { font-size: 10px; letter-spacing: 0.2em; text-transform: uppercase; opacity: 0.75; margin-bottom: auto; }
.acell__name { font-family: var(--f-display); font-size: clamp(15px, 1.3vw, 20px); line-height: 1.15; overflow-wrap: break-word; }
.acell__line { font-size: 12px; line-height: 1.45; opacity: 0.85; }
.acell:hover .acell__info,
.acell:focus-visible .acell__info { opacity: 1; }
:root[data-accent="red"] .acell__info { color: #fff; }
@media (hover: none) { .acell:hover .acell__info { opacity: 0; } }

/* ==========================================================================
   CONTACT
   ========================================================================== */
.contact {
  min-height: 90vh;
  display: grid;
  padding: 0 var(--gutter);
}
.contact__inner {
  align-self: center;
  justify-self: center;
  display: flex;
  align-items: center;
  gap: clamp(28px, 5vw, 80px);
  flex-wrap: wrap;
  padding: 18vh 0 10vh;
}
.contact__title {
  font-family: var(--f-display);
  font-weight: 500;
  font-size: clamp(34px, 4.4vw, 64px);
  line-height: 1;
  letter-spacing: -0.02em;
  color: var(--gold);
}
.contact__info { display: grid; gap: 14px; justify-items: start; }
.contact__info p { color: var(--muted); font-size: 15px; max-width: 280px; }
.contact__actions { display: flex; gap: 10px; flex-wrap: wrap; }

/* ---------- banner lightbox ---------- */
.dcard { padding: 0; display: block; text-align: left; }
.lightbox {
  position: fixed;
  inset: 0;
  z-index: 80;
  display: grid;
  place-items: center;
  padding: 72px var(--gutter) 40px;
  background: rgba(0, 0, 0, 0.94);
  cursor: zoom-out;
  opacity: 0;
  transition: opacity 0.4s var(--ease);
}
.lightbox[hidden] { display: none; }
.lightbox.is-open { opacity: 1; }
.lightbox__stage {
  transform: scale(0.94);
  transition: transform 0.5s var(--ease);
}
.lightbox.is-open .lightbox__stage { transform: none; }
.lightbox__stage img {
  display: block;
  max-width: min(92vw, 1080px);
  max-height: calc(100vh - 140px);
  width: auto;
  height: auto;
  border-radius: 12px;
  box-shadow: 0 0 0 2px var(--gold), 0 40px 80px -30px rgba(0, 0, 0, 0.95);
}
.lightbox__ph {
  width: min(80vw, calc((100vh - 140px) * 0.8));
  aspect-ratio: 4 / 5;
  border-radius: 12px;
  overflow: hidden;
  box-shadow: 0 0 0 2px var(--gold);
}
.lightbox__close {
  position: absolute;
  top: 24px;
  right: var(--gutter);
  font-size: 13px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--muted);
  padding: 8px 0;
}
.lightbox__close:hover { color: var(--gold); }
.lightbox__stage img { transition: opacity 0.45s var(--ease), transform 0.55s var(--ease); }
.lightbox__stage img.from-right { opacity: 0; transform: translateX(40px); }
.lightbox__stage img.from-left { opacity: 0; transform: translateX(-40px); }
.lightbox__prev,
.lightbox__next {
  position: absolute;
  top: 50%;
  width: 48px;
  height: 48px;
  margin-top: -24px;
  border-radius: 50%;
  font-size: 18px;
  color: var(--ink);
  background: rgba(0, 0, 0, 0.6);
  box-shadow: 0 0 0 1px rgba(var(--accent-rgb), 0.7);
  cursor: pointer;
  transition: color 0.3s, box-shadow 0.3s;
}
.lightbox__prev { left: var(--gutter); }
.lightbox__next { right: var(--gutter); }
.lightbox__prev:hover,
.lightbox__next:hover { color: var(--gold-hi); box-shadow: 0 0 0 2px var(--gold); }
.lightbox__prev[hidden],
.lightbox__next[hidden],
.lightbox__count[hidden] { display: none; }
.lightbox__count {
  position: absolute;
  bottom: 18px;
  left: 50%;
  transform: translateX(-50%);
  font-size: 12px;
  letter-spacing: 0.2em;
  color: var(--muted);
}
.lightbox__stage img { max-width: min(calc(100vw - 2 * var(--gutter) - 130px), 1400px); }
@media (max-width: 600px) { .lightbox__stage img { max-width: 92vw; max-height: calc(100vh - 200px); } }
@media (max-width: 600px) {
  .lightbox__prev, .lightbox__next { top: auto; bottom: 8px; margin-top: 0; width: 42px; height: 42px; }
}

/* ---------- Frontend tile slideshow ---------- */
.bcell { display: block; width: 100%; padding: 0; cursor: zoom-in; text-align: left; }
.slides { position: absolute; inset: 0; }
/* below the desktop layout, a trimmed picture keeps its top (headings, text) instead of its middle */
@media (max-width: 900px) { .bento__grid .bcell .media { object-position: 50% 12%; } }
.slides .slide {
  position: absolute;
  inset: 0;
  opacity: 0;
  transform: scale(1.06);
  transition: opacity 0.8s var(--ease), transform 5s var(--ease);
}
.slides .slide.is-on { opacity: 1; transform: scale(1); z-index: 1; }
.slides .slide.is-off { opacity: 0; transform: scale(1); transition: opacity 0.8s var(--ease) 0.1s, transform 0s 1s; }

/* The hover glow of every Home card, in one place. The strong one (tried 2026-09-30) is kept
   only on the "Some of what I do" tiles. */
:root {
  --hover-glow: 0 0 34px -6px rgba(var(--accent-rgb), 0.45);
  --hover-glow-strong: 0 0 26px 2px rgba(var(--accent-rgb), 0.75), 0 0 70px 8px rgba(var(--accent-rgb), 0.35);
}

/* ==========================================================================
   One card style: every Home card (except the design books) gets the same
   gold border as the "Some of what I do" tiles; hovering adds the glow.
   ========================================================================== */
.dcard,
.fcard,
.bcell,
.acell,
.reel__screen,
.reel__thumb {
  box-shadow: 0 0 0 2px var(--gold), 0 24px 48px -18px rgba(0, 0, 0, 0.9); /* v1.4.2: the hover border, always on, 2px */
}
.dcard,
.fcard,
.reel__screen { transition: box-shadow 0.35s; } /* card transforms are driven by scroll */
.bcell,
.acell,
.reel__thumb { transition: box-shadow 0.35s, transform 0.6s var(--ease), opacity 0.3s; }
.dcard:hover,
.dcard:focus-visible,
.fcard:hover,
.fcard:focus-visible,
.bcell:hover,
.bcell:focus-visible,
.acell:hover,
.acell:focus-visible,
.reel__screen:hover,
.reel__thumb:hover,
.reel__thumb:focus-visible {
  box-shadow: 0 0 0 2px var(--gold), var(--hover-glow), 0 24px 48px -18px rgba(0, 0, 0, 0.9);
}
.bcell:hover,
.acell:hover { transform: translateY(-8px); }
.reel__thumb.is-on { box-shadow: 0 0 0 2px var(--gold); }
.dcard:focus-visible,
.fcard:focus-visible,
.bcell:focus-visible,
.acell:focus-visible { outline: none; }

/* ==========================================================================
   Responsive (tablet + phone)
   ========================================================================== */
@media (max-width: 900px) {
  /* the title (and the project in front) on top, the cards under it */
  .flow__track { left: 50%; top: min(390px, 56%); }
  .flow .caption {
    top: 84px;
    bottom: auto;
    left: var(--gutter);
    right: var(--gutter);
    width: auto;
    max-width: none;
    transform: none;
  }
  .flow .caption__blurb { display: none; }
  .flow .caption__title { margin-bottom: 0; }
  .flow__current { margin-top: 12px; }

  .bento, .books, .reel { grid-template-columns: 1fr; padding-block: 12vh; }
  .reel { min-height: 0; align-content: start; gap: 28px; } /* the player sits right under its heading */
  .caption--sticky { position: static; }
  .bento__grid { grid-template-columns: repeat(2, 1fr); }
  .bcell--big { grid-column: span 2; grid-row: span 1; aspect-ratio: 16 / 9; }
  .bcell--tall { grid-row: span 1; aspect-ratio: 16 / 9; } /* keeps the tablet grid gap-free */
  .books__shelf { height: 70vh; }

  .contact__inner { flex-direction: column; align-items: flex-start; }
}

@media (max-width: 520px) {
  .services__grid { grid-template-columns: repeat(2, 1fr); width: 100%; max-width: 320px; }
  .bento__grid { grid-template-columns: 1fr; }
  .bcell--wide, .bcell--big { grid-column: span 1; }
  .bcell--tall { grid-row: span 1; }
  .bcell, .bcell--wide, .bcell--tall, .bcell--big { aspect-ratio: 16 / 9; }
  .bcell--full { aspect-ratio: 16 / 9; }
  .book3d { --w: clamp(120px, 34vw, 170px); }
}

@media (prefers-reduced-motion: reduce) {
  .book3d { animation: none; }
}

/* ---------- Frontend views: the buttons + Digital Graphics grid ---------- */
.views { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 28px; }
.views[hidden] { display: none; }
.view-btn { cursor: pointer; }
.view-btn.is-active { background: var(--gold); border-color: var(--gold); color: var(--on-accent); }
.view-btn.is-active:hover { color: var(--on-accent); }
#frontend .caption__title,
#frontend .caption__blurb,
#frontend .caption__list,
.bento__stack > * { transition: opacity 0.28s var(--ease); }
#frontend .caption.is-switching .caption__title,
#frontend .caption.is-switching .caption__blurb,
#frontend .caption.is-switching .caption__list,
.bento__stack.is-switching > * { opacity: 0; }
.bento__stack { transform-origin: 50% 0%; will-change: transform; }
.bento__stack > [hidden] { display: none; }

/* Digital Graphics: a fixed 11-slot bento (layout from the reference video).
   4 columns (= 2 main columns split in half) and 6 rows sized in quarters of a
   column pair, so every tile keeps its shape:
     [01 01 02 02]   01 4:5   02 4:3
     [01 01 03 03]            03 2:1
     [04 04 05 05]   04 1:1   05 8:3
     [04 04 06 07]            06 07 4:5
     [08 08 11 11]   08 8:3   11 1:1
     [09 10 11 11]   09 10 4:5              */
.gfx {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-template-rows: 1.5fr 1fr 0.75fr 1.25fr 0.75fr 1.25fr;
  grid-template-areas:
    "g01 g01 g02 g02"
    "g01 g01 g03 g03"
    "g04 g04 g05 g05"
    "g04 g04 g06 g07"
    "g08 g08 g11 g11"
    "g09 g10 g11 g11";
  gap: clamp(10px, 1.2vw, 18px);
  aspect-ratio: 4 / 6.5;
}
.gcell--01 { grid-area: g01; } .gcell--02 { grid-area: g02; } .gcell--03 { grid-area: g03; }
.gcell--04 { grid-area: g04; } .gcell--05 { grid-area: g05; } .gcell--06 { grid-area: g06; }
.gcell--07 { grid-area: g07; } .gcell--08 { grid-area: g08; } .gcell--09 { grid-area: g09; }
.gcell--10 { grid-area: g10; } .gcell--11 { grid-area: g11; }
.gcell .ph { position: absolute; inset: 0; border-radius: 16px; }
@media (max-width: 560px) {
  /* phone: two columns, every tile at its own shape */
  .gfx { grid-template-columns: 1fr 1fr; grid-template-rows: none; grid-template-areas: none; aspect-ratio: auto; }
  .gcell { grid-area: auto; grid-column: span 2; }
  .gcell--01 { aspect-ratio: 4 / 5; } .gcell--02 { aspect-ratio: 4 / 3; } .gcell--03 { aspect-ratio: 2 / 1; }
  .gcell--04, .gcell--11 { aspect-ratio: 1 / 1; } .gcell--05, .gcell--08 { aspect-ratio: 8 / 3; }
  .gcell--06, .gcell--07, .gcell--09, .gcell--10 { grid-column: span 1; aspect-ratio: 4 / 5; }
}
.gcell {
  position: relative;
  display: block;
  width: 100%;
  padding: 0;
  border-radius: 16px;
  overflow: hidden;
  cursor: zoom-in;
  text-align: left;
  box-shadow: 0 0 0 2px var(--gold), 0 24px 48px -18px rgba(0, 0, 0, 0.9);
  transition: box-shadow 0.35s, transform 0.6s var(--ease);
}
.gcell .media { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.gcell__info {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  gap: 6px;
  padding: 18px;
  text-align: center;
  background: var(--gold);
  color: var(--on-accent);
  opacity: 0;
  transition: opacity 0.35s var(--ease);
}
.gcell__name { font-family: var(--f-display); font-size: clamp(16px, 1.5vw, 22px); line-height: 1.15; }
.gcell__line { font-size: 13px; line-height: 1.4; opacity: 0.8; }
:root[data-accent="red"] .gcell__info { color: #fff; }
.gcell:hover,
.gcell:focus-visible {
  outline: none;
  transform: translateY(-6px);
  box-shadow: 0 0 0 2px var(--gold), var(--hover-glow), 0 24px 48px -18px rgba(0, 0, 0, 0.9);
}
/* Brand & UI: the same hover as Digital Graphics, naming the set on screen; click = next set */
.bento__grid .bcell { cursor: pointer; }
.bcell__info {
  position: absolute;
  inset: 0;
  z-index: 3;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  gap: 6px;
  padding: 18px;
  text-align: center;
  background: var(--gold);
  color: var(--on-accent);
  opacity: 0;
  transition: opacity 0.35s var(--ease);
  pointer-events: none;
}
.bcell__name { font-family: var(--f-display); font-size: clamp(16px, 1.5vw, 22px); line-height: 1.15; }
.bcell__line { font-size: 13px; line-height: 1.4; opacity: 0.8; }
.bcell__line:empty { display: none; }
:root[data-accent="red"] .bcell__info { color: #fff; }
.bcell:hover .bcell__info,
.bcell:focus-visible .bcell__info { opacity: 1; }
@media (hover: none) { .bcell:hover .bcell__info { opacity: 0; } }
.gcell:hover .gcell__info,
.gcell:focus-visible .gcell__info { opacity: 1; }
@media (hover: none) { .gcell:hover .gcell__info { opacity: 0; } .gcell:hover { transform: none; } }

/* Section index: opens above the round back-to-top button when it's hovered (computers only);
   same black and thin line as the button, gold = the section you're in */
.jump {
  position: fixed;
  right: var(--gutter);
  bottom: 80px; /* just above the 46px button at bottom 24px */
  z-index: 41;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  padding: 8px 0;
  border-radius: 14px;
  background: #000;
  border: 1px solid var(--line-soft);
  opacity: 0;
  transform: translateY(6px);
  pointer-events: none;
  transition: opacity 0.25s var(--ease), transform 0.25s var(--ease);
}
.jump.is-open { opacity: 1; transform: none; pointer-events: auto; }
.jump__item {
  padding: 6px 16px;
  font-size: 13px;
  white-space: nowrap;
  color: var(--muted);
  text-decoration: none;
  transition: color 0.2s;
}
.jump__item.is-at { color: var(--gold); }
.jump__item:hover, .jump__item:focus-visible { color: var(--gold-hi); outline: none; }
@media (hover: none), (max-width: 900px) { .jump { display: none; } }

/* ==========================================================================
   Phones and tablets (touch screens)
   - shorter scroll scenes: the intro and Software Projects take fewer swipes
   - flat card layers: phone browsers can drop 3D-layered cards for a moment while
     the page is flung (the "disappearing deck"); the cards keep their perspective
     tilt, and their stacking comes from z-index
   ========================================================================== */
@media (hover: none) and (pointer: coarse) {
  .intro { height: 210vh; }
  .deck__cards, .flow__track { transform-style: flat; }
  /* nothing may stick out past the screen edge (the phone would let the page be zoomed out) */
  .bento, .books, .reel, .services, .contact { overflow-x: clip; }
  .flow__stage { height: 100svh; }
  /* Frontend Works never tilts on a phone, so it gets no 3D layer: as one tall column of big
     pictures, that layer was too large for the phone's graphics memory and the scrolling stuttered */
  .bento__persp { perspective: none; }
  .bento__stack, .bento__grid { will-change: auto; transform: none !important; }
}

/* ==========================================================================
   Phones (≤600px)
   - Archives on Home: 6 cards, 3 rows of 2
   - Brand & UI: on one-column phones each tile takes its picture's own shape (home.js fitTiles);
     anything still trimmed keeps the top, where the headings and text usually are
   - book covers: the text scales with the book, so nothing is cut off or runs together
   - Graphic Design books: three in a row, no overlapping (the wide-screen spots overlap here)
   ========================================================================== */
@media (max-width: 600px) {
  .archive__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
  .acell .ph { padding: 14px; }
  .acell .ph__top { font-size: 9px; letter-spacing: 0.16em; }
  .acell .ph__title, .acell--long .ph__title { font-size: 15px; }

  .books__shelf {
    height: auto;
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: 10px;
    padding: 28px 2px 64px;
  }
  .book3d {
    position: relative;
    left: auto !important;
    top: auto !important;
    flex: 0 0 auto;
    --w: calc((100vw - 2 * var(--gutter) - 30px) / 3);
    --d: 14px;
  }
  .book3d:nth-child(2) { margin-top: 36px; } /* a gentle stagger, like the wide-screen shelf */
  .book3d .ph { padding: calc(var(--w) * 0.09); }
  .book3d .ph__top { font-size: calc(var(--w) * 0.058); letter-spacing: 0.12em; gap: 4px; }
  .book3d .ph__num { font-size: calc(var(--w) * 0.34); margin-bottom: calc(var(--w) * 0.04); }
  .book3d .ph__title { font-size: calc(var(--w) * 0.11); white-space: nowrap; }
  .book3d__label { left: 50%; transform: translateX(-50%); white-space: nowrap; font-size: 10px; letter-spacing: 0.1em; bottom: -28px; }
  .books__hint { right: 0; bottom: 8px; font-size: 11px; }
}
