/* ============================================================
   Version B - interior pages (About + case studies).
   Loads on top of v2.css.

   The immersive language is concentrated where it earns its place:
   the page opening, the title, media and section dividers. Long-form
   reading is deliberately calm - generous measure, quiet colour, no
   animation per paragraph.
   ============================================================ */

.page-head {
  min-height: 62svh;
  display: grid; align-content: end;
  padding-block: 9rem clamp(2.5rem, 6vh, 4rem);
}

.page-kicker {
  display: flex; align-items: center; gap: 0.9rem; margin: 0 0 1.25rem;
  font-size: 0.68rem; letter-spacing: 0.28em; text-transform: uppercase;
  color: var(--accent, var(--cyan));
}
.page-kicker::before {
  content: ""; width: clamp(1.5rem, 5vw, 3.5rem); height: 1px;
  background: currentColor; opacity: 0.55;
}

.page-title {
  margin: 0;
  font-family: Anton, "Arial Narrow", Impact, ui-sans-serif, sans-serif;
  font-weight: 400;
  font-size: clamp(2.5rem, 9vw, 7.5rem);
  line-height: 0.92; letter-spacing: -0.01em;
  text-transform: uppercase; color: var(--paper);
}

.page-meta {
  margin: clamp(1.25rem, 3vw, 2rem) 0 0;
  font-size: 0.68rem; letter-spacing: 0.2em; text-transform: uppercase;
  color: var(--paper-dim);
}

/* Divider that carries the page's accent - the main structural use of
   colour on these pages. */
.rule {
  height: 1px; border: 0; margin: 0;
  background: linear-gradient(90deg, var(--accent, var(--cyan)), var(--paper-faint) 42%, transparent);
}

/* ---- long-form reading ------------------------------------- */
.prose { padding-block: clamp(3rem, 8vh, 5.5rem); }
.prose h2 {
  margin: 0 0 1.25rem;
  font-family: ui-sans-serif, system-ui, sans-serif;
  font-size: 0.7rem; font-weight: 500; letter-spacing: 0.28em;
  text-transform: uppercase; color: var(--accent, var(--cyan));
}
.prose p {
  max-width: 62ch; margin: 0 0 1.35rem;
  font-size: clamp(1rem, 0.97rem + 0.25vw, 1.14rem);
  line-height: 1.75; color: #cfd3dc;      /* softened, easier for long text */
}
.prose p:last-child { margin-bottom: 0; }

/* Numbered chapters.
   Spaced so that roughly one chapter occupies the screen at a time -
   that is the progressive disclosure: nothing is hidden behind a
   click, but the reader is never handed the whole essay at once. */
.chapter {
  display: grid; gap: clamp(1rem, 3vw, 3rem);
  grid-template-columns: 1fr;
  padding-block: clamp(3rem, 9vh, 6rem);
  border-top: 1px solid var(--rule);
}
.chapter-index {
  font-size: 0.66rem; letter-spacing: 0.24em; text-transform: uppercase;
  color: var(--accent, var(--cyan)); opacity: 0.75;
}
@media (min-width: 52rem) {
  .chapter { grid-template-columns: 8rem 1fr; }
  .chapter-index { position: sticky; top: 6rem; }
}

/* Shorter reading groups: a lead paragraph carries the weight, the
   rest steps down. Keeps any single block from becoming a wall. */
.chapter .prose p { max-width: 58ch; }
.chapter .prose p:first-of-type {
  font-size: clamp(1.05rem, 1rem + 0.4vw, 1.28rem);
  color: #dfe3ea;
}

/* One-time entrance per chapter, added by v2.js. Default state is
   fully visible, so a failed script or no script changes nothing. */
.reveal-ready { opacity: 0; transform: translateY(14px); }

/* ---- media --------------------------------------------------
   Every piece of media is capped against the viewport's height as
   well as its width. A 9:16 asset at full width is taller than the
   screen it is on, which is exactly what made the vertical piece feel
   oversized and clumsy. */
