/* ============================================================================
   SABUKiD PROJECT — page styles.
   Grammar: rhythmic cutlist. Grounds are painted per section and land on a hard
   edge; there is no drift, because a cut is not an interpolation and several
   short acts are part-way through at once.
   Nothing here restyles .sc-* or [data-sc-*]. Those are the mechanism.
   ========================================================================== */

/* Self-hosted so the page never depends on a third party to render its own
   voice. Both faces are SIL Open Font License 1.1. Variable, so one file per
   family covers the whole weight range the page uses. */
@font-face {
  font-family: "Archivo";
  src: url("assets/fonts/archivo-latin.woff2") format("woff2");
  font-weight: 400 800;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "JetBrains Mono";
  src: url("assets/fonts/jetbrains-latin.woff2") format("woff2");
  font-weight: 400 500;
  font-style: normal;
  font-display: swap;
}

:root {
  --sc-canvas:     #08090b;
  --sc-surface:    #101114;
  --sc-ink:        #f2efe9;
  --sc-ink-soft:   #8f8a81;   /* warm-tinted, derived from the ink, never flat grey */
  --sc-accent:     #f0ae1e;   /* the flower */
  --sc-accent-ink: #0a0906;

  --sc-font-display: "Archivo", system-ui, sans-serif;
  --sc-font-text:    "Archivo", system-ui, sans-serif;
  --sc-font-mono:    "JetBrains Mono", ui-monospace, monospace;

  /* grounds, painted per section */
  --g-street: #08090b;
  --g-black:  #060607;
  --g-room:   #0b0a0c;
  --g-dawn:   #0d0f12;

  --bar-h: 3.25rem;

  /* published by sabukid.js */
  --night: 0;
  --grade: rgb(20, 32, 56);
  --grade-a: 0;
  --grain: 0.045;
  --ignite: 0;
  --residue: 0;
}

/* Light text on a dark ground needs compensating on three axes: a little more
   leading, a little more tracking, one step more weight. */
body { font-weight: 420; }
.sc-display { font-weight: 800; }

.sr-only {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap; border: 0;
}

/* ------------------------------------------------------------ atmosphere -- */

/* The night grade. Sits above the stages and below the copy, so it colours the
   footage without touching the legibility of anything set on top of it. */
.grade {
  position: fixed; inset: 0;
  z-index: 2;
  pointer-events: none;
  background: var(--grade);
  opacity: var(--grade-a);
  mix-blend-mode: soft-light;
}
.sc-grain { opacity: var(--grain); }

/* ---------------------------------------------------------------- chrome -- */
/* A cutlist wants a loud bar, not a minimal one: full width, high contrast,
   the CTA carrying the same weight as the wordmark. */

.bar {
  position: fixed; inset: 0 0 auto 0;
  z-index: var(--sc-z-chrome);
  height: var(--bar-h);
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: var(--sc-4);
  padding-inline: var(--sc-gutter);
  background: var(--sc-canvas);
  border-bottom: 1px solid var(--sc-hairline-strong);
}
/* NEVER text-transform the wordmark. The lowercase i in SABUKiD is part of the
   mark, and uppercasing it silently renders a brand that does not exist. */
.bar__mark {
  font-family: var(--sc-font-display);
  font-weight: 800;
  font-size: var(--sc-t-sm);
  letter-spacing: 0.04em;
  text-decoration: none;
  justify-self: start;
  white-space: nowrap;
}
.bar__mark b { color: var(--sc-accent); font-weight: inherit; }

/* The night clock. A readout, not a progress meter: no total, no fraction, no
   section index. It is the time inside the world the page is set in. */
