/* ==========================================================================
   system.css — loaded AFTER site.css
   --------------------------------------------------------------------------
   site.css is a well-built system for a stills-and-text site. This layer adds
   what a motion-led, work-first homepage needs on top of it:

     - shared motion + type tokens (site.css hardcodes ten separate curves)
     - a layered video tile (poster + clip + scrim) instead of a bare <img>
     - a full-bleed video hero
     - the hover-swap film index (option B)
     - autoplay-aware reduced-motion handling

   Kept as a separate file so the original system stays readable and you can
   see exactly what the motion work costs.
   ========================================================================== */

:root {
  /* --- Motion tokens ---------------------------------------------------- */
  --ease-out:    cubic-bezier(.2, .7, .3, 1);
  --ease-reveal: cubic-bezier(.16, 1, .3, 1);
  --dur-fast: 160ms;
  --dur-med:  450ms;
  --dur-slow: 650ms;

  /* --- Type scale --------------------------------------------------------
     One formula, one viewport anchor (400–1600px), so the hierarchy between
     tiers stays constant at every width instead of drifting. */
  --step-0: clamp(1rem,    0.96rem + 0.17vw, 1.125rem);  /* body        16→18 */
  --step-1: clamp(1.125rem, 1rem   + 0.5vw,  1.5rem);    /* lede        18→24 */
  --step-2: clamp(1.5rem,  1.33rem + 0.67vw, 2rem);      /* tile title  24→32 */
  --step-3: clamp(2rem,    1.75rem + 1vw,    2.75rem);   /* h3          32→44 */
  --step-4: clamp(2.75rem, 2.33rem + 1.67vw, 4rem);      /* h2          44→64 */
  --step-5: clamp(3.5rem,  2.83rem + 2.67vw, 5.5rem);    /* stat digits 56→88 */
  --step-6: clamp(3.25rem, 2.1rem  + 4.6vw,  6.5rem);    /* hero h1     52→104 */

  /* Ink in raw RGB, for scrims. Scrims are always ink — never hot. */
  --ink-rgb: 24, 34, 65;

  --section-pad-tight: clamp(3rem, 6vw, 5.5rem);
}

/* --- Apply the scale ------------------------------------------------------ */
.section-head h2  { font-size: var(--step-4); }
.tile__title      { font-size: var(--step-2); }
.stat dt          { font-size: var(--step-5); }
.footer-cta       { font-size: var(--step-5); }
.door h3          { font-size: var(--step-3); }
.stuck__card h3   { font-size: var(--step-3); }
.split h2         { font-size: var(--step-4); }

/* Work grid is a curated reel, not a marketing section — tighten it. */
.work-section { padding-block: var(--section-pad-tight); }

/* The films carry the section on their own, so there's no heading above them —
   only the way out to the rest. Without an h2 the flex row has nothing to push
   against, so the link is pinned right explicitly. */
.section-head--link-only {
  justify-content: flex-end;
  margin-bottom: clamp(1rem, 2vw, 1.5rem);
}

/* ==========================================================================
   Layered video tile
   ========================================================================== */

.tile__frame { transition: transform var(--dur-med) var(--ease-out); }

/* Scale the frame as one unit so poster, clip, scrim and flag move together.
   site.css scaled the <img> alone, which would leave the video layer behind. */
.tile:hover .tile__frame,
.tile:focus-visible .tile__frame { transform: scale(1.03); }
.tile:hover .tile__frame img { transform: none; }

.tile__clip {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  transition: opacity 550ms var(--ease-out);
}
.tile__frame.is-playing .tile__clip,
.tile__clip.is-playing { opacity: 1; }

/* Six different shoots — arena light, Disneyland dusk, a kitchen table —
   pulled fractionally toward each other so they don't fight the palette. */
.tile__frame img,
.tile__frame video { filter: saturate(.94) contrast(1.02); }

/* --- Third-party embed cover ---------------------------------------------
   Vimeo/YouTube iframes can't be object-fit, so the frame is grown until it
   covers the box on both axes while holding 16:9, then centred and clipped.
   min-width + min-height + aspect-ratio (with no explicit width/height) is
   what produces true "cover" behaviour here. */
.embed-cover {
  position: absolute;
  inset: 0;
  overflow: hidden;
  opacity: 0;
  transition: opacity 700ms var(--ease-out);
  pointer-events: none;         /* the tile is a link; the iframe mustn't eat clicks */
}
.embed-cover.is-playing { opacity: 1; }

/* Nothing inside is interactive — the loop is wallpaper, not a player. */
.embed-cover, .embed-cover * { pointer-events: none !important; user-select: none; }

.embed-cover iframe {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  min-width: 100%;
  min-height: 100%;
  width: auto;
  height: auto;
  aspect-ratio: 16 / 9;
  border: 0;
  filter: saturate(.94) contrast(1.02);
}

/* YouTube draws its own furniture — title bar, watch-later, share, end-card
   arrows — around the edges of the player and there is no parameter that
   removes all of it. Overscaling pushes that band outside the visible frame.
   Costs a little crop; buys a clean picture. */
.embed-cover[data-embed^="youtube"] iframe {
  transform: translate(-50%, -50%) scale(1.32);
}

/* Native video ratios rather than arbitrary fractions, so delivered footage
   isn't needlessly cropped. */
.tile__frame        { aspect-ratio: 16 / 9; }
.tile--wide .tile__frame { aspect-ratio: 21 / 9; }

/* Award flag: lifted off the flush corner, pill-shaped, shadowed — reads as
   UI sitting on the footage rather than something baked into the frame. */
