/* ==========================================================================
   Derakhshan — cinematic poster archive
   Portrait sqrt(2) posters on landscape screens. Two layouts solve that:
   feature beats spend the leftover width on live type; contact sheets spend
   it on more posters. Neither ever crops a poster.
   ========================================================================== */

:root {
  --bg:        #0a0a0b;
  --bg-elev:   #131316;
  --fg:        #f2f0ed;
  --fg-dim:    #8e8e96;
  --hairline:  rgba(242, 240, 237, 0.14);

  /* Overridden per-act from the manifest. */
  --accent:    #c4703a;

  /* The brief's 0.6s–1.2s band. Nothing outside it without a reason. */
  --dur-1: 0.6s;
  --dur-2: 0.9s;
  --dur-3: 1.2s;
  --ease:  cubic-bezier(0.16, 1, 0.3, 1);

  --poster-ratio: 0.7071;   /* A-series portrait: 1 / sqrt(2) */
  --gutter: clamp(1.25rem, 4vw, 4rem);
  --measure: 34ch;

  --font: "Inter", "Segoe UI", system-ui, -apple-system, "Helvetica Neue", Arial, sans-serif;
}

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

/* figure defaults to `margin: 1em 40px` — left unreset it silently shaves 80px off
   every poster at every breakpoint. */
figure { margin: 0; }

html { scroll-behavior: smooth; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--fg);
  font-family: var(--font);
  font-size: clamp(1rem, 0.95rem + 0.2vw, 1.075rem);
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

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

/* --------------------------------------------------------------- type ---- */

.kicker {
  font-size: 0.75rem;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--accent);
  margin: 0 0 1.25rem;
}

.display {
  font-size: clamp(2.5rem, 7vw, 5.5rem);
  line-height: 0.98;
  letter-spacing: -0.03em;
  font-weight: 700;
  margin: 0;
  text-wrap: balance;
}

.lede {
  color: var(--fg-dim);
  max-width: var(--measure);
  text-wrap: pretty;
}

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 100;
  padding: 0.75rem 1.25rem;
  background: var(--fg);
  color: var(--bg);
}
.skip-link:focus { left: 0; }

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 4px;
}

/* --------------------------------------------------------------- chrome -- */

/* 80px tall, at the very top of the document. Once it scrolls out, JS knows the
   masthead is over content rather than over the hero. */
.top-sentinel {
  position: absolute;
  top: 0;
  left: 0;
  width: 1px;
  height: 80px;
  pointer-events: none;
}

.masthead {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 20;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 1.5rem var(--gutter);
  pointer-events: none;
  border-bottom: 1px solid transparent;
  transition:
    background-color   var(--dur-1) var(--ease),
    backdrop-filter    var(--dur-1) var(--ease),
    border-color       var(--dur-1) var(--ease),
    padding            var(--dur-1) var(--ease);
}

/* Over the hero the header floats on the dark page and needs nothing. Over posters
   it needs a scrim, or it competes with the artwork it sits on. The bar is only
   ~1440x70 (~0.1 MPx), so unlike the act backdrops this blur is cheap. */
.masthead.is-scrolled {
  background-color: rgba(10, 10, 11, 0.72);
  backdrop-filter: blur(14px) saturate(1.4);
  border-bottom-color: var(--hairline);
  padding-block: 1rem;
}
@supports not (backdrop-filter: blur(1px)) {
  .masthead.is-scrolled { background-color: rgba(10, 10, 11, 0.94); }
}

.masthead__mark {
  width: clamp(120px, 12vw, 170px);
  pointer-events: auto;
  display: block;
}
/* The SVG declares no fill, so it paints black. Force it white for the dark page. */
.masthead__mark img { width: 100%; filter: brightness(0) invert(1); }

