/* ==========================================================================
   Minsoo Koh — writer & director
   ========================================================================== */

:root{
  --bg:          #F6F6F6;
  --panel:       #EAEAEA;
  --ink:         #111111;
  --ink-mid:     #6E6E6E;
  --ink-soft:    #A6A6A6;
  /* the one colour on the page — used sparingly, three places */
  --navy:        #1B2A4A;
  --hairline:    rgba(17,17,17,.13);
  /* the page colour again as bare numbers, so gradients that need to fade it
     out to nothing can be written once and follow the palette */
  --bg-rgb:      246,246,246;
  --chip:        #FFFFFF;   /* the round close / arrow buttons */
  --paper:       #FFFFFF;   /* the white backing behind a print */
  --radius:      22px;

  /* The page is one composition: [ edge | name block | gap | card | edge ].
     Defining it this way keeps the outer margins equal, instead of pinning the
     name to the far left and letting the card float in whatever is left. */
  /* card geometry first — the composition is measured from it */
  --card-w:      clamp(250px, 31vw, 480px);
  --card-h:      calc(var(--card-w) * 0.5625);

  --bio-w:       clamp(250px, 25vw, 336px);  /* the name block itself */
  --mid:         clamp(32px, 7vw, 120px);    /* air between name and card */
  --edge-min:    clamp(24px, 5vw, 60px);     /* never tighter than this */

  /* Centre [ name | gap | card ] as one block, so the margin to the left of
     the name equals the margin to the right of the card. */
  --lead:        max(var(--edge-min),
                     calc((100vw - var(--bio-w) - var(--mid) - var(--card-w)) / 2));
  --bio-col:     calc(var(--lead) + var(--bio-w) + var(--mid));

  --edge:        var(--lead);
  --gutter:      var(--lead);                /* everything lines up to it */

  --ease:        cubic-bezier(.22,.61,.36,1);
}

*,
*::before,
*::after{ box-sizing: border-box; }

html,
body{
  height: 100%;
  overflow: hidden;          /* the document never scrolls — .scroller does */
  background: var(--bg);
  -webkit-text-size-adjust: 100%;
}

body{
  margin: 0;
  color: var(--ink);
  font-family: "Suisse Intl", "Helvetica Neue", Inter, -apple-system,
               BlinkMacSystemFont, "Segoe UI", Arial, sans-serif;
  font-size: 15px;
  line-height: 1.45;
  letter-spacing: -0.005em;
  -webkit-font-smoothing: antialiased;
}

/* --------------------------------------------------------------------------
   Hover wash — the page takes on the colour of the film you're pointing at.
   Sampled from the still itself, then lifted to a pale tint so it reads as a
   change in light rather than a coloured panel.
   -------------------------------------------------------------------------- */

.wash{
  position: fixed;
  inset: 0;
  z-index: 0;
  background-color: var(--wash, transparent);
  opacity: 0;
  pointer-events: none;
  transition: opacity .75s var(--ease), background-color .75s var(--ease);
}
body.is-washed .wash{ opacity: 1; }

/* --------------------------------------------------------------------------
   Scroll architecture
   .scroller is the one scrolling box. .pinned is a zero-height sticky layer,
   so it adds no scroll height but its children can sit over the full viewport.
   .track supplies all the scroll height, one snap point per card.
   -------------------------------------------------------------------------- */

.scroller{
  position: absolute;
  inset: 0;
  overflow-y: auto;
  overflow-x: hidden;
  scroll-snap-type: y mandatory;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior-y: none;
  scrollbar-width: none;
}
.scroller::-webkit-scrollbar{ width: 0; height: 0; }

.pinned{
  position: sticky;
  top: 0;
  height: 0;
  z-index: 10;
}

body[data-mode="art"]{
  --card-w: clamp(240px, 27vw, 430px);
  --card-h: calc(var(--card-w) * 1.28);
}

a{ color: inherit; text-decoration: none; }
ul{ list-style: none; margin: 0; padding: 0; }
button{ font: inherit; color: inherit; background: none; border: 0; padding: 0; cursor: pointer; }

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


/* ==========================================================================
   Left column
   ========================================================================== */

.bio{
  position: absolute;
  top: 0;
  left: 0;
  height: 100vh;
  height: 100dvh;
  width: var(--bio-col);
  padding-left: var(--edge);
  padding-right: var(--mid);
  display: flex;
  align-items: center;
  z-index: 20;
  pointer-events: none;
}
.bio__inner{ pointer-events: auto; width: 100%; max-width: var(--bio-w); }