.bar__clock {
  font-family: var(--sc-font-mono);
  font-variant-numeric: tabular-nums;
  font-size: var(--sc-t-sm);
  letter-spacing: 0.06em;
  color: var(--sc-ink);
  justify-self: center;
  display: inline-flex;
  align-items: center;
  gap: 0.55em;
}
.bar__clock::before {
  content: "";
  width: 0.42em; height: 0.42em;
  border-radius: 50%;
  background: var(--sc-accent);
  opacity: calc(0.25 + var(--night) * 0.75);
}
.bar__cta {
  justify-self: end;
  font-family: var(--sc-font-display);
  font-weight: 800;
  font-size: var(--sc-t-sm);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  text-decoration: none;
  white-space: nowrap;
  padding: 0.42em 0.9em;
  background: var(--sc-accent);
  color: var(--sc-accent-ink);
  transition: transform 140ms var(--sc-ease-out), filter 140ms var(--sc-ease-out);
}
@media (hover: hover) and (pointer: fine) {
  .bar__cta:hover { filter: brightness(1.12); }
}
.bar__cta:active { transform: translateY(1px); }

/* The filament: how far into the night you are, drawn as heat rather than as a
   percentage. Same single --night value that drives the clock and the grade. */
.filament {
  position: fixed; top: var(--bar-h); left: 0;
  z-index: var(--sc-z-chrome);
  height: 2px; width: 100%;
  transform-origin: 0 50%;
  transform: scaleX(var(--night));
  background: linear-gradient(90deg,
    color-mix(in oklab, var(--sc-accent) 30%, transparent),
    var(--sc-accent));
}

/* ------------------------------------------------------------------ peak -- */
/* The ignition runs in the chrome layer, not in an act. The grammar caps acts
   at ~1.4vh and bans pin, and the peak needs to outlive the act it starts in,
   so it is driven from page scroll and simply holds. */

/* The light comes OUT OF THE FLOWER. A flat fill would just be the screen
   turning yellow; the whole promise in the brief is that the flower in the mark
   becomes a light source, so the flood is a radial burst whose origin is the
   flower and whose radius is the ignition value. Below it the crowd is still
   there, being washed out, which is what makes the emptiness afterwards read as
   caused rather than as a gap. */
.peak {
  position: fixed; inset: 0;
  z-index: 40;
  pointer-events: none;
  display: grid;
  place-items: center;
  /* Opaque almost immediately, and STAYS opaque nearly to zero, so both the
     bloom and the collapse are carried by the RADIUS rather than by a fade.
     Fading the layer out would make the light dissolve; shrinking it makes the
     light retract into the flower it came from, which is what stops the moment
     reading as a final slate. */
  opacity: clamp(0, calc(var(--ignite) * 16), 1);
  background: radial-gradient(circle at 50% 46%,
    var(--sc-accent) 0%,
    var(--sc-accent) calc(var(--ignite) * 108%),
    color-mix(in oklab, var(--sc-accent) 55%, transparent) calc(var(--ignite) * 108% + 7%),
    transparent calc(var(--ignite) * 108% + 22%));
}

.peak__burst,
.peak__mark { grid-area: 1 / 1; }

/* Stage one: the flower alone, a small hot light in the middle of the room. */
.peak__burst {
  width: clamp(3rem, 9vw, 8rem);
  height: clamp(3rem, 9vw, 8rem);
  transform: scale(calc(0.4 + var(--ignite) * 3.6));
  opacity: clamp(0, calc(1 - (var(--ignite) - 0.30) * 3.2), 1);
  filter: drop-shadow(0 0 2.5rem color-mix(in oklab, var(--sc-accent) 70%, transparent));
}
/* Hot white rather than accent yellow. On the bloom it reads as the light
   source; on the collapse the field behind it is already yellow, so yellow
   petals vanish and leave a bare white dot with no flower in it. */
