/* ==========================================================================
   The opening (home): a dark ocean, ENTER, a few words, then a white surface
   that rises from the bottom, pushes the ocean away and opens the white,
   prismatic world of Wizo.

   Two editions from the same markup (templates/marketing/home.html):
   - live (.opening.is-live, set before the first paint unless the visitor prefers
     reduced motion): the ocean stays on screen while the page scrolls, and
     opening.js cuts it along a rising white edge and pushes it up;
   - still (reduced motion, no script): the ocean, then the white world under it.
   ========================================================================== */

.page-opening {
  --ocean: #03070c;              /* the ocean at depth: the very first paint */
  --white: #fdfdfc;              /* the wall of the white world */
  --ink-cool: #0e1114;           /* words on the white */
  --pearl: #e9eef2;              /* words on the ocean */
  --track: 0.42em;               /* letter spacing of the small capitals */
  --halo: 0 0 14px rgb(2 10 14 / 0.55), 0 0 3px rgb(2 10 14 / 0.35);   /* keeps small words legible on bright water */
  background: var(--ocean);
}
/* Overscrolling past either end shows the colour of the world you are in. */
html:has(body.page-opening) { background: var(--ocean); scroll-padding-top: 0; }   /* ENTER (still edition) lands with the ocean just out of view */
html:has(body.page-opening.is-white) { background: var(--white); }