/* ==========================================================================
   Left column — a screenplay page
   Courier, scene heading, centred character cue, transitions set right.
   ========================================================================== */

.sc{
  font-family: "Courier Prime", "Courier New", Courier, monospace;
  font-size: 13px;
  line-height: 1.65;
  letter-spacing: 0;
}
.sc__page{
  margin: 0 0 30px;
  text-align: right;
  color: var(--navy);
  opacity: .62;
}
.sc__slug{
  margin: 0 0 22px;
  text-transform: uppercase;
  color: var(--ink);
  letter-spacing: .01em;
}
.sc__block{ padding-left: 12%; }

/* the name is the headline of this page — it outranks everything near it.
   It is also the control that brings the opening photograph back. */
.sc__cue{
  display: block;
  width: 100%;
  margin: 0;
  text-align: center;
  font-size: 19px;
  font-weight: 700;
  line-height: 1.25;
  letter-spacing: .09em;
  color: var(--ink);
}
/* the Korean name carries the same weight as the English — same size, same
   colour, same letterspacing; only the typeface differs, because Courier has
   no Hangul */
.sc__cue:hover .sc__ko,
.sc__cue:focus-visible .sc__ko{ color: var(--ink-mid); }
.sc__cue:focus-visible{ outline: none; }

.sc__ko{
  display: block;
  margin-top: 2px;
  transition: color .3s var(--ease);
  font-family: "Apple SD Gothic Neo", "Noto Sans KR", "Malgun Gothic", sans-serif;
  font-size: 15px;
  font-weight: 700;
  letter-spacing: .10em;
  color: var(--ink);
}
/* the one line that says what he does — given weight, colour and air so it
   doesn't read as just another grey parenthetical */
.sc__paren{
  margin: 6px 0 4px;
  text-align: center;
  font-weight: 700;
  font-size: 11.5px;
  letter-spacing: .13em;
  text-transform: uppercase;
  color: var(--navy);
}

/* --- navigation, set right like transitions (CUT TO:) --- */

.tabs{
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 3px;
  margin-top: 40px;
  font-family: "Courier Prime", "Courier New", Courier, monospace;
}
.tab{
  font-size: 13px;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--ink-soft);
  transition: color .3s var(--ease);
}
.tab::after{ content: ":"; }
.tab:hover{ color: var(--ink-mid); }
.tab[aria-pressed="true"]{ color: var(--navy); }

/* --- contact block --- */

.bio__meta{
  margin-top: 20px;
  font-family: "Courier Prime", "Courier New", Courier, monospace;
  font-size: 12.5px;
  color: var(--ink-soft);
}
.bio__location{ margin: 0; }
.bio__email{
  display: inline-block;
  margin-top: 2px;
  color: var(--ink-mid);
  border-bottom: 1px solid transparent;
  transition: color .25s var(--ease), border-color .25s var(--ease);
}
.bio__email:hover{ color: var(--navy); border-bottom-color: rgba(27,42,74,.35); }

.bio__links{
  display: flex;
  gap: 14px;
  margin-top: 14px;
}
.bio__links a{
  color: var(--ink-soft);
  transition: color .25s var(--ease);
}
.bio__links a:hover{ color: var(--ink); }


/* ==========================================================================
   The photograph that follows the cursor off the name
   ========================================================================== */

.namephoto{
  position: fixed;
  top: 0;
  left: 0;
  width: clamp(150px, 17vw, 250px);
  z-index: 40;
  pointer-events: none;
  opacity: 0;
  transform: translate(-50%, -50%) scale(.94) rotate(-1.2deg);
  transition: opacity .4s var(--ease), transform .55s var(--ease);
  will-change: transform, opacity;
}
/* a fixed frame so the photographs can cross-fade without the box resizing */
.namephoto{
  aspect-ratio: 4 / 5;
  border-radius: 2px;
  background: var(--panel);
  box-shadow: 0 2px 5px rgba(17,17,17,.16), 0 26px 60px -26px rgba(17,17,17,.55);
  overflow: hidden;
}
.namephoto img{
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  transition: opacity .65s var(--ease);
}
.namephoto img.is-front{ opacity: 1; }
.namephoto.is-on{
  opacity: 1;
  transform: translate(-50%, -50%) scale(1) rotate(0deg);
}

/* the name reads as touchable */
.sc__cue{ cursor: pointer; }


