/* ==========================================================================
   Date 8 Animation Studio — base stylesheet
   Brand system: Ink / Paper / Guide Blue / Retake Red / Mute Grey
   Spacing unit: 8px · Layout: 8-column grid · Font: Inter

   Accent-contrast rule (WCAG-driven, brand colors used exactly as given):
   On Paper (light) backgrounds, text/accents/focus rings use Ink — Guide
   Blue falls to 2.2:1 on Paper. Retake Red (4.7:1) is only used on Paper
   for form errors, always with an icon and text. On Ink (dark) backgrounds,
   Guide Blue (7.8:1) and Mute Grey (4.95:1) are used for text; Retake Red
   (3.7:1) is limited to non-text marks there. All clear WCAG AA.

   Architecture: cascade layers keep specificity predictable instead of
   reaching for BEM. Layer order is declared once, up front.
   ========================================================================== */

@layer reset, tokens, fonts, base, layout, components, motion, utilities;

@layer fonts {
  /* Self-hosted Inter (OFL-licensed, converted from the official Google
     Fonts download — see assets/fonts/Inter-OFL.txt). Each file is a
     variable font covering the full 100–900 weight range plus the optical
     size axis, so two files replace what would otherwise be dozens of
     static weight/style files. */
  @font-face {
    font-family: 'Inter Variable';
    src: url('../assets/fonts/Inter-Variable.woff2') format('woff2');
    font-weight: 100 900;
    font-style: normal;
    font-display: swap;
  }
  @font-face {
    font-family: 'Inter Variable';
    src: url('../assets/fonts/Inter-Italic-Variable.woff2') format('woff2');
    font-weight: 100 900;
    font-style: italic;
    font-display: swap;
  }
}

@layer reset {
  *, *::before, *::after { box-sizing: border-box; }
  html { scroll-behavior: smooth; }
  body, h1, h2, h3, h4, p, figure, blockquote, dl, dd { margin: 0; }
  ul[class], ol[class] { list-style: none; margin: 0; padding: 0; }
  img, picture, video { display: block; max-width: 100%; }
  input, button, textarea, select { font: inherit; }
  a { color: inherit; text-decoration: none; }

  @media (prefers-reduced-motion: reduce) {
    html { scroll-behavior: auto; }
  }
}

@layer tokens {
  :root {
    /* Brand colors — literal (Tier 1) tokens, used exactly as specified */
    --ink: #101820;
    --paper: #FBFAF7;
    --guide-blue: #69B3E7;
    --retake-red: #DA291C;
    --mute-grey: #7C8894;

    /* Fonts — one typeface site-wide; both tokens kept so every selector
       that references display/reading text doesn't need to change. */
    --font-display: 'Inter Variable', 'Inter', system-ui, sans-serif;
    --font-reading: 'Inter Variable', 'Inter', system-ui, sans-serif;

    /* Spacing scale — base unit 8px */
    --sp-1: 8px;
    --sp-2: 16px;
    --sp-3: 24px;
    --sp-4: 32px;
    --sp-5: 40px;
    --sp-6: 48px;
    --sp-8: 64px;
    --sp-10: 80px;
    --sp-12: 96px;
    --sp-16: 128px;
    --sp-20: 160px;

    /* Layout */
    --container-max: 1280px;
    --nav-height: 88px;

    /* Semantic (Tier 2) tokens — accent-contrast rule lives here so
       components just consume --accent / --focus-ring. */
    --text-on-paper: var(--ink);
    --accent-on-paper: var(--ink);
    --text-on-ink: var(--paper);
    --accent-on-ink: var(--guide-blue);
    --focus-ring: var(--ink);
  }
}