.media { margin: 0 0 clamp(2rem, 5vh, 3rem); }
.media img, .media video {
  display: block; width: 100%; height: auto;
  max-height: 78svh; object-fit: contain;
  border: 1px solid var(--rule); background: var(--void-2);
}
.media figcaption {
  margin-top: 0.75rem;
  font-size: 0.66rem; letter-spacing: 0.18em; text-transform: uppercase;
  color: var(--paper-faint);
}

/* Vertical assets live in a narrow framed column and are limited by
   height first, so they read as deliberate portrait format rather than
   as something that overflowed. */
.media--tall img, .media--tall video {
  width: auto; max-width: 100%;
  max-height: min(68svh, 34rem);
  margin-inline: auto;
}
@media (min-width: 52rem) {
  .media--tall img, .media--tall video { margin-inline: 0; }
}

/* A vertical asset paired with its text: the media is the narrow
   column, the writing is the counterweight. Neither dominates. */
.pair {
  display: grid; gap: clamp(1.5rem, 4vw, 3rem);
  grid-template-columns: 1fr;
  align-items: start;
  padding-block: clamp(2rem, 5vh, 3.5rem);
}
@media (min-width: 52rem) {
  .pair { grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr); }
  .pair--flip > :first-child { order: 2; }
}
.pair .media { margin-bottom: 0; }

/* A single moment given the full width, used sparingly between
   chapters rather than as a wall of assets. */
.spot { padding-block: clamp(2rem, 5vh, 3.5rem); }
.spot .media { margin-bottom: 0; }

/* ---- centred stage ------------------------------------------
   For a portrait piece that should read as the focus of its own
   moment. The media is centred and the light is generated by a halo
   sized to the media itself, so the glow belongs to the object
   instead of washing a large empty rectangle beside it. */
.stage {
  display: grid; justify-items: center;
  padding-block: clamp(3rem, 8vh, 5.5rem);
  text-align: center;
}
.stage-frame {
  position: relative;
  display: inline-block;          /* shrink-wraps the media exactly */
  margin: 0;
  max-width: 100%;
}
.stage-frame::before {
  content: ""; position: absolute;
  /* the halo is measured from the media's own edges */
  inset: -12% -18%;
  background: radial-gradient(closest-side, var(--accent, var(--cyan)), transparent 72%);
  opacity: 0.20; filter: blur(38px);
  pointer-events: none; z-index: -1;
}
.stage-frame img, .stage-frame video {
  display: block; width: auto; max-width: 100%;
  max-height: min(66svh, 32rem);
  border: 1px solid var(--rule); background: var(--void-2);
}
.stage-frame figcaption {
  margin-top: 1rem;
  font-size: 0.66rem; letter-spacing: 0.18em; text-transform: uppercase;
  color: var(--paper-faint);
}
/* Paired stage: the media and its text travel together as one block,
   and it is that block which is centred in the section. The portrait
   keeps its format, the writing sits beside it, and there is no large
   dead area left over on either side. */
@media (min-width: 56rem) {
  .stage--paired {
    grid-auto-flow: column;
    grid-template-columns: auto minmax(0, 36ch);
    justify-content: center;      /* centres the pair, not the media alone */
    align-items: center;
    gap: clamp(2.5rem, 5vw, 4.5rem);
    text-align: left;
  }
  .stage--paired .stage-text { margin: 0; max-width: none; }
  .stage--paired .stage-frame { justify-self: end; }
}

/* the writing sits under the piece, centred to the same axis */
.stage-text { max-width: 54ch; margin: clamp(2rem, 5vh, 3rem) auto 0; text-align: left; }
.stage-text p {
  margin: 0 0 1.25rem;
  font-size: clamp(1rem, 0.97rem + 0.25vw, 1.14rem);
  line-height: 1.75; color: #cfd3dc;
}
.stage-text p:last-child { margin-bottom: 0; }
@media (max-width: 40rem) {
  .stage-frame img, .stage-frame video { max-height: min(58svh, 26rem); }
  .stage-frame::before { inset: -8% -12%; filter: blur(26px); }
}