/* ==========================================================================
   ART — full-screen scatter field
   Items are absolutely placed in viewport space; JS drives the pan and the
   per-item parallax. Hover raises one and quiets the rest.
   ========================================================================== */

.scatter{
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100vh;
  height: 100dvh;
  overflow: hidden;
  z-index: 8;
  display: none;
  touch-action: none;
}
body[data-mode="art"] .scatter{ display: block; }
body[data-mode="art"] .stage{ display: none; }

/* the bio has to stay readable over the field: a veil wider than the column,
   sitting behind the text but in front of the artwork */
/* wide screens: the bio is a left column, so the veil fades to the right.
   narrow screens are handled in the media query at the foot of this file —
   there the bio spans the whole viewport and this would grey out everything. */
@media (min-width: 901px){
  body[data-mode="art"] .bio::after{
    content: "";
    position: absolute;
    inset: 0 -12% 0 0;
    background: linear-gradient(to right,
                rgba(var(--bg-rgb),.62) 0%, rgba(var(--bg-rgb),.42) 58%,
                rgba(var(--bg-rgb),0) 100%);
    z-index: -1;
    pointer-events: none;
  }
}
/* a halo of page colour around the glyphs guarantees legibility over any
   image, without needing a heavy panel that would grey out the artwork */
body[data-mode="art"] .sc{
  text-shadow: 0 0 7px var(--bg), 0 0 14px var(--bg), 0 0 3px var(--bg);
}

.art{
  position: absolute;
  margin: 0;
  will-change: transform;
  transition: opacity .45s var(--ease);
}
.art__btn{
  display: block;
  width: 100%;
  line-height: 0;
  border-radius: 1px;
  overflow: hidden;
  background: var(--paper);
  /* prints lying on a surface: a tight contact shadow plus a soft cast one */
  box-shadow:
    0 1px 2px rgba(17,17,17,.30),
    0 10px 26px -10px rgba(17,17,17,.42);
  transition: transform .45s var(--ease), box-shadow .45s var(--ease);
  /* hold space before the image arrives, so the field doesn't reflow */
  aspect-ratio: 4 / 5;
}
.art.is-loaded .art__btn{ aspect-ratio: auto; }
.art__btn img,
.art__btn video{ opacity: 0; transition: opacity .5s var(--ease); }
.art.is-loaded .art__btn img,
.art.is-loaded .art__btn video{ opacity: 1; }
/* lifted off the table, not just enlarged */
.art__btn:hover,
.art__btn:focus-visible{
  transform: scale(1.05) translateY(-4px);
  box-shadow:
    0 2px 4px rgba(17,17,17,.18),
    0 34px 60px -24px rgba(17,17,17,.55);
  outline: none;
}
.art__btn img,
.art__btn video{
  width: 100%;
  height: auto;
  display: block;
}

/* quiet everything except the one under the cursor */
.scatter.is-hovering .art:not(:hover){ opacity: .34; }

.scatter__empty{
  position: absolute;
  top: 50%;
  left: 58%;
  transform: translate(-50%,-50%);
  font-family: "Courier Prime", "Courier New", Courier, monospace;
  font-size: 12.5px;
  color: var(--ink-soft);
}


/* ==========================================================================
   LAB — grid view
   The same tiles laid out plainly, on their own scroll.
   ========================================================================== */

body[data-mode="art"] .scatter[data-view="grid"]{
  overflow-y: auto;
  overflow-x: hidden;
  touch-action: auto;                 /* the drag-to-pan is off in grid view */
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(clamp(104px, 9vw, 148px), 1fr));
  gap: clamp(9px, 1.1vw, 16px);
  align-content: start;
  padding: clamp(44px, 8vh, 88px) clamp(24px, 4vw, 72px);
  scrollbar-width: none;
}
.scatter[data-view="grid"]::-webkit-scrollbar{ width: 0; height: 0; }

@media (min-width: 901px){
  body[data-mode="art"] .scatter[data-view="grid"]{
    /* clear the name block only — not the whole centred composition, which
       on a wide screen would squeeze the grid down to two columns */
    padding-left: calc(var(--lead) + var(--bio-w) + clamp(24px, 3vw, 56px));
    padding-right: clamp(24px, 4vw, 72px);
  }
}

