/* ------------------------------------------------------- */
/* Iron Triangle — shared stylesheet                       */
/* ------------------------------------------------------- */

:root {
  --color-black: #0a0a0a;
  --color-white: #ffffff;
  --color-text-muted: #c9c9c9;
  --color-accent: #d8232a;
  --glow-color: 110, 168, 255;
  --font-heading: "Anton", sans-serif;
  --font-body: "Barlow Condensed", sans-serif;
}

* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

html {
  scroll-behavior: smooth;
}

body {
  font-family: var(--font-body);
  background: var(--color-black);
  color: var(--color-white);
  line-height: 1.5;
}

img {
  display: block;
  max-width: 100%;
}

a {
  color: inherit;
  text-decoration: none;
}

/* ------------------------------------------------------- */
/* Ambient cursor light                                     */
/* ------------------------------------------------------- */

/* A large, heavily blurred blob that drifts to the cursor position (set via
   translate3d in js/main.js) so it reads as a distant lamp in haze, not a
   spotlight. mix-blend-mode: screen means it can only lighten, never
   obscure, and pointer-events: none keeps it fully click-through. Hidden
   outright on touch devices and reduced motion, both here and in JS, so it
   never attaches a listener it isn't allowed to use. */
.cursor-glow {
  position: fixed;
  top: 0;
  left: 0;
  width: 900px;
  height: 900px;
  margin: -450px 0 0 -450px;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(var(--glow-color), 0.22) 0%, rgba(var(--glow-color), 0.08) 40%, rgba(var(--glow-color), 0) 70%);
  filter: blur(80px);
  transform: translate3d(-9999px, -9999px, 0);
  opacity: 0;
  transition: opacity 0.6s ease;
  mix-blend-mode: screen;
  pointer-events: none;
  z-index: 9999;
  will-change: transform;
}

.cursor-glow.is-visible {
  opacity: 1;
}

@media (hover: none), (pointer: coarse) {
  .cursor-glow {
    display: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  .cursor-glow {
    display: none;
  }

  /* No auto-drifting marquee for reduced motion: js/main.js skips the
     duplication and animation setup entirely, and this falls back to a
     plain, manually scrollable strip so the laurels stay reachable. */
  .laurels__viewport {
    overflow-x: auto;
  }

  .custom-cursor {
    display: none;
  }
}

/* ------------------------------------------------------- */
/* Custom cursor                                            */
/* ------------------------------------------------------- */

/* A small ring that trails the real pointer with a touch of lag (eased
   toward it every frame in js/main.js) and swells over anything clickable.
   js only adds is-active for actual links/buttons/tiles, so it never fires
   on plain text. Desktop only: js checks for a fine, hover-capable pointer
   before ever showing this or hiding the native cursor, and the media
   queries below are a belt-and-braces fallback for touch and reduced
   motion so nothing is left stuck invisible. */
.custom-cursor {
  position: fixed;
  top: 0;
  left: 0;
  width: 18px;
  height: 18px;
  margin: -9px 0 0 -9px;
  border-radius: 50%;
  border: 1px solid rgba(245, 245, 245, 0.55);
  background: rgba(245, 245, 245, 0.06);
  opacity: 0;
  transform: translate3d(-9999px, -9999px, 0);
  transition: width 0.25s ease, height 0.25s ease, margin 0.25s ease, border-color 0.25s ease, background 0.25s ease, opacity 0.4s ease;
  pointer-events: none;
  z-index: 10020;
  will-change: transform;
}

.custom-cursor.is-visible {
  opacity: 1;
}

.custom-cursor.is-active {
  width: 42px;
  height: 42px;
  margin: -21px 0 0 -21px;
  border-color: var(--color-accent);
  background: rgba(216, 35, 42, 0.08);
}

.has-custom-cursor,
.has-custom-cursor a,
.has-custom-cursor button {
  cursor: none;
}

@media (hover: none), (pointer: coarse) {
  .custom-cursor {
    display: none;
  }
}

/* ------------------------------------------------------- */
/* Scroll progress bar                                      */
/* ------------------------------------------------------- */

/* A hairline that fills left to right as the page scrolls, redrawn via a
   custom property js/main.js updates on scroll (rAF-throttled). transform:
   scaleX rather than animating width so the browser can composite it
   without a layout pass on every scroll tick. Sits above the header, which
   is itself position: absolute and only ever the height of its own content,
   so the bar never gets covered by it. */
.scroll-progress {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 2px;
  background: var(--color-accent);
  transform: scaleX(var(--scroll-progress, 0));
  transform-origin: left center;
  z-index: 10010;
  pointer-events: none;
}

/* ------------------------------------------------------- */
/* Site header                                              */
/* ------------------------------------------------------- */

/* Fixed rather than the old position: absolute, so the header (and its
   Get In Touch CTA) stay reachable the moment a visitor wants them,
   instead of scrolling away after the hero. Transparent by default so it
   still reads as floating over the hero exactly as before; .site-header
   --scrolled (toggled in js/main.js, rAF-throttled) fades in a blurred
   near-black bar with a hairline border once there's real page behind it,
   so the transition only ever happens against content, never against the
   hero image itself. */
.site-header {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  z-index: 30;
  background: rgba(10, 10, 10, 0);
  border-bottom: 1px solid rgba(255, 255, 255, 0);
  transition: background 0.4s ease, border-color 0.4s ease, box-shadow 0.4s ease;
}

.site-header--scrolled {
  background: rgba(10, 10, 10, 0.82);
  border-bottom-color: rgba(255, 255, 255, 0.08);
  box-shadow: 0 12px 30px rgba(0, 0, 0, 0.25);
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
}

.site-header__inner {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  column-gap: 2rem;
  max-width: 1400px;
  margin: 0 auto;
  padding: 1.65rem 3rem;
  transition: padding 0.4s ease;
}

.site-header--scrolled .site-header__inner {
  padding: 1rem 3rem;
}

.logo {
  display: inline-flex;
  align-items: center;
  color: var(--color-white);
  transition: color 0.25s ease;
}

.logo:hover {
  color: var(--color-accent);
}

.logo__text {
  font-family: var(--font-heading);
  font-size: 1.3rem;
  letter-spacing: 0.055em;
  text-transform: uppercase;
}

.main-nav {
  display: flex;
  justify-content: center;
  gap: 2.25rem;
}

.main-nav a {
  position: relative;
  display: inline-block;
  padding-bottom: 0.4rem;
  font-size: 0.92rem;
  font-weight: 500;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--color-white);
  transition: color 0.25s ease;
}