@layer base {
  body {
    background: var(--paper);
    color: var(--ink);
    font-family: var(--font-reading);
    font-size: 17px;
    line-height: 1.6;
    -webkit-font-smoothing: antialiased;
    /* All text on the site is set in capitals. Done in CSS (not in the
       markup) so the source copy, alt text and copy/paste keep normal
       case. Caps read tighter, so tracking is opened up slightly. */
    text-transform: uppercase;
    letter-spacing: 0.03em;
  }

  h1, h2, h3, h4, .font-display {
    font-family: var(--font-display);
    font-weight: 700;
    line-height: 1.1;
    letter-spacing: 0;
  }

  /* Balanced headline wrapping — scoped to headings only; the binary-search
     algorithm behind text-wrap:balance is too costly to apply broadly. */
  h1, h2, h3, h4 { text-wrap: balance; }

  h1 { font-size: clamp(2.5rem, 5vw + 1rem, 4.5rem); }
  h2 { font-size: clamp(1.75rem, 2.5vw + 1rem, 2.75rem); }
  h3 { font-size: clamp(1.25rem, 1.2vw + 1rem, 1.5rem); }

  .eyebrow {
    font-family: var(--font-display);
    font-weight: 600;
    font-size: 0.8rem;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--accent-on-paper);
  }

  .lede {
    font-family: var(--font-reading);
    font-size: clamp(1.05rem, 0.4vw + 1rem, 1.25rem);
    color: var(--text-on-paper);
    font-style: italic;
  }

  p, li, blockquote { text-wrap: pretty; }
  p { max-width: 62ch; }
  p + p { margin-top: var(--sp-3); }
}

@layer layout {
  .container {
    max-width: var(--container-max);
    margin: 0 auto;
    padding: 0 var(--sp-4);
  }

  /* 8-column page grid — viewport-driven layout, as distinct from the
     container-query-driven component sizing used inside cards below. */
  .grid-8 {
    display: grid;
    grid-template-columns: repeat(8, 1fr);
    gap: var(--sp-3);
  }

  @media (max-width: 900px) {
    .grid-8 { grid-template-columns: repeat(4, 1fr); }
  }
  @media (max-width: 560px) {
    .grid-8 { grid-template-columns: 1fr; }
  }

  .span-3 { grid-column: span 3; min-width: 0; }
  .span-4 { grid-column: span 4; min-width: 0; }
  .span-5 { grid-column: span 5; min-width: 0; }
  .span-6 { grid-column: span 6; min-width: 0; }
  .span-8 { grid-column: span 8; min-width: 0; }

  @media (max-width: 900px) {
    .span-3, .span-4, .span-5, .span-6, .span-8 { grid-column: span 4; }
  }
  @media (max-width: 560px) {
    .span-3, .span-4, .span-5, .span-6, .span-8 { grid-column: 1 / -1; }
  }

  section { padding: var(--sp-16) 0; }
  @media (max-width: 700px) {
    section { padding: var(--sp-10) 0; }
  }

  /* Logo clear space is kept in eighths of the logo's own rendered width,
     via the --logo-w custom property set per instance. */
  .logo-clearspace {
    display: inline-block;
    padding: calc(var(--logo-w, 120px) / 8);
  }
  .logo-clearspace img {
    display: block;
    width: var(--logo-w, 120px);
    height: auto;
  }
}

