/* ═══════════════════════════════════════════════════════════════════════════
   The landing screen's back layers, and the stages that stand in front.

   In this file: the vignette that closes the frame, the mark's
   place in the stack, and the stages. On compositing: everything here is laid
   over the page with plain source-over. `mix-blend-mode: plus-lighter` is
   deliberately NOT used: the wave is already additive inside its own canvas
   (`gl.blendFunc(ONE, ONE)`, see scripts/lib/renderer.js) and that canvas is
   genuinely transparent between its points, so source-over lays the result over
   the page exactly as drawn. plus-lighter would re-blend an already-additive
   image against an un-isolated backdrop, which is a second set of rules to
   reason about for no visible gain.
   ═════════════════════════════════════════════════════════════════════════ */

/* A soft darkening at the edges of the frame. The formations are widest at
   their dust shell, and without this the cloud ends at the window rather than
   receding past it. */
.landing-vignette {
  position: fixed;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background:
    radial-gradient(ellipse 128% 96% at 50% 46%,
      transparent 56%, rgba(2, 6, 11, 0.26) 82%, rgba(2, 6, 11, 0.64) 100%);
}

/* ── the mark ─────────────────────────────────────────────────────────────
   The studio's own mark, standing at the back of the landing screen,
   discovered by light and served from this origin.

   Layering: it carries the wave canvas's z-index and comes before it in the
   document, so paint order (not a magic number) puts it behind the water.
   Nothing here may raise it above. One thing stands behind it: the
   atmosphere (`.hero-atmos`, styles/depth.css), the fog the mark is seen
   through, which is the first positioned element in the document.

   Placement: 64% across, in the pocket on the right while the copy keeps the
   left. Centred was tried and is a trap: the hero's scrim is a left-hand
   wash, so half of it arrives at 8% brightness.

   The reveal itself: rest opacity, the cold pool and the travelling window,
   is in styles/hero.css beside the rest of the hero's furniture. What lives
   here is only where it sits in the stack. */
.hero-mark {
  position: fixed;
  left: 64%;
  top: 50%;
  z-index: 0;
  width: min(54vw, 720px);
  aspect-ratio: 1 / 1;
  pointer-events: none;
  opacity: 0;
  /* Two transforms, and they are different kinds of thing. The first is the
     boot choreography: the mark rises 26px into place once. The second is
     its LEAVING: `--exit`, written by scripts/scene/journey.js as the
     landing screen gives way to the formations, rises it a little and steps
     it back, as it dims (below). Identity until the reader leaves the hero,
     so the resting mark is exactly the resting mark; on THIS rule as well as
     the lit one so that the moment the landing screen releases the mark, it fades
     where it is instead of snapping back. */
  transform: translate(-50%, calc(-50% + 26px))
             translate(0, calc(var(--exit, 0) * -10svh))
             scale(calc(1 - var(--exit, 0) * 0.12));
  transition: opacity 900ms var(--ease-soft) 260ms,
              transform 1100ms var(--ease-out) 260ms;
}

/* It belongs to the landing screen: `at-hero` is set on the root by main.js
   while the landing screen is in view, so it comes up when the reader is in
   the hero: and it stays the journey's while the formations
   arrive: `html.journey` is set by scripts/scene/journey.js while their
   section is on its way up or on screen, and it is what lets the V leave on
   the scroll rather than on a clock. */
html.at-hero .hero-mark,
html.journey .hero-mark {
  opacity: 1;
  transform: translate(-50%, -50%)
             translate(0, calc(var(--exit, 0) * -10svh))
             scale(calc(1 - var(--exit, 0) * 0.12));
}

/* As the landing screen gives way the V leaves on the same number that
   moves it: and nothing about it is transitioned: every value is rewritten
   on the frame it changes, and a transition on a value that changes every
   frame is a layer lagging the page. */
html.journey .hero-mark {
  opacity: calc(1 - var(--exit, 0));
  transition: none;
}

/* ── the hero yields ───────────────────────────────────────────────────────
   As the reader scrolls, the opening copy is already moving up and out with
   the page. `--yield`, written on the section by scripts/scene/journey.js
   as the formations arrive, takes its WEIGHT away before its
   position has gone: less light, a short drift ahead of the scroll, and a
   softness that says the eye has moved on to the next plane. The controls
   and the small labels go with it. Restrained on purpose: it is one number
   on one block, and at rest it is the identity. */
.section--hero .hero__inner .chapter-copy {
  opacity: calc(1 - var(--yield, 0));
  /* The copy is the nearest plane in the frame, and the camera is moving
     forward: what is nearest leaves fastest and grows a little as it passes
     the lens. Six per cent, from its own left edge, so it leans out of the
     frame rather than swelling in it. */
  transform: translate3d(0, calc(var(--yield, 0) * -28px), 0)
             scale(calc(1 + var(--yield, 0) * 0.06));
  transform-origin: 0% 50%;
  filter: blur(calc(var(--yield, 0) * 3px));
}
.section--hero .chapter-scroll { opacity: calc(1 - var(--yield, 0)); }