.main-nav a::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: 0;
  width: 100%;
  height: 1px;
  background: var(--color-accent);
  transform: scaleX(0);
  transform-origin: center;
  transition: transform 0.3s ease;
}

.main-nav a:hover {
  color: var(--color-accent);
}

.main-nav a:hover::after,
.main-nav a.is-active::after {
  transform: scaleX(1);
}

.main-nav a.is-active {
  color: var(--color-accent);
}

.site-header__actions {
  display: flex;
  align-items: center;
  gap: 1.5rem;
}

.header-cta {
  display: inline-block;
  padding: 0.55rem 1.35rem;
  font-size: 0.82rem;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-white);
  border: 1.5px solid rgba(255, 255, 255, 0.55);
  transition: background 0.25s ease, color 0.25s ease, border-color 0.25s ease;
}

.header-cta:hover {
  background: var(--color-accent);
  border-color: var(--color-accent);
  color: var(--color-white);
}

/* Two CTA instances share this look: one in .site-header__actions for
   desktop, one inside .main-nav for the mobile panel. Only one is ever
   displayed at a given width, swapped below at the hamburger breakpoint. */
.main-nav .header-cta {
  display: none;
}

.nav-toggle {
  display: none;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  gap: 5px;
  width: 44px;
  height: 44px;
  background: transparent;
  border: none;
  padding: 0;
  cursor: pointer;
  z-index: 20;
}

.nav-toggle span {
  display: block;
  width: 22px;
  height: 2px;
  background: var(--color-white);
  transition: transform 0.25s ease, opacity 0.25s ease;
}

.nav-toggle[aria-expanded="true"] span:nth-child(1) {
  transform: translateY(7px) rotate(45deg);
}

.nav-toggle[aria-expanded="true"] span:nth-child(2) {
  opacity: 0;
}

.nav-toggle[aria-expanded="true"] span:nth-child(3) {
  transform: translateY(-7px) rotate(-45deg);
}

/* Tablet: nav still fits as a row, just tighter, before the hamburger
   takes over at 860px. */
@media (max-width: 1100px) {
  .site-header__inner {
    column-gap: 1.25rem;
    padding: 1.5rem 2rem;
  }

  .main-nav {
    gap: 1.5rem;
  }
}

@media (max-width: 860px) {
  .site-header__inner {
    grid-template-columns: auto auto;
    padding: 1.3rem 1.75rem;
  }

  .site-header__actions > .header-cta {
    display: none;
  }

  .nav-toggle {
    display: flex;
  }

  .main-nav {
    position: fixed;
    inset: 0;
    flex-direction: column;
    align-items: flex-start;
    justify-content: center;
    gap: 2rem;
    padding: 2rem 2rem;
    background: var(--color-black);
    opacity: 0;
    visibility: hidden;
    transform: translateY(-8px);
    transition: opacity 0.25s ease, transform 0.25s ease, visibility 0s linear 0.25s;
    z-index: 15;
  }

  .main-nav.is-open {
    opacity: 1;
    visibility: visible;
    transform: translateY(0);
    transition: opacity 0.25s ease, transform 0.25s ease;
  }

  .main-nav a {
    font-size: 1.75rem;
    padding: 0.5rem 0;
    opacity: 0;
    transform: translateY(10px);
    transition: opacity 0.35s ease, transform 0.35s ease;
  }

  .main-nav.is-open a {
    opacity: 1;
    transform: translateY(0);
  }

  .main-nav.is-open a:nth-child(1) {
    transition-delay: 0.05s;
  }

  .main-nav.is-open a:nth-child(2) {
    transition-delay: 0.12s;
  }

  .main-nav.is-open a:nth-child(3) {
    transition-delay: 0.19s;
  }

  .main-nav .header-cta {
    display: inline-block;
    margin-top: 1rem;
  }

  body.nav-open {
    overflow: hidden;
  }
}