/* The final piece gets a framed treatment with its accent as rim light */
.media--feature { position: relative; }
.media--feature::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  box-shadow: inset 0 0 90px -18px var(--accent, var(--cyan));
  opacity: 0.5;
}

.audio-row { margin: 0 0 1.5rem; }
.audio-row audio { width: 100%; max-width: 34rem; display: block; }
.audio-row p {
  margin: 0.5rem 0 0;
  font-size: 0.66rem; letter-spacing: 0.18em; text-transform: uppercase; color: var(--paper-faint);
}
.audio-row--lead audio { max-width: 42rem; }

/* Six stems as six full-width players is a wall. Two compact columns
   on anything wider than a phone keeps the section light. */
.stems { display: grid; gap: 1.25rem 2.5rem; grid-template-columns: 1fr; }
@media (min-width: 44rem) { .stems { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.stems .audio-row { margin: 0; }
.stems .audio-row audio { max-width: 100%; }
.stems-note {
  margin: 1.5rem 0 0;
  font-size: 0.66rem; letter-spacing: 0.18em; text-transform: uppercase; color: var(--paper-faint);
}

/* ---- credits / documentation -------------------------------- */
.credits {
  display: grid; gap: 0.6rem 2rem; margin: 0;
  padding-block: clamp(2rem, 5vh, 3rem);
  border-top: 1px solid var(--rule);
  font-size: 0.72rem; letter-spacing: 0.14em; text-transform: uppercase;
}
.credits div { display: flex; gap: 1rem; flex-wrap: wrap; }
.credits dt { color: var(--paper-faint); min-width: 7rem; }
.credits dd { margin: 0; color: var(--paper-dim); }

/* ---- next / back navigation --------------------------------- */
.page-nav {
  display: flex; flex-wrap: wrap; gap: 1rem 2rem;
  justify-content: space-between; align-items: baseline;
  padding-block: clamp(2.5rem, 6vh, 4rem);
  border-top: 1px solid var(--rule);
}
.page-nav a { text-decoration: none; }
.page-nav .next {
  font-family: Anton, "Arial Narrow", Impact, ui-sans-serif, sans-serif;
  font-size: clamp(1.3rem, 4vw, 2.5rem); text-transform: uppercase;
  color: var(--paper);
  transition: color 0.35s var(--ease-out);
}
.page-nav .next:hover, .page-nav .next:focus-visible { color: var(--accent, var(--cyan)); }
.page-nav .back {
  font-size: 0.68rem; letter-spacing: 0.24em; text-transform: uppercase; color: var(--paper-dim);
}
.page-nav .back:hover { color: var(--paper); }

/* ---- About: portrait + bio ---------------------------------- */
.about-grid {
  display: grid; gap: clamp(2rem, 5vw, 4rem);
  grid-template-columns: 1fr; align-items: start;
  padding-block: clamp(2.5rem, 6vh, 4rem);
}
@media (min-width: 52rem) {
  .about-grid { grid-template-columns: 20rem 1fr; }
  .about-grid .about-portrait { position: sticky; top: 6rem; }
}
.about-portrait img {
  display: block; width: 100%; height: auto;
  border: 1px solid var(--rule);
}

/* ---- opening reveal -----------------------------------------
   One CSS entrance for the page opening. The title never fades - it
   is the LCP element here too. */
@keyframes pgSettle { from { transform: scale(1.02); } to { transform: none; } }
@keyframes pgLift   { from { opacity: 0; transform: translateY(0.6rem); } to { opacity: 1; transform: none; } }
@keyframes pgWipe   { from { transform: scaleX(0); } to { transform: scaleX(1); } }

.page-title  { animation: pgSettle 0.9s var(--ease-out) both; }
.page-kicker { animation: pgLift 0.7s var(--ease-out) 0.08s both; }
.page-meta   { animation: pgLift 0.7s var(--ease-out) 0.4s both; }
.page-head .rule { animation: pgWipe 1s var(--ease-out) 0.3s both; transform-origin: left; }

@media (prefers-reduced-motion: reduce) {
  .page-title, .page-kicker, .page-meta, .page-head .rule {
    animation: none; opacity: 1; transform: none;
  }
}

/* ---- archive grid -------------------------------------------
   The complete process lives here rather than on the project page.
   Everything is lazy or preload="none", so reaching the page costs
   almost nothing until you scroll into a given item. */
.archive {
  display: grid; gap: clamp(1rem, 2.5vw, 2rem);
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 15rem), 1fr));
}
.archive-item { margin: 0; }
.archive-item img, .archive-item video {
  display: block; width: 100%; height: auto;
  aspect-ratio: 16 / 9; object-fit: cover;
  border: 1px solid var(--rule); background: var(--void-2);
}
.archive-item figcaption {
  margin-top: 0.6rem;
  font-size: 0.62rem; letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--paper-faint);
}