/* Forced colours asks for a page made of system colours; a lit mark
   discovered by a pointer, under a vignette, is the opposite of that. */
@media (forced-colors: active) {
  .landing-vignette,
  .hero-mark { display: none; }
}

/* ── the landing stage ────────────────────────────────────────────────────
   A screen with its copy held to one side. The mark and the water are behind
   it and the copy is over it, so the only thing the stage draws is the
   gradient that keeps type legible against them. */

.chapter-stage {
  position: relative;
  z-index: 2;
  min-height: 100svh;
  display: flex;
  align-items: center;
}

.chapter-stage .section__pin {
  position: relative;
  width: 100%;
  min-height: 100svh;
  display: flex;
  align-items: center;
}

/* The scrim is a one-sided wash, not a full-frame dimmer: the cloud stays
   fully visible on the empty side of the layout, which is the side the
   composition is actually on. */
.chapter-scrim {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: -1;
}

/* The hero's copy sits left, so its wash is a left one. A centred pool was
   tried and is a trap: it lands squarely on the composition and darkens the
   one part of the frame the reader is meant to be looking at. */
.section--hero .chapter-scrim {
  background: linear-gradient(100deg,
    rgba(2, 6, 11, 0.92) 0%, rgba(2, 6, 11, 0.74) 22%,
    rgba(2, 6, 11, 0.22) 46%, transparent 66%);
}

/* `.section__inner` is `position:absolute; inset:0` (experience.css); the
   hero's copy is the only thing in the frame, so the inner does the
   centring. */
.hero__inner {
  display: flex;
  align-items: center;
  padding: 0 var(--gutter);
}

.hero__inner .chapter-copy {
  position: relative;
  width: min(52ch, 56vw);
  max-width: 44ch;
}

/* ── the wordmark ─────────────────────────────────────────────────────────
   The studio's name, crowning the landing screen. It is set on `.display`
   (foundation.css) like every other piece of display type on the page, in the
   `--cyan` variant, and everything below is composition rather than colour.

   Tracking: this is the one place Bebas is set OPEN. Section headings on this
   site are tracked tight and synthetically condensed, because they are reading
   matter set at a distance; a logotype is not read as a word at all, it is read
   as a shape, and the letters need air between them to hold one. There is no
   compensating text-indent here, unlike `.whisper` in experience.css: letter
   spacing is trailing space, so it only ever moves a CENTRED line off centre.
   This one is ranged left, and an indent would push it off the gutter that the
   kicker above it and the headline below it both start on.

   The halo is what makes the face read as cyan-lit rather than merely cool. It
   is L2, not L3: structural light, wide and low, the kind you notice only when
   it is taken away. The second shadow is not decoration, the wordmark is
   painted through `background-clip: text`, so it has no fill of its own to sit
   on, and against a bright band of the cloud its top edge would otherwise
   disappear. */
.hero-wordmark {
  font-size: clamp(3rem, 6.4vw, 6.4rem);
  line-height: 0.88;
  letter-spacing: 0.085em;
  margin: 0 0 0.16em;
  filter: drop-shadow(0 0 34px var(--cyan-l2))
          drop-shadow(0 2px 3px rgba(0, 0, 0, 0.72));
}

.chapter-body {
  font-size: clamp(0.95rem, 1.15vw, 1.06rem);
  line-height: 1.62;
  color: var(--text-2);
  margin: 0 0 1.5em;
  max-width: 46ch;
}

.chapter-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1.1rem 1.6rem;
}

/* ── the hero's furniture ─────────────────────────────────────────────── */

.chapter-scroll {
  position: absolute;
  right: var(--gutter);
  bottom: 3.6rem;
  display: inline-flex;
  align-items: center;
  gap: 0.7rem;
  font-family: var(--font-mono, 'JetBrains Mono', monospace);
  font-size: 0.72rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--text-2);
  text-decoration: none;
  transition: color 240ms ease;
}