@layer components {
  /* --------------------------------- Nav ---------------------------------- */
  .site-nav {
    position: sticky;
    top: 0;
    z-index: 50;
    background: var(--paper);
    border-bottom: 1px solid rgba(16, 24, 32, 0.08);
    overflow: clip;
    /* Scroll state queries let a descendant react once the nav is actually
       stuck, with zero JS. Progressive enhancement — see @supports below.
       Per the scroll-state spec, the container element cannot style
       itself from its own query, only descendants can — hence the
       box-shadow-as-full-bleed-background trick on .container below. */
    container-name: site-nav;
  }
  @supports (container-type: scroll-state) {
    .site-nav { container-type: scroll-state; }
  }

  .site-nav .container {
    display: flex;
    align-items: center;
    justify-content: space-between;
    min-height: var(--nav-height);
  }

  .site-nav .logo-clearspace { padding-left: 0; }

  @supports (container-type: scroll-state) {
    @container site-nav scroll-state(stuck: top) {
      .site-nav .container {
        box-shadow:
          0 0 0 100vmax color-mix(in oklab, var(--paper) 92%, transparent),
          0 8px 24px rgba(16, 24, 32, 0.08);
      }
    }
  }

  .nav-links {
    display: none;
    align-items: center;
    gap: var(--sp-6);
  }

  .nav-links a {
    font-family: var(--font-display);
    font-weight: 600;
    font-size: 0.95rem;
    letter-spacing: 0.02em;
    padding: var(--sp-1) 0;
    position: relative;
    color: var(--ink);
  }

  .nav-links a::after {
    content: '';
    position: absolute;
    left: 0;
    right: 0;
    bottom: -2px;
    height: 2px;
    background: var(--accent-on-paper);
    transform: scaleX(0);
    transform-origin: left;
    transition: transform 0.2s ease;
  }

  .nav-links a:hover::after,
  .nav-links a[aria-current="page"]::after {
    transform: scaleX(1);
  }

  .nav-toggle {
    display: none;
    background: none;
    border: none;
    cursor: pointer;
    padding: var(--sp-1);
    min-inline-size: 44px;
    min-block-size: 44px;
  }
  .nav-toggle span {
    display: block;
    width: 24px;
    height: 2px;
    background: var(--ink);
    margin: 5px auto;
    transition: transform 0.2s ease, opacity 0.2s ease;
  }

  /* Mobile nav panel is a native popover: no JS required to open/close,
     light-dismiss and Esc-to-close come free. Below 700px it renders as a
     dropdown sheet; at 700px+ the popover machinery is neutralised and it
     renders as an ordinary inline row (see the min-width block). */
  @media (max-width: 700px) {
    .nav-toggle { display: block; }

    /* !important throughout: overriding the UA popover default box
       (position: fixed; inset: 0; margin: auto; width/height: fit-content)
       which otherwise centers the panel as a small floating box instead of
       a top-anchored full-width sheet. */
    .nav-links[popover] {
      position: fixed !important;
      top: var(--nav-height) !important;
      left: 0 !important;
      right: 0 !important;
      bottom: auto !important;
      margin: 0 !important;
      width: auto !important;
      height: auto !important;
      max-height: calc(100dvh - var(--nav-height));
      overflow: auto;
      border: 0;
      border-bottom: 1px solid rgba(16, 24, 32, 0.08);
      background: var(--paper);
      color: inherit;
      flex-direction: column;
      align-items: flex-start;
      gap: var(--sp-2);
      padding: var(--sp-3) var(--sp-4) var(--sp-4);

      opacity: 0;
      translate: 0 -8px;
      transition: opacity 0.2s ease, translate 0.2s ease, display 0.2s allow-discrete, overlay 0.2s allow-discrete;
    }

    .nav-links:popover-open {
      display: flex;
      opacity: 1;
      translate: 0 0;
    }

    @starting-style {
      .nav-links:popover-open {
        opacity: 0;
        translate: 0 -8px;
      }
    }

    /* Fallback path for browsers without Popover API support: main.js
       toggles this class manually and it must win over the [popover]
       hidden state. */
    .nav-links.is-open-fallback {
      display: flex;
      opacity: 1;
      translate: 0 0;
    }

    @media (prefers-reduced-motion: reduce) {
      .nav-links[popover] { transition-duration: 0.01s; translate: none; }
    }
  }

  @media (min-width: 701px) {
    .nav-toggle { display: none; }
    /* Force the popover permanently visible and back in normal flow —
       the standard technique for a popover-backed panel that should only
       behave as a popover below the mobile breakpoint. */
    .nav-links {
      display: flex !important;
      position: static !important;
      top: auto !important;
      left: auto !important;
      right: auto !important;
      bottom: auto !important;
      margin: 0 !important;
      width: auto !important;
      height: auto !important;
      max-height: none;
      overflow: visible;
      border: 0;
      background: transparent;
      flex-direction: row;
      align-items: center;
      gap: var(--sp-6);
      padding: 0;
      opacity: 1;
      translate: none;
    }
  }

  /* --------------------------------- Hero ---------------------------------- */
  .hero {
    position: relative;
    min-height: min(92dvh, 880px);
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    text-align: center;
    background-color: var(--ink);
    background-image: url('../assets/img/hero-poster-eyes.jpg');
    background-size: cover;
    background-position: center;
    color: var(--paper);
    overflow: hidden;
    padding: var(--sp-10) var(--sp-4);
  }

  .hero-video {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    z-index: 0;
    transition: opacity 0.8s ease;
  }
  .hero-video.is-loading { opacity: 0; }

  .hero-scrim {
    position: absolute;
    inset: 0;
    background: linear-gradient(180deg, rgba(16,24,32,0.55) 0%, rgba(16,24,32,0.35) 40%, rgba(16,24,32,0.75) 100%);
    z-index: 1;
  }

  .hero-content {
    position: relative;
    z-index: 2;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--sp-4);
  }

  .hero .logo-clearspace { --logo-w: min(46vw, 360px); }
  .hero-logo { display: flex; justify-content: center; }

  /* Portrait screens (phones, tablets held upright): a tall hero would crop
     the wide video down to a thin slice of its middle. Instead the hero
     becomes a 16:9 band the width of the screen, so the whole frame shows.
     The logo stays on top of the video. */
  @media (max-aspect-ratio: 1 / 1) {
    .hero {
      min-height: 0;
      aspect-ratio: 16 / 9;
      padding: 0;
    }
    .hero .logo-clearspace { --logo-w: min(38vw, 300px); }
    .hero-scroll-cue { display: none; }
  }

  .hero-scroll-cue {
    position: absolute;
    bottom: var(--sp-4);
    left: 50%;
    transform: translateX(-50%);
    z-index: 2;
    font-family: var(--font-display);
    font-size: 0.75rem;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--paper);
    opacity: 0.6;
  }

  /* ------------------------------- Buttons --------------------------------- */
  .btn {
    display: inline-flex;
    align-items: center;
    gap: var(--sp-1);
    font-family: var(--font-display);
    font-weight: 600;
    font-size: 0.9rem;
    letter-spacing: 0.03em;
    padding: var(--sp-2) var(--sp-4);
    border-radius: 2px;
    border: 1px solid currentColor;
    transition: background 0.2s ease, color 0.2s ease;
  }

  .btn-primary {
    background: var(--ink);
    color: var(--paper);
    border-color: var(--ink);
  }
  .btn-primary:hover { background: transparent; color: var(--ink); }

  .btn-ghost {
    background: transparent;
    color: var(--paper);
    border-color: rgba(251, 250, 247, 0.5);
  }
  .btn-ghost:hover { background: var(--paper); color: var(--ink); border-color: var(--paper); }

  /* ------------------------------ Sections --------------------------------- */
  .section-head {
    display: flex;
    flex-direction: column;
    gap: var(--sp-2);
    margin-bottom: var(--sp-8);
  }

  .section-alt { background: var(--ink); color: var(--paper); }
  .section-alt .eyebrow { color: var(--accent-on-ink); }
  .section-alt .lede { color: rgba(251, 250, 247, 0.7); }

  /* Production key art — a mosaic of stills. Layout switches on the
     figure's own width (container query), not the viewport: a 4-column
     stack when narrow, then an 8-column x 6-row mosaic on the 8px-gap grid
     (one lead still, two wide stills, four close-ups). The 16:9 grid ratio
     keeps every tile near its native 16:9 so little is cropped. */
  .key-art {
    container-type: inline-size;
    margin: 0;
  }

  .key-art-grid {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: var(--sp-1);
  }

  .key-art-tile {
    position: relative;
    overflow: clip;
    border-radius: 2px;
    aspect-ratio: 16 / 9;
    background: rgba(251, 250, 247, 0.06);
  }
  .key-art-tile img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    transition: scale 0.6s cubic-bezier(0.2, 0.7, 0.2, 1);
  }
  /* Hairline edge so tiles read as framed against the Ink background. */
  .key-art-tile::after {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: inherit;
    box-shadow: inset 0 0 0 1px rgba(251, 250, 247, 0.1);
    pointer-events: none;
  }

  .key-art-caption {
    margin-top: var(--sp-2);
    font-size: 0.75rem;
    letter-spacing: 0.1em;
    color: var(--mute-grey);
  }

  /* Narrow: lead and both wide stills full width, the four close-ups 2x2. */
  .key-art-tile:nth-child(-n + 3) { grid-column: span 4; }
  .key-art-tile:nth-child(n + 4) { grid-column: span 2; aspect-ratio: 4 / 3; }

  .key-art-tile:nth-child(3) img { object-position: 50% 18%; }

  @container (min-width: 640px) {
    .key-art-grid {
      grid-template-columns: repeat(8, 1fr);
      grid-template-rows: repeat(6, 1fr);
      aspect-ratio: 16 / 9;
    }
    .key-art-tile,
    .key-art-tile:nth-child(n + 4) { aspect-ratio: auto; }

    .key-art-tile:nth-child(1) { grid-area: 1 / 1 / 5 / 6; }
    .key-art-tile:nth-child(2) { grid-area: 1 / 6 / 3 / 9; }
    .key-art-tile:nth-child(3) { grid-area: 3 / 6 / 5 / 9; }
    .key-art-tile:nth-child(4) { grid-area: 5 / 1 / 7 / 3; }
    .key-art-tile:nth-child(5) { grid-area: 5 / 3 / 7 / 5; }
    .key-art-tile:nth-child(6) { grid-area: 5 / 5 / 7 / 7; }
    .key-art-tile:nth-child(7) { grid-area: 5 / 7 / 7 / 9; }
  }

  @media (hover: hover) and (prefers-reduced-motion: no-preference) {
    .key-art-tile:hover img { scale: 1.04; }
  }

  .status-badge {
    display: inline-flex;
    align-items: center;
    gap: var(--sp-1);
    font-family: var(--font-display);
    font-weight: 600;
    font-size: 0.75rem;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--accent-on-ink);
  }
  .status-badge::before {
    content: '';
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--retake-red);
  }

  /* Studio / about page */
  .value-list {
    display: grid;
    gap: var(--sp-2);
  }
  .value-list li {
    padding-left: var(--sp-3);
    border-left: 2px solid var(--accent-on-paper);
    color: var(--text-on-paper);
    font-family: var(--font-display);
    font-size: 0.95rem;
  }

  .studio-statement {
    font-family: var(--font-display);
    font-weight: 600;
    color: var(--ink);
  }

  /* Entry-point / contact cards — container-query-sized so heading type
     scales with the card's own width (component context), with a clamp()
     fallback for browsers without container query unit support. */
  .entry-card {
    container-type: inline-size;
  }
  .entry-card h3 {
    font-size: clamp(1.25rem, 6vw, 1.5rem);
  }
  @supports (font-size: 1cqi) {
    .entry-card h3 {
      font-size: clamp(1.25rem, 8cqi, 1.5rem);
    }
  }

  /* Contact page */
  .contact-card {
    container-type: inline-size;
    background: var(--ink);
    color: var(--paper);
    border-radius: 4px;
    padding: var(--sp-8) var(--sp-6);
    display: flex;
    flex-direction: column;
    gap: var(--sp-2);
    align-items: flex-start;
  }

  .contact-email {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: var(--sp-2);
    font-family: var(--font-display);
    font-weight: 700;
    font-size: clamp(1rem, 5cqi, 2.25rem);
    overflow-wrap: anywhere;
    max-width: 100%;
  }
  @media (max-width: 560px) {
    .contact-card { padding: var(--sp-6) var(--sp-3); }
  }

  /* Guide Blue is the dark-surface accent (7.8:1 on Ink), so the link is
     marked by a blue underline rather than relying on colour alone. */
  .contact-email a {
    border-bottom: 2px solid var(--accent-on-ink);
    padding-bottom: 2px;
    transition: color 0.2s ease;
  }
  .contact-email a:hover { color: var(--accent-on-ink); }

  /* ------------------------------ Enquiry form ----------------------------- */
  /* Sits on Paper: Ink text and focus rings, Mute Grey control borders (3.5:1),
     Retake Red for errors (4.7:1 on Paper). Errors always pair colour with an
     icon and text. What visitors type stays in natural case; labels and the
     reason list follow the site-wide capitals. */
  .form-note {
    margin-top: var(--sp-2);
    font-size: 0.8rem;
  }

  .enquiry {
    display: grid;
    gap: var(--sp-4);
    margin-top: var(--sp-6);
  }

  .field {
    display: grid;
    gap: var(--sp-1);
  }
  .field[hidden] { display: none; }

  .field-label {
    display: flex;
    justify-content: space-between;
    gap: var(--sp-2);
    font-family: var(--font-display);
    font-size: 0.8rem;
    font-weight: 600;
    letter-spacing: 0.1em;
  }
  .field-flag {
    font-weight: 500;
    white-space: nowrap;
  }

  .field-hint {
    font-size: 0.8rem;
  }

  .enquiry :is(input:not([type="radio"]), textarea) {
    inline-size: 100%;
    min-block-size: 48px;
    padding: 0.75rem 1rem;
    font: inherit;
    font-size: 1rem;
    letter-spacing: normal;
    text-transform: none;
    color: var(--ink);
    background: var(--paper);
    border: 1px solid var(--mute-grey);
    border-radius: 2px;
  }
  .enquiry :is(input:not([type="radio"]), textarea, .select-trigger):hover {
    border-color: var(--ink);
  }

  /* Reason picker — built into the page rather than a native <select>, so the
     page keeps scrolling while it is open (native dropdowns freeze it,
     especially on phones). The list opens inline, below the button. */
  .select-trigger {
    position: relative;
    display: block;
    inline-size: 100%;
    min-block-size: 48px;
    padding: 0.75rem 3rem 0.75rem 1rem;
    text-align: start;
    font: inherit;
    font-size: 1rem;
    letter-spacing: 0.03em;
    text-transform: uppercase;
    color: var(--ink);
    background: var(--paper);
    border: 1px solid var(--mute-grey);
    border-radius: 2px;
    cursor: pointer;
  }
  .select-trigger::after {
    content: "";
    position: absolute;
    inset-inline-end: 1.25rem;
    inset-block-start: 50%;
    inline-size: 0.55rem;
    block-size: 0.55rem;
    border-inline-end: 2px solid var(--ink);
    border-block-end: 2px solid var(--ink);
    translate: 0 -75%;
    rotate: 45deg;
    transition: rotate 0.2s ease;
  }
  .select-trigger[aria-expanded="true"]::after { rotate: 225deg; translate: 0 -25%; }
  .select-trigger[aria-invalid="true"] {
    border-color: var(--retake-red);
    box-shadow: inset 0 0 0 1px var(--retake-red);
  }

  .select-panel {
    border: 1px solid var(--ink);
    border-radius: 2px;
    background: var(--paper);
  }
  .option-group {
    margin: 0;
    padding: 0;
    border: 0;
    min-inline-size: 0;
  }
  .option-group + .option-group { border-block-start: 1px solid rgba(16, 24, 32, 0.2); }
  .option-group legend {
    padding: 0.75rem 1rem 0.25rem;
    font-family: var(--font-display);
    font-size: 0.75rem;
    font-weight: 600;
    letter-spacing: 0.1em;
  }
  .option {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    min-block-size: 48px;
    padding: 0.5rem 1rem;
    cursor: pointer;
  }
  .option input {
    flex: none;
    inline-size: 1.1rem;
    block-size: 1.1rem;
    margin: 0;
    accent-color: var(--ink);
  }
  .option:hover { background: rgba(16, 24, 32, 0.06); }
  .option:has(:checked) { background: rgba(16, 24, 32, 0.08); font-weight: 600; }
  .option:has(:focus-visible) { outline: 2px solid var(--focus-ring); outline-offset: -2px; }

  .enquiry textarea {
    min-block-size: 9rem;
    resize: vertical;
    field-sizing: content;
  }

  .enquiry :is(input:not([type="radio"]), textarea)[aria-invalid="true"],
  .enquiry :is(input:not([type="radio"]), textarea):user-invalid {
    border-color: var(--retake-red);
    box-shadow: inset 0 0 0 1px var(--retake-red);
  }

  .field-error {
    display: none;
    align-items: baseline;
    gap: 0.5em;
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--retake-red);
  }
  .field-error::before {
    content: "!" / "";
    display: inline-grid;
    place-items: center;
    flex: none;
    inline-size: 1.25em;
    block-size: 1.25em;
    border-radius: 50%;
    font-size: 0.8em;
    color: var(--paper);
    background: var(--retake-red);
  }
  :is(input:not([type="radio"]), textarea, .select-trigger)[aria-invalid="true"] ~ .field-error,
  :is(input:not([type="radio"]), textarea):user-invalid ~ .field-error {
    display: flex;
  }

  .form-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--sp-3);
  }
  .form-actions .btn {
    min-block-size: 48px;
    cursor: pointer;
  }
  .form-actions .btn:disabled {
    opacity: 0.6;
    cursor: progress;
  }
  .form-status {
    flex: 1 1 16rem;
    font-size: 0.9rem;
    font-weight: 600;
  }
  .form-status:empty { display: none; }
  .form-status[data-state="error"] { color: var(--retake-red); }
  .form-status a { border-bottom: 1px solid currentColor; }

  /* -------------------------------- Footer --------------------------------- */
  .site-footer {
    border-top: 1px solid rgba(16, 24, 32, 0.08);
    padding: var(--sp-6) 0;
  }
  .site-footer .container {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-3);
  }
  .footer-meta {
    font-family: var(--font-display);
    font-size: 0.8rem;
    color: var(--text-on-paper);
    letter-spacing: 0.02em;
  }
  .footer-links {
    display: flex;
    gap: var(--sp-4);
  }
  .footer-links a {
    font-family: var(--font-display);
    font-size: 0.8rem;
    font-weight: 600;
    color: var(--text-on-paper);
    padding-block: var(--sp-1);
    border-bottom: 1px solid transparent;
  }
  .footer-links a:hover { border-color: currentColor; }

  /* Simple page hero for interior pages (Studio / Contact) */
  .page-header {
    padding: var(--sp-10) 0 var(--sp-6);
    border-bottom: 1px solid rgba(16, 24, 32, 0.08);
  }
}