.scatter[data-view="grid"] .art{
  position: static;
  width: auto !important;
  opacity: 1 !important;
  transform: none !important;
}
/* uniform cells — nearly every piece is already 4:5, so little is lost */
.scatter[data-view="grid"] .art__btn,
.scatter[data-view="grid"] .art.is-loaded .art__btn{
  aspect-ratio: 4 / 5;
  border-radius: 2px;
  box-shadow: 0 1px 2px rgba(17,17,17,.12);
  transition: transform .35s var(--ease), box-shadow .35s var(--ease);
}
.scatter[data-view="grid"] .art__btn:hover{
  transform: translateY(-3px);
  box-shadow: 0 2px 4px rgba(17,17,17,.14), 0 18px 34px -18px rgba(17,17,17,.45);
}
.scatter[data-view="grid"] .art__btn img,
.scatter[data-view="grid"] .art__btn video{
  width: 100%;
  height: 100%;
  object-fit: cover;
}
/* dimming the rest makes sense in a pile, not in a grid */
.scatter[data-view="grid"].is-hovering .art:not(:hover){ opacity: 1 !important; }


/* ==========================================================================
   LAB — the view toggle
   ========================================================================== */

.labview{
  position: absolute;
  right: clamp(24px, 4vw, 72px);
  top: 100vh;
  top: 100dvh;
  transform: translateY(-100%);
  display: none;
  align-items: baseline;
  gap: 14px;
  padding: 10px 16px 12px;
  z-index: 30;                 /* above the field, not tangled in it */
  font-family: "Courier Prime", "Courier New", Courier, monospace;
  /* the photographs run right up to the edge, so give the control its own
     ground: a soft pool of page colour plus a halo on the glyphs */
  background: radial-gradient(120% 160% at 78% 60%,
              var(--bg) 0%, rgba(var(--bg-rgb),.92) 46%, rgba(var(--bg-rgb),0) 100%);
  text-shadow: 0 0 6px var(--bg), 0 0 12px var(--bg), 0 0 3px var(--bg);
}
body[data-mode="art"] .labview{ display: flex; }

.labview__label{
  font-size: 11px;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--ink-soft);
}
.labview__btn{
  padding: 0 0 3px;
  font-size: 12.5px;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--ink-soft);
  border-bottom: 1px solid transparent;
  transition: color .25s var(--ease), border-color .25s var(--ease);
}
.labview__btn:hover{ color: var(--ink-mid); }
.labview__btn[aria-pressed="true"]{
  color: var(--navy);
  border-bottom-color: var(--navy);
}


/* ==========================================================================
   ART — click to enlarge
   ========================================================================== */

.zoom{
  position: fixed;
  inset: 0;
  z-index: 90;
  display: grid;
  place-items: center;
  padding: clamp(28px, 6vh, 70px) clamp(20px, 6vw, 90px);
  background: rgba(var(--bg-rgb),0);
  visibility: hidden;
  transition: background .45s var(--ease), visibility .45s;
}
.zoom.is-open{
  visibility: visible;
  background: rgba(var(--bg-rgb),.965);
}

.zoom__frame{
  position: relative;
  max-width: 100%;
  transform-origin: center center;
  will-change: transform;
}
.zoom__media{
  display: flex;
  justify-content: center;
}
.zoom__media img,
.zoom__media video{
  display: block;
  max-width: min(1100px, 100%);
  max-height: 78vh;
  width: auto;
  height: auto;
  border-radius: 3px;
  box-shadow: 0 40px 90px -40px rgba(17,17,17,.5);
  background: var(--panel);
}

.zoom__cap{
  margin-top: 14px;
  font-family: "Courier Prime", "Courier New", Courier, monospace;
  font-size: 12px;
  letter-spacing: .03em;
  color: var(--ink-mid);
  opacity: 0;
  transition: opacity .3s var(--ease) .18s;
}
.zoom.is-settled .zoom__cap{ opacity: 1; }
.zoom__cap b{ font-weight: 400; color: var(--ink); }
.zoom__cap span{ color: var(--ink-soft); }

.zoom__close,
.zoom__nav{
  position: fixed;
  border-radius: 999px;
  background: var(--chip);
  display: grid;
  place-items: center;
  box-shadow: 0 1px 2px rgba(17,17,17,.06), 0 0 0 1px rgba(17,17,17,.05);
  opacity: 0;
  transition: opacity .3s var(--ease), transform .3s var(--ease);
}
.zoom.is-settled .zoom__close,
.zoom.is-settled .zoom__nav{ opacity: 1; }