.masthead__nav {
  display: flex;
  gap: 1.75rem;
  font-size: 0.75rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  pointer-events: auto;
}
.masthead__nav a { color: var(--fg); text-decoration: none; opacity: 0.65; transition: opacity var(--dur-1) var(--ease); }
.masthead__nav a:hover,
.masthead__nav a[aria-current="page"] { opacity: 1; }

@media (max-width: 899px) { .masthead__nav { gap: 1rem; font-size: 0.65rem; } }
@media (max-width: 599px) { .masthead__nav a:not([aria-current]) { display: none; } }

/* ----------------------------------------------------------------- hero -- */

.hero {
  min-height: 100svh;
  display: grid;
  place-items: center;
  text-align: center;
  padding: 6rem var(--gutter) 4rem;
  position: relative;
}

.hero__inner { max-width: 52rem; }

/* "Derakhshan Uniforms": the wordmark IS the logo, "Uniforms" is live text. */
.hero__title {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1.25rem;
  margin: 0 0 2rem;
  font-weight: 700;
}

.hero__wordmark {
  width: clamp(260px, 44vw, 580px);
  height: auto;
  filter: brightness(0) invert(1);   /* SVG paints black by default */
}

.hero__word {
  font-size: clamp(0.85rem, 1.6vw, 1.25rem);
  letter-spacing: 0.42em;
  text-transform: uppercase;
  text-indent: 0.42em;   /* letter-spacing trails the last glyph; re-centre it */
  color: var(--fg-dim);
  font-weight: 400;
}

/* ferewr.png is the spark on its own — the only asset that can animate
   independently. (D rakhs.png has the spark fused into the monogram.) */
.hero__spark {
  width: clamp(38px, 5vw, 64px);
  aspect-ratio: 1;
  background: url("../logo/ferewr.png") center / contain no-repeat;
  filter: brightness(0) invert(1) drop-shadow(0 0 14px rgba(255, 255, 255, 0.4));
  animation: spark 3.6s var(--ease) infinite;
}

@keyframes spark {
  0%, 100% { scale: 0.82; opacity: 0.5;  rotate: 0deg; }
  50%      { scale: 1;    opacity: 1;    rotate: 90deg; }
}

.hero__lede { margin-inline: auto; font-size: 1.15rem; }

.hero__cue {
  position: absolute;
  bottom: 2.5rem;
  left: 50%;
  translate: -50% 0;
  font-size: 0.7rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--fg-dim);
}
.hero__cue::after {
  content: "";
  display: block;
  width: 1px;
  height: 3rem;
  margin: 0.75rem auto 0;
  background: linear-gradient(var(--fg-dim), transparent);
  animation: cue 2.4s var(--ease) infinite;
  transform-origin: top;
}
@keyframes cue {
  0%, 100% { scale: 1 0.4; opacity: 0.3; }
  50%      { scale: 1 1;   opacity: 1; }
}

/* ------------------------------------------------------------------ act -- */

/* A 1x1 grid with the backdrop and the content stacked in the same cell. The cell
   is sized by the content, and the backdrop's sticky constraint rectangle is its
   grid area — i.e. this act exactly. That containment is the entire point: see the
   backdrop rule below. Padding lives on __content so the wash covers the full act. */
.act {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  isolation: isolate;
}

.act__content {
  grid-area: 1 / 1;
  min-width: 0;
  padding-block: clamp(5rem, 14vh, 10rem);
}

/* Blurred scale-up of the act's feature poster. Does three jobs: fills desktop
   dead space with an ambient wash, provides the slower parallax layer, and is
   only a ~1KB inline LQIP.

   Sticky and viewport-sized, NOT `inset: 0`. An act is ~3600px tall, so an
   absolutely-positioned backdrop asks the GPU to gaussian-blur ~5 MPx per act
   (21.8 MPx across four) and re-composite it every scroll frame. Sticky pins it to
   the viewport: 6.7 MPx total.

   It is a grid item sharing a cell with .act__content rather than being pulled out
   of flow with `margin-bottom: -130vh`. A negative bottom margin *expands* the
   sticky constraint rectangle by that amount, which let the last act's wash slide
   130vh past its act and bury the outro and footer. Sharing a grid cell removes the
   backdrop from layout without touching the constraint. */