.tile__flag {
  top: 0.85rem;
  left: 0.85rem;
  bottom: auto;
  border-radius: 999px;
  box-shadow: 0 4px 14px rgba(0, 0, 0, .35);
  transition: transform var(--dur-fast) var(--ease-out);
}
.tile:hover .tile__flag { transform: translateY(-2px); }

/* ==========================================================================
   Full-bleed video hero
   ========================================================================== */

.hero--video {
  position: relative;
  min-height: 88svh;
  display: flex;
  align-items: flex-end;
  padding-block: clamp(3rem, 8vw, 6rem) clamp(2.5rem, 5vw, 4rem);
  overflow: hidden;
  color: var(--cream);
  background: var(--ink);
}

.hero__media {
  position: absolute;
  inset: 0;
  z-index: 0;
}
.hero__media img,
.hero__media video {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.hero__media video { opacity: 0; transition: opacity 700ms var(--ease-out); }
.hero__media video.is-playing { opacity: 1; }

/* Top scrim keeps the translucent sticky header legible over any first frame;
   bottom scrim carries the title. Always ink, never hot. */
.hero--video::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background: linear-gradient(
    180deg,
    rgba(var(--ink-rgb), .55) 0%,
    rgba(var(--ink-rgb), .10) 22%,
    rgba(var(--ink-rgb), .10) 48%,
    rgba(var(--ink-rgb), .70) 80%,
    rgba(var(--ink-rgb), .94) 100%
  );
}

.hero--video .wrap { position: relative; z-index: 2; width: 100%; }

.hero--video h1 {
  font-size: var(--step-6);
  font-weight: 800;
  letter-spacing: -0.045em;
  text-shadow: 0 2px 24px rgba(var(--ink-rgb), .45);
  max-width: 14ch;
}
.hero--video .eyebrow { color: var(--cream); opacity: .8; }
.hero--video .lede { color: var(--cream); opacity: .92; }

.hero__credit {
  margin-top: 1.5rem;
  font-size: 0.75rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  opacity: .7;
}

/* Header sits over the hero rather than pushing it down. */
.site-header--over {
  position: fixed;
  inset-inline: 0;
  background: transparent;
  backdrop-filter: none;
  border-bottom-color: transparent;
  color: var(--cream);
}
.site-header--over .nav__cta { background: var(--cream); color: var(--ink) !important; }
.site-header--over .nav__cta:hover { background: var(--hot); color: var(--cream) !important; }
/* Stays fixed throughout — only the surface changes. Swapping position
   fixed→sticky mid-scroll costs a frame of jump for no benefit. */
.site-header--over.is-stuck {
  background: color-mix(in srgb, var(--cream) 90%, transparent);
  backdrop-filter: saturate(180%) blur(14px);
  border-bottom-color: color-mix(in srgb, var(--ink) 12%, transparent);
  color: var(--ink);
}

/* ==========================================================================
   Option B — the hover-swap film index (the mechanic the old site used)
   ========================================================================== */

/* The stage is a scroll runway: the pin holds still while the page moves under
   it, which is what gives the loop room to contract into the grid. Height is
   set by JS only when motion is allowed, so no-JS and reduced-motion get a
   plain one-screen stage instead. */
.index-stage {
  position: relative;
  background: var(--ink);
  color: var(--cream);
}

.index-stage__pin {
  position: sticky;
  top: 0;
  min-height: 100svh;
  display: flex;
  align-items: center;
  overflow: hidden;
  padding-block: clamp(4rem, 9vw, 7rem);
}

/* Everything that shrinks lives in here, scrim included, so the scrim tracks
   the footage instead of staying stuck to the viewport. */
.index-stage__frame {
  position: absolute;
  inset: 0;
  z-index: 0;
  overflow: hidden;
}

.index-stage__media { position: absolute; inset: 0; z-index: 0; }
.index-stage__layer {
  position: absolute;
  inset: 0;
  opacity: 0;
  transition: opacity 700ms var(--ease-out);
}
.index-stage__layer.is-active { opacity: 1; }
.index-stage__layer img,
.index-stage__layer video {
  width: 100%; height: 100%;
  /* cover: scales proportionally and crops the overflow. Never distorts —
     `fill` is the one that stretches. */
  object-fit: cover;
}

.index-stage__frame::after {
  content: "";
  position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background: linear-gradient(
    90deg,
    rgba(var(--ink-rgb), .92) 0%,
    rgba(var(--ink-rgb), .72) 38%,
    rgba(var(--ink-rgb), .30) 70%,
    rgba(var(--ink-rgb), .20) 100%
  );
  /* As the frame contracts the list clears out of the way, so the heavy left
     wash is no longer earning its keep — fade it toward an even scrim. */
  opacity: calc(1 - 0.55 * var(--p, 0));
}
@media (max-width: 860px) {
  .index-stage__frame::after {
    background: linear-gradient(
      180deg,
      rgba(var(--ink-rgb), .55) 0%,
      rgba(var(--ink-rgb), .30) 35%,
      rgba(var(--ink-rgb), .88) 100%
    );
  }
}

.index-stage__ui { position: relative; z-index: 2; width: 100%; }

.film-index { list-style: none; margin: 0; padding: 0; }

.film-index li { border-top: 1px solid rgba(255, 245, 217, .22); }
.film-index li:last-child { border-bottom: 1px solid rgba(255, 245, 217, .22); }