.zoom__close{
  top: clamp(20px, 3vh, 34px);
  right: var(--gutter);
  width: 38px;
  height: 38px;
}
.zoom__close:hover{ transform: rotate(90deg); }
.zoom__close svg{
  width: 15px; height: 15px;
  fill: none; stroke: var(--ink); stroke-width: 1.4; stroke-linecap: round;
}

.zoom__nav{
  top: 50%;
  margin-top: -21px;
  width: 42px;
  height: 42px;
  font-size: 15px;
  color: var(--ink-mid);
}
.zoom__nav:hover{ color: var(--navy); }
.zoom__nav--prev{ left: clamp(12px, 2.4vw, 30px); }
.zoom__nav--next{ right: clamp(12px, 2.4vw, 30px); }


/* ==========================================================================
   Card stage
   ========================================================================== */

.stage{
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100vh;
  height: 100dvh;
  z-index: 10;
  pointer-events: none;
  display: grid;
  grid-template-columns: var(--bio-col) 1fr;
}

.deck{
  grid-column: 2;
  position: relative;
  perspective: 1400px;
  perspective-origin: 50% 50%;
  transform-style: preserve-3d;
}

.card{
  position: absolute;
  top: 50%;
  left: 0;
  width: var(--card-w);
  height: var(--card-h);
  margin-top: calc(var(--card-h) / -2);
  transform-style: preserve-3d;
  backface-visibility: hidden;
  will-change: transform, opacity;
  pointer-events: auto;
}

.card__button{
  display: block;
  width: 100%;
  height: 100%;
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--panel);
  position: relative;
  text-align: left;
  transition: box-shadow .5s var(--ease);
  box-shadow: 0 1px 1px rgba(17,17,17,.03);
}
.card.is-active .card__button:hover{
  box-shadow: 0 22px 60px -18px rgba(17,17,17,.28), 0 2px 6px rgba(17,17,17,.06);
}

.card__media{
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  transform: scale(1.001);
  transition: transform 1.1s var(--ease);
}
.card.is-active .card__button:hover .card__media{ transform: scale(1.035); }

/* a silent clip that plays while you point at the card */
.card__preview{
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  opacity: 0;
  transition: opacity .55s var(--ease);
}
.card.is-playing .card__preview{ opacity: 1; }

/* legible caption over a photo */
.card__scrim{
  position: absolute;
  inset: auto 0 0 0;
  height: 46%;
  background: linear-gradient(to top, rgba(0,0,0,.42), rgba(0,0,0,0));
  opacity: 0;
  transition: opacity .5s var(--ease);
}
.card.has-media .card__scrim{ opacity: 1; }