@layer motion {
  /* Cross-document view transitions: opt in on every page that shares this
     stylesheet so navigating between Home/Studio/Contact cross-fades
     instead of hard-cutting. Pure progressive enhancement — unsupported
     browsers just navigate normally. */
  @media (prefers-reduced-motion: no-preference) {
    @view-transition {
      navigation: auto;
    }
  }

  /* Scroll-triggered reveal for major section content. Decorative only,
     so per guidance no IntersectionObserver fallback is provided —
     browsers without scroll-driven animation support simply show the
     content in its final state with no animation. */
  @media (prefers-reduced-motion: no-preference) {
    @supports ((animation-timeline: view()) and (animation-range: entry)) {
      .reveal {
        animation: reveal-in linear both;
        animation-timeline: view();
        /* Capped at 240px of scroll: without the cap, a tall block (the
           enquiry form, the stacked stills on a phone) stays partly
           transparent for most of its height. */
        animation-range: entry 0% entry min(100%, 240px);
      }

      @keyframes reveal-in {
        from {
          opacity: 0;
          translate: 0 24px;
        }
      }
    }
  }

  /* Hero parallax. As the hero scrolls out, the video lags behind the page
     (it drifts down while the page moves up) and the logo lifts and
     fades faster, so the layers separate. The video is oversized upward only
     inside this block so the drift never exposes a gap at the top; without
     support (or with reduced motion) the hero is exactly as before.
     Transform-only (via individual `translate`) so it stays on the
     compositor; named timeline because the animated layers are children of
     the tracked hero, not the hero itself. */
  @media (prefers-reduced-motion: no-preference) {
    @supports ((animation-timeline: view()) and (animation-range: entry)) {
      /* The inset stops the timeline at the bottom of the sticky nav, so the
         fade starts the moment the hero begins to slide up, not after it
         has already vanished behind the nav bar. */
      .hero {
        view-timeline: --hero block;
        view-timeline-inset: var(--nav-height) 0px;
      }

      .hero-video {
        top: -20%;
        bottom: auto;
        height: 140%;
        animation: hero-video-drift linear both;
        animation-timeline: --hero;
        animation-range: exit;
      }

      .hero-content {
        animation: hero-content-lift linear both;
        animation-timeline: --hero;
        animation-range: exit 0% exit 75%;
      }

      .hero-scroll-cue {
        animation: hero-cue-fade linear both;
        animation-timeline: --hero;
        animation-range: exit 0% exit 25%;
      }

      /* Portrait: the hero is a 16:9 band, so the video is overscanned only
         a little (12%) to keep as much of the frame visible as possible. */
      @media (max-aspect-ratio: 1 / 1) {
        .hero-video {
          top: -6%;
          height: 112%;
          animation-name: hero-video-drift-compact;
        }
      }

      @keyframes hero-video-drift {
        to { translate: 0 14%; }
      }
      @keyframes hero-video-drift-compact {
        to { translate: 0 5%; }
      }
      @keyframes hero-content-lift {
        to { translate: 0 -30%; opacity: 0; }
      }
      @keyframes hero-cue-fade {
        to { opacity: 0; }
      }
    }
  }

  /* Key-art tiles: each still drifts inside its own frame as it crosses the
     viewport, at a different rate per tile size (--drift), so the mosaic
     feels layered. The image is overscanned (114% tall) only here so the
     drift (max 6% of the image) never exposes the tile background. */
  @media (prefers-reduced-motion: no-preference) {
    @supports ((animation-timeline: view()) and (animation-range: entry)) {
      .key-art-tile {
        --drift: 6%;
        view-timeline: --tile block;
      }
      .key-art-tile:nth-child(1) { --drift: 3%; }
      .key-art-tile:nth-child(2),
      .key-art-tile:nth-child(3) { --drift: 4.5%; }

      .key-art-tile img {
        top: -7%;
        bottom: auto;
        height: 114%;
        animation: tile-drift linear both;
        animation-timeline: --tile;
        animation-range: cover;
      }

      @keyframes tile-drift {
        from { translate: 0 calc(var(--drift) * -1); }
        to { translate: 0 var(--drift); }
      }
    }
  }
}

@layer utilities {
  /* Focus states — Ink on Paper contexts, Guide Blue where the surrounding
     surface is already Ink (see the accent-contrast rule at the top). */
  :where(a, button, input, textarea, select, [tabindex]):focus-visible {
    outline: 2px solid var(--focus-ring);
    outline-offset: 2px;
  }
  .hero, .section-alt, .contact-card {
    --focus-ring: var(--accent-on-ink);
  }

  /* Hides content visually but keeps it in the accessibility tree. */
  .visually-hidden:where(:not(:focus-within, :active)) {
    position: absolute !important;
    clip-path: inset(50%) !important;
    overflow: hidden !important;
    width: 1px !important;
    height: 1px !important;
    margin: -1px !important;
    padding: 0 !important;
    border: 0 !important;
    white-space: nowrap !important;
  }

  .skip-link:focus {
    position: fixed;
    top: var(--sp-2);
    left: var(--sp-2);
    z-index: 100;
    background: var(--ink);
    color: var(--paper);
    padding: var(--sp-2) var(--sp-3);
    border-radius: 2px;
    font-family: var(--font-display);
    font-weight: 600;
  }
}