/* The site's own bar and footer are part of the white world only. */
.page-opening main,
.page-opening .site-footer { position: relative; z-index: 1; }
.page-opening .site-footer { color: var(--ink-cool); border-top-color: rgb(14 17 20 / 0.1); }
.page-opening .topbar { color: var(--ink-cool); opacity: 0; visibility: hidden; transition: opacity 0.9s var(--ease-out), visibility 0s 0.9s; }
.page-opening.is-white .topbar { opacity: 1; visibility: visible; transition: opacity 1.2s var(--ease-out) 0.15s, visibility 0s; }
.page-opening .topbar[data-tone="light"] { color: var(--pearl); }   /* still edition, over the last of the ocean */
.page-opening .topbar[data-open="true"] { color: #f1eee8; }


/* The white world ---------------------------------------------------------
   Mostly white. Light seems to pass through glass somewhere out of frame and
   lands on the wall as a few large, soft pools of cold blue, pale rose and
   pale gold, in no particular order. They drift so slowly that the wall looks
   still. Every beam is one soft radial gradient: no blur filter, nothing to
   recompute while it moves (the browser only slides finished pictures). */
.prism {
  position: fixed; inset: 0 0 auto; z-index: 0; height: 100lvh;
  background: var(--white); overflow: hidden; pointer-events: none;
}
.prism__light { position: absolute; inset: 0; }
/* A faint grain over the light, so its soft gradients never show steps (8-bit banding). In
   "overlay" mode mid-grey changes nothing: pure white stays pure white. */
.prism::after { content: ""; position: absolute; inset: 0; background: url("../opening/grain.png"); mix-blend-mode: overlay; }
.beam {
  --x: 50%; --y: 50%; --w: 60vmax; --h: 20vmax; --r: -24deg; --o: 0.2; --c: 60 90 170;
  --dx: 2vw; --dy: -1.5vh; --dr: 2deg; --ds: 1.04; --t: 60s; --delay: 0s;
  position: absolute; left: var(--x); top: var(--y); width: var(--w); height: var(--h);
  margin: calc(var(--h) / -2) 0 0 calc(var(--w) / -2);
  opacity: var(--o);
  background: radial-gradient(closest-side, rgb(var(--c)) 0%, rgb(var(--c) / 0.66) 30%, rgb(var(--c) / 0.3) 58%, rgb(var(--c) / 0.08) 82%, rgb(var(--c) / 0) 100%);
  transform: rotate(var(--r));
  animation: beam-drift var(--t) var(--ease-in-out) var(--delay) infinite alternate both;
  will-change: transform;
}
@keyframes beam-drift {
  from { transform: translate3d(0, 0, 0) rotate(var(--r)) scale(1); }
  to { transform: translate3d(var(--dx), var(--dy), 0) rotate(calc(var(--r) + var(--dr))) scale(var(--ds)); }
}
/* A wide cold-blue pool rising from the lower left. */
.beam--blue { --x: 10%; --y: 90%; --w: 96vmax; --h: 40vmax; --r: -17deg; --o: 0.46; --c: 160 184 240; --dx: 3vw; --dy: -2.5vh; --t: 72s; }
/* A faint rose edge along the top of the blue: where the light splits. */
.beam--sliver { --x: 30%; --y: 70%; --w: 62vmax; --h: 12vmax; --r: -17deg; --o: 0.3; --c: 240 178 188; --dx: 2.5vw; --dy: -2vh; --dr: 1deg; --t: 56s; --delay: -14s; }
/* Soft red-pink light coming in from the right. */
.beam--rose { --x: 99%; --y: 60%; --w: 58vmax; --h: 34vmax; --r: 26deg; --o: 0.34; --c: 244 172 180; --dx: -2.5vw; --dy: 2vh; --dr: -3deg; --t: 60s; --delay: -22s; }
/* Pale gold washing down from the top. */
.beam--gold { --x: 58%; --y: -4%; --w: 92vmax; --h: 36vmax; --r: -7deg; --o: 0.5; --c: 248 222 168; --dx: -2vw; --dy: 2.5vh; --ds: 1.06; --t: 78s; --delay: -36s; }
/* A thin cold line just under the gold, like the edge of a pane of glass. */
.beam--pool { --x: 66%; --y: 17%; --w: 70vmax; --h: 6vmax; --r: -7deg; --o: 0.13; --c: 176 198 246; --dx: -1.5vw; --dy: 2vh; --dr: -1deg; --t: 66s; --delay: -9s; }
/* A breath of warm light low on the right. */
.beam--dawn { --x: 84%; --y: 104%; --w: 50vmax; --h: 26vmax; --r: -10deg; --o: 0.34; --c: 248 226 184; --dx: -2vw; --dy: -1.5vh; --t: 68s; --delay: -44s; }


/* The opening, both editions ------------------------------------------------ */
.opening { position: relative; }
.opening__stage { position: relative; }

/* The ocean */
.ocean {
  position: relative; height: 100svh; min-height: 30rem; overflow: hidden;
  background: var(--ocean); color: var(--pearl); isolation: isolate;
}
.ocean picture { position: absolute; inset: 0; }
.ocean__still,
.ocean__video { position: absolute; inset: 0; width: 100%; height: 100%; max-width: none; object-fit: cover; }
.ocean__video { transition: opacity 1.6s var(--ease-out); }
.ocean__still { transition: opacity 1.6s var(--ease-out); }
/* With the script, each picture fades in once it is really there (no black or white flash). */
.js .ocean:not(.has-still) .ocean__still,
.js .ocean:not(.has-video) .ocean__video { opacity: 0; }
/* Deepen the edges and the top towards black, keep the middle open. */
.ocean__shade {
  position: absolute; inset: 0; pointer-events: none;
  background:
    radial-gradient(130% 95% at 50% 46%, rgb(2 5 9 / 0) 38%, rgb(2 5 9 / 0.62) 100%),
    linear-gradient(180deg, rgb(2 5 9 / 0.4) 0%, rgb(2 5 9 / 0) 26%, rgb(2 5 9 / 0) 72%, rgb(2 5 9 / 0.35) 100%);
}
/* Darkens the water as it is pushed away (opacity set by opening.js). */
.ocean__dusk { position: absolute; inset: 0; background: #010307; opacity: 0; pointer-events: none; }

/* ENTER: small capitals and a hairline, like the name of a room on a wall. */
.enter {
  position: absolute; left: 50%; top: 50svh; z-index: 2;
  display: grid; justify-items: center; gap: 0.95rem;
  padding: 1.2rem 1.8rem; transform: translate(-50%, -50%);
  color: var(--pearl); font-size: 0.6875rem; font-weight: 500; line-height: 1;
  text-transform: uppercase; -webkit-tap-highlight-color: transparent; text-shadow: var(--halo);
}
.enter__label {
  letter-spacing: var(--track); padding-left: var(--track);   /* the spacing after the last letter, balanced on the left */
  transition: letter-spacing 0.9s var(--ease-out), padding 0.9s var(--ease-out), opacity 0.35s ease, transform 0.6s var(--ease-out);
}
.enter__line {
  width: 1.5rem; height: 1px; background: currentColor; opacity: 0.55; box-shadow: 0 0 8px rgb(2 10 14 / 0.5);
  transition: transform 0.9s var(--ease-out), opacity 0.6s ease;
}
.enter:hover .enter__label,
.enter:focus-visible .enter__label { letter-spacing: 0.56em; padding-left: 0.56em; }
.enter:hover .enter__line,
.enter:focus-visible .enter__line { transform: scaleX(2.4); opacity: 0.9; }
.enter:focus-visible { outline: 1px solid rgb(233 238 242 / 0.4); outline-offset: 0; }

/* The words after ENTER (decorative: the page does not depend on them). */
.words { position: absolute; inset: 0 0 auto; height: 100svh; pointer-events: none; z-index: 2; }
.word {
  position: absolute; left: var(--x); top: var(--y); transform: translate(-50%, -50%);
  overflow: hidden; padding: 0.14em 0.1em; white-space: nowrap;
  font-weight: 500; line-height: 1.1; text-transform: uppercase; color: var(--pearl); text-shadow: var(--halo);
}
.word > span { display: block; letter-spacing: var(--track); padding-left: var(--track); opacity: 0; transform: translateY(105%); }
.word--xs { font-size: 0.625rem; --track: 0.46em; opacity: 0.8; }
.word--s { font-size: 0.75rem; --track: 0.4em; }
.word--m { font-size: clamp(1rem, 1.45vw, 1.45rem); --track: 0.26em; font-weight: 450; }
.word--l { font-size: clamp(2.3rem, 5.6vw, 5.4rem); --track: 0.16em; font-weight: 400; }

/* After the words, when nothing has moved for a moment: where to go next. */
.cue {
  position: absolute; left: 50%; top: calc(100svh - 5.4rem); z-index: 2;
  display: grid; justify-items: center; gap: 0.9rem; transform: translateX(-50%);
  font-size: 0.625rem; font-weight: 500; line-height: 1; letter-spacing: var(--track); padding-left: var(--track);
  text-transform: uppercase; color: rgb(233 238 242 / 0.72); text-shadow: var(--halo);
  opacity: 0; visibility: hidden; transition: opacity 1.8s var(--ease-out), visibility 0s 1.8s;
}
.cue::after {
  content: ""; width: 1px; height: 2.6rem; margin-left: calc(var(--track) * -1);
  background: linear-gradient(currentColor, rgb(233 238 242 / 0));
  transform-origin: top; animation: cue-fall 2.8s var(--ease-in-out) infinite;
}
@keyframes cue-fall {
  0% { transform: scaleY(0); opacity: 1; }
  55% { transform: scaleY(1); opacity: 1; }
  100% { transform: scaleY(1); opacity: 0; }
}
.opening.is-hinting .cue { opacity: 1; visibility: visible; transition: opacity 1.8s var(--ease-out), visibility 0s; }

/* The first words of the white world: two lines, a lot of air, the second one stepping in. */
.statement {
  position: relative; display: grid; place-items: center;
  min-height: 100svh; padding: calc(var(--bar) + 3rem) var(--gutter) 4rem;
  color: var(--ink-cool); outline: none;
}
.statement__text {
  font-size: clamp(1.55rem, 3.3vw, 3.9rem); font-weight: 400; line-height: 1.16;
  letter-spacing: 0.045em; text-transform: uppercase; text-wrap: balance;
  transform: translateY(-4%);   /* sits a little above the middle, where the eye expects it */
}
.statement__line { display: block; overflow: hidden; padding-block: 0.04em 0.02em; }
.statement__line > span { display: block; }
.statement__line + .statement__line { padding-left: 2.2em; }


/* Still edition -------------------------------------------------------------
   The ocean first, the white world under it, and across the line where they meet one still
   frame of the wave's foam (rendered from opening-foam.js; only this edition downloads it).
   In that picture the foam's unit is a tenth of the screen's height and the line where the
   ocean stops lies 54.74% of the way down. */
.opening:not(.is-live) .statement::before {
  content: ""; position: absolute; left: 0; right: 0; top: calc(38svh * -0.5474); height: 38svh;
  background: url("../opening/foam-still.webp") 50% 0 / auto 100% no-repeat;
  pointer-events: none;
}
.opening:not(.is-live) .words,
.opening:not(.is-live) .cue { display: none; }


/* Live edition --------------------------------------------------------------
   The stage stays on screen for 1.6 screens of scrolling; opening.js turns that
   distance into the white edge rising (see "The wave" in opening.js). */
.opening.is-live { height: calc(100lvh + 160vh); }
.opening.is-live .opening__stage { position: sticky; top: 0; height: 100lvh; overflow: hidden; }
.opening.is-live .statement { position: absolute; inset: 0; z-index: 1; min-height: 0; }
.opening.is-live .ocean {
  position: absolute; inset: 0 0 auto; z-index: 2; min-height: 0;
  height: calc(100% + var(--spill, 30lvh));   /* reaches below the screen: the edge dips into it */
  will-change: transform;
}

/* The foam's canvas lies over the ocean; opening.js shows it while the wave is on screen. */
.foam { display: none; }
.opening.is-live .foam { display: block; position: absolute; inset: 0; z-index: 3; width: 100%; height: 100%; pointer-events: none; visibility: hidden; }
.opening.is-live .foam.is-on { visibility: visible; }

/* 1. Loading: ENTER waits until the ocean is there. */
.opening.is-live .enter { opacity: 0; visibility: hidden; transition: opacity 1.4s var(--ease-out), visibility 0s 1.4s; }
.opening.is-live.is-ready .enter { opacity: 1; visibility: visible; transition: opacity 1.4s var(--ease-out), visibility 0s; }

/* 2. ENTER is pressed: the word lifts away and its hairline opens across the water. */
.opening.is-live.is-entering .enter,
.opening.is-live.is-calm .enter { opacity: 1; visibility: hidden; pointer-events: none; transition: visibility 0s 1s; }
.opening.is-entering .enter__label,
.opening.is-calm .enter__label { opacity: 0; transform: translateY(-0.6rem); }
.opening.is-entering .enter__line,
.opening.is-calm .enter__line { transform: scaleX(26); opacity: 0; transition: transform 1.1s var(--ease-out), opacity 1s ease 0.1s; }

/* 3. The white world's first words wait for the ocean to leave. */
.opening.is-live .statement__line > span {
  opacity: 0; transform: translateY(102%);
  transition: transform 0.7s var(--ease-in-out), opacity 0.5s ease;
}
.opening.is-live.is-stated .statement__line > span {
  opacity: 1; transform: none;
  transition: transform 1.6s var(--ease-out), opacity 1.3s ease;
}
.opening.is-live.is-stated .statement__line + .statement__line > span { transition-delay: 0.16s; }

/* Once the water moves, the hint has done its job. */
.opening.is-moving .cue { opacity: 0; visibility: hidden; transition: opacity 0.5s ease, visibility 0s 0.5s; }


/* Phones ----------------------------------------------------------------------- */
@media (max-width: 640px) {
  .statement__text { font-size: clamp(1.3rem, 6.1vw, 1.9rem); letter-spacing: 0.03em; line-height: 1.2; }
  .statement__line + .statement__line { padding-left: 1.2em; }
  .word--m { font-size: 0.95rem; }
  .word--l { font-size: clamp(2rem, 11vw, 3rem); --track: 0.12em; }
}