.peak__burst .petal { fill: #fff3d0; }
.peak__burst .eye { fill: #fff; }

/* Stage two: the field is yellow, and the mark stands in it. */
.peak__mark {
  font-family: var(--sc-font-display);
  font-weight: 800;
  color: var(--sc-accent-ink);
  font-size: clamp(2.2rem, 12vw, 10rem);
  line-height: 0.9;
  letter-spacing: -0.04em;
  text-align: center;
  margin: 0;
  transform: scale(calc(0.95 + var(--ignite) * 0.05));
  /* Arrives late and fast. A slow fade of near-black over yellow does not read
     as type appearing, it reads as the yellow going dirty. */
  opacity: clamp(0, calc((var(--ignite) - 0.80) * 6), 1);
}
.peak__mark span { display: block; }
/* The O of PROJECT is the flower, the same way it is on the bag. */
.peak__mark svg {
  display: inline-block;
  width: 0.78em; height: 0.78em;
  vertical-align: -0.09em;
  margin-inline: -0.02em;
}
.peak__mark .petal { fill: var(--sc-accent-ink); }
.peak__mark .eye { fill: var(--sc-accent); }

/* --------------------------------------------------------------- sections -- */

.sec { position: relative; background: var(--g-black); }
.sec--street { background: var(--g-street); }
.sec--room   { background: var(--g-room); }
.sec--dawn   { background: var(--g-dawn); }

.sec__inner {
  width: 100%; max-width: var(--sc-maxw);
  margin-inline: auto;
  padding-inline: var(--sc-gutter);
}

/* A full-bleed frame with copy on it. The picture goes edge to edge; the type
   never does. */
.frame { position: relative; overflow: clip; }
.frame > img { width: 100%; height: 100%; object-fit: cover; }
.frame__copy {
  position: absolute; z-index: var(--sc-z-copy);
  left: var(--sc-gutter); right: var(--sc-gutter);
  bottom: clamp(2rem, 7vh, 5rem);
  max-width: min(44rem, 82vw);
}

/* ------------------------------------------------------- 02 · the mark ---- */
.slab {
  min-height: 90vh;
  display: grid;
  align-content: center;
  padding-block: var(--sc-9);
}
.slab h2 {
  font-size: clamp(2.6rem, 8.4vw, 8rem);
  line-height: 0.92;
  letter-spacing: -0.045em;
  text-transform: uppercase;
  max-width: 16ch;
}
.slab p { margin-top: var(--sc-7); max-width: 48ch; color: var(--sc-ink-soft); }

/* ------------------------------------------------- 03 · who carries it ---- */
.faces {
  min-height: 110vh;
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  align-items: center;
  gap: clamp(1rem, 4vw, 4rem);
  padding-block: var(--sc-9);
}
.faces figure { margin: 0; }
.faces img { width: 100%; height: auto; }
/* Offset the pair so it reads as two frames pinned to a wall, not a grid. */
.faces figure:first-child { transform: translateY(-6%); }
.faces figure:last-child  { transform: translateY(9%); }
.faces__say {
  grid-column: 1 / -1;
  font-size: clamp(1.6rem, 4.4vw, 3.4rem);
  line-height: 1.02;
  letter-spacing: -0.035em;
  font-family: var(--sc-font-display);
  font-weight: 800;
  text-transform: uppercase;
  margin: 0;
  max-width: 20ch;
}

/* ----------------------------------------------------------- 04 · inside -- */
.inside { min-height: 95vh; }
.inside .frame { height: 95vh; }
.inside .frame__copy p {
  font-family: var(--sc-font-display);
  font-weight: 800;
  font-size: clamp(1.5rem, 4vw, 3rem);
  line-height: 1.04;
  letter-spacing: -0.03em;
  margin: 0;
  max-width: 22ch;
}

/* ----------------------------------------------------------- 05 · object -- */
.obj {
  min-height: 100vh;
  display: grid;
  align-content: center;
  gap: var(--sc-7);
  padding-block: var(--sc-8);
}
.obj__shot { width: 100%; }
/* Both dimensions overridden, never one: leaving height to resolve from the
   attribute renders a 16:9 file at its raw pixel height. Capped so the heading
   and the object are on screen together, instead of the act spending half its
   scroll showing a headline on an empty ground. */
.obj__shot img { width: 100%; height: 58vh; object-fit: cover; }
.obj h2 {
  font-size: clamp(2rem, 6vw, 5rem);
  line-height: 0.96;
  letter-spacing: -0.04em;
  text-transform: uppercase;
  max-width: 14ch;
}

/* ------------------------------------------------------------ 07 · after -- */
.after { min-height: 100vh; }
.after .frame { height: 100vh; }
.after .frame__copy h2 {
  font-size: clamp(1.8rem, 5.2vw, 4.2rem);
  line-height: 1;
  letter-spacing: -0.035em;
  text-transform: uppercase;
}

/* ------------------------------------------------------------- 09 · pair -- */
.pair {
  min-height: 100vh;
  display: grid;
  align-content: center;
  gap: var(--sc-6);
  padding-block: var(--sc-8);
}
.pair img { width: 100%; height: auto; }
.pair__names {
  display: flex; flex-wrap: wrap;
  gap: var(--sc-3) var(--sc-7);
  margin: 0; padding: 0;
  list-style: none;
  border-top: 1px solid var(--sc-hairline);
  padding-top: var(--sc-4);
}
.pair__names li {
  font-family: var(--sc-font-mono);
  font-size: var(--sc-t-sm);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--sc-ink-soft);
}

/* ------------------------------------------------------------- 10 · spec -- */
.spec {
  min-height: 100vh;
  display: grid;
  grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr);
  align-items: center;
  gap: clamp(2rem, 6vw, 6rem);
  padding-block: var(--sc-9);
}
.spec h2 {
  font-size: clamp(1.9rem, 5vw, 4rem);
  line-height: 0.98;
  letter-spacing: -0.04em;
  text-transform: uppercase;
  margin: 0;
}
.spec dl { margin: 0; }
/* Scoped to the definition rows. An unscoped `.spec div` also matched the
   wrapper, turning it into a two-column grid and squeezing the heading into the
   8.5rem label track, where it overflowed across the list. */