.card__caption{
  position: absolute;
  left: 22px;
  right: 22px;
  bottom: 19px;
  display: flex;
  align-items: baseline;
  gap: 10px;
}
.card__title{
  font-size: 14px;
  font-weight: 500;
  letter-spacing: -0.012em;
  color: var(--ink);
}
.card__year{
  font-size: 13px;
  color: var(--ink-soft);
}
.card.has-media .card__title{ color: #fff; }
.card.has-media .card__year{ color: rgba(255,255,255,.72); }

/* placeholder cards, before stills are added */
.card__ghost{
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  color: var(--ink-soft);
  font-size: 12px;
  letter-spacing: .02em;
  opacity: .55;
}
.card.has-media .card__ghost{ display: none; }

.deck__empty{
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  font-family: "Courier Prime", "Courier New", Courier, monospace;
  font-size: 12.5px;
  letter-spacing: .04em;
  color: var(--ink-soft);
  white-space: nowrap;
}

/* --- index counter, bottom right --- */
.counter{
  position: absolute;
  right: var(--gutter);
  bottom: calc(var(--gutter) * .7);
  font-size: 12.5px;
  color: var(--ink-soft);
  font-variant-numeric: tabular-nums;
  letter-spacing: .02em;
  pointer-events: none;
}


/* ==========================================================================
   Scroll track — invisible, drives the deck
   ========================================================================== */

.track{ position: relative; z-index: 0; }
.track__tick{
  height: 62vh;
  scroll-snap-align: center;
  scroll-snap-stop: always;
}


/* ==========================================================================
   Detail sheet
   ========================================================================== */

.sheet{
  position: fixed;
  inset: 0;
  z-index: 100;
  background: var(--bg);
  opacity: 0;
  visibility: hidden;
  transform: translateY(14px);
  transition: opacity .5s var(--ease), transform .5s var(--ease), visibility .5s;
  overflow: hidden;
}
.sheet.is-open{
  opacity: 1;
  visibility: visible;
  transform: none;
}

.sheet__scroll{
  height: 100%;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: clamp(72px, 9vh, 120px) var(--gutter) 22vh;
}

.sheet__close{
  position: fixed;
  top: clamp(20px, 3vh, 34px);
  right: var(--gutter);
  z-index: 2;
  width: 38px;
  height: 38px;
  border-radius: 999px;
  background: var(--chip);
  display: grid;
  place-items: center;
  box-shadow: 0 1px 2px rgba(17,17,17,.06), 0 0 0 1px rgba(17,17,17,.05);
  transition: transform .3s var(--ease);
}
.sheet__close:hover{ transform: rotate(90deg); }
.sheet__close svg{
  width: 15px; height: 15px;
  fill: none; stroke: var(--ink); stroke-width: 1.4; stroke-linecap: round;
}

.detail{ max-width: 1080px; margin: 0 auto; }

.detail__head{
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 6px 16px;
  padding-bottom: 22px;
  border-bottom: 1px solid var(--hairline);
}
.detail__title{
  margin: 0;
  font-size: clamp(23px, 2.5vw, 34px);
  font-weight: 500;
  letter-spacing: -0.028em;
  line-height: 1.08;
}
.detail__year{
  font-size: clamp(13px, 1.1vw, 15px);
  color: var(--ink-soft);
  letter-spacing: -0.02em;
}
.detail__kind{
  font-size: clamp(13px, 1.1vw, 15px);
  color: var(--ink-mid);
  letter-spacing: -0.02em;
}
.detail__kind::before{
  content: "|";
  margin-right: 14px;
  color: var(--ink-soft);
}

.detail__player{
  position: relative;
  margin: 34px 0 0;
  border-radius: var(--radius);
  overflow: hidden;
  background: #111;
  aspect-ratio: 16 / 9;
}
.detail__player iframe{
  position: absolute; inset: 0;
  width: 100%; height: 100%; border: 0;
}

/* video artwork: no fixed ratio, so vertical pieces aren't cropped */
.detail__player--free{
  aspect-ratio: auto;
  max-width: 760px;
  background: transparent;
}
.detail__player--free video{
  display: block;
  width: 100%;
  height: auto;
  max-height: 76vh;
  border-radius: var(--radius);
  background: #111;
}

/* cut selector under the player — set like the rest of the site's controls:
   monospace, uppercase, the chosen one underlined in navy */
.cuts{
  display: flex;
  align-items: baseline;
  gap: 18px;
  margin-top: 15px;
  padding-top: 13px;
  border-top: 1px solid var(--hairline);
}
.cuts::before{
  content: "Cut";
  font-family: "Courier Prime", "Courier New", Courier, monospace;
  font-size: 11px;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--ink-soft);
  margin-right: -6px;
}
.cut{
  padding: 0 0 4px;
  font-family: "Courier Prime", "Courier New", Courier, monospace;
  font-size: 13px;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--ink-soft);
  border-bottom: 1px solid transparent;
  transition: color .25s var(--ease), border-color .25s var(--ease);
}
.cut:hover{ color: var(--ink-mid); }
.cut[aria-pressed="true"]{
  color: var(--navy);
  border-bottom-color: var(--navy);
}

/* the synopsis is set in Courier, like an action line in a script — it reads
   as the writing, while the credits stay in the clean sans beside it */
.detail__logline{
  margin: 30px 0 0;
  max-width: 54ch;
  font-family: "Courier Prime", "Courier New", Courier, monospace;
  font-size: 13.5px;
  line-height: 1.66;
  letter-spacing: 0;
  color: var(--ink);
}

/* two-column press-kit body: synopsis + specs left, crew + cast right */
.detail__body{
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr);
  gap: 30px clamp(40px, 7vw, 120px);
  margin-top: 40px;
  padding-top: 28px;
  border-top: 1px solid var(--hairline);
}

.detail__left .detail__logline{ margin-top: 0; }

.spec{
  margin: 26px 0 0;
  font-size: 13px;
}
.spec__row{
  display: flex;
  gap: 10px;
  padding: 4px 0;
}
.spec dt{ color: var(--ink-mid); }
.spec dt::after{ content: ":"; }
.spec dd{ margin: 0; color: var(--ink); }