.film-index a {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.5rem 1.25rem;
  padding-block: clamp(0.85rem, 1.6vw, 1.35rem);
  text-decoration: none;
  color: inherit;
  opacity: .62;
  transition: opacity var(--dur-fast) var(--ease-out),
              padding-inline-start var(--dur-med) var(--ease-out);
}
.film-index a:hover,
.film-index a:focus-visible,
.film-index a.is-active {
  opacity: 1;
  padding-inline-start: 1.1rem;
}

.film-index__title {
  font-family: var(--display);
  font-weight: 700;
  font-size: clamp(1.65rem, 1.05rem + 2.6vw, 3.4rem);
  letter-spacing: -0.035em;
  line-height: 1;
}
.film-index a:hover .film-index__title,
.film-index a.is-active .film-index__title { color: var(--hot); }

.film-index__meta {
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--slate-lt);
  margin-left: auto;
  text-align: right;
}

/* ==========================================================================
   Compact header
   --------------------------------------------------------------------------
   The header is chrome, not content. Over a full-bleed loop it should be a
   thin strip that stays out of the footage's way.
   ========================================================================== */

.site-header__inner { min-height: 52px; gap: 1.5rem; }

.wordmark { font-size: 0.875rem; letter-spacing: -0.02em; }

.nav { gap: clamp(0.85rem, 1.8vw, 1.6rem); }
.nav a { font-size: 0.8125rem; padding-block: 0.25rem; }
.nav__cta { padding: 0.42rem 0.85rem !important; font-size: 0.75rem; }

@media (max-width: 780px) {
  .site-header__inner { padding-block: 0.6rem; }
  .nav a { font-size: 0.75rem; }
}

/* ==========================================================================
   Work grid rises over the contracting loop
   --------------------------------------------------------------------------
   The stage stays pinned while this section climbs over it, so the grid
   arrives on top of the shrinking footage instead of following after it.
   ========================================================================== */

.work-section {
  position: relative;
  z-index: 3;
  background: var(--cream);
  margin-top: -16svh;
  border-radius: 18px 18px 0 0;
  box-shadow: 0 -28px 60px rgba(0, 0, 0, .28);
}

.index-stage__head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem 2rem;
  margin-bottom: clamp(1.5rem, 3vw, 2.25rem);
}
.index-stage__head .eyebrow { margin: 0; color: var(--cream); opacity: .8; }

/* Work-first: the film list is the top of the page, so the studio descriptor
   and the motion control sit underneath it as a footnote rather than a
   headline. */
.index-stage__foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 1rem 2rem;
  margin-top: clamp(1.75rem, 3.5vw, 2.75rem);
}
.index-stage__note {
  margin: 0;
  font-size: 0.875rem;
  color: var(--cream);
  opacity: .78;
}
.index-stage__note a {
  color: inherit;
  text-decoration: none;
  border-bottom: 1px solid currentColor;
  padding-bottom: 1px;
  margin-left: 0.35rem;
}
.index-stage__note a:hover { color: var(--hot); border-bottom-color: var(--hot); opacity: 1; }

/* With no headline above it, the list carries the whole first screen, so it
   gets more room per row. */
.index-stage[data-index-stage] .film-index a { padding-block: clamp(1rem, 2vw, 1.7rem); }

/* ==========================================================================
   Select clients / Film festivals
   --------------------------------------------------------------------------
   Names set as a typographic wall rather than a logo grid. Logos would need
   permission and consistent lockups from twenty different brand teams; set in
   the site's own display face they read as one confident list, and nothing
   goes stale when a logo is redrawn.
   ========================================================================== */

.roster { display: grid; gap: clamp(2.5rem, 5vw, 4rem); }
@media (min-width: 900px) { .roster { grid-template-columns: 1fr 1fr; } }

.roster__head {
  font-family: var(--body);
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--slate);
  padding-bottom: 0.85rem;
  margin-bottom: 1.5rem;
  border-bottom: 2px solid var(--hot);
}
.band--ink .roster__head,
.band--slate .roster__head { color: var(--slate-lt); }

.roster__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem 0;
  font-family: var(--display);
  font-weight: 600;
  font-size: clamp(1.05rem, 0.9rem + 0.7vw, 1.5rem);
  letter-spacing: -0.02em;
  line-height: 1.25;
}
.roster__list li { display: flex; align-items: baseline; }
.roster__list li:not(:last-child)::after {
  content: "·";
  color: var(--hot);
  margin-inline: 0.6em;
  font-weight: 700;
}

.roster__note {
  margin-top: 1.25rem;
  font-size: 0.8125rem;
  color: var(--slate);
}
.band--ink .roster__note, .band--slate .roster__note { color: var(--slate-lt); }

/* ==========================================================================
   Theme switch — prototype only
   ========================================================================== */

.theme-switch {
  display: inline-flex;
  align-items: center;
  gap: 0;
  border: 1px solid currentColor;
  border-radius: 999px;
  padding: 2px;
  opacity: .75;
}
.theme-switch button {
  font: inherit;
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  background: transparent;
  color: inherit;
  border: 0;
  border-radius: 999px;
  padding: 0.35rem 0.7rem;
  cursor: pointer;
}
.theme-switch button[aria-pressed="true"] {
  background: var(--hot);
  color: var(--cream);
}

/* ==========================================================================
   ALT THEME — "Cinema"
   --------------------------------------------------------------------------
   A screening-room inversion of the warm daylight palette: charcoal paper,
   bone ink, amber accent, and an editorial serif in place of the grotesque.
   Same structure, different temperature — dark surfaces let footage carry
   the colour instead of competing with it.
   ========================================================================== */