.act__backdrop {
  grid-area: 1 / 1;
  align-self: start;
  position: sticky;
  top: -15vh;
  height: 130vh;          /* headroom so parallax never exposes an edge */
  z-index: -1;
  background-image: var(--lqip);
  background-size: cover;
  background-position: center;
  /* The source is a 32px LQIP upscaled ~45x — already smooth. A large radius here
     costs a great deal and shows almost nothing; 36px only kills residual banding. */
  filter: blur(36px) saturate(1.4) brightness(0.42);
  opacity: 0;
  transition: opacity var(--dur-3) var(--ease);
  will-change: transform;
}
.act.is-visible .act__backdrop { opacity: 1; }

.act__intro {
  padding-inline: var(--gutter);
  margin-bottom: clamp(3rem, 8vh, 6rem);
  max-width: 90rem;
  margin-inline: auto;
}
.act__intro .lede { margin-top: 1.5rem; }

/* -------------------------------------------------------------- feature -- */

/* Desktop: poster keeps its native ratio and takes ~36vw; the two-thirds of the
   viewport it cannot fill becomes the home for real, selectable HTML type. */
.feature {
  display: grid;
  gap: clamp(2rem, 5vw, 5rem);
  align-items: center;
  padding-inline: var(--gutter);
  max-width: 90rem;
  margin-inline: auto;
}

@media (min-width: 900px) {
  .feature { grid-template-columns: minmax(0, 36vw) minmax(0, 1fr); }
  .feature--flip { grid-template-columns: minmax(0, 1fr) minmax(0, 36vw); }
  .feature--flip .feature__poster { order: 2; }
}

.feature__copy p { color: var(--fg-dim); max-width: var(--measure); }

.feature__meta {
  margin-top: 2rem;
  padding-top: 1.5rem;
  border-top: 1px solid var(--hairline);
  font-size: 0.78rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--fg-dim);
}

/* ---------------------------------------------------------------- sheet -- */

/* Portrait posters tile across a landscape viewport with no wasted width —
   the same geometry that fights the feature beat works for the sheet. */
.sheet {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: clamp(0.75rem, 2vw, 1.75rem);
  padding-inline: var(--gutter);
  max-width: 90rem;
  margin: clamp(3rem, 8vh, 6rem) auto 0;
}
@media (min-width: 900px) { .sheet { grid-template-columns: repeat(3, 1fr); } }

/* --------------------------------------------------------------- poster -- */

.poster {
  position: relative;
  aspect-ratio: var(--poster-ratio);
  background-color: var(--bg-elev);
  background-image: var(--lqip);
  background-size: cover;
  overflow: hidden;
  border-radius: 2px;
}

.poster img {
  width: 100%;
  height: 100%;
  object-fit: contain;   /* never `cover` — these posters have baked-in type
                            that a crop would decapitate */
  opacity: 0;
  transition: opacity var(--dur-2) var(--ease);
}
.poster img.is-loaded { opacity: 1; }

.poster::after {   /* faint edge so light posters don't bleed into the dark page */
  content: "";
  position: absolute;
  inset: 0;
  box-shadow: inset 0 0 0 1px var(--hairline);
  pointer-events: none;
}

.sheet .poster { transition: scale var(--dur-3) var(--ease); }
@media (hover: hover) and (min-width: 900px) {
  .sheet .poster:hover { scale: 1.02; }
}

/* --------------------------------------------------------------- outro --- */

/* --------------------------------------------------------- about page ---- */