@media (prefers-reduced-motion: reduce) {
  .main-nav a,
  .main-nav.is-open a {
    transition: opacity 0.25s ease;
    transform: none;
  }
}

/* ------------------------------------------------------- */
/* Hero                                                     */
/* ------------------------------------------------------- */

.hero {
  position: relative;
  min-height: 85vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}

.hero__media {
  position: absolute;
  inset: 0;
  z-index: 0;
}

.hero__image {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  animation: hero-ken-burns 20s ease-in-out infinite alternate;
}

/* Ken Burns drift: 20s to creep from 1.0 to 1.08 (0.4% per second, barely
   perceptible moment to moment), then the same 20s in reverse via
   animation-direction: alternate, so it never "snaps" back. Scale only
   ever goes up from 1.0, and .hero/.hero__media both clip overflow, so
   there's never a gap at the edges to reveal. */
@keyframes hero-ken-burns {
  from {
    transform: scale(1);
  }
  to {
    transform: scale(1.08);
  }
}

@media (prefers-reduced-motion: reduce) {
  .hero__image {
    animation: none;
  }
}

/* Ghosted wordmark on the hero image itself, sized to always fit on one
   line within the viewport (vw-capped, unlike the far larger, deliberately
   overflowing version this replaced) so it never wraps or clips. Sits
   between the image and .hero__overlay in the DOM, so the same dark
   gradient that grounds the hero text dims it too, and .hero's own
   overflow: hidden is the safety net if it ever runs long. */
.hero__watermark {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-heading);
  font-size: clamp(2rem, 7.5vw, 8rem);
  letter-spacing: 0.03em;
  color: var(--color-white);
  opacity: 0.04;
  white-space: nowrap;
  text-align: center;
  pointer-events: none;
}

.hero__overlay {
  position: absolute;
  inset: 0;
  background:
    linear-gradient(180deg, rgba(10, 10, 10, 0.55) 0%, rgba(10, 10, 10, 0.75) 55%, rgba(10, 10, 10, 0.95) 88%, var(--color-black) 100%);
}

.hero__content {
  position: relative;
  z-index: 1;
  max-width: 900px;
  padding: 6rem 2rem 7rem;
  text-align: center;
}

.hero__eyebrow {
  font-size: 1.1rem;
  font-weight: 600;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: var(--color-accent);
  margin-bottom: 1rem;
}

.hero__title {
  font-family: var(--font-heading);
  font-size: clamp(2.75rem, 7vw, 6rem);
  line-height: 1.05;
  text-transform: uppercase;
  letter-spacing: 0.01em;
  margin-bottom: 1.5rem;
}

.hero__subtitle {
  font-size: 1.35rem;
  font-weight: 400;
  color: var(--color-text-muted);
  max-width: 640px;
  margin: 0 auto 2.5rem;
}

.hero__actions {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 1.25rem;
  flex-wrap: wrap;
}

/* Page load sequence: label, headline, paragraph, then buttons, each
   starting 150ms after the last so they read as one deliberate reveal
   rather than everything popping in at once. animation-fill-mode "both"
   keeps each element invisible until its own delay elapses, and holds the
   end state afterwards. Skipped outright under reduced motion below. */