[data-theme="cinema"] {
  --cream:      #14151A;   /* "paper" is now charcoal */
  --cream-deep: #1C1E24;
  --ink:        #ECE6D9;   /* "ink" is now bone */
  --ink-soft:   #D6CFC0;
  --slate:      #8D8779;
  --slate-lt:   #A9A395;
  --slate-dk:   #22242B;
  --hot:        #E8A33A;   /* amber */
  --hot-dk:     #CE8B27;

  --paper: #14151A;
  --text:  #ECE6D9;

  --ink-rgb: 10, 11, 14;

  --display: "Fraunces", Georgia, "Times New Roman", serif;
  --body:    "Inter", "Helvetica Neue", Helvetica, Arial, sans-serif;

  --rule: 1px solid rgba(236, 230, 217, .2);
}

/* In cinema mode the light/dark relationship inverts, so the bands that were
   "dark breaks" in a cream page become lighter breaks in a charcoal one. */
[data-theme="cinema"] body { background: var(--paper); color: var(--text); }

[data-theme="cinema"] .band--ink {
  background: #0D0E12;
  color: var(--ink);
}
[data-theme="cinema"] .band--slate { background: #1B1D23; color: var(--ink); }
[data-theme="cinema"] .band--deep  { background: #1A1C22; color: var(--ink); }
[data-theme="cinema"] .site-footer { background: #0D0E12; color: var(--ink); }

[data-theme="cinema"] .site-header {
  background: color-mix(in srgb, #14151A 88%, transparent);
  border-bottom-color: rgba(236, 230, 217, .14);
}
[data-theme="cinema"] .site-header--over.is-stuck {
  background: color-mix(in srgb, #14151A 92%, transparent);
  color: var(--ink);
}

[data-theme="cinema"] .btn--ink { background: var(--ink); color: #14151A; }
[data-theme="cinema"] .btn--ink:hover { background: var(--ink-soft); }
[data-theme="cinema"] .btn--hot { color: #14151A; }
[data-theme="cinema"] .nav__cta { background: var(--ink); color: #14151A !important; }
[data-theme="cinema"] .nav__cta:hover { background: var(--hot); color: #14151A !important; }
[data-theme="cinema"] .theme-switch button[aria-pressed="true"] { color: #14151A; }
[data-theme="cinema"] .tile__flag { color: #14151A; }
[data-theme="cinema"] ::selection { background: var(--hot); color: #14151A; }

/* Fraunces is a high-contrast serif — it wants slightly less negative tracking
   than a grotesque, or the thin strokes start to collide. */
[data-theme="cinema"] h1,
[data-theme="cinema"] h2,
[data-theme="cinema"] h3,
[data-theme="cinema"] .film-index__title,
[data-theme="cinema"] .tile__title {
  letter-spacing: -0.015em;
  font-weight: 600;
}
[data-theme="cinema"] .hero--video h1,
[data-theme="cinema"] .film-index__title { font-weight: 600; }

/* ==========================================================================
   Motion controls + filters
   ========================================================================== */

.motion-toggle {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font: inherit;
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: inherit;
  background: transparent;
  border: 1px solid currentColor;
  border-radius: 999px;
  padding: 0.5rem 0.9rem;
  cursor: pointer;
  opacity: .7;
  transition: opacity var(--dur-fast) var(--ease-out);
}
.motion-toggle:hover { opacity: 1; }
.motion-toggle::before {
  content: "";
  width: 8px; height: 8px;
  background: var(--hot);
  border-radius: 1px;
}
.motion-toggle[aria-pressed="true"]::before {
  border-radius: 50%;
  clip-path: polygon(0 0, 100% 50%, 0 100%);
}

.filters {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-bottom: clamp(1.75rem, 3vw, 2.5rem);
}
.filter-pill {
  font: inherit;
  font-size: 0.8125rem;
  font-weight: 600;
  padding: 0.55rem 1.05rem;
  border-radius: 999px;
  border: 1px solid color-mix(in srgb, var(--ink) 25%, transparent);
  background: transparent;
  color: inherit;
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease-out),
              color var(--dur-fast) var(--ease-out),
              border-color var(--dur-fast) var(--ease-out);
}
.filter-pill:hover { border-color: var(--ink); }
.filter-pill[aria-pressed="true"] {
  background: var(--ink);
  color: var(--cream);
  border-color: var(--ink);
}

.tile[hidden] { display: none; }


/* ==========================================================================
   Scroll reveal
   ========================================================================== */

@media (prefers-reduced-motion: no-preference) {
  .js [data-reveal] {
    opacity: 0;
    transform: translateY(16px);
    transition: opacity var(--dur-slow) var(--ease-reveal),
                transform var(--dur-slow) var(--ease-reveal);
    transition-delay: calc(var(--i, 0) * 70ms);
  }
  .js [data-reveal].is-visible { opacity: 1; transform: none; }
}

/* ==========================================================================
   Reduced motion — the part site.css didn't cover: autoplay itself
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {
  /* Nothing moves on its own. The poster still is the design, and the play
     button lets someone opt in per clip rather than losing the feature. */
  .tile__clip,
  .hero__media video,
  .index-stage__layer video,
  .embed-cover { opacity: 0 !important; }


  .tile:hover .tile__frame { transform: none; }
  .film-index a:hover { padding-inline-start: 0; }
}

/* ==========================================================================
   Splash layout
   --------------------------------------------------------------------------
   The loop and nothing else: no header, no list, no copy. One moving image
   holding the whole screen, until a scroll brings in the header and the work.
   ========================================================================== */

/* Held back until the splash has been scrolled past. Not display:none — the
   links stay in the accessibility tree and a keyboard tab brings it straight
   in, so "no chrome" never means "no navigation". */
.site-header--held {
  opacity: 0;
  transform: translateY(-100%);
  transition: opacity 320ms var(--ease-out), transform 380ms var(--ease-out);
  pointer-events: none;
}
.site-header--held.is-stuck,
.site-header--held:focus-within {
  opacity: 1;
  transform: none;
  pointer-events: auto;
}

/* No scrim over a splash — nothing is sitting on the footage that needs to be
   legible, so the picture is left alone. */

.index-stage__cue {
  position: absolute;
  z-index: 2;
  left: 50%;
  bottom: clamp(1.75rem, 4vh, 3rem);
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.7rem;
  color: var(--cream);
  /* Fades on the first scroll — it has done its job. */
  opacity: 1;
  transition: opacity 300ms var(--ease-out);
}
.is-scrolled .index-stage__cue { opacity: 0; }

.index-stage__cue-text {
  font-family: var(--meta, var(--body));
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  opacity: .8;
}

.index-stage__cue-line {
  width: 1px;
  height: clamp(2rem, 5vh, 3.25rem);
  background: linear-gradient(180deg, transparent, var(--cream));
  transform-origin: top;
  animation: cue-drop 2.1s var(--ease-reveal) infinite;
}

@keyframes cue-drop {
  0%        { transform: scaleY(0);   opacity: 0; }
  35%       { transform: scaleY(1);   opacity: 1; }
  70%, 100% { transform: scaleY(1);   opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .index-stage__cue-line { animation: none; opacity: .8; }
  .site-header--held { opacity: 1; transform: none; pointer-events: auto; }
}

/* Shared heading for the full-width bands — the JessZilla numbers and the two
   doors. Both were already on var(--step-4), but one carried it as an inline
   style and the other as a class, which is how they drift. One class now. */
.band-head {
  /* A step up from --step-4. Both band headings are statements, not section
     labels, and they were reading as the latter. */
  font-size: clamp(3rem, 2.25rem + 2.9vw, 5rem);
  /* Full width — these run across the frame rather than sitting in a column. */
  max-width: none;
  margin-bottom: clamp(2rem, 4vw, 3rem);
  letter-spacing: -0.035em;
  text-wrap: balance;
}

/* ==========================================================================
   Splash header — transparent, but present
   --------------------------------------------------------------------------
   Earlier this was held back until you scrolled. Visible from the first frame
   is better: someone landing on a full-screen image needs a way out of it.
   Transparent over the footage, solid once the grid arrives.
   ========================================================================== */

.site-header--bare {
  background: transparent;
  backdrop-filter: none;
  border-bottom-color: transparent;
  color: var(--cream);
}

/* Over moving footage the only thing keeping the nav legible is this shadow
   plus the thin scrim at the top of the frame. */
.site-header--bare .wordmark,
.site-header--bare .nav a { text-shadow: 0 1px 12px rgba(0, 0, 0, .55); }

.site-header--bare .nav__cta {
  background: rgba(255, 255, 255, .14);
  color: var(--cream) !important;
  border: 1px solid rgba(255, 255, 255, .45);
  backdrop-filter: blur(8px);
  text-shadow: none;
}
.site-header--bare .nav__cta:hover {
  background: var(--hot);
  border-color: var(--hot);
  color: var(--cream) !important;
}

.site-header--bare.is-stuck {
  background: color-mix(in srgb, var(--cream) 90%, transparent);
  backdrop-filter: saturate(180%) blur(14px);
  border-bottom-color: color-mix(in srgb, var(--ink) 12%, transparent);
  color: var(--ink);
}
.site-header--bare.is-stuck .wordmark,
.site-header--bare.is-stuck .nav a { text-shadow: none; }
.site-header--bare.is-stuck .nav__cta {
  background: var(--ink);
  color: var(--cream) !important;
  border-color: var(--ink);
  backdrop-filter: none;
}

/* A little more cover at the very top now that the nav lives there. */
.index-stage--splash .index-stage__pin {
  position: static;
  height: 100svh;
  min-height: 100svh;
  padding-block: 0;
}

/* The grid follows the frame instead of climbing over it — the climb only
   reads as intentional when something is pinned behind it. */
.index-stage--splash + .work-section,
.index-stage--splash ~ .work-section {
  margin-top: 0;
  border-radius: 0;
  box-shadow: none;
}

.index-stage--splash .index-stage__frame::after {
  background: linear-gradient(
    180deg,
    rgba(var(--ink-rgb), .48) 0%,
    rgba(var(--ink-rgb), .10) 18%,
    rgba(var(--ink-rgb), 0) 40%,
    rgba(var(--ink-rgb), 0) 66%,
    rgba(var(--ink-rgb), .42) 100%
  );
  opacity: 1;
}

/* ==========================================================================
   Splash slideshow
   ========================================================================== */

[data-slideshow] .index-stage__layer {
  opacity: 0;
  transition: opacity 1400ms var(--ease-out);
}
[data-slideshow] .index-stage__layer img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center center;
  transform: none;
}
[data-slideshow] .index-stage__layer.is-active { opacity: 1; }

/* No drift. Every still holds at its delivered size — a slow zoom would push a
   1920-wide source past its native resolution and soften it, and the whole
   point here is that the image doesn't move or resize. The crossfade alone
   carries the change. */

/* Once idle.mp4 exists the loop is the backdrop and the stills stand down. */
[data-slideshow] .index-stage__layer--idle ~ [data-slide] { display: none; }

/* ==========================================================================
   Sub-pages
   ========================================================================== */

.page-head { padding-block: clamp(6rem, 12vw, 9rem) clamp(2rem, 4vw, 3rem); }
.page-head h1 { font-size: var(--step-4); max-width: 18ch; margin-bottom: 1.25rem; }
.page-head .lede { max-width: 58ch; }

.work-section--flat {
  margin-top: 0;
  border-radius: 0;
  box-shadow: none;
  background: transparent;
  padding-top: 0;
}

.split-section { padding-block: clamp(3rem, 6vw, 5rem); }

/* --- Film page ------------------------------------------------------------ */

.film__hero {
  position: relative;
  min-height: clamp(52svh, 60vw, 76svh);
  display: flex;
  align-items: flex-end;
  overflow: hidden;
  background: var(--ink);
  padding-block: clamp(3rem, 8vw, 5rem);
}
.film__still {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  filter: saturate(.94) contrast(1.02);
}
.film__hero::after {
  content: "";
  position: absolute; inset: 0;
  background: linear-gradient(
    180deg,
    rgba(var(--ink-rgb), .5) 0%,
    rgba(var(--ink-rgb), .1) 30%,
    rgba(var(--ink-rgb), .6) 78%,
    rgba(var(--ink-rgb), .94) 100%
  );
}
.film__hero-inner { position: relative; z-index: 2; width: 100%; color: var(--cream); }
.film__hero-inner .eyebrow { color: var(--cream); opacity: .8; }
.film__title {
  font-size: clamp(2.5rem, 1.4rem + 5vw, 5.5rem);
  letter-spacing: -0.045em;
  text-shadow: 0 2px 24px rgba(var(--ink-rgb), .45);
}

.film__player-wrap { padding-block: clamp(2rem, 4vw, 3.5rem) 0; }
.film__player {
  position: relative;
  aspect-ratio: 16 / 9;
  border-radius: 6px;
  overflow: hidden;
  background: var(--ink);
}
.film__player iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }

.film__body {
  display: grid;
  grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr);
  gap: clamp(2rem, 6vw, 5rem);
  padding-block: clamp(3rem, 6vw, 5rem);
}
@media (max-width: 860px) { .film__body { grid-template-columns: 1fr; } }

.film__premiere {
  font-family: var(--meta, var(--body));
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--hot);
  margin-bottom: 1.5rem;
}
.film__main p { font-size: var(--step-1); line-height: 1.5; max-width: 46ch; }
.film__watch { font-size: 0.9375rem; line-height: 1.7; color: var(--slate-dk); }

.credits { margin: 0; display: grid; gap: 0.85rem; }
.credit dt {
  font-size: 0.6875rem; font-weight: 700; letter-spacing: 0.13em;
  text-transform: uppercase; color: var(--slate);
}
.credit dd { margin: 0.15rem 0 0; font-size: 0.9375rem; }

.film__awards { padding-block: 0 clamp(3rem, 6vw, 4.5rem); }
.film__awards { max-width: var(--maxw); margin-inline: auto; padding-inline: var(--gutter); }
.film__award-list { list-style: none; margin: 0; padding: 0; columns: 2; column-gap: 3rem; }
@media (max-width: 700px) { .film__award-list { columns: 1; } }
.film__award-list li {
  break-inside: avoid; margin-bottom: 0.8rem; padding-left: 1.25rem;
  position: relative; font-size: 0.9375rem; line-height: 1.5;
}
.film__award-list li::before {
  content: ""; position: absolute; left: 0; top: 0.6em;
  width: 6px; height: 6px; border-radius: 50%; background: var(--hot);
}

.film__nav { border-top: var(--rule); }
.film__nav-inner {
  display: flex; justify-content: space-between; gap: 2rem;
  padding-block: clamp(1.75rem, 3vw, 2.5rem);
}
.film__nav-link { text-decoration: none; display: grid; gap: 0.3rem; }
.film__nav-link--next { text-align: right; }
.film__nav-dir {
  font-size: 0.6875rem; font-weight: 700; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--slate);
}
.film__nav-title {
  font-family: var(--display); font-weight: 700;
  font-size: clamp(1.15rem, 1rem + 0.8vw, 1.75rem); letter-spacing: -0.03em;
}
.film__nav-link:hover .film__nav-title { color: var(--hot); }

/* --- About ---------------------------------------------------------------- */

.who { display: grid; gap: clamp(1.5rem, 3vw, 2.5rem);
       grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr)); }
.who__card h3 { font-size: var(--step-2); margin-bottom: 0.25rem; }
.who__role {
  font-size: 0.6875rem; font-weight: 700; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--hot); margin-bottom: 0.9rem;
}
.who__card p { font-size: 0.9375rem; line-height: 1.6; }

.award-list { display: grid; }
.award-row {
  display: grid;
  grid-template-columns: 5rem minmax(0, 1fr);
  gap: 1.5rem;
  padding-block: 1.1rem;
  border-top: var(--rule);
  align-items: baseline;
}
.award-row:last-child { border-bottom: var(--rule); }
.award-row__year {
  font-family: var(--meta, var(--body));
  font-size: 0.8125rem; font-weight: 700; color: var(--hot);
}
.award-row__body { font-size: 0.9375rem; line-height: 1.5; }
@media (max-width: 600px) {
  .award-row { grid-template-columns: 1fr; gap: 0.3rem; }
}

/* --- Press ---------------------------------------------------------------- */

.press-block { margin-bottom: clamp(2.5rem, 5vw, 4rem); }
.press-list { display: grid; }
.press-row {
  display: grid;
  grid-template-columns: 14rem minmax(0, 1fr);
  gap: 1.5rem;
  padding-block: 1.1rem;
  border-top: var(--rule);
  text-decoration: none;
  align-items: baseline;
  transition: padding-inline-start var(--dur-fast) var(--ease-out);
}
.press-list .press-row:last-child { border-bottom: var(--rule); }
.press-row:hover { padding-inline-start: 0.75rem; }
.press-row:hover .press-row__head { color: var(--hot); }
.press-row__outlet {
  font-size: 0.6875rem; font-weight: 700; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--slate);
}
.press-row__head {
  font-family: var(--display); font-weight: 600;
  font-size: clamp(1.05rem, 0.95rem + 0.5vw, 1.35rem);
  letter-spacing: -0.02em; line-height: 1.25;
}
@media (max-width: 700px) {
  .press-row { grid-template-columns: 1fr; gap: 0.35rem; }
}

/* Was a list of items each prefixed with a dash. Real markers instead. */
.tick-list { list-style: none; padding: 0; font-size: 0.9375rem; line-height: 1.9; }
.tick-list li { position: relative; padding-left: 1.2rem; }
.tick-list li::before {
  content: "";
  position: absolute; left: 0; top: 0.78em;
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--hot);
}

/* Quotes are links now, so they need a hover state and must not inherit the
   underline that a bare <a> would bring in. */
a.quote { display: block; text-decoration: none; color: inherit;
          transition: border-color var(--dur-fast) var(--ease-out); }
a.quote:hover { border-left-color: var(--ink); }
a.quote:hover cite { color: var(--hot); }
a.quote cite { transition: color var(--dur-fast) var(--ease-out); }
.band--slate a.quote:hover { border-left-color: var(--cream); }

/* Film names on the press page are the subject of each block, not a column
   label — so they read as titles rather than as the small uppercase headers
   used for "Select clients" and the like. */
.press-block__title {
  font-family: var(--display);
  font-weight: 700;
  font-size: clamp(1.75rem, 1.4rem + 1.5vw, 2.6rem);
  letter-spacing: -0.03em;
  line-height: 1.05;
  padding-bottom: 0.7rem;
  margin-bottom: 0.35rem;
  border-bottom: 2px solid var(--hot);
}

/* A little more air between blocks now that the titles carry more weight. */
.press-block { margin-bottom: clamp(3rem, 6vw, 4.5rem); }

/* ==========================================================================
   Case-study imagery
   --------------------------------------------------------------------------
   Stills sit between the claims rather than alongside them, so the page still
   reads as evidence with pictures, not a gallery with captions. The wide band
   keeps the film's own 2.39:1 so nothing is cropped away.
   ========================================================================== */

.case-band {
  margin: clamp(2.5rem, 5vw, 4rem) 0;
  overflow: hidden;
  border-radius: 4px;
}
.case-band img {
  width: 100%;
  aspect-ratio: 2.39 / 1;
  object-fit: cover;
  display: block;
}

.case-pair {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 280px), 1fr));
  gap: clamp(1rem, 2vw, 1.5rem);
  margin-top: clamp(2.5rem, 5vw, 4rem);
}
.case-pair figure { margin: 0; overflow: hidden; border-radius: 4px; }
.case-pair img {
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  display: block;
}