.page-head {
  position: relative;
  isolation: isolate;
  display: grid;
  align-items: end;
  min-height: 62svh;
  padding: 9rem var(--gutter) clamp(3rem, 8vh, 5rem);
  overflow: hidden;
}
.page-head__backdrop {
  position: absolute;
  inset: 0;
  z-index: -1;
  background-image: var(--lqip);
  background-size: cover;
  background-position: center;
  filter: blur(36px) saturate(1.4) brightness(0.34);
}
/* Fade the wash into the page rather than ending on a hard edge. */
.page-head__backdrop::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(to bottom, rgba(10, 10, 11, 0.5) 0%, var(--bg) 100%);
}
.page-head__inner { max-width: 90rem; margin-inline: auto; width: 100%; }
.page-head .lede { margin-top: 1.5rem; font-size: 1.15rem; }

.prose {
  display: grid;
  gap: clamp(2.5rem, 6vw, 5rem);
  max-width: 90rem;
  margin-inline: auto;
  padding: clamp(3rem, 10vh, 6rem) var(--gutter);
}
@media (min-width: 900px) {
  .prose { grid-template-columns: minmax(0, 1fr) minmax(0, 32vw); align-items: start; }
  .prose__aside { position: sticky; top: 7rem; }
}

.prose__block + .prose__block { margin-top: clamp(2rem, 5vh, 3.5rem); }
.prose__block h2 {
  font-size: clamp(1.35rem, 2.4vw, 1.9rem);
  letter-spacing: -0.02em;
  margin: 0 0 0.75rem;
}
.prose__block p { color: var(--fg-dim); margin: 0; max-width: 62ch; }

.stats { margin: 2rem 0 0; display: grid; gap: 1rem; }
.stat { border-top: 1px solid var(--hairline); padding-top: 0.85rem; }
.stat dt {
  font-size: 0.7rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--accent);
}
.stat dd { margin: 0.25rem 0 0; color: var(--fg-dim); font-size: 0.9rem; }

/* --------------------------------------------------------------- outro --- */

.outro {
  position: relative;
  z-index: 1;
  background: var(--bg);   /* the closing statement sits on clean page, never on a wash */
  min-height: 80svh;
  display: grid;
  place-items: center;
  text-align: center;
  padding: 6rem var(--gutter);
  border-top: 1px solid var(--hairline);
}
.outro__inner { max-width: 44rem; }
.outro .lede { margin-inline: auto; margin-bottom: 2.5rem; }

.button {
  display: inline-block;
  padding: 1rem 2.5rem;
  border: 1px solid var(--fg);
  color: var(--fg);
  text-decoration: none;
  font-size: 0.78rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  transition: background var(--dur-1) var(--ease), color var(--dur-1) var(--ease);
}
.button:hover { background: var(--fg); color: var(--bg); }

.colophon {
  padding: 2rem var(--gutter);
  text-align: center;
  color: var(--fg-dim);
  font-size: 0.78rem;
  border-top: 1px solid var(--hairline);
}

/* --------------------------------------------------------------- motion -- */

[data-reveal] {
  opacity: 0;
  translate: 0 2.5rem;
  transition:
    opacity   var(--dur-3) var(--ease),
    translate var(--dur-3) var(--ease);
  transition-delay: var(--reveal-delay, 0s);
}
[data-reveal].is-visible { opacity: 1; translate: 0 0; }

/* Ken Burns: whole-poster drift only. There is no intra-image depth to fake —
   the posters are flattened collages. */
.feature__poster .poster img { transition: opacity var(--dur-2) var(--ease), scale 8s linear; }
.feature.is-visible .poster img.is-loaded { scale: 1.03; }

/* The artifact-first approach degrades cleanly: posters were always meant to be
   seen whole and still. */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }

  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }

  [data-reveal] { opacity: 1; translate: 0 0; }
  .act__backdrop { opacity: 1; transform: none !important; }
  .feature.is-visible .poster img.is-loaded { scale: 1; }
  .poster img { opacity: 1; }
  .hero__cue::after { animation: none; scale: 1 1; opacity: 0.6; }
  /* Hold the spark at its bright pose rather than mid-fade. */
  .hero__spark { animation: none; scale: 1; opacity: 1; }
}