@keyframes hero-fade-up {
  from {
    opacity: 0;
    transform: translateY(20px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.hero__eyebrow,
.hero__title,
.hero__subtitle,
.hero__actions {
  animation: hero-fade-up 0.6s ease-out both;
}

.hero__eyebrow {
  animation-delay: 0s;
}

.hero__title {
  animation-delay: 0.15s;
}

.hero__subtitle {
  animation-delay: 0.3s;
}

.hero__actions {
  animation-delay: 0.45s;
}

@media (prefers-reduced-motion: reduce) {
  .hero__eyebrow,
  .hero__title,
  .hero__subtitle,
  .hero__actions {
    animation: none;
  }
}

.btn {
  display: inline-block;
  padding: 0.9rem 2.2rem;
  font-size: 1.05rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  border: 2px solid transparent;
  transition: background 0.2s ease, color 0.2s ease, border-color 0.2s ease;
}

.btn--primary {
  background: var(--color-accent);
  color: var(--color-white);
  border-color: var(--color-accent);
}

.btn--primary:hover {
  background: transparent;
  color: var(--color-accent);
}

.btn--ghost {
  background: transparent;
  color: var(--color-white);
  border-color: var(--color-white);
}

.btn--ghost:hover {
  background: var(--color-white);
  color: var(--color-black);
}

.hero__scroll {
  position: absolute;
  bottom: 2.5rem;
  left: 50%;
  transform: translateX(-50%);
  z-index: 1;
  width: 26px;
  height: 42px;
  border: 2px solid var(--color-white);
  border-radius: 999px;
}

.hero__scroll span {
  position: absolute;
  top: 8px;
  left: 50%;
  width: 4px;
  height: 8px;
  background: var(--color-white);
  border-radius: 999px;
  transform: translateX(-50%);
  animation: scroll-dot 1.6s ease infinite;
}

@keyframes scroll-dot {
  0% { opacity: 1; top: 8px; }
  70% { opacity: 0; top: 22px; }
  100% { opacity: 0; top: 22px; }
}

/* Hero timecode: a continuously running HH:MM:SS:FF readout driven by
   js/main.js, styled to read as burnt-in editorial timecode on a rush
   rather than a UI element — plain monospace, no label, barely there. */
.hero__timecode {
  position: absolute;
  bottom: 1.75rem;
  left: 2rem;
  z-index: 1;
  font-family: "Courier New", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.85rem;
  letter-spacing: 0.15em;
  color: var(--color-white);
  opacity: 0.35;
  pointer-events: none;
  user-select: none;
}

/* ------------------------------------------------------- */
/* Section label (short rule + small caps heading)          */
/* ------------------------------------------------------- */

.section-label {
  display: flex;
  align-items: center;
  gap: 1rem;
  max-width: 1400px;
  margin: 0 auto clamp(2rem, 4vw, 3rem);
  padding: 0 3rem;
}

.section-label__rule {
  width: 48px;
  height: 2px;
  background: var(--color-accent);
  flex: 0 0 auto;
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 0.6s ease;
}

.section-label__text {
  font-family: var(--font-body);
  font-size: 1rem;
  font-weight: 700;
  letter-spacing: 0.35em;
  text-transform: uppercase;
  color: var(--color-white);
  opacity: 0;
  transition: opacity 0.4s ease;
}

/* Reveal state: js/main.js adds this to the label wrapper (whichever of
   the three variants it is) once it scrolls into view. The rule draws
   itself first; the text's transition-delay holds it back until the rule
   has finished, so the text visibly follows rather than arriving together. */
:is(.section-label, .project-detail__subhead, .project-detail__stills-heading).is-revealed .section-label__rule {
  transform: scaleX(1);
}

:is(.section-label, .project-detail__subhead, .project-detail__stills-heading).is-revealed .section-label__text {
  opacity: 1;
  transition-delay: 0.6s;
}

@media (prefers-reduced-motion: reduce) {
  .section-label__rule,
  .section-label__text {
    transform: none !important;
    opacity: 1 !important;
    transition: none !important;
  }
}

/* ------------------------------------------------------- */
/* Projects                                                  */
/* ------------------------------------------------------- */

.projects {
  padding: clamp(4rem, 8vw, 6rem) 0;
}

.projects__grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(1.5rem, 3vw, 2.5rem);
  max-width: 1400px;
  margin: 0 auto;
  padding: 0 3rem;
}

/* Tablet gets its own two-up layout rather than three columns squeezed
   into a width that was never designed for them (a 768px-wide viewport
   otherwise leaves each poster under 210px, noticeably tighter than
   either the mobile single column or the desktop three-up). Three columns
   resume once there's enough room for them not to feel cramped again. */
@media (max-width: 860px) and (min-width: 701px) {
  .projects__grid {
    grid-template-columns: repeat(2, 1fr);
    max-width: 640px;
  }
}

.project-tile {
  display: block;
}

.project-tile__frame {
  position: relative;
  aspect-ratio: 2 / 3;
  overflow: hidden;
  background: #0d0d0d;
}

/* Posters arrive in different ratios (portrait one sheets, landscape
   banners). Rather than cropping the odd one out, every frame gets a
   blurred, darkened copy of its own poster filling the corners, with the
   full uncropped poster centred on top. Portrait posters already fill
   the frame almost edge to edge so the backdrop barely shows; a landscape
   poster is never cut, it just letterboxes gracefully. */
.project-tile__backdrop {
  position: absolute;
  inset: -10%;
  width: 120%;
  height: 120%;
  object-fit: cover;
  object-position: center;
  filter: blur(35px) brightness(0.4) saturate(1.1);
  transform: scale(1.1);
}

.project-tile__img {
  position: relative;
  z-index: 1;
  width: 100%;
  height: 100%;
  object-fit: contain;
  object-position: center;
}

/* Same breathing pulse as .lightbox-trigger/.pulse-hover elsewhere on the
   site, so a poster tile reads as clickable the same way any other
   clickable poster does, rather than a bespoke effect of its own. */
.project-tile:hover .project-tile__img {
  animation: poster-pulse 1.1s ease-in-out infinite;
}

.project-tile__title {
  font-family: var(--font-heading);
  font-size: clamp(1.1rem, 1.6vw, 1.4rem);
  text-transform: uppercase;
  letter-spacing: 0.01em;
  margin-top: 1.25rem;
  margin-bottom: 0.4rem;
}

.project-tile__meta {
  font-size: 1.05rem;
  font-weight: 400;
  color: var(--color-text-muted);
  letter-spacing: 0.02em;
}

/* ------------------------------------------------------- */
/* Project detail (individual project pages)                */
/* ------------------------------------------------------- */

.project-detail {
  padding: clamp(8rem, 16vw, 10rem) 0 clamp(5rem, 10vw, 7rem);
}

.project-detail__container {
  max-width: 1400px;
  margin: 0 auto;
  padding: 0 3rem;
}

.project-detail__back {
  display: inline-block;
  font-size: 0.95rem;
  letter-spacing: 0.05em;
  color: var(--color-text-muted);
  margin-bottom: clamp(2rem, 4vw, 3rem);
  transition: color 0.2s ease;
}

.project-detail__back:hover {
  color: var(--color-white);
}

.project-detail__title {
  font-family: var(--font-heading);
  font-size: clamp(2.5rem, 6vw, 4.5rem);
  text-transform: uppercase;
  line-height: 1.05;
  margin-bottom: 0.75rem;
}

.project-detail__meta {
  font-size: 1.1rem;
  color: var(--color-text-muted);
  letter-spacing: 0.02em;
  margin-bottom: clamp(2.5rem, 5vw, 3.5rem);
}

.project-detail__poster {
  max-width: 380px;
  margin: 0 0 clamp(2.5rem, 5vw, 3.5rem);
}

.project-detail__poster img {
  width: 100%;
  height: auto;
  display: block;
}

/* Poster plus a companion image (e.g. the cast card) side by side. Wraps
   to stacked on narrow viewports since the pair together are wider than
   the poster's own column, and the row absorbs the bottom margin so the
   poster itself doesn't need one when paired like this. */
.project-detail__poster-row {
  display: flex;
  align-items: flex-start;
  flex-wrap: wrap;
  gap: 4rem;
  margin: 0 0 clamp(2.5rem, 5vw, 3.5rem);
}

.project-detail__poster-row .project-detail__poster {
  margin: 0;
}

.project-detail__cast {
  flex: 0 1 620px;
  max-width: 620px;
}

.project-detail__cast img {
  width: 100%;
  height: auto;
  display: block;
  /* -6.33% lifts the image so the red rule under "CAST" (sitting 64px
     into the 1011px-tall source image) lands level with the poster's
     top edge, matching the two visually. */
  transform: translateY(-6.33%);
  transition: transform 0.35s ease;
}

.project-detail__cast img:hover {
  transform: translateY(-6.33%) scale(1.06);
}

/* Any poster wired up to open the lightbox: a soft breathing pulse on
   hover signals it's clickable, more inviting than a flat cursor change. */
.lightbox-trigger {
  cursor: pointer;
}

.lightbox-trigger:hover {
  animation: poster-pulse 1.1s ease-in-out infinite;
}

/* Same hover pulse as .lightbox-trigger, minus the pointer cursor and any
   click behaviour — for images that should read as alive/interesting on
   hover without implying they open into anything. */
.pulse-hover:hover {
  animation: poster-pulse 1.1s ease-in-out infinite;
}

@keyframes poster-pulse {
  0%,
  100% {
    transform: scale(1);
  }
  50% {
    transform: scale(1.035);
  }
}

@media (prefers-reduced-motion: reduce) {
  .lightbox-trigger:hover,
  .pulse-hover:hover,
  .project-tile:hover .project-tile__img {
    animation: none;
  }

  .about-gallery .stills-grid__item:hover img {
    transform: none;
  }
}

.project-detail__tagline {
  font-style: italic;
  font-size: 1.4rem;
  color: var(--color-white);
  max-width: 640px;
  line-height: 1.4;
  margin-bottom: 1.5rem;
}

.project-detail__synopsis {
  font-size: 1.2rem;
  color: var(--color-text-muted);
  max-width: 640px;
  margin-bottom: 0.5rem;
}

/* General running body copy (as opposed to .project-detail__synopsis, which
   is sized for a single tight logline): normal paragraph rhythm, and any
   <strong> inside pops to white so it reads as deliberate emphasis rather
   than default browser bold. */
.project-detail__body {
  font-size: 1.2rem;
  color: var(--color-text-muted);
  max-width: 640px;
  margin-bottom: 1.5rem;
}

.project-detail__body strong {
  color: var(--color-white);
  font-weight: 700;
}

.project-detail__body a {
  color: var(--color-white);
  text-decoration: underline;
  text-underline-offset: 3px;
  transition: color 0.2s ease;
}

.project-detail__body a:hover {
  color: var(--color-accent);
}

.project-detail__body + .stills-grid,
.project-detail__body + .project-detail__subhead {
  margin-top: clamp(1rem, 3vw, 1.5rem);
}

.project-detail__emphasis {
  font-size: 1.6rem;
  font-weight: 700;
  color: var(--color-white);
  max-width: 640px;
  margin-bottom: clamp(2.5rem, 5vw, 3.5rem);
}

.project-detail__cta {
  font-size: 1.05rem;
  color: var(--color-text-muted);
  max-width: 640px;
}

.project-detail__cta em {
  font-style: italic;
  color: var(--color-white);
}

.project-detail__cta a {
  color: var(--color-white);
  text-decoration: underline;
  text-underline-offset: 3px;
  transition: color 0.2s ease;
}

.project-detail__cta a:hover {
  color: var(--color-accent);
}

.project-detail__stills-heading {
  display: flex;
  align-items: center;
  gap: 1rem;
  margin-top: clamp(3rem, 6vw, 4.5rem);
  margin-bottom: 1rem;
}

.project-detail__stills-note {
  font-size: 1rem;
  color: var(--color-text-muted);
  margin-bottom: clamp(2rem, 4vw, 3rem);
}

.stills-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(1rem, 2vw, 1.5rem);
}

/* Four photos read better as two even rows of two than three-plus-one. */
.about-gallery {
  grid-template-columns: repeat(2, 1fr);
}

.stills-grid__item {
  aspect-ratio: 16 / 9;
  overflow: hidden;
  background: #0d0d0d;
}

.stills-grid__item img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
}