/* ==========================================================================
   Client marks + laurel wall
   --------------------------------------------------------------------------
   Two walls, one system. Only a third of the clients have a usable free
   monochrome logo, so the rest are set as wordmarks in the same ink at the
   same optical weight. Because everything is one colour and one height, a
   partial logo set reads as deliberate rather than as gaps.
   ========================================================================== */

.wall + .wall { margin-top: clamp(2.25rem, 4vw, 3.25rem); }

/* Proof strip, not a marketing section — it should register on the way past
   rather than demand a stop. */
.band--deep:has(.laurel-grid) { padding-block: clamp(3rem, 5.5vw, 4.5rem); }

.mark-grid {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.1rem 0;
}

.mark {
  display: inline-flex;
  align-items: baseline;
  opacity: .68;
  transition: opacity var(--dur-fast) var(--ease-out);
}
.mark:hover { opacity: 1; }

/* Separator carried by the item, so the names stay tight and the rhythm holds
   however the list wraps. */
.mark:not(:last-child)::after {
  content: "\00b7";
  color: var(--hot);
  margin-inline: 0.45em;
  font-weight: 700;
}

.mark--word {
  font-family: var(--display);
  font-weight: 600;
  font-size: clamp(0.9375rem, 0.86rem + 0.34vw, 1.125rem);
  line-height: 1.35;
  letter-spacing: -0.01em;
  color: var(--ink);
  white-space: nowrap;
}