.crew{ font-size: 13px; line-height: 1.66; }
.crew li{ display: flex; gap: 8px; flex-wrap: wrap; }
.crew__role{ color: var(--ink-mid); }
.crew__role::after{ content: ":"; }
.crew__name{ color: var(--ink); }

.cast{ margin-top: 26px; }
.cast h3{
  margin: 0 0 4px;
  font-size: 13px;
  font-weight: 400;
  color: var(--ink-mid);
}
.cast h3::after{ content: ":"; }
.cast li{ font-size: 13px; line-height: 1.66; color: var(--ink); }

/* photo series grid */
.gallery{
  margin-top: 38px;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 320px), 1fr));
  gap: 14px;
}
.gallery img{
  width: 100%;
  height: auto;
  display: block;
  border-radius: 12px;
  background: var(--panel);
}
/* a single piece gets shown at size, not stretched across a grid cell */
.gallery--single{
  grid-template-columns: 1fr;
  max-width: 860px;
}
.gallery--single img{
  width: auto;
  max-width: 100%;
  max-height: 78vh;
  margin: 0 auto;
}
.gallery__empty,
.detail__empty{
  margin-top: 34px;
  padding: 40px 26px;
  border: 1px dashed var(--hairline);
  border-radius: var(--radius);
  color: var(--ink-soft);
  font-size: 13.5px;
  text-align: center;
}


/* ==========================================================================
   Intro reveal
   ========================================================================== */

.reveal{
  opacity: 0;
  transform: translateY(9px);
}
body.is-ready .reveal{
  opacity: 1;
  transform: none;
  transition: opacity .9s var(--ease), transform .9s var(--ease);
  transition-delay: var(--d, 0ms);
}


/* ==========================================================================
   Small screens
   ========================================================================== */

@media (max-width: 900px){
  :root{
    --bio-col: 100%;
    --card-w: min(76vw, 420px);
    --card-h: calc(var(--card-w) * 0.5625);
  }
  body[data-mode="art"]{
    --card-w: min(70vw, 380px);
    --card-h: calc(var(--card-w) * 1.28);
  }

  .bio{
    width: 100%;
    padding: clamp(22px, 4vh, 34px) var(--gutter) 18px;
    align-items: flex-start;
  }
  /* soft fade so cards don't collide with the header text */
  .bio::before{
    content: "";
    position: absolute;
    inset: 0 0 auto 0;
    height: 310px;
    background: linear-gradient(to bottom, var(--bg) 80%, rgba(var(--bg-rgb),0));
    z-index: -1;
  }
  .bio__inner{ max-width: none; width: 100%; }
  .sc__page{ margin-bottom: 18px; }
  .sc__block{ padding-left: 0; }
  .tabs{
    flex-direction: row;
    align-items: baseline;
    gap: 18px;
    margin-top: 20px;
  }
  .bio__meta{
    position: absolute;
    left: var(--gutter);
    right: var(--gutter);
    bottom: calc(env(safe-area-inset-bottom) + 20px);
    margin: 0;
    font-size: 12.5px;
  }
  .bio__links{ margin-top: 8px; }

  /* art mode: the contact block sits at the foot of the scatter, so fade the
     bottom edge rather than veiling the column the way wide screens do */
  body[data-mode="art"] .bio::after{
    content: "";
    position: absolute;
    inset: auto 0 0 0;
    height: 230px;
    background: linear-gradient(to top,
                var(--bg) 0%, var(--bg) 46%, rgba(var(--bg-rgb),0) 100%);
    z-index: -1;
    pointer-events: none;
  }

  .stage{ grid-template-columns: 1fr; }
  body[data-mode="art"] .scatter[data-view="grid"]{
    padding-top: 300px;
    /* the contact block is pinned to the bottom of the screen on a phone, so
       leave it room — otherwise the last rows scroll underneath the text */
    padding-bottom: 190px;
    grid-template-columns: repeat(auto-fill, minmax(96px, 1fr));
  }
  .labview{ margin-top: calc(var(--gutter) * -0.2); }

  .intro{ grid-template-columns: 1fr; }
  .intro img{
    grid-column: 1;
    max-width: 68vw;
    max-height: 52vh;
    margin-top: 8vh;
  }
  .deck{ grid-column: 1; perspective: 1000px; }
  /* the stage is a single column here, so the card centres in it again —
     `left: 0` is only right when it sits beside the name block */
  .card{
    left: 50%;
    margin-left: calc(var(--card-w) / -2);
    margin-top: calc(var(--card-h) / -2 - 2vh);
  }

  .counter{ display: none; }
  .detail__body{ grid-template-columns: 1fr; gap: 30px; }
  .track__tick{ height: 52vh; }
  .sheet__scroll{ padding-top: 78px; padding-bottom: 18vh; }
}