.about-gallery .stills-grid__item img {
  transition: transform 0.4s ease;
}

.about-gallery .stills-grid__item:hover img {
  transform: scale(1.06);
}

/* Generic version of .project-detail__stills-heading, for pages with more
   than one subsection (trailer, stills, posters, awards, ...). */
.project-detail__subhead {
  display: flex;
  align-items: center;
  gap: 1rem;
  margin-top: clamp(3rem, 6vw, 4.5rem);
  margin-bottom: 1.5rem;
}

.project-detail__tagline--small {
  font-size: 1.1rem;
}

.video-embed {
  position: relative;
  aspect-ratio: 16 / 9;
  max-width: 900px;
  overflow: hidden;
  background: #0d0d0d;
}

.video-embed iframe {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
}

.project-detail__press-btn {
  display: inline-block;
}

/* Full artwork, uncropped, stacked large rather than squeezed into
   equal-height grid cells. */
.posters-list {
  display: flex;
  flex-direction: column;
  gap: clamp(1.5rem, 3vw, 2rem);
  max-width: 480px;
}

.posters-list__item {
  background: #0d0d0d;
}

.posters-list__item img {
  display: block;
  width: 100%;
  height: auto;
}

/* ------------------------------------------------------- */
/* Privacy policy                                           */
/* ------------------------------------------------------- */