/* --- Laurels -------------------------------------------------------------- */

.laurel-grid {
  list-style: none;
  margin: 0 0 1.25rem;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 124px), 1fr));
  gap: clamp(0.9rem, 1.6vw, 1.35rem) clamp(0.75rem, 1.4vw, 1.1rem);
  align-items: center;
  justify-items: center;
}

.laurel {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 78px;
  opacity: 1;
  transition: opacity var(--dur-fast) var(--ease-out),
              transform var(--dur-fast) var(--ease-out);
}
.laurel:hover { opacity: 1; transform: translateY(-2px); }

.laurel img {
  max-height: 100%;
  max-width: 100%;
  width: auto;
  object-fit: contain;
}

/* Laurels are supplied as black artwork. On a dark band they'd vanish, so
   they invert rather than being shipped twice. */
.band--ink .laurel img,
.band--slate .laurel img { filter: invert(1) brightness(1.6); }

@media (max-width: 520px) {
  .laurel-grid { grid-template-columns: repeat(auto-fill, minmax(96px, 1fr)); }
  .laurel { height: 62px; }
}

/* Bigger work thumbnails: two per row on desktop instead of three, so each
   still gets enough size to actually read as a frame from the film. */
.work-section .work-grid {
  /* Explicit rather than auto-fill: the minmax maths tipped to a single
     864px-wide tile at tablet widths. Two up until it genuinely can't. */
  grid-template-columns: 1fr;
  gap: clamp(2rem, 3.5vw, 3.25rem) clamp(1.5rem, 2.5vw, 2.5rem);
}
@media (min-width: 800px) {
  .work-section .work-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* Every client is a wordmark now, so the cells can be sized for text rather
   than having to accommodate a logo too. */

/* Laurel strip standing in for the old text festival list on consulting. */
.laurel-strip { padding-block: clamp(1.5rem, 3vw, 2.5rem) 0; }
.laurel-strip .laurel-grid { margin-bottom: 0; }

/* The intro and the first film heading were separated by a full section's
   worth of padding stacked on the page-head's own. Close it up. */
.press-body { padding-top: clamp(1.25rem, 2.5vw, 2rem); }

/* ==========================================================================
   Inline gif pop
   --------------------------------------------------------------------------
   One joke in the About copy opens as an overlay. Built on <dialog> so the
   Escape key, the focus trap and the inert background all come from the
   platform instead of from us.
   ========================================================================== */

.gif-link {
  color: inherit;
  text-decoration: none;
  border-bottom: 2px solid var(--hot);
  padding-bottom: 1px;
  cursor: pointer;
  transition: color var(--dur-fast, 180ms) var(--ease-out, ease);
}
.gif-link:hover { color: var(--hot); }

/* The colophon runs at 13px in muted slate, so the 2px rule the body copy uses
   would sit on the text like a highlighter. Thinner line, brighter text, same
   hot hover as everywhere else. */
.colophon .gif-link {
  color: var(--cream);
  border-bottom-width: 1px;
}

.gif-pop {
  border: 0;
  padding: 0;
  background: transparent;
  max-width: min(760px, 92vw);
  max-height: 88svh;
  overflow: visible;
}

/* The 50% black sits between the page and the gif — the gif is a child of the
   dialog, so it renders above its own backdrop. */
.gif-pop::backdrop { background: rgba(0, 0, 0, .5); }

.gif-pop img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: 10px;
  box-shadow: 0 30px 90px rgba(0, 0, 0, .5);
}