.chapter-scroll:hover,
.chapter-scroll:focus-visible { color: var(--cyan-2, #22e6ff); }

.chapter-scroll i {
  width: 1px;
  height: 34px;
  background: linear-gradient(to bottom, var(--cyan-2, #22e6ff), transparent);
  animation: chapter-scroll-pulse 2.4s ease-in-out infinite;
}

@keyframes chapter-scroll-pulse {
  0%, 100% { opacity: 0.30; transform: scaleY(0.7); transform-origin: top; }
  50%      { opacity: 0.95; transform: scaleY(1);   transform-origin: top; }
}

/* ── narrow and short windows ─────────────────────────────────────────────
   This condition is copied exactly from experience.css, where the same query
   turns `.section__inner` from an absolute overlay into an in-flow block. The
   two must agree: if this one is narrower,
   there is a band of window sizes where the copy is in normal flow but the
   hero furniture is still absolutely positioned over it. */
@media (max-width: 900px), (max-height: 639px), (max-aspect-ratio: 1/1) {
  /* experience.css dissolves the pin here (`display: contents`) so the section
     itself becomes the flex column. This stylesheet loads last and its
     `.chapter-stage .section__pin` rule is the more specific one, so it has to
     hand the layout back explicitly rather than leave the pin as a flex row. */
  .chapter-stage .section__pin { display: contents; }

  /* The composition turns ninety degrees on one column. There is no empty
     side to leave the mark in, so it is given the empty TOP instead: the copy
     is anchored to the foot of the screen and the mark stands in the upper
     part of it, so the picture and the sentence share the screen rather than
     the sentence standing on the picture. Centred, the copy sat squarely over the one part
     of the frame the reader was meant to be looking at, under a wash that took
     three quarters of its light away. */
  .chapter-stage {
    flex-direction: column;
    justify-content: flex-end;
    align-items: stretch;
    min-height: 92svh;
  }

  /* The wash follows the copy down: clear over the drawing, and only closing
     in where the type actually is. */
  .section--hero .chapter-scrim {
    background: linear-gradient(180deg,
      transparent 0%, rgba(2, 6, 11, 0.16) 28%, rgba(2, 6, 11, 0.70) 48%,
      rgba(2, 6, 11, 0.88) 66%, rgba(2, 6, 11, 0.92) 100%);
  }

  /* On one column the mark stands in the upper part of the first screen,
     the room the copy leaves when it is anchored to the foot, and the room
     the wash above keeps clear on purpose, so a phone never opens on a
     black screen with the studio's one object missing from it.

     It is still fixed, still the one element, still lit while the landing
     screen is in view, and it leaves on the same number it does on a wide
     screen: `--exit`, written
     by scripts/scene/journey.js as the hero leaves, the mark dims, rises a
     little and steps back on it. Sized by the shorter of the two so a
     landscape strip gets a mark that fits under its header rather than one
     that fills it. */
  .hero-mark,
  html.at-hero .hero-mark,
  html.journey .hero-mark {
    left: 50%;
    top: calc(var(--header-h) - 2svh);
    width: min(72vw, 46svh);
    transform: translate(-50%, calc(var(--exit, 0) * -12svh)) scale(calc(1 - var(--exit, 0) * 0.1));
    transition: opacity 900ms var(--ease-soft) 260ms;
  }
  html.at-hero .hero-mark { opacity: calc(1 - var(--exit, 0)); }

  .hero__inner { padding: 0; }
  .hero__inner .chapter-copy { width: 100%; max-width: none; }

  /* Set smaller and tighter on one column, where the copy runs full width and
     6.4vw would put the wordmark alone on the first screen with the sentence it
     is meant to be crowning pushed under the fold.

     Fitted by the one relationship that has to survive the breakpoint: the
     wordmark is twice the height of the headline under it. Measured, Bebas at
     this tracking sets the string 3.54× its font size, so the ceiling is what
     keeps that ratio at 834px (an 80px wordmark over a 40px headline) rather
     than what keeps it inside the gutter, the column is 742px there and the
     string is 283px, so overflow is not the binding constraint at any width in
     this range. The floor is: at 320px the vw term is what the clamp discards,
     and 2.6rem is where the string still reads as a logotype rather than as a
     line of small caps. */
  .hero-wordmark {
    font-size: clamp(2.6rem, 13vw, 5rem);
    letter-spacing: 0.06em;
  }

  /* With the pin dissolved these become direct flex children of the section,
     in DOM order: and experience.css gives `.section__inner` `order: 1`, which
     puts everything with the default order 0 AHEAD of the copy. The hero's
     furniture belongs under its headline, so it is ordered explicitly rather
     than left to inherit a source order that no longer means what it did. */
  /* The scroll hint leaves with the pointer it was written for: a thumb does
     not need to be told the page scrolls, and the sixty pixels it took at
     the foot of the screen are the room between the mark and the kicker. */
  .chapter-scroll { display: none; }
  .chapter-scrim { order: 0; }
  .chapter-scroll i { display: none; }
  /* The landing screen is one full screen, copy at its foot, the mark above. */
  .section--hero.chapter-stage { min-height: 100svh; }
}

/* The signals are four offers now, and at the foot of a narrower window they
   run into the scroll hint on the right (measured at 1024: "GAMES AND APPS"
   under "SCROLL"). The offers are what a reader can buy; the hint is what the
   wheel already knows. So the hint goes first. */
@media (max-width: 1180px) {
  .chapter-scroll { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .chapter-scroll i { animation: none; opacity: 0.6; }
  /* Reduced motion keeps the mark, and stops it moving: the attention field
     does not run there at all (scripts/studio/attention.js returns early), so
     what is left is a still artifact at its resting brightness rather than one
     that rises, settles and is read across by a travelling window. */
  .hero-mark { transition: none !important; }
  /* ...and on one column it does not travel on the scroll either: it dims as
     the hero leaves, and stays where it stood. */
  @media (max-width: 900px), (max-height: 639px), (max-aspect-ratio: 1/1) {
    .hero-mark,
    html.at-hero .hero-mark { transform: translate(-50%, 0); }
  }
}