/* Narrower than the usual 1400px .project-detail__container: a single
   reading column rather than a wide layout, since this page is nothing
   but headings and paragraphs. */
.privacy__container {
  max-width: 700px;
  margin: 0 auto;
  padding: 0 3rem;
}

.privacy__container .project-detail__body {
  max-width: none;
  line-height: 1.7;
}

/* ------------------------------------------------------- */
/* Contact                                                   */
/* ------------------------------------------------------- */

.about {
  border-top: 1px solid rgba(255, 255, 255, 0.12);
  padding: clamp(4rem, 8vw, 6rem) 0;
}

/* Two columns so the section fills the row instead of one narrow block of
   text with dead space beside it: copy on the left, a photo grid or pull
   quote on the right. Text loses its usual 640px cap here since the grid
   column itself is now what sets a sensible reading width. */
.about__grid {
  display: grid;
  grid-template-columns: 3fr 2fr;
  gap: clamp(2.5rem, 5vw, 5rem);
  align-items: start;
}

/* At tablet widths the 3fr/2fr split leaves the photo column too narrow
   to be worth it (each about-gallery photo drops under 120px), so this
   stacks to a single column a bit earlier than the general mobile
   breakpoint below — full-width copy, then a properly sized photo grid
   underneath, rather than two columns neither of which has room to work. */
@media (max-width: 900px) and (min-width: 701px) {
  .about__grid {
    grid-template-columns: 1fr;
    gap: 2.5rem;
  }
}

.about__grid + .project-detail__subhead {
  margin-top: clamp(3rem, 6vw, 4.5rem);
}

.about__col .project-detail__tagline,
.about__col .project-detail__body {
  max-width: none;
}

.about__col .about-gallery {
  margin: 0;
}

.about__col:last-child .project-detail__body:last-of-type,
.about__col .btn {
  margin-bottom: 0;
}

.about__pull-quote {
  font-family: var(--font-heading);
  font-size: clamp(1.8rem, 3vw, 2.5rem);
  line-height: 1.2;
  text-transform: uppercase;
  color: var(--color-white);
  border-left: 3px solid var(--color-accent);
  padding-left: 1.5rem;
}

.contact {
  border-top: 1px solid rgba(255, 255, 255, 0.12);
  padding: clamp(4rem, 8vw, 6rem) 0;
}

.contact__container {
  max-width: 1400px;
  margin: 0 auto;
  padding: 0 3rem;
}

.contact-form {
  display: flex;
  flex-direction: column;
  gap: 2.25rem;
  max-width: 640px;
  margin-top: clamp(1rem, 3vw, 1.5rem);
}

/* .contact-form's own display: flex above outranks the browser default
   [hidden] { display: none } (an author rule always beats a user-agent
   one), so without this the form would stay visually laid out — just
   emptied of interaction — once js/main.js hides it on a successful
   submit. This restores the expected behaviour explicitly. */