.spec dl > div {
  display: grid;
  grid-template-columns: 8.5rem minmax(0, 1fr);
  gap: var(--sc-4);
  padding-block: var(--sc-4);
  border-top: 1px solid var(--sc-hairline);
}
.spec dt {
  font-family: var(--sc-font-mono);
  font-size: var(--sc-t-xs);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--sc-ink-soft);
  padding-top: 0.2em;
}
.spec dd { margin: 0; }
.spec__note {
  margin-top: var(--sc-6);
  color: var(--sc-ink-soft);
  font-size: var(--sc-t-sm);
  max-width: 44ch;
}

/* ------------------------------------------------------------- 11 · walk -- */
.walk { min-height: 90vh; }
.walk .frame { height: 90vh; }
.walk .frame__copy h2 {
  font-size: clamp(1.7rem, 4.8vw, 3.8rem);
  line-height: 1.02;
  letter-spacing: -0.035em;
  text-transform: uppercase;
  max-width: 20ch;
}

/* ------------------------------------------------------------ 12 · close -- */
/* Abrupt, full bleed, the last cut. No spotlight, no magnet, no drift-down. */
.close { min-height: 100vh; position: relative; overflow: clip; }
.close__bg { position: absolute; inset: 0; }
.close__bg img { width: 100%; height: 100%; object-fit: cover; }
.close__inner {
  position: relative; z-index: var(--sc-z-copy);
  min-height: 100vh;
  display: grid;
  align-content: center;
  padding-block: calc(var(--bar-h) + var(--sc-8)) var(--sc-8);
}
.close h2 {
  font-size: clamp(2.4rem, 7.6vw, 7rem);
  line-height: 0.92;
  letter-spacing: -0.045em;
  text-transform: uppercase;
  margin: 0;
  max-width: 12ch;
}
.close p { margin-top: var(--sc-5); color: var(--sc-ink-soft); max-width: 42ch; }