/* ==========================================================================
   DARK — this is how the site ships.
   Two things happen here: the palette is swapped, and the lettering is
   retuned for a dark ground. It is switched on by class="dark" on the <html>
   tag in index.html; remove that attribute and the light version above takes
   over untouched. Nothing here changes layout, spacing or size.
   ========================================================================== */

:root.dark{
  --bg:          #000000;
  --bg-rgb:      0,0,0;
  --panel:       #121212;
  /* not white. Pure white on pure black glares and the letters bloom at their
     edges; pulling it back and warming it very slightly is what stops the
     page from buzzing */
  --ink:         #E9E6E0;
  --ink-mid:     #98938B;
  /* the soft grey has to come up on black: the value that reads as a quiet
     aside on a pale page reads as unreadable on a dark one */
  --ink-soft:    #7B766E;
  /* the same blue, lifted until it reads on black — a navy this dark would
     simply disappear */
  --navy:        #8FA6D8;
  --hairline:    rgba(233,230,224,.13);
  --chip:        #1C1C1C;
  /* prints keep their white paper edge: that is what makes them read as
     photographs lying on a dark surface rather than floating rectangles */
  --paper:       #FFFFFF;
}

/* --- lettering on a dark ground --------------------------------------------
   Type gains apparent weight when it is light-on-dark — the same setting that
   looks composed on paper looks crowded and heavy here. The corrections are
   the traditional ones: open the tracking, add a little line, and take the
   weight off anything that isn't carrying rank.
   -------------------------------------------------------------------------- */

.dark .sc{ line-height: 1.74; }

.dark .sc__slug{ letter-spacing: .15em; }

/* The name comes off the bold entirely and is tracked wide instead. Courier
   bold on black is the heaviest thing on the page; letterspacing gives the
   same authority quietly. It still outranks the role by size — 19px against
   11.5px — which is what the ranking actually rests on. */
.dark .sc__cue{ font-weight: 400; letter-spacing: .24em; }
.dark .sc__ko{ font-weight: 400; letter-spacing: .22em; }

/* the role line drops to a normal weight and opens right up: on black the
   tracking does the work that bold was doing on paper, and the gap between
   this and the name widens rather than closes */
.dark .sc__paren{
  margin-top: 9px;
  font-weight: 400;
  letter-spacing: .22em;
}

.dark .tabs{ gap: 5px; }
.dark .tab{ letter-spacing: .11em; }

.dark .bio__meta{ letter-spacing: .035em; }
.dark .bio__links{ gap: 16px; }

/* large text at 500 reads as semibold against black — 400 is the same
   presence without the thickening */
.dark .detail__title{ font-weight: 400; letter-spacing: -0.018em; }
.dark .detail__logline{ line-height: 1.78; }
.dark .crew{ line-height: 1.72; }

.dark .zoom__cap{ letter-spacing: .09em; }

/* captions over a still: the same warm off-white, for the same reason */
.dark .card.has-media .card__title{ color: #F0EDE7; }
.dark .card.has-media .card__year{ color: rgba(240,237,231,.7); }

/* a still that is itself nearly black dissolves into a black page and the card
   stops being an object — the faintest edge of light gives it back its shape
   without drawing a visible frame */
.dark .card__button{ box-shadow: 0 0 0 1px rgba(233,230,224,.08); }
.dark .card.is-active .card__button:hover{
  box-shadow: 0 0 0 1px rgba(233,230,224,.16),
              0 22px 60px -18px rgba(0,0,0,.9);
}

/* the hover wash is sampled from the still and lifted to 93% lightness, which
   is right over a pale page and blinding over a dark one — so let it through
   as a breath of colour instead of a full pane */
.dark body.is-washed .wash{ opacity: .12; }

/* drop shadows do nothing against black, so the photograph gets a faint rim
   of light to hold its edge */
.dark .namephoto{
  box-shadow: 0 0 0 1px rgba(233,230,224,.12), 0 26px 60px -26px rgba(0,0,0,.9);
}

@media (prefers-reduced-motion: reduce){
  html{ scroll-behavior: auto; }
  .card{ transition: none !important; }
  body.is-ready .reveal{ transition-duration: .01ms; }
}