.contact-form[hidden] {
  display: none;
}

.form-field {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}

.form-field label {
  font-family: var(--font-body);
  font-size: 0.85rem;
  font-weight: 700;
  letter-spacing: 0.25em;
  text-transform: uppercase;
  color: var(--color-white);
}

.form-field input,
.form-field textarea {
  font-family: var(--font-body);
  font-size: 1.15rem;
  color: var(--color-white);
  background: transparent;
  border: none;
  border-bottom: 1px solid rgba(255, 255, 255, 0.3);
  border-radius: 0;
  padding: 0.75rem 0;
  transition: border-color 0.2s ease;
}

.form-field textarea {
  resize: vertical;
  min-height: 6rem;
}

.form-field input::placeholder,
.form-field textarea::placeholder {
  color: rgba(255, 255, 255, 0.35);
}

.form-field input:focus,
.form-field textarea:focus {
  outline: none;
  border-bottom-color: var(--color-accent);
}

.contact-form__submit {
  align-self: flex-start;
  margin-top: 0.5rem;
}

.contact-form__submit:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}

.contact-form__error {
  font-size: 0.95rem;
  color: var(--color-accent);
}

.contact-form__error a {
  color: inherit;
  text-decoration: underline;
  text-underline-offset: 3px;
}

/* Swapped in for the form on a successful submit (js/main.js hides the
   form and reveals this rather than navigating away), so the visitor
   never leaves the page to confirm their message sent. */
.contact-form__success {
  max-width: 640px;
  margin-top: clamp(1rem, 3vw, 1.5rem);
}

.contact-form__success-title {
  font-family: var(--font-heading);
  font-size: 1.8rem;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  margin-bottom: 0.5rem;
}

.contact-form__success-body {
  font-size: 1.2rem;
  color: var(--color-text-muted);
}

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

.laurels {
  border-top: 1px solid rgba(255, 255, 255, 0.12);
  padding: clamp(3rem, 6vw, 5rem) 0;
}

/* The viewport masks the track; no scrollbar, no manual scrolling — the
   track itself drifts sideways on its own via the .is-marquee animation,
   which js/main.js starts once it has duplicated the laurel set. */
.laurels__viewport {
  overflow: hidden;
  max-width: 1400px;
  margin: 0 auto;
  padding: 0 3rem;
  -webkit-mask-image: linear-gradient(to right, transparent 0%, black 10%, black 90%, transparent 100%);
  mask-image: linear-gradient(to right, transparent 0%, black 10%, black 90%, transparent 100%);
}

.laurels__track {
  display: flex;
  align-items: center;
  flex-wrap: nowrap;
  gap: clamp(2.5rem, 6vw, 5rem);
  width: max-content;
}

/* Duration is set by js/main.js from the measured width of one set of
   laurels, so the drift speed stays constant no matter how many are added.
   Keyframes travel exactly half the (now doubled) track, landing back on
   the same visual frame the duplicate set started on, for a seamless loop. */
.laurels__track.is-marquee {
  animation-name: laurels-marquee;
  animation-timing-function: linear;
  animation-iteration-count: infinite;
}

/* Hover-to-pause is a mouse-only affordance: on touch, tapping triggers a
   :hover state that never clears (no mouseleave equivalent), which is what
   made the marquee look like it just froze. Scoping this to true
   hover-capable, fine-pointer devices keeps desktop exactly as it was;
   touch gets its own tap-to-pause-then-resume handled in js/main.js via
   .is-touch-paused instead. */
@media (hover: hover) and (pointer: fine) {
  .laurels__track.is-marquee:hover {
    animation-play-state: paused;
  }
}

.laurels__track.is-marquee.is-touch-paused {
  animation-play-state: paused;
}

@keyframes laurels-marquee {
  from {
    transform: translateX(0);
  }
  to {
    transform: translateX(-50%);
  }
}

/* While there is only one laurel, flank it with rule lines so the strip
   reads as a deliberate feature rather than one item stranded in space.
   The lines are added by js/main.js and vanish automatically as soon as
   a second .laurel-item is present. */
.laurels__track--single {
  justify-content: center;
}

.laurels__track--single::before,
.laurels__track--single::after {
  content: "";
  flex: 1 1 auto;
  height: 1px;
  min-width: 2rem;
  background: rgba(255, 255, 255, 0.18);
}

.laurel-item {
  flex: 0 0 auto;
}

/* Each badge sits in a fixed-height box with its own hand-measured
   aspect-ratio (set inline in the HTML). Several source files have a lot
   of empty padding baked in, so sizing the <img> itself would leave those
   badges looking tiny next to tightly-cropped ones; instead the <img> is
   absolutely positioned and oversized/offset (also set inline, per badge)
   to fill the box with just its actual artwork, and the box clips the rest. */
.laurel-crop {
  position: relative;
  display: block;
  height: clamp(90px, 9vw, 130px);
  overflow: hidden;
}

.laurel-item__img {
  position: absolute;
  max-width: none;
  filter: brightness(0) invert(1);
  opacity: 0.88;
}