/* ---- paired calls to action ---------------------------------- */
.cta-row {
  display: flex; flex-wrap: wrap; gap: 1rem 2rem; align-items: center;
  padding-block: clamp(2rem, 5vh, 3rem);
  border-top: 1px solid var(--rule);
}
.cta-secondary {
  display: inline-flex; align-items: center; gap: 0.7rem;
  font-size: 0.7rem; letter-spacing: 0.24em; text-transform: uppercase;
  color: var(--paper); text-decoration: none;
  border: 1px solid var(--paper-faint); padding: 0.85rem 1.35rem;
  transition: border-color 0.35s var(--ease-out), color 0.35s var(--ease-out);
}
.cta-secondary:hover, .cta-secondary:focus-visible {
  color: var(--accent, var(--cyan)); border-color: currentColor;
}

/* ---- media hover ---------------------------------------------
   A small lift and a slight enlargement, nothing more. Fine pointers
   only: on a touch screen there is no hover state to enter, so these
   rules never apply and the media simply sits still.

   Deliberately NOT a contained zoom. Clipping the frame would cut the
   halo, which sits outside the media on purpose, and would crop the
   caption that shares the same figure. Scaling the media itself keeps
   both intact, and keeps native video controls where the pointer
   expects them. */
@media (hover: hover) and (pointer: fine) {

  .media img, .media video,
  .archive-item img, .archive-item video,
  .stage-frame img, .stage-frame video,
  .about-portrait img {
    transition: transform 0.6s var(--ease-out),
                filter 0.6s var(--ease-out),
                box-shadow 0.6s var(--ease-out);
    filter: saturate(0.93);
    will-change: transform;
  }

  .media:hover img, .media:hover video,
  .archive-item:hover img, .archive-item:hover video,
  .stage-frame:hover img, .stage-frame:hover video,
  .about-portrait:hover img {
    transform: translateY(-5px) scale(1.022);
    filter: saturate(1);
    box-shadow: 0 22px 50px -22px rgba(0, 0, 0, 0.9);
  }

  /* the caption warms slightly so the label belongs to the movement */
  .media figcaption, .archive-item figcaption, .stage-frame figcaption {
    transition: color 0.5s var(--ease-out);
  }
  .media:hover figcaption, .archive-item:hover figcaption,
  .stage-frame:hover figcaption { color: var(--paper-dim); }

  /* the halo answers the hover too, so the light belongs to the piece */
  .stage-frame::before { transition: opacity 0.6s var(--ease-out); }
  .stage-frame:hover::before { opacity: 0.32; }
}

@media (prefers-reduced-motion: reduce) {
  .media img, .media video, .archive-item img, .archive-item video,
  .stage-frame img, .stage-frame video, .about-portrait img {
    transition: none !important; transform: none !important;
    filter: none !important; box-shadow: none !important;
  }
}
