/* ============================================================================
   LAYOUT — the room itself. Surface, containers, the celluloid grain, the
   letterbox frame, and the accessibility scaffolding.
   ============================================================================ */

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

body {
  background: var(--bg);
  color: var(--fg);
  overflow-x: clip;
  transition: background var(--d-3) var(--e-inout), color var(--d-3) var(--e-inout);
}

/* Lenis smooth-scroll wiring. */
html.lenis, html.lenis body { height: auto; }
.lenis.lenis-smooth { scroll-behavior: auto !important; }
.lenis.lenis-stopped { overflow: hidden; }

/* When any overlay owns the screen, freeze the page beneath it. */
body.is-locked { overflow: hidden; }

/* ── Container & the invisible grid ───────────────────────────────────────── */
.container {
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

/* ── Accessibility scaffolding ─────────────────────────────────────────────── */
.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.skip-link {
  position: fixed;
  top: var(--sp-3);
  left: var(--sp-3);
  z-index: var(--z-loader);
  padding: 0.75rem 1.25rem;
  background: var(--c-ink);
  color: var(--c-void);
  font-family: var(--f-mono);
  font-size: var(--fs-nano);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  transform: translateY(-150%);
  transition: transform var(--d-1) var(--e-out);
}
.skip-link:focus-visible { transform: translateY(0); }

/* ── The letterbox frame — a persistent 1.85:1 hint of the gate ──────────────── */
.frame { position: fixed; inset: 0; z-index: var(--z-frame); pointer-events: none; }
.frame__edge { position: absolute; background: var(--fg); opacity: 0.14; transition: background var(--d-3) var(--e-inout); }
.frame__edge--t, .frame__edge--b { left: var(--frame-inset); right: var(--frame-inset); height: 1px; }
.frame__edge--l, .frame__edge--r { top: var(--frame-inset); bottom: var(--frame-inset); width: 1px; }
.frame__edge--t { top: var(--frame-inset); }
.frame__edge--b { bottom: var(--frame-inset); }
.frame__edge--l { left: var(--frame-inset); }
.frame__edge--r { right: var(--frame-inset); }
/* The frame draws itself once, after the loader lifts. */
.frame__edge { transform: scale(0); transform-origin: center; }
.frame__edge--t, .frame__edge--b { transform: scaleX(0); }
.frame__edge--l, .frame__edge--r { transform: scaleY(0); }
body.is-ready .frame__edge--t, body.is-ready .frame__edge--b { transform: scaleX(1); transition: transform var(--d-4) var(--e-out) 0.1s; }
body.is-ready .frame__edge--l, body.is-ready .frame__edge--r { transform: scaleY(1); transition: transform var(--d-4) var(--e-out) 0.25s; }
@media (max-width: 40rem) { .frame { display: none; } } /* mobile keeps its edges free */

/* ── Celluloid grain — WebGL canvas, blended, barely there ───────────────────── */
.grain {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: var(--z-grain);
  pointer-events: none;
  mix-blend-mode: overlay;
  opacity: 0;
  transition: opacity var(--d-4) ease;
}
body.is-ready .grain { opacity: 0.3; }
/* Static SVG grain fallback if WebGL is unavailable. */
.grain--fallback {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.5'/%3E%3C/svg%3E");
  opacity: 0.06;
  mix-blend-mode: overlay;
}
@media (prefers-reduced-motion: reduce) {
  body.is-ready .grain { opacity: 0.18; }
}

/* Utility for pinned/animated section reveal targets. */
[data-reveal] { will-change: transform, opacity; }

/* Editable corner radius, applied to the media surfaces only. */
.work__media, .plate__img, .player, .lightbox__img,
.project-card__media, .project-view__cover, .project-view__still,
.project-view__film, .viewer__strip > span { border-radius: var(--radius); }

/* Section labels — shared across every section (numbered eyebrow + accent). */
.section-label {
  display: inline-flex; align-items: center; gap: 0.75rem;
  color: var(--c-ink-dim);
  margin-bottom: clamp(1.25rem, 3vh, 2rem);
}
.section-label span { color: var(--c-accent); }
.section-label--dark { color: var(--c-paper-dim); }
.section-label--dark span { color: var(--c-paper-ink); }

/* ── No-JS: a graceful, fully readable fallback ──────────────────────────────
   The inline head script flips .no-js → .js synchronously, so JS visitors
   never see these. If scripts are disabled entirely, the film simply becomes
   a well-set page: loader gone, everything present. */
html.no-js .loader { display: none; }
html.no-js .grain,
html.no-js .cursor { display: none; }
html.no-js .chrome { opacity: 1; transform: none; }
html.no-js .frame__edge--t, html.no-js .frame__edge--b { transform: scaleX(1); }
html.no-js .frame__edge--l, html.no-js .frame__edge--r { transform: scaleY(1); }
html.no-js .film__media { clip-path: none; }
html.no-js .plate { opacity: 1; transform: none; }
html.no-js .hero__scroll { opacity: 1; }