.gif-pop__close {
  position: absolute;
  top: -0.85rem; right: -0.85rem;
  width: 2.25rem; height: 2.25rem;
  display: grid; place-items: center;
  border: 0; border-radius: 50%;
  background: var(--hot);
  color: var(--cream);
  font-family: var(--body);
  font-size: 1.05rem;
  line-height: 1;
  cursor: pointer;
}

@media (prefers-reduced-motion: no-preference) {
  .gif-pop[open] { animation: gif-pop-in 240ms var(--ease-out, cubic-bezier(.16,1,.3,1)); }
  @keyframes gif-pop-in {
    from { opacity: 0; transform: scale(.96); }
    to   { opacity: 1; transform: none; }
  }
}

/* ==========================================================================
   Series extras
   --------------------------------------------------------------------------
   A series has more than one piece. Vertical cuts and a landscape short film
   are genuinely different shapes, so they get different rows rather than a
   single grid that would letterbox one of them.
   ========================================================================== */

.film__extras {
  padding-block: clamp(3rem, 6vw, 5.5rem);
  border-top: 1px solid color-mix(in srgb, var(--slate) 22%, transparent);
}

.film__extras .band-head { margin-bottom: clamp(1rem, 2vw, 1.5rem); }
.film__extras-intro { max-width: 60ch; margin-bottom: clamp(2rem, 4vw, 3rem); }

.reel-row { display: grid; gap: clamp(1.25rem, 2.5vw, 2rem); }
.reel-row + .reel-row { margin-top: clamp(1.75rem, 3.5vw, 2.75rem); }

.reel-row--wide { grid-template-columns: 1fr; max-width: 900px; }
.reel-row--tall { grid-template-columns: repeat(auto-fit, minmax(min(100%, 220px), 1fr)); }

.reel { margin: 0; }

.reel__frame {
  position: relative;
  overflow: hidden;
  border-radius: 8px;
  background: var(--ink);
}
.reel--wide .reel__frame { aspect-ratio: 16 / 10; }
.reel--tall .reel__frame { aspect-ratio: 9 / 16; }

.reel__frame iframe {
  position: absolute;
  inset: 0;
  width: 100%; height: 100%;
  border: 0;
}

.reel figcaption {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.35rem 0.7rem;
  margin-top: 0.7rem;
}
.reel__title {
  font-family: var(--display);
  font-weight: 700;
  font-size: 1.0625rem;
  letter-spacing: -0.02em;
}
.reel__note {
  font-family: var(--meta, var(--body));
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--hot);
}
