/*
  DZANA - AGAINST THE STREAM
  One idea: the cover's room continues past the edges of the picture, and its
  bands of light drift across the screen like a current.

  Colours are sampled from the final cover. The slant (36.5 degrees) is the
  slant of the title lettering; steps, buttons and wipes all follow it.
  Layers, back to front: scene (-1) < content (auto) < skip link (10).
*/

@font-face {
  font-family: "ATS Blade";
  src: url("../fonts/ATS-Blade-V3-Regular.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: block;
}

:root {
  --wall: #8ebcf5;
  --wall-2: #6aa3e7;
  --floor: #1b6db3;
  --navy: #012369;
  --ink: #04143a;
  --glass: #cddef9;
  --light: #f4f8ff;
  --deep: #030e2a;

  --slant: 0.74;                       /* tan(36.5deg) */
  --pad: clamp(18px, 2.5vw, 38px);
  --ease: cubic-bezier(0.16, 1, 0.3, 1);

  --font-display: "ATS Blade", "Arial Black", sans-serif;
  --font-text: "Helvetica Neue", Helvetica, "Nimbus Sans", "Liberation Sans", Arial, sans-serif;
}

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

html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }
@media (prefers-reduced-motion: no-preference) { html { scroll-behavior: smooth; } }

body {
  margin: 0;
  background: var(--deep);
  color: var(--ink);
  font: 400 16px/1.4 var(--font-text);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

a { color: inherit; }
[hidden] { display: none !important; }

:focus-visible { outline: 2px solid currentColor; outline-offset: 3px; }

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

.skip {
  position: absolute; left: 12px; top: -60px; z-index: 10;
  padding: 10px 14px; background: var(--ink); color: var(--light);
  font-weight: 700; text-decoration: none;
}
.skip:focus { top: 12px; }

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

.hero {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  background: var(--wall-2);
}

/* ----------------------------------------------------------------- scene */

.scene {
  position: absolute; inset: 0; z-index: -1;
  overflow: hidden;
  container-type: size;
  background: var(--wall-2);
}

/* the room moves and scales as one piece: --dx shifts her sideways, --zoom brings her closer.
   Both are set on .scene by the out-now layouts further down; by default she is centred */
.scene__room {
  position: absolute; inset: 0;
  transform: translateX(var(--dx, 0px)) scale(var(--zoom, 1));
  transform-origin: 44% 24%;           /* her face: zooming keeps it where it was */
}

/* the wall and floor carried on beyond the picture: left side blue, right side pale glass.
   Wider than the screen, so a shifted room never shows a bare edge */
.scene__base { position: absolute; inset: 0 -80%; }
.scene__base::after { position: absolute; inset: 0; }
.scene__base {
  background: linear-gradient(180deg, #93bff6 0%, #7fb2f0 20%, #6aa3e7 50%, #6fa5e6 62%, #328ccf 72%, #258bd0 84%, #1b6db3 100%);
}
.scene__base::after {
  content: "";
  background: linear-gradient(180deg, #d5e2fb 0%, #cbdcf9 38%, #a9c4ea 55%, #9fbfe8 75%, #b4cbee 86%, #98b2e0 100%);
  -webkit-mask-image: linear-gradient(90deg, transparent 48%, #000 54%);
          mask-image: linear-gradient(90deg, transparent 48%, #000 54%);
  -webkit-mask-image: linear-gradient(90deg, transparent calc(50% - 6cqh), #000 calc(50% + 22cqh));
          mask-image: linear-gradient(90deg, transparent calc(50% - 6cqh), #000 calc(50% + 22cqh));
}

.scene__wing { display: none; }

/* On phones the picture fills the screen. --py moves it down and --ph changes its height,
   which the phone layouts below use to make room for the title above her head. */
.scene__cover {
  position: absolute; left: 0; top: var(--py, 0%);
  width: 100%; height: var(--ph, 100%);
  object-fit: cover;
  object-position: 38% 50%;            /* keeps her face in frame on a tall phone */
}
/* the picture's top edge mirrored upward and faded out: the wall carries on without a seam */
.scene__top { display: none; }

/* the stream: bands of light, moved by site.js. They fade out completely where she is: the
   light passes behind her, and nothing ever moves across her or the middle of the artwork */
.stream {
  position: absolute; inset: 0; pointer-events: none;
  -webkit-mask-image: linear-gradient(90deg, #000 0, transparent 24%, transparent 76%, #000 100%);
          mask-image: linear-gradient(90deg, #000 0, transparent 24%, transparent 76%, #000 100%);
}
.band {
  position: absolute; top: -4%; bottom: -4%; left: 0;
  width: var(--w);
  will-change: transform;
}
.band--streak {
  --w: clamp(22px, 3vw, 54px);
  background: linear-gradient(90deg, rgba(255,255,255,0), rgba(255,255,255,0.66) 40%, rgba(255,255,255,0.84) 50%, rgba(255,255,255,0.66) 60%, rgba(255,255,255,0));
  filter: blur(5px);
  opacity: 0.78;
}
.band--veil {
  --w: clamp(110px, 17vw, 300px);
  background: linear-gradient(90deg, rgba(222,234,255,0), rgba(222,234,255,0.3) 30%, rgba(238,245,255,0.42) 50%, rgba(222,234,255,0.3) 70%, rgba(222,234,255,0));
  filter: blur(16px);
}
/* a pane of glass: flat and pale, brighter towards one side. Soft on both edges, so no hard
   line ever travels across the picture. It only lightens; nothing is blurred */
.band--glass {
  --w: clamp(96px, 13vw, 230px);
  background: linear-gradient(90deg, rgba(255,255,255,0) 0, rgba(244,249,255,0.34) 14%, rgba(236,244,255,0.22) 34%, rgba(236,244,255,0.2) 66%, rgba(236,244,255,0.08) 90%, rgba(255,255,255,0) 100%);
  filter: blur(6px);
}

/* the floor falls into shadow so the white lettering holds everywhere */
.scene__shade {
  position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(4,20,58,0) 32%, rgba(4,20,58,0.5) 55%, rgba(3,14,42,0.92) 100%);
}

.scene__grain {
  position: absolute; inset: 0;
  background: url("../img/grain.png") 0 0 / 190px 190px;
  mix-blend-mode: overlay;
  opacity: 0.3;
}

/* ------------------------------------------------------------------- bar */

.bar {
  display: flex; justify-content: space-between; align-items: baseline; gap: 16px;
  padding: var(--pad);
  padding-top: max(var(--pad), env(safe-area-inset-top));
}
.bar__name {
  margin: -10px 0; padding: 10px 0;       /* a comfortable tap area without moving the word */
  font-weight: 700;
  font-size: clamp(17px, 1.45vw, 22px);
  letter-spacing: 0.03em;
  text-decoration: none;
}
.bar__links {
  display: flex; gap: clamp(14px, 1.7vw, 28px);
  margin: 0 0 0 auto; padding: 0; list-style: none;   /* stays right even when the name is not in the bar */
  font-size: 14px;
}

/* Her name, three ways (nameStyle in config.js):
   "sleeve"  above the title, as on a record sleeve          (shown by default)
   "corner"  top left corner
   "none"    not shown apart from the copyright line
   "sleeve" and "corner" follow the back cover: Helvetica Bold capitals, half an em between letters.
   "plain" keeps the first version of the corner word, for comparison only. */
.title__name { display: none; }
[data-name="sleeve"] .bar__name,
[data-name="none"] .bar__name { display: none; }
[data-name="sleeve"] .title__name {
  display: block;
  margin: 0 0 clamp(10px, 1.5vh, 16px);
  font: 700 clamp(13px, 1.05vw, 16px)/1 var(--font-text);
  letter-spacing: 0.5em;
}
[data-name="corner"] .bar__name {
  font-size: clamp(13px, 1.05vw, 16px);
  letter-spacing: 0.5em;
}
.bar__links a { display: inline-block; margin: -12px 0; padding: 12px 0; text-decoration: none; }
.bar__links a:hover { text-decoration: underline; text-underline-offset: 4px; }

/* ----------------------------------------------------------------- stage */

.stage {
  --fg: var(--light);
  --btn-bg: var(--light);
  --btn-fg: var(--ink);
  margin-top: auto;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: clamp(16px, 2.6vh, 24px);
  padding: 0 var(--pad);
  color: var(--fg);
}
.stage > * { min-width: 0; }

.title { margin: 0; }
/* the title is the vector master itself, inline in the page, coloured by the text colour */
.title__art { display: block; width: 100%; height: auto; overflow: visible; }
.title__art--line { display: none; }

/* countdown */
.count__lead {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.3em 0.6em;
  margin: 0 0 12px;
  font-size: 14px; line-height: 1.3;
}
.count__lead time { font-weight: 700; }
.tbc {
  padding: 1px 6px;
  border: 1px dashed currentColor;
  font-size: 11px; line-height: 1.5;
}

.clock {
  display: flex; gap: clamp(10px, 3.4vw, 22px);
  font-family: var(--font-display);
  font-feature-settings: "tnum" 1;
}
.clock__row { display: grid; gap: 7px; justify-items: start; }
.clock__row b {
  display: block;
  padding-left: 0.1em;                 /* the slanted digits overhang their own left edge */
  font-weight: 400;
  font-size: clamp(26px, 8.4vw, 52px);
  line-height: 0.72;                   /* the line box is exactly the cap height */
}
.clock__row span {
  padding-left: 0.1em;
  font: 400 12px/1 var(--font-text);
}

/* sign-up */
.form__label {
  display: block;
  margin-bottom: 12px;
  font-size: clamp(15px, 1.15vw, 17px);
  font-weight: 700;
  line-height: 1.25;
}
/* One row: the field, and at its right end a blade cut on the lettering's slant (the send
   button, styled further down). Only the blade's tip shows until the field is used. */
.form__row {
  --fh: 50px;
  --cut: calc(var(--fh) * var(--slant));   /* how far the slanted edge leans over the field's height */
  --send: 116px;                           /* the blade's full width */
  position: relative; overflow: hidden;
}
.form__row:focus-within { outline: 2px solid var(--fg); outline-offset: 2px; }
.form__input {
  display: block; width: 100%; min-width: 0;
  height: var(--fh); padding: 0 calc(var(--cut) + 18px) 0 12px;
  border: 0; border-bottom: 2px solid var(--fg); border-radius: 0;
  background: rgba(255, 255, 255, 0.14);
  background: color-mix(in srgb, var(--fg) 12%, transparent);
  color: var(--fg);
  font: inherit; font-size: 17px;
  -webkit-appearance: none; appearance: none;
}
.form__input::placeholder { color: var(--fg); opacity: 0.88; }   /* 0.62 fell under 4.5:1 on the pale wall */
/* the row carries the focus ring, so the blade and the light can be clipped to the field */
.form__input:focus-visible {
  outline: none;
  background: color-mix(in srgb, var(--fg) 20%, transparent);
}
.form__trap { position: absolute; left: -9999px; width: 1px; height: 1px; opacity: 0; }
.form__note { margin: 12px 0 0; font-size: 12px; line-height: 1.45; }
.form__status { min-height: 1.4em; margin: 6px 0 0; font-size: 13px; font-weight: 700; line-height: 1.4; }
.form__status:empty { min-height: 0; margin: 0; }   /* takes no room until it has something to say */
.form__status[data-kind="preview"] { padding: 6px 8px; border: 1px dashed currentColor; font-weight: 400; }
/* signed up: the question, the field and the small print go; one clear line takes their place */
.form.is-done .form__label, .form.is-done .form__row, .form.is-done .form__note { display: none; }
.form.is-done .form__status { margin: 0; font-size: 13px; font-weight: 400; line-height: 1.45; }
.form.is-done .form__status strong {
  display: block; margin-bottom: 8px;
  font-size: clamp(19px, 1.5vw, 23px); line-height: 1.2; letter-spacing: -0.005em;
  text-wrap: balance;                  /* no single word left alone on the second line */
}

/* button: a block cut on the lettering's slant */
.btn {
  position: relative; isolation: isolate;
  display: inline-flex; align-items: center; justify-content: center;
  flex: 0 0 auto;
  height: 50px; padding: 0 44px;
  border: 0; background: none;
  color: var(--btn-fg);
  font: 700 14px/1 var(--font-text);
  letter-spacing: 0.01em; white-space: nowrap; text-decoration: none;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.btn::before {
  content: "";
  position: absolute; inset: 0 19px; z-index: -1;
  background: var(--btn-bg);
  transform: skewX(-36.5deg);
  transition: inset 0.35s var(--ease), background-color 0.2s;
}
.btn:hover::before { inset: 0 13px; }
.btn:active { transform: translateY(1px); }
.btn:focus-visible { outline: none; }
.btn:focus-visible::before { outline: 2px solid var(--btn-bg); outline-offset: 3px; }
.btn[disabled], .btn[aria-disabled="true"] { cursor: default; opacity: 0.55; }
.btn[disabled]:hover::before, .btn[aria-disabled="true"]:hover::before { inset: 0 19px; }
.btn--light { --btn-bg: var(--light); --btn-fg: var(--ink); }
.presave { margin: 0 0 18px; }

/* The send blade. At rest only its slanted tip shows at the end of the field. When the field
   is used (or holds an address) a streak of light crosses the field and the blade comes out
   with its word. Pressing the tip itself also works: it is the send button all along. */
.form__row .form__send {
  position: absolute; top: 0; right: 0; z-index: 2;
  width: var(--send); height: 100%;
  padding: 0 12px 0 calc(var(--cut) + 2px);
  background: var(--btn-bg);
  -webkit-clip-path: polygon(var(--cut) 0, 100% 0, 100% 100%, 0 100%);
          clip-path: polygon(var(--cut) 0, 100% 0, 100% 100%, 0 100%);
  transform: translateX(calc(100% - var(--cut) - 9px));
}
.form__row .form__send::before { content: none; }
.form__row .form__send span { opacity: 0; transform: translateX(12px); }
@media (hover: hover) {
  .form__row:hover .form__send { transform: translateX(calc(100% - var(--cut) - 17px)); }
}
.form__row:focus-within .form__send,
.form__input:not(:placeholder-shown) ~ .form__send { transform: none; }
.form__row:focus-within .form__send span,
.form__input:not(:placeholder-shown) ~ .form__send span { opacity: 1; transform: none; }
.form__row:focus-within .form__input,
.form__row .form__input:not(:placeholder-shown) { padding-right: calc(var(--send) + 4px); }
.form__row .form__send:focus-visible { outline: 2px solid var(--btn-fg); outline-offset: -6px; }
/* the streak of light */
.form__row::after {
  content: ""; position: absolute; z-index: 1; top: 0; bottom: 0; left: 0; width: 30%;
  background: linear-gradient(90deg, rgba(255,255,255,0), rgba(255,255,255,0.62) 50%, rgba(255,255,255,0));
  transform: translateX(-140%) skewX(-36.5deg);
  opacity: 0; pointer-events: none;
}

/* released */
.out { display: flex; align-items: center; justify-content: space-between; gap: 16px; }
.out__word {
  display: flex; gap: 0.42em;
  margin: 0;
  font: 400 clamp(22px, 6.6vw, 52px)/0.72 var(--font-display);
}

/* ------------------------------------------------------------------ foot */

.foot {
  display: flex; justify-content: space-between; gap: 16px;
  padding: 16px var(--pad) max(14px, env(safe-area-inset-bottom));
  color: var(--light);
  font-size: 12px;
}
.foot a { text-underline-offset: 3px; }

/* ---------------------------------------------------- phones and tall screens */
/* mobileLayout in config.js:
   "top"      the title sits above her head; the picture moves down, she keeps her size
   "top-out"  the same, with the picture zoomed out so more of the room shows
   "low"      the title lies over the picture near the bottom (the first version) */

@media not all and (min-aspect-ratio: 5/4) and (min-width: 880px) {
  [data-mobile="top"] .scene { --py: 13%; }
  [data-mobile="top-out"] .scene { --py: 16%; --ph: 84%; }

  [data-mobile^="top"] .scene__top {
    display: block;
    position: absolute; left: 0; top: calc(var(--py) - var(--ph, 100%));
    width: 100%; height: var(--ph, 100%);
    background: var(--cover-src, none) 38% 50% / cover no-repeat;
    transform: scaleY(-1);
    /* gone within 8% of the picture's height: her hair starts at 10%, and must never mirror */
    -webkit-mask-image: linear-gradient(180deg, #000 0, #000 1.5%, transparent 8%);
            mask-image: linear-gradient(180deg, #000 0, #000 1.5%, transparent 8%);
  }

  /* on the pale wall the title is navy, as it is on the front cover */
  [data-mobile^="top"] .title {
    position: absolute;
    top: calc(max(var(--pad), env(safe-area-inset-top)) + 40px);
    left: var(--pad); right: var(--pad);
    color: var(--ink);
  }

  /* Her three links (mobileNav in config.js):
     "right"   top right (the first version)
     "center"  top centre
     "spread"  across the title's width: first link on its left edge, last on its right
     "foot"    at the bottom, above the copyright line; the top is the title alone */
  .bar__links { font-size: 15px; gap: 20px; }
  [data-nav="center"] .bar__links { margin: 0 auto; }
  [data-nav="spread"] .bar__links { width: 100%; margin: 0; justify-content: space-between; }
  [data-nav="foot"] .stage { order: 1; }
  [data-nav="foot"] .bar { order: 2; padding: 8px var(--pad) 0; color: var(--light); }
  [data-nav="foot"] .bar__links { margin: 0; }
  [data-nav="foot"] .foot { order: 3; padding-top: 14px; }
  /* with no links above it the title moves up, and the picture follows */
  [data-nav="foot"][data-mobile^="top"] .title { top: max(var(--pad), env(safe-area-inset-top)); }
  [data-nav="foot"][data-mobile="top"] .scene { --py: 9%; }
  [data-nav="foot"][data-mobile="top-out"] .scene { --py: 12%; }

  /* The light on a phone. She fills the width here, so it crosses the wall above her head and
     the two upper corners beside her, and is gone before it could reach her hair.
     --sky is where her hair begins, as a share of the screen's height */
  .stream {
    --sky: 9%;
    -webkit-mask-image:
      linear-gradient(180deg, #000 0, #000 calc(var(--sky) - 8%), transparent var(--sky)),
      radial-gradient(ellipse 30% 44% at 0% 16%, #000 0, #000 30%, transparent 100%),
      radial-gradient(ellipse 20% 30% at 100% 12%, #000 0, #000 30%, transparent 100%);
            mask-image:
      linear-gradient(180deg, #000 0, #000 calc(var(--sky) - 8%), transparent var(--sky)),
      radial-gradient(ellipse 30% 44% at 0% 16%, #000 0, #000 30%, transparent 100%),
      radial-gradient(ellipse 20% 30% at 100% 12%, #000 0, #000 30%, transparent 100%);
  }
  [data-mobile="top"] .stream { --sky: 21%; }
  [data-mobile="top-out"] .stream { --sky: 23%; }
  [data-nav="foot"][data-mobile="top"] .stream { --sky: 17%; }
  [data-nav="foot"][data-mobile="top-out"] .stream { --sky: 19%; }
  /* the bands keep their share of the screen instead of their smallest desktop size */
  .band--streak { --w: 5vw; filter: blur(3px); }
  .band--veil { --w: 24vw; filter: blur(10px); }
  .band--glass { --w: 18vw; filter: blur(4px); }
  /* a sideways swipe is left to the page, so it can push the light; scrolling and zoom stay */
  .hero { touch-action: pan-y pinch-zoom; }
}

/* --------------------------------------------- wide screens: the full room */

@media (min-aspect-ratio: 5/4) and (min-width: 880px) {
  .hero { display: block; height: 100dvh; min-height: 560px; }

  .scene__cover {
    inset: auto; top: 0; left: 50%;
    width: auto; height: 100%; aspect-ratio: 1 / 1;
    translate: -50% 0;
    object-fit: fill;
    -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 2.5%, #000 97.5%, transparent 100%);
            mask-image: linear-gradient(90deg, transparent 0, #000 2.5%, #000 97.5%, transparent 100%);
  }

  /* the picture mirrored outward from each edge, so wall, floor and light carry on without a seam,
     then faded into the plain wall before anything of her could repeat */
  .scene__wing {
    display: block;
    position: absolute; top: 0;
    height: 100%; aspect-ratio: 1 / 1;
    background: var(--cover-src, none) center / 100% 100% no-repeat;
    transform: scaleX(-1);
  }
  /* each wing tucks 1px under the picture so no hairline can open between them */
  .scene__wing--l {
    left: calc(50% - 150cqh + 1px);
    -webkit-mask-image: linear-gradient(90deg, #000 0, #000 5%, transparent 23%);
            mask-image: linear-gradient(90deg, #000 0, #000 5%, transparent 23%);
  }
  .scene__wing--r {
    left: calc(50% + 50cqh - 1px);
    -webkit-mask-image: linear-gradient(270deg, #000 0, #000 4%, transparent 19%);
            mask-image: linear-gradient(270deg, #000 0, #000 4%, transparent 19%);
  }
  /* once the wings are in place the picture keeps its true edge: the mirror continues it exactly.
     (The soft edge above is only for the case where the wings could not be drawn.) */
  .scene.has-wings .scene__cover { -webkit-mask-image: none; mask-image: none; }
  /* browsers without container units cannot place the wings: the plain wall shows instead */
  @supports not (width: 1cqh) { .scene__wing { display: none; } }

  .scene__shade {
    background: linear-gradient(180deg, rgba(1,29,83,0) 58%, rgba(1,29,83,0.45) 79%, rgba(3,14,42,0.85) 100%);
  }
  /* on a wide screen she stands in the middle third; the light is full strength either side */
  .stream {
    --cx: calc(50% + var(--dx, 0px));  /* where she stands */
    --z: var(--zoom, 1);
    -webkit-mask-image: linear-gradient(90deg, #000 0, #000 calc(var(--cx) - 46cqh * var(--z)), transparent calc(var(--cx) - 29cqh * var(--z)), transparent calc(var(--cx) + 33cqh * var(--z)), #000 calc(var(--cx) + 47cqh * var(--z)), #000 100%);
            mask-image: linear-gradient(90deg, #000 0, #000 calc(var(--cx) - 46cqh * var(--z)), transparent calc(var(--cx) - 29cqh * var(--z)), transparent calc(var(--cx) + 33cqh * var(--z)), #000 calc(var(--cx) + 47cqh * var(--z)), #000 100%);
  }

  .bar { position: absolute; inset: 0 0 auto 0; }

  .stage { position: absolute; inset: 0; display: block; margin: 0; padding: 0; pointer-events: none; }
  .stage > * { pointer-events: auto; }

  .title {
    position: absolute; left: var(--pad); right: var(--pad);
    bottom: clamp(50px, 8.4vh, 86px);
  }
  .title__art--line { display: block; }
  .title__art--stack { display: none; }

  /* the countdown steps down the wall along the lettering's slant */
  /* on very wide screens both side blocks stay within reach of the picture */
  .count, .out {
    position: absolute; left: max(var(--pad), calc(50% - 900px)); top: 46%;
    translate: 0 -50%;
    color: var(--ink);
  }
  .clock, .out__word {
    --fs: min(9.4vh, 5.5vw);
    --row: calc(var(--fs) * 0.92);
    display: grid; gap: 0;
  }
  .clock__row {
    display: flex; align-items: baseline; gap: calc(var(--fs) * 0.2);
    height: var(--row);
    margin-left: calc((3 - var(--i)) * var(--row) * var(--slant));
  }
  .clock__row b { font-size: var(--fs); }
  .clock__row span { font-size: 13px; }
  /* The date is the next step up the same slanted line the digits stand on.
     2.042 = the top row's own step (3 rows x 0.92 x slant). -0.117 = where a digit's slanted
     stem meets the baseline inside its box. 0.781 and 11px = the climb from the top row's
     baseline to the top of the date's capitals, times the slant. */
  .count__lead {
    margin: 0 0 calc(var(--fs) * 0.34) calc(var(--fs) * (2.042 - 0.117 + 0.781) + 11px);
    font-size: 14px;
  }
  .count .clock { --fs: min(9.4vh, 5.5vw); }
  .count { --fs: min(9.4vh, 5.5vw); }

  .notify {
    --fg: var(--ink);
    --btn-bg: var(--ink);
    --btn-fg: var(--light);
    position: absolute; right: max(var(--pad), calc(50% - 900px)); top: 46%;
    translate: 0 -50%;
    width: min(340px, 25vw);
    color: var(--fg);
  }

  .out { display: block; --fs: min(13vh, 7.2vw); }
  .out__word { --fs: min(13vh, 7.2vw); font-size: var(--fs); margin-bottom: calc(var(--fs) * 0.36); padding-left: 0.22em; }
  .out__word span { display: block; height: var(--row); margin-left: calc((1 - var(--i)) * var(--row) * var(--slant)); }
  .out .btn { --btn-bg: var(--ink); --btn-fg: var(--light); }

  .foot { position: absolute; left: 0; right: 0; bottom: 0; padding: 16px var(--pad); }

  /* Out-now layouts (releasedLayout in config.js). "a" is the default: she stays centred.
     "b"  she stands to the right, the words get the wall on the left
     "c"  she stands to the left, the words sit on the right
     "d"  closer: the room comes forward, she is larger and a little right of centre
     On a phone all four look the same: there she already fills the screen. */
  [data-state="released"][data-layout="b"] .scene { --dx: 13vw; }
  [data-state="released"][data-layout="c"] .scene { --dx: -13vw; }
  [data-state="released"][data-layout="d"] .scene { --dx: 9vw; --zoom: 1.26; }

  [data-state="released"][data-layout="b"] .out,
  [data-state="released"][data-layout="b"] .out__word { --fs: min(15vh, 8.2vw); }
  [data-state="released"][data-layout="c"] .out { left: auto; right: max(var(--pad), calc(50% - 900px)); }
}

/* when the clock reaches zero while someone is watching, she moves to her out-now place */
@media (prefers-reduced-motion: no-preference) {
  .is-turning .scene__room { transition: transform 1.6s var(--ease); }
}

/* ---------------------------------------------------------------- listen */

.listen {
  background: var(--deep);
  color: var(--light);
  padding: clamp(44px, 9vh, 104px) var(--pad) clamp(56px, 11vh, 128px);
}
.listen__grid {
  display: grid; gap: clamp(36px, 5vw, 76px);
  max-width: 1240px; margin: 0 auto;
}
.player__poster {
  display: grid; grid-template-columns: minmax(112px, 40%) minmax(0, 1fr);
  gap: clamp(16px, 2.6vw, 32px);
  align-items: end;
}
.player__poster img { display: block; width: 100%; height: auto; }
.player__title { margin: 0; font-size: clamp(18px, 2.1vw, 28px); font-weight: 700; line-height: 1.1; }
.player__artist { margin: 4px 0 20px; font-size: clamp(16px, 1.5vw, 20px); }
.player__note { margin: 14px 0 0; font-size: 13px; line-height: 1.4; max-width: 34ch; }
.player__note[data-kind="preview"] { padding: 6px 8px; border: 1px dashed currentColor; }
.player iframe { display: block; width: 100%; height: 352px; border: 0; border-radius: 12px; }

.listen__side { display: grid; gap: clamp(28px, 4vw, 44px); }
.listen__h { margin: 0 0 10px; font-size: 13px; font-weight: 400; }

/* the services sit under the player as one line of plain links */
.services__list { display: flex; flex-wrap: wrap; gap: 0 clamp(18px, 2.2vw, 30px); margin: 0; padding: 0; list-style: none; }
.services__list a {
  display: inline-block; padding: 10px 0;
  font-size: clamp(16px, 1.3vw, 18px); font-weight: 700;
  text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 5px;
}
.services__list a:hover { text-decoration-thickness: 2px; }

/* the tracklist is the type of this section: album-sleeve numbers in the album's own face */
.tracks__list { margin: 0; padding: 0; list-style: none; counter-reset: t; display: grid; gap: clamp(10px, 1.1vw, 15px); }
.tracks__list li {
  counter-increment: t;
  display: grid; grid-template-columns: 2.7em minmax(0, 1fr); align-items: baseline;
  font-size: clamp(18px, 1.65vw, 24px); line-height: 1.2;
}
.tracks__list li::before {
  content: counter(t, decimal-leading-zero);
  font: 400 0.72em/0.72 var(--font-display);
  font-feature-settings: "tnum" 1;
}
.credits { margin: 0; font-size: 13px; line-height: 1.5; max-width: 60ch; }

@media (min-width: 880px) {
  /* player and services on the left, tracklist down the right */
  .listen__grid {
    grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.9fr);
    grid-template-areas: "player side" "services side";
    grid-template-rows: auto 1fr;
    align-items: start;
    row-gap: clamp(22px, 2.6vw, 34px);
  }
  .player { grid-area: player; }
  .services { grid-area: services; }
  .listen__side { grid-area: side; }
  /* nothing for the right column yet: the player takes a comfortable single column */
  .listen--solo .listen__grid { grid-template-columns: minmax(0, 760px); grid-template-areas: "player" "services"; justify-content: start; }
}

/* ------------------------------------------------- plain pages: privacy, 404 */

.page {
  min-height: 100dvh;
  display: flex; flex-direction: column;
  background: linear-gradient(180deg, #a9cbf7 0%, #8ebcf5 46%, #6aa3e7 100%);
  color: var(--ink);
}
.page__bar { display: flex; justify-content: space-between; align-items: center; gap: 16px; padding: var(--pad); }
.page__home { display: block; width: min(320px, 62vw); color: var(--ink); }
.page__home svg { display: block; width: 100%; height: auto; overflow: visible; }
.page__main { flex: 1; width: 100%; max-width: 720px; margin: 0 auto; padding: clamp(18px, 4vh, 48px) var(--pad) clamp(48px, 9vh, 96px); }
.page__main h1 { margin: 0 0 22px; font-size: clamp(28px, 4.2vw, 44px); line-height: 1.05; letter-spacing: -0.01em; }
.page__main h2 { margin: 34px 0 8px; font-size: 18px; line-height: 1.25; }
.page__main p, .page__main li { font-size: 16px; line-height: 1.55; }
.page__main p { margin: 0 0 12px; max-width: 65ch; }
.page__main ul { margin: 0 0 12px; padding-left: 1.1em; max-width: 65ch; }
.page__main a { text-underline-offset: 3px; }
.page__meta { margin-top: 34px; font-size: 13px; }
.page__foot { padding: 16px var(--pad) max(16px, env(safe-area-inset-bottom)); font-size: 12px; }

.lost { flex: 1; display: grid; align-content: center; justify-items: start; gap: 22px; padding: var(--pad); max-width: 720px; }
.lost__code { margin: 0; font: 400 clamp(72px, 19vw, 190px)/0.72 var(--font-display); font-feature-settings: "tnum" 1; padding-left: 0.1em; }
.lost p { margin: 0; font-size: clamp(17px, 1.6vw, 21px); line-height: 1.4; }
.lost .btn { --btn-bg: var(--ink); --btn-fg: var(--light); }

/* shown only with ?demo=1 while preview is on */
.demo-flag {
  position: fixed; left: 50%; bottom: 10px; z-index: 10;
  translate: -50% 0;
  margin: 0; padding: 6px 12px;
  background: var(--light); color: var(--ink);
  border: 1px dashed var(--ink);
  font-size: 12px; white-space: nowrap;
}

/* ---------------------------------------------------------------- motion */
/* Each move has one job: the title arrives first (it is the name of the thing), then the
   date and clock, then the action. Everything travels along the lettering's slant. */

@media (prefers-reduced-motion: no-preference) {
  .title__art--line  { animation: wipe-line 1.25s var(--ease) 0.1s both; }
  .title__art--stack { animation: wipe-stack 1.1s var(--ease) 0.1s both; }
  .count__lead, .clock__row, .out__word span { animation: rise 0.9s var(--ease) both; animation-delay: calc(0.45s + var(--i, 0) * 0.07s); }
  .count__lead { animation-delay: 0.38s; }
  .notify, .out .btn { animation: fade 0.9s var(--ease) 0.75s both; }

  /* the field opening: light first, then the blade, then its word */
  .form__row .form__send { transition: transform 0.6s var(--ease); }
  .form__row .form__send span { transition: opacity 0.3s, transform 0.55s var(--ease); }
  .form__row:focus-within .form__send { transition-delay: 0.14s; }
  .form__row:focus-within .form__send span { transition-delay: 0.3s; }
  .form__row:focus-within::after { animation: glint 0.75s cubic-bezier(0.3, 0, 0.2, 1) both; }
}
@keyframes glint {
  0%   { transform: translateX(-140%) skewX(-36.5deg); opacity: 0; }
  18%  { opacity: 1; }
  100% { transform: translateX(390%) skewX(-36.5deg); opacity: 0; }
}

@keyframes wipe-line {
  from { clip-path: polygon(0 0, 0 0, -4% 100%, 0 100%); }
  to   { clip-path: polygon(0 0, 104% 0, 100% 100%, 0 100%); }
}
@keyframes wipe-stack {
  from { clip-path: polygon(0 0, 0 0, -16% 100%, 0 100%); }
  to   { clip-path: polygon(0 0, 116% 0, 100% 100%, 0 100%); }
}
@keyframes rise {
  from { opacity: 0; transform: translate(-13px, 18px); }
  to   { opacity: 1; transform: none; }
}
@keyframes fade {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: none; }
}