/* The three photographic entries (two certificates and an illustrated
   graphic) would turn into a high-contrast mess under the white silhouette
   filter the line-art laurels use, so they keep their own colour instead. */
.laurel-item__img--photo {
  filter: none;
  opacity: 1;
}

/* ------------------------------------------------------- */
/* Footer                                                    */
/* ------------------------------------------------------- */

.site-footer {
  border-top: 1px solid rgba(255, 255, 255, 0.12);
  padding: clamp(3.5rem, 7vw, 5.5rem) 3rem 2rem;
}

.site-footer__grid {
  display: grid;
  grid-template-columns: 1.4fr 1fr 1fr;
  gap: clamp(2.5rem, 6vw, 4rem);
  max-width: 1400px;
  margin: 0 auto;
}

.footer-logo-link {
  display: inline-block;
  vertical-align: top;
  margin-bottom: 24px;
}

.footer-logo {
  display: block;
  width: 180px;
  height: auto;
}

.footer-tagline {
  color: var(--color-text-muted);
  font-size: 1.05rem;
  max-width: 320px;
}

.footer-col__heading {
  font-family: var(--font-body);
  font-size: 0.95rem;
  font-weight: 700;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  margin-bottom: 1.5rem;
}

.footer-links {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 0.85rem;
}

.footer-links a {
  font-size: 1.05rem;
  color: var(--color-text-muted);
  transition: color 0.2s ease;
}

.footer-links a:hover {
  color: var(--color-white);
}

.footer-email {
  display: inline-block;
  font-size: 1.1rem;
  color: var(--color-white);
  margin-bottom: 1.75rem;
  transition: color 0.2s ease;
}

.footer-email:hover {
  color: var(--color-accent);
}

.footer-socials {
  display: flex;
  align-items: center;
  gap: 0.9rem;
}

.footer-social {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border: 1px solid rgba(255, 255, 255, 0.25);
  border-radius: 999px;
  color: var(--color-white);
  transition: background 0.2s ease, border-color 0.2s ease, color 0.2s ease;
}

.footer-social svg {
  width: 18px;
  height: 18px;
}

.footer-social:hover {
  background: var(--color-accent);
  border-color: var(--color-accent);
  color: var(--color-white);
}

.site-footer__bottom {
  max-width: 1400px;
  margin: clamp(3rem, 6vw, 4rem) auto 0;
  padding-top: 1.5rem;
  border-top: 1px solid rgba(255, 255, 255, 0.08);
}

.site-footer__bottom p {
  font-size: 0.9rem;
  color: rgba(255, 255, 255, 0.4);
}

/* ------------------------------------------------------- */
/* Small screens                                            */
/* ------------------------------------------------------- */

@media (max-width: 700px) {
  .hero__content {
    padding: 5.5rem 1.5rem 6.5rem;
  }

  .hero__subtitle {
    font-size: 1.15rem;
  }

  .section-label,
  .projects__grid,
  .contact__container,
  .project-detail__container,
  .privacy__container {
    padding: 0 1.5rem;
  }

  /* .laurels__viewport already carries the outer inset (reduced here to
     match every other section's mobile padding); .laurels__track only
     needs its own bottom gutter for the scroll shadow, not a second,
     stacking left/right inset on top of the viewport's. */
  .laurels__viewport {
    padding: 0 1.5rem;
  }

  .laurels__track {
    padding-bottom: 1rem;
  }

  .projects__grid {
    grid-template-columns: 1fr;
    gap: 3rem;
    max-width: 420px;
  }

  .stills-grid {
    grid-template-columns: 1fr;
  }

  .about__grid {
    grid-template-columns: 1fr;
    gap: 2.5rem;
  }

  .site-footer {
    padding: 3rem 1.5rem 2rem;
  }

  .site-footer__grid {
    grid-template-columns: 1fr;
    gap: 2.75rem;
  }

  .footer-logo {
    width: 140px;
  }
}

/* ------------------------------------------------------- */
/* Lightbox                                                  */
/* ------------------------------------------------------- */

.lightbox {
  position: fixed;
  inset: 0;
  z-index: 10000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: clamp(2rem, 6vw, 4rem);
  background: rgba(5, 5, 5, 0.94);
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.25s ease, visibility 0s linear 0.25s;
}

.lightbox.is-open {
  opacity: 1;
  visibility: visible;
  transition: opacity 0.25s ease;
}

.lightbox__img {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
  box-shadow: 0 30px 80px rgba(0, 0, 0, 0.6);
}

.lightbox__close {
  position: absolute;
  top: clamp(1rem, 3vw, 1.5rem);
  right: clamp(1rem, 3vw, 1.5rem);
  width: 44px;
  height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid rgba(255, 255, 255, 0.3);
  border-radius: 999px;
  background: transparent;
  color: var(--color-white);
  font-size: 1.75rem;
  line-height: 1;
  cursor: pointer;
  transition: background 0.2s ease, border-color 0.2s ease;
}

.lightbox__close:hover {
  background: var(--color-accent);
  border-color: var(--color-accent);
}

body.lightbox-open {
  overflow: hidden;
}