.form {
  margin-top: var(--sc-7);
  display: flex; flex-wrap: wrap; gap: var(--sc-3);
  max-width: 34rem;
}
.form input[type="email"] {
  flex: 1 1 16rem;
  min-width: 0;
  padding: 0.85em 1em;
  background: color-mix(in oklab, var(--sc-ink) 8%, transparent);
  border: 1px solid var(--sc-hairline-strong);
  color: var(--sc-ink);
  font-size: var(--sc-t-base);
  transition: border-color 160ms var(--sc-ease-out),
              background-color 160ms var(--sc-ease-out);
}
.form input[type="email"]::placeholder { color: var(--sc-ink-soft); }
.form input[type="email"]:hover { border-color: color-mix(in oklab, var(--sc-ink) 34%, transparent); }
.form input[type="email"]:focus-visible { background: color-mix(in oklab, var(--sc-ink) 12%, transparent); }
.form button {
  flex: 0 0 auto;
  padding: 0.85em 1.4em;
  border: 0;
  background: var(--sc-accent);
  color: var(--sc-accent-ink);
  font-family: var(--sc-font-display);
  font-weight: 800;
  font-size: var(--sc-t-base);
  letter-spacing: 0.02em;
  text-transform: uppercase;
  white-space: nowrap;
  cursor: pointer;
  transition: transform 140ms var(--sc-ease-out), filter 140ms var(--sc-ease-out);
}
@media (hover: hover) and (pointer: fine) { .form button:hover { filter: brightness(1.12); } }
.form button:active { transform: translateY(1px); }
.form button:disabled { opacity: 0.5; cursor: not-allowed; }
.form__said {
  margin-top: var(--sc-4);
  font-family: var(--sc-font-mono);
  font-size: var(--sc-t-sm);
  color: var(--sc-accent);
}

.foot {
  margin-top: var(--sc-9);
  padding-top: var(--sc-5);
  border-top: 1px solid var(--sc-hairline);
  display: flex; flex-wrap: wrap;
  gap: var(--sc-3) var(--sc-6);
  align-items: baseline;
  font-family: var(--sc-font-mono);
  font-size: var(--sc-t-xs);
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--sc-ink-soft);
}
.foot .brandmark { text-transform: none; letter-spacing: 0.02em; }
.foot a { text-decoration-thickness: 1px; }
@media (hover: hover) and (pointer: fine) { .foot a:hover { color: var(--sc-ink); } }

/* --------------------------------------------------------------- mobile --- */
@media (max-width: 860px) {
  .faces { grid-template-columns: 1fr; min-height: auto; }
  .faces figure:first-child, .faces figure:last-child { transform: none; }
  .spec { grid-template-columns: 1fr; min-height: auto; padding-block: var(--sc-8); }
  .spec div { grid-template-columns: 1fr; gap: var(--sc-1); }
  /* .sc-copy--lead re-anchors and spans the full width below 860px, so a
     bottom-LEFT corner gradient darkens a corner the copy has just left. The
     engine ships this switch for .sc-scrim--trail and says in its own comment
     that BOTH corner anchors become full width here; --lead needs it too.
     Denser than the stock band because the portrait crop of the hero centres on
     the doorway, which is the brightest thing in the clip. Measured: the stock
     band left the headline at 2.04:1. */
  .sc-scrim--lead {
    background: linear-gradient(to top,
      color-mix(in oklab, var(--sc-canvas) 97%, transparent) 0%,
      color-mix(in oklab, var(--sc-canvas) 88%, transparent) 26%,
      color-mix(in oklab, var(--sc-canvas) 46%, transparent) 48%,
      transparent 66%);
  }

  .bar { grid-template-columns: auto 1fr auto; gap: var(--sc-2); }
  .bar__mark, .bar__clock, .bar__cta { font-size: var(--sc-t-xs); }
  .bar__cta { padding: 0.4em 0.7em; }
}
/* The hero display size steps down a rung on phones: --sc-t-4xl floors at
   3.4rem, which is a desktop floor and wraps a hero headline to six lines. */
@media (max-width: 700px) {
  .hero-h1 { font-size: var(--sc-t-2xl); }
  .slab h2 { font-size: clamp(2.1rem, 10vw, 3.4rem); }
}

/* ------------------------------------------------------- reduced motion --- */
@media (prefers-reduced-motion: reduce) {
  .faces figure:first-child, .faces figure:last-child { transform: none; }
  .peak__mark { transform: none; }
}
