/* ==========================================================================
   site.css — Ryevolution teaser.

   Layout archetype: a single full-bleed stage. No container, no max-width
   wrapper; the lockup is sized off the viewport and is the only object.

   The one gesture, at three scales:
   One flat ember field covers the screen and withdraws to the right,
   LEAVING THE LOCKUP BEHIND IT. That is the whole entrance: one pass,
   one field, nothing tinted and nothing faded in.
   ========================================================================== */

html, body { height: 100%; }

body {
  overflow: hidden;
  background: var(--ground);
}

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

/* --- Stage ---------------------------------------------------------------
   Optical centre, not geometric: the group sits a touch above the middle,
   which is where the eye expects it on a field this empty.              */

.stage {
  position: relative;
  z-index: 1;
  min-height: 100dvh;
  display: grid;
  align-content: center;
  justify-items: center;
  padding: var(--s-8) var(--gutter) calc(var(--s-8) + 4dvh);
  gap: clamp(4rem, 8dvh, 7rem);          /* between groups. never less */
}

/* --- The lockup ----------------------------------------------------------
   Breaks any column there might have been: it is sized off the viewport.  */

.mark {
  position: relative;
  width: clamp(19rem, 56vw, 50rem);
  margin: 0;
  max-width: none;
  line-height: 0;
  letter-spacing: normal;
}

.mark__art { display: block; width: 100%; height: auto; }

/* On a phone the lockup should own the screen. Capped in rem as well as vw
   so a 430px handset does not get a wider mark than the gutters allow. */
@media (max-width: 40em) {
  .mark { width: min(86vw, 23rem); }
}

/* --- The line ------------------------------------------------------------ */

.line {
  margin: 0;
  max-width: none;
  font-size: var(--t-1);                 /* 19 → 26. it is the whole message */
  line-height: 1.1;                      /* Kapra caps clip below ~1.05 */
  letter-spacing: 0.2em;
  text-indent: 0.2em;                    /* put the trailing letterspace back */
  text-transform: uppercase;
  color: var(--paint);
  text-align: center;
}

/* --- Ember ---------------------------------------------------------------
   Opaque canvas that paints its own ground, held at 0 until the field is
   gone. Under it the glow would be hidden anyway; the moment the field
   leaves, a glow that was already up would show as a seam.

   `absolute`, not `fixed` — see the note on .curtain.                  */

.ember {
  position: absolute;
  inset: 0;
  width: 100%; height: 100%;
  z-index: 0;
  opacity: 0;
  pointer-events: none;
}

/* --- The pass ------------------------------------------------------------
   One flat ember field, one viewport wide, parked over the page. Moving it
   by p x 100vw withdraws it to the right and leaves the lockup behind.

   Flat colour and a hard edge on purpose — no bar, no glow, no falloff. A
   soft edge reads as a light passing OVER the page; a hard one reads as a
   surface being taken off it. Same reason it is transform only: nothing
   repaints, the field just moves.

   **`absolute`, not `fixed`, and that is not a detail.** Safari 26 dropped
   `theme-color`: it tints the iOS address bar and the safe areas from the
   body background — unless the page has a position:FIXED element carrying a
   background-color, in which case it uses that one instead. A full-screen
   fixed ember field therefore painted the whole browser chrome orange, and
   because the tint is sampled once and never re-sampled, it stayed orange
   long after JavaScript had removed the field. The page never scrolls, so
   absolute and fixed are visually identical here — and absolute keeps
   Safari looking at the body, which is dark. Do not change it back.    */

.curtain {
  position: absolute;
  top: 0; left: 0;
  width: 100vw; height: 100dvh;
  background: var(--paint);
  z-index: 5;
  pointer-events: none;
  transform: translate3d(var(--x, 0px), 0, 0);
  will-change: transform;
}

/* --- No JS, or JS that never arrived --------------------------------------
   The intro is additive: everything that hides the page is switched on by
   the `js` class, and the head script arms a 5s watchdog that removes that
   class again. A script that fails to load, is blocked, or throws leaves a
   finished page rather than a dark rectangle.                            */

html:not(.js) .curtain { display: none; }
html:not(.js) .ember { opacity: 1; }

/* --- Reduced motion ------------------------------------------------------
   No movement, but not a blank page: the lockup resolves on opacity and
   the ember canvas draws one still frame.                               */

@media (prefers-reduced-motion: reduce) {
  .curtain { display: none; }
  .ember { opacity: 1; }
}
