/* /winyl: Winyl's page, after the iOS app's onboarding. Always black but for
 * the gallery's colour, which comes only from the covers. Winyl's own faces
 * (Playfair Display for the wordmark and headings, Inter for the rest); the
 * shell keeps the site's. Scoped to body.wy-page. Written by build_winyl.py,
 * which also gives the font URLs their content hash.
 *
 * The order (the spec's "Structure, revised a third time", 2026-10-13): the
 * arrival, the gallery, the questions, the wall with the beta card, the
 * sign-off and the footer.
 *
 * Hooks for the motion (winyl-motion.js):
 *   sections   #wy-arrival, #wy-gallery, #wy-questions, #wy-beta, each
 *              [data-wy-act] with its id's name; #wy-beta stands in
 *              .wy-finale, over the wall (.wy-ground)
 *   arrival    .wy-crate-card[data-wy-index] (17, the onboarding's first
 *              covers, z-index 17 - index: earlier covers in front), each
 *              drawn from --wy-cy (its centre, a share of the crate box's
 *              height), --wy-s (scale), --wy-t (tilt, degrees about x),
 *              --wy-shade and --wy-o; at rest they are the app's crate as
 *              the intro lands (data-wy-n = 17 - index records flipped,
 *              winyl_crate.py). At rest each draws the 240 file (the
 *              480 one is in data-wy-src-480, for a cover turning face
 *              on), and the four hidden ones carry data-wy-hidden (not
 *              rendered, so their lazy picture is not fetched): remove it
 *              to deal them in.
 *   gallery    .wy-block[data-wy-block] (home, player, album, history,
 *              stats, then web), each with its own colours (--wy-own-glow,
 *              --wy-own-label) and, but for the web, its phone
 *              (.wy-block-shot); .wy-stage, the pinned phone, ships
 *              hidden, and its .wy-screen[data-wy-for] layers (an <img>, or
 *              a <video> with data-wy-timeline) take .is-on; --wy-glow on
 *              #wy-gallery is the colour of the moment, as accents on the
 *              black: a light behind the phone, the label, a thin rule.
 *   wall       .wy-wall-plane (its data-wy-covers: every cover's small
 *              picture, by index), its .wy-wall-tile[data-wy-row]
 *              [data-wy-col][data-wy-cover] at --wy-x/--wy-y (points,
 *              scaled by --wy-u) with --wy-f (fog x seam); still, the wall
 *              is softened where the motion settles it (--wy-wall-dim,
 *              --wy-wall-drift, --wy-wall-tilt, --wy-wall-scale,
 *              --wy-wall-z on .wy-page), and does not drift; with motion
 *              the script draws the tiles and then .wy-ground-view: the
 *              wall's picture (.wy-ground-tex, drifting) under its fog
 *              (.wy-ground-fog).
 *   motion     html.wy-motion (from a line in the head, unless reduced
 *              motion is asked for) holds the hero black, the arrival's
 *              first frame, until the script starts (html.wy-still, the
 *              still hero fading in, if it does not);
 *              html.wy-motion-live (from winyl-motion.js, once it has
 *              started without fault) lays the page out for the motion:
 *              the end of this file. Without it everything is the still
 *              page: plain rows, the wall still.
 */


@font-face {
  font-family: "Playfair Display";
  src: url("/assets/fonts/PlayfairDisplay-Variable.woff2?v=4c8334e8") format("woff2");
  font-weight: 400 900;
  font-style: normal;
  font-display: block;
}

@font-face {
  font-family: "Inter";
  src: url("/assets/fonts/InterVariable-latin.woff2?v=ef65711d") format("woff2");
  font-weight: 400 700;
  font-style: normal;
  font-display: block;
}

.wy-page {
  --wy-bg: #000;
  --wy-fg: #fafaf9;
  --wy-muted: #a8a29e;
  /* body copy on the ground: light, a step down from the headings */
  --wy-text: rgb(250 250 249 / 0.88);
  /* the page's side margin from a phone up */
  --wy-gutter: max(20px, 5vw);
  --wy-serif: "Playfair Display", Georgia, serif;
  --wy-sans: "Inter", -apple-system, BlinkMacSystemFont, "Helvetica Neue", Arial, sans-serif;
  /* the header above the stage (winyl.js measures it; these are its heights
     with the announcement bar, for when no script runs) */
  --wy-head: 126px;
  /* the hero: a window under the header, at least 560 tall */
  --wy-hero-h: max(calc(100svh - var(--wy-head)), 560px);
  /* the app scales the wall by the screen's width over 393 points; a wide
     window would show two rows, so it stops growing */
  --wy-u: min(calc(100vw / 393), 1.75px);
  /* the wall, still: as the motion settles it (winyl-motion.js's
     SETTLE), from WallStage's 0.52, 40deg, 0.72 and -120 */
  --wy-wall-dim: 0.6;
  --wy-wall-drift: 0;
  --wy-wall-tilt: 38deg;
  --wy-wall-scale: 0.74;
  --wy-wall-z: -112;
  /* SwiftUI's .smooth (a spring without bounce), as a curve: over 1.03 s
     it is .smooth(duration: 0.7), over 0.66 s .smooth(duration: 0.45) */
  --wy-smooth: linear(0, 0.006 1.2%, 0.044 3.6%, 0.133 6.9%, 0.266 10.9%, 0.421 15.6%, 0.573 20.8%,
    0.705 26.6%, 0.808 33%, 0.882 39.8%, 0.931 47.1%, 0.962 54.9%, 0.98 63.1%, 0.99 71.7%, 0.995 80.8%, 0.998 90.2%, 1);
  --wy-spring: linear(0, 0.21 6%, 0.56 14%, 0.86 24%, 1.03 34%, 1.065 42%, 1.055 50%, 1.02 62%, 0.996 76%, 1);
  color-scheme: dark;
}

@supports not (height: 100svh) {
  .wy-page { --wy-hero-h: max(calc(100vh - var(--wy-head)), 560px); }
}
@media (min-width: 768px) { .wy-page { --wy-head: 171px; } }
@media (min-width: 1024px) { .wy-page { --wy-head: 154px; } }
@media (min-width: 1440px) { .wy-page { --wy-head: 193px; } }
@media (min-width: 1920px) { .wy-page { --wy-head: 226px; } }

html:has(.wy-page), body.wy-page, .wy-page #siteWrapper, .wy-page #page { background: var(--wy-bg); }
.wy-page #header { position: relative; }
.wy-page .header .header-background, .wy-page .header-menu .header-menu-bg { background: var(--wy-bg) !important; }

.wy {
  color: var(--wy-fg);
  font: 400 16px/1.5 var(--wy-sans);
  letter-spacing: -0.006em;
  font-synthesis: none;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: clip;
}
.wy *, .wy *::before, .wy *::after { box-sizing: border-box; }
.wy [hidden] { display: none !important; }
.wy-page .wy h1, .wy-page .wy h2, .wy-page .wy p { margin: 0; letter-spacing: inherit; text-transform: none; }
.wy-page .wy p { font: inherit; color: inherit; }
.wy-page .wy a { color: inherit; }
.wy-page .wy :focus-visible { outline: 2px solid var(--wy-fg); outline-offset: 3px; }

.wy-act { position: relative; }

/* ------------------------------------------------------------------ glass */

/* Glass, as near Apple's Liquid Glass as a page gets: two layers under the
   card's words, both seeing the page behind it (so the card itself has no
   backdrop-filter, opacity, filter or mask: any of those would make it the
   backdrop root and its layers would see nothing). ::before is the body,
   the colours behind blurred and lifted under the app's dark tint, with a
   soft light inside the top; ::after is the edge, a narrow band where the
   colours come through brighter, richer and less blurred, as if bent by the
   glass's rim, and the rim's own light, strongest along the top. The glass
   is meant to move over what is behind it: on /winyl the ground stays put
   and the cards scroll. Without backdrop-filter, the app's own fallback. */
.wy-glass {
  position: relative;
  isolation: isolate;
  --wy-tint: 0.32;
  --wy-edge: 18px;
}
.wy-glass::before,
.wy-glass::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  pointer-events: none;
}
.wy-glass::before {
  background:
    linear-gradient(rgb(255 255 255 / 0.07), rgb(255 255 255 / 0) 42%),
    rgb(0 0 0 / var(--wy-tint));
  -webkit-backdrop-filter: blur(22px) saturate(1.5);
  backdrop-filter: blur(22px) saturate(1.5);
  box-shadow:
    0 30px 70px -30px rgb(0 0 0 / 0.75),
    0 2px 6px -2px rgb(0 0 0 / 0.35),
    inset 0 26px 34px -30px rgb(255 255 255 / 0.28);
}
.wy-glass::after {
  -webkit-backdrop-filter: blur(4px) saturate(1.8) brightness(1.22);
  backdrop-filter: blur(4px) saturate(1.8) brightness(1.22);
  box-shadow:
    inset 0 1px 0.5px rgb(255 255 255 / 0.6),
    inset 1px 0 0.5px -0.5px rgb(255 255 255 / 0.22),
    inset -1px 0 0.5px -0.5px rgb(255 255 255 / 0.14),
    inset 0 -1px 0.5px rgb(255 255 255 / 0.2),
    inset 0 0 0 0.5px rgb(255 255 255 / 0.12);
  -webkit-mask:
    linear-gradient(to right, #000, rgb(0 0 0 / 0) var(--wy-edge), rgb(0 0 0 / 0) calc(100% - var(--wy-edge)), #000),
    linear-gradient(to bottom, #000, rgb(0 0 0 / 0) var(--wy-edge), rgb(0 0 0 / 0) calc(100% - var(--wy-edge)), #000);
  mask:
    linear-gradient(to right, #000, rgb(0 0 0 / 0) var(--wy-edge), rgb(0 0 0 / 0) calc(100% - var(--wy-edge)), #000),
    linear-gradient(to bottom, #000, rgb(0 0 0 / 0) var(--wy-edge), rgb(0 0 0 / 0) calc(100% - var(--wy-edge)), #000);
}
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .wy-glass::before { background: rgb(20 20 20 / 0.85); box-shadow: 0 30px 70px -30px rgb(0 0 0 / 0.75); }
  .wy-glass::after { -webkit-mask: none; mask: none; box-shadow: inset 0 0 0 0.75px rgb(255 255 255 / 0.2), inset 0 1px 0 rgb(255 255 255 / 0.3); }
}

/* The onboarding's card: 38 corners, 26/20/20 inside, at most 520 wide,
   14 from a phone's edges; Playfair's title (28) over Inter at 16, muted,
   centred. In the beta card (Adam, 2026-10-14: "so many type styles it
   hurts the eyes") the title is the one Playfair; every other line, the
   field and the button are Inter at 16, regular, but the button and the
   thanks' address at 600, and the secondary lines (the line under the
   title, winyl.app's, the sign-off) one muted white. */
.wy-card {
  --wy-card-muted: rgb(250 250 249 / 0.76);
  width: min(520px, 100% - 28px);
  margin-inline: auto;
  padding: 26px 20px 20px;
  border-radius: 38px;
  text-align: center;
}
.wy-page .wy .wy-card-title {
  font: 400 28px/1.18 var(--wy-serif);
  letter-spacing: 0;
  color: var(--wy-fg);
  text-wrap: balance;
}
.wy-page .wy .wy-card-text {
  margin-top: 10px;
  font-size: 16px;
  line-height: 1.5;
  /* lighter than the page's muted grey: it stands on the covers' colours */
  color: var(--wy-card-muted);
  text-wrap: pretty;
}

/* ---------------------------------------------------------------- buttons */

.wy-page .wy .wy-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.3em;
  min-height: 50px;
  padding: 0 24px;
  border: 0;
  border-radius: 999px;
  font: 600 16px/1 var(--wy-sans);
  letter-spacing: -0.01em;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  transition: background-color 0.2s ease, color 0.2s ease, opacity 0.2s ease;
}
.wy-page .wy .wy-btn-prominent { background: #fff; color: #000; }
.wy-page .wy .wy-btn-prominent:hover { background: #e7e5e4; }
/* a glass button: the glass in one layer, the rim's light in its shadows */
.wy-page .wy .wy-btn-glass {
  color: var(--wy-fg);
  background: linear-gradient(rgb(255 255 255 / 0.1), rgb(255 255 255 / 0.04));
  -webkit-backdrop-filter: blur(16px) saturate(1.9);
  backdrop-filter: blur(16px) saturate(1.9);
  box-shadow:
    inset 0 1px 0.5px rgb(255 255 255 / 0.5),
    inset 0 -1px 0.5px rgb(255 255 255 / 0.14),
    inset 0 0 0 0.75px rgb(255 255 255 / 0.18),
    inset 0 12px 16px -12px rgb(255 255 255 / 0.18),
    0 8px 20px -10px rgb(0 0 0 / 0.6);
}
.wy-page .wy .wy-btn-glass:hover { background: rgb(255 255 255 / 0.13); }
.wy-out { font-size: 0.85em; transform: translateY(-0.08em); opacity: 0.8; }
.wy-page .wy .wy-btn:disabled { cursor: default; opacity: 0.55; }

/* ------------------------------------------------------- act 1, arrival */

.wy-arrival {
  --wy-crate-h: min(var(--wy-hero-h), calc(100vw / 0.6));
  --wy-mark: clamp(64px, 3.6vw + 44px, 124px);
  /* how far under the buttons the pile's first sliver starts */
  --wy-pile-gap: clamp(28px, 4.5svh, 52px);
  display: flex;
  flex-direction: column;
  align-items: center;
  min-height: var(--wy-hero-h);
  /* the wordmark, words, buttons and the pile under them, as one block,
     centred in the window under the header (Adam, 2026-10-13: the
     wordmark on the app's viewing line, 0.48 down, sat the pile on the
     window's foot) */
  justify-content: center;
  overflow: hidden;
}

.wy-arrival-copy {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 100%;
  padding-inline: 14px;
  text-align: center;
}

/* The crate, laid out as the app lays out a phone's: a box 0.6 as wide as
   tall. At rest every cover has flipped into the pile below the viewing
   line, so the box hangs from the copy's foot: the first sliver (the
   record just flipped, its top 0.837 down the box) starts --wy-pile-gap
   under the buttons at every width, and the stage grows rather than let
   the two touch. .wy-crate-pile is the strip the pile shows in. */
.wy-crate-pile {
  --wy-pile-top: 0.837;
  --wy-pile-foot: 0.955;
  position: relative;
  width: 100%;
  flex: 0 0 auto;
  height: calc(var(--wy-pile-gap) + (var(--wy-pile-foot) - var(--wy-pile-top)) * var(--wy-crate-h));
  pointer-events: none;
}
.wy-crate,
.wy-crate-veil {
  position: absolute;
  top: calc(var(--wy-pile-gap) - var(--wy-pile-top) * var(--wy-crate-h));
  height: var(--wy-crate-h);
}
.wy-crate {
  left: 50%;
  aspect-ratio: 0.6;
  transform: translateX(-50%);
  container-type: size;
}
.wy-crate-card {
  --wy-side: calc(var(--wy-side-of-h) * 100cqh);
  position: absolute;
  left: 50%;
  top: 0;
  width: var(--wy-side);
  aspect-ratio: 1;
  margin-left: calc(var(--wy-side) / -2);
  opacity: var(--wy-o);
  transform:
    translateY(calc(var(--wy-cy) * 100cqh - var(--wy-side) / 2))
    scale(var(--wy-s));
  /* the app's perspective, on the card for its face's tilt: a perspective()
     inside the card's own transform drew the resting slivers in Safari as
     large tilted covers over the buttons (2026-10-13) */
  perspective: calc(var(--wy-side) / 0.35);
}
.wy-crate-face {
  position: relative;
  width: 100%;
  height: 100%;
  border-radius: var(--wy-radius);
  overflow: hidden;
  transform: rotateX(calc(var(--wy-t) * 1deg));
  backface-visibility: hidden;
}
.wy-crate-card[data-wy-hidden] { display: none; }
.wy-crate-face img { display: block; width: 100%; height: 100%; }
/* light and shade, drawn on the cover so it tilts with it */
.wy-crate-face::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(rgb(0 0 0 / 0.3), rgb(0 0 0 / 0.65));
  opacity: var(--wy-shade);
}
/* the crate's veil, across the whole stage: the flipped records slide
   behind it into the black */
.wy-crate-veil {
  inset-inline: 0;
  background: linear-gradient(to bottom, rgb(0 0 0 / 0) var(--wy-veil-start), #000 var(--wy-veil-end));
}

.wy-page .wy .wy-wordmark {
  font: 400 var(--wy-mark)/1.333 var(--wy-serif);
  letter-spacing: 0;
  color: var(--wy-fg);
}
.wy-page .wy .wy-tagline {
  margin-top: 2px;
  font: 400 clamp(22px, 0.9vw + 17px, 30px)/1.25 var(--wy-serif);
  letter-spacing: 0;
  color: var(--wy-fg);
}
.wy-page .wy .wy-line {
  margin-top: 10px;
  font-size: clamp(16px, 0.25vw + 15px, 18px);
  line-height: 1.45;
  color: var(--wy-muted);
  text-wrap: balance;
}
.wy-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 10px;
  margin-top: 28px;
}

/* Replay the intro (Adam, 2026-10-14), made by winyl-motion.js, so only
   with motion: under the pile, in a slot of no height, so the centred
   block does not move for it; the muted grey, no fill, no glass, the
   site's white on hover and focus. It shows once the arrival has landed. */
.wy-replay-slot {
  position: relative;
  z-index: 1;
  display: flex;
  justify-content: center;
  width: 100%;
  height: 0;
}
.wy-page .wy .wy-replay {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 44px;
  margin-top: 2px;
  padding: 0 12px;
  border: 0;
  border-radius: 22px;
  background: none;
  color: var(--wy-muted);
  font: 500 13px/1 var(--wy-sans);
  letter-spacing: 0.01em;
  cursor: pointer;
  opacity: 0.85;
  transition: color 0.2s ease, opacity 0.2s ease;
  -webkit-tap-highlight-color: transparent;
}
.wy-replay svg { display: block; width: 14px; height: 14px; }
.wy-page .wy .wy-replay:is(:hover, :focus-visible) { color: var(--wy-fg); opacity: 1; }
html.wy-motion-live:not(.wy-arrived) .wy-replay { visibility: hidden; opacity: 0; transition: none; }
html.wy-arrived .wy-replay { animation: wy-replay-in 0.6s ease 0.4s backwards; }
@keyframes wy-replay-in { from { opacity: 0; } }

/* ------------------------------------------------------ the wall, the end */

/* The end stands on the wall (still .wy-ground): sticky in its wrapper (its
   negative margin leaves it no height in the flow, and the wrapper clips
   it), so it stays behind the beta card while the card is on screen (the
   spec: "the wall stays behind the card"). Still (no script, Reduce
   Motion, a fault), it is the wall softened where it rests, its top rising
   out of the black and its foot fading to black before the footer; with
   motion, the covers bloom out onto it (the end of this file). */
.wy-finale {
  position: relative;
  overflow: clip;
  isolation: isolate;
}
.wy-ground {
  position: sticky;
  top: 0;
  z-index: 0;
  height: 100vh;
  height: 100lvh;
  margin-bottom: -100vh;
  margin-bottom: -100lvh;
  overflow: hidden;
  pointer-events: none;
}
.wy-finale > .wy-act { z-index: 2; }
.wy-finale::before,
.wy-finale::after {
  content: "";
  position: absolute;
  inset-inline: 0;
  z-index: 1;
  pointer-events: none;
}
.wy-finale::before { top: 0; height: 45svh; background: linear-gradient(#000 15%, rgb(0 0 0 / 0)); }
.wy-finale::after { bottom: 0; height: 75svh; background: linear-gradient(rgb(0 0 0 / 0), rgb(0 0 0 / 0.85) 55%, #000); }

.wy-wall-view {
  position: absolute;
  inset: 0;
  perspective: calc(820 * var(--wy-u));
  perspective-origin: 50% 10%;
  /* the ground: the wall, softened a little (what the motion settles on) */
  filter: blur(calc(2.2 * var(--wy-u)));
}
.wy-wall-plane {
  --wy-pitch: calc((var(--wy-tile) + 10) * var(--wy-u));
  position: absolute;
  left: 50%;
  top: 36.5%;
  width: 0;
  height: 0;
  transform-origin: 0 0;
  transform:
    translateZ(calc(var(--wy-wall-z) * var(--wy-u)))
    rotateX(var(--wy-wall-tilt))
    scale(var(--wy-wall-scale))
    translateY(calc(var(--wy-wall-drift) * var(--wy-pitch)));
}
.wy-wall-tile {
  position: absolute;
  left: calc(var(--wy-x) * var(--wy-u));
  top: calc(var(--wy-y) * var(--wy-u));
  width: calc(var(--wy-tile) * var(--wy-u));
  height: calc(var(--wy-tile) * var(--wy-u));
  max-width: none;
  border-radius: calc(var(--wy-tile-radius) * var(--wy-u));
  /* dimmed towards black: on black, opacity is the app's brightness */
  opacity: calc(var(--wy-wall-dim) * var(--wy-f));
}
/* the edges blurred through the app's ellipse (only the sharp wall of the
   bloom has them) */
.wy-wall-edges {
  position: absolute;
  inset: 0;
  display: none;
  -webkit-backdrop-filter: blur(calc(5 * var(--wy-u)));
  backdrop-filter: blur(calc(5 * var(--wy-u)));
  -webkit-mask-image: radial-gradient(ellipse 62% 46% at 50% 44%, transparent 45%, #000 100%);
  mask-image: radial-gradient(ellipse 62% 46% at 50% 44%, transparent 45%, #000 100%);
}
.wy-wall-vignette {
  position: absolute;
  inset: 0;
  opacity: 0.7;
  background:
    linear-gradient(to bottom, #000 0, rgb(0 0 0 / 0) calc(150 * var(--wy-u)), rgb(0 0 0 / 0) 70%, rgb(0 0 0 / 0.6) 100%),
    radial-gradient(ellipse 75% 60% at 50% 42%, rgb(0 0 0 / 0) 40%, rgb(0 0 0 / 0.85) 100%);
}


/* ---------------------------------------------------------------- gallery */

/* The colour of the moment, from the cover leading on the phone's screen
   (winyl_colour.py): --wy-glow, the cover's own CoverTone. Registered, so
   it changes smoothly. */
@property --wy-glow { syntax: "<color>"; inherits: true; initial-value: #000; }

/* Short blocks of words, each a small label, a heading and a sentence or
   two, after Apple's Apple TV 4K page. Still (no script, Reduce Motion, a
   fault) they are plain rows, each with its own phone and in its own
   colour; with motion one phone is pinned beside them (the end of this
   file). */
.wy-gallery {
  --wy-ph: min(66svh, 920px, 82vw);
  position: relative;
  padding-block: clamp(64px, 9vw, 150px) clamp(40px, 5vw, 80px);
}
.wy-gallery-in {
  position: relative;
  z-index: 1;
  width: min(1120px, 100% - 2 * var(--wy-gutter));
  margin-inline: auto;
}
.wy-block {
  --wy-glow: var(--wy-own-glow);
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 28rem) auto;
  justify-content: space-between;
  align-items: center;
  column-gap: clamp(40px, 6vw, 120px);
  padding-block: clamp(48px, 6vw, 100px);
}
.wy-page .wy .wy-block-shot {
  position: relative;
  order: 2;
  width: min(clamp(220px, 24vw, 300px), 66svh / 2.0444);
  margin: 0;
  justify-self: center;
}
.wy-block-shot img { position: relative; display: block; width: 100%; height: auto; }
/* a soft light of the cover's colour behind the phone */
.wy-block-shot::before,
.wy-glow {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  width: 190%;
  aspect-ratio: 1;
  transform: translate(-50%, -50%);
  background: radial-gradient(closest-side,
    color-mix(in oklab, var(--wy-glow) 34%, transparent),
    color-mix(in oklab, var(--wy-glow) 10%, transparent) 58%,
    transparent);
  pointer-events: none;
}

.wy-words { position: relative; }
/* the small label: an icon and a word, in the cover's colour lifted to
   7.5:1 on black */
.wy-page .wy .wy-label {
  display: flex;
  align-items: center;
  gap: 8px;
  font: 600 15px/1.2 var(--wy-sans);
  letter-spacing: 0;
  color: var(--wy-own-label);
}
.wy-label-icon {
  flex: none;
  width: 16px;
  height: 16px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.4;
  stroke-linecap: round;
  stroke-linejoin: round;
}
/* a thin rule of the cover's colour over the label */
.wy-words::before {
  content: "";
  display: block;
  width: 36px;
  height: 1px;
  margin-bottom: 18px;
  background: var(--wy-own-glow);
  opacity: 0.8;
}
.wy-page .wy .wy-block-title {
  margin-top: 12px;
  font: 400 clamp(30px, 1.5vw + 22px, 46px)/1.1 var(--wy-serif);
  letter-spacing: -0.01em;
  color: var(--wy-fg);
  text-wrap: balance;
}
.wy-page .wy .wy-block-text {
  margin-top: clamp(12px, 1vw, 18px);
  max-width: 26em;
  font-size: clamp(17px, 0.25vw + 16px, 20px);
  line-height: 1.55;
  color: var(--wy-text);
  text-wrap: pretty;
}
.wy-block-text a, .wy-qa-a a {
  color: var(--wy-fg) !important;
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
}

/* winyl.app on a Mac, a block of its own after the phone (it does not fit
   a phone's screen): the words, then the coverflow, cut to its covers, at
   its own size or smaller, whole from 768 up */
.wy-page .wy .wy-block-web {
  display: block;
  width: min(1120px, 100% - 2 * var(--wy-gutter));
  margin-inline: auto;
  padding-block: clamp(56px, 8vw, 140px) 0;
}
.wy-block-web .wy-words { max-width: 30rem; }
.wy-page .wy .wy-web-shot {
  position: relative;
  width: min(var(--wy-w), 100%);
  margin: clamp(32px, 4vw, 56px) auto 0;
}
.wy-web-shot::before {
  content: "";
  position: absolute;
  inset: -20% -10%;
  background: radial-gradient(closest-side,
    color-mix(in oklab, var(--wy-glow) 26%, transparent),
    color-mix(in oklab, var(--wy-glow) 8%, transparent) 60%,
    transparent);
  pointer-events: none;
}
.wy-web-shot img { position: relative; display: block; width: 100%; height: auto; }

/* the pinned phone: its frame over the screens, which cross-fade (the
   script hides all but the leading one from a screen reader) */
.wy-stage { display: none; }
.wy-device {
  position: relative;
  height: var(--wy-ph);
  aspect-ratio: 900 / 1840;
  margin-inline: auto;
}
.wy-screens {
  position: absolute;
  left: var(--wy-screen-l);
  top: var(--wy-screen-t);
  width: var(--wy-screen-w);
  height: var(--wy-screen-h);
  border-radius: var(--wy-screen-rx) / var(--wy-screen-ry);
  overflow: hidden;
  background: #0a0a0a;
}
.wy-page .wy .wy-screen {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  max-width: none;
  object-fit: cover;
  opacity: 0;
  transition: opacity 0.55s cubic-bezier(0.33, 1, 0.68, 1);
}
.wy-page .wy .wy-screen.is-on { opacity: 1; }
.wy-frame { position: absolute; inset: 0; display: block; width: 100%; height: 100%; pointer-events: none; }

/* ------------------------------------------------------------- questions */

/* A collapsed list: one native <details> per question, closed to start,
   in the site's disclosure look (thin rules, a 1px plus that turns minus),
   the question in Playfair, the answer in Inter. */
.wy-questions {
  width: min(820px, 100% - 2 * var(--wy-gutter));
  margin-inline: auto;
  padding-block: clamp(96px, 11vw, 180px) clamp(56px, 7vw, 110px);
}
.wy-page .wy .wy-questions-title {
  font: 400 clamp(30px, 1.5vw + 22px, 46px)/1.1 var(--wy-serif);
  letter-spacing: -0.01em;
  color: var(--wy-fg);
}
.wy-qa {
  margin-top: clamp(24px, 3vw, 40px);
  border-bottom: 1px solid rgb(250 250 249 / 0.24);
}
.wy-qa-item { border-top: 1px solid rgb(250 250 249 / 0.24); }
.wy-qa-summary {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  column-gap: 1em;
  padding: 20px 0;
  list-style: none;
  cursor: pointer;
}
.wy-qa-summary::-webkit-details-marker { display: none; }
.wy-page .wy .wy-qa-summary:focus-visible { outline: 2px solid var(--wy-fg); outline-offset: 2px; }
.wy-page .wy .wy-qa-q {
  margin: 0;
  font: 400 clamp(20px, 0.5vw + 17px, 25px)/1.3 var(--wy-serif);
  letter-spacing: 0;
  text-transform: none;
  color: var(--wy-fg);
}
/* the plus, centred on the question's first line: two 1px strokes, the
   upright one folding away when open */
.wy-qa-icon {
  --wy-icon: 14px;
  position: relative;
  flex: none;
  width: var(--wy-icon);
  height: var(--wy-icon);
  margin-top: calc((1.3em - var(--wy-icon)) / 2);
  font-size: clamp(20px, 0.5vw + 17px, 25px);
  color: var(--wy-fg);
}
.wy-qa-icon::before,
.wy-qa-icon::after {
  content: "";
  position: absolute;
  background: currentColor;
}
.wy-qa-icon::before { left: 0; right: 0; top: calc(50% - 0.5px); height: 1px; }
.wy-qa-icon::after { top: 0; bottom: 0; left: calc(50% - 0.5px); width: 1px; transition: transform 0.15s ease; }
.wy-qa-item[open] > summary > .wy-qa-icon::after { transform: scaleY(0); }
.wy-qa-a { padding: 0 0 24px; }
.wy-page .wy .wy-qa-a p {
  max-width: 36em;
  font-size: 17px;
  line-height: 1.55;
  color: var(--wy-text);
  text-wrap: pretty;
}

/* Stacked below 768: the phone, then its words */
@media (max-width: 767px) {
  .wy-block { grid-template-columns: minmax(0, 1fr); row-gap: 32px; }
  .wy-page .wy .wy-block-shot { order: 0; width: min(260px, 64vw); }
  /* the coverflow: a cut the window's width, its middle, the covers at a
     size a phone can read (never past their own) */
  .wy-page .wy .wy-web-shot {
    width: 100vw;
    max-width: none;
    margin-inline: calc(50% - 50vw);
    overflow: hidden;
  }
  .wy-page .wy .wy-web-shot img {
    width: auto;
    max-width: none;
    height: min(300px, var(--wy-w) / var(--wy-ratio));
    margin-left: calc(50vw - min(300px, var(--wy-w) / var(--wy-ratio)) * var(--wy-ratio) / 2);
  }
}

/* ------------------------------------------------------------------ beta */

/* the card over the wall: in the still, some of the wall above it. Below
   it, room enough that at the page's foot the card stands a little above
   the window's middle (Adam, 2026-10-14: "this form should be a bit
   higher"): its middle at about 46% of the window, the sign-off close
   under it. The room is the window's 54% less half the card (about 113,
   or 171 below 768, where it is taller), the sign-off (44) and the
   footer (113), and never less than it was. */
.wy-beta {
  padding-block: clamp(140px, 30svh, 320px) max(clamp(72px, 9vw, 128px), 54svh - 270px);
  text-align: center;
}
@media (max-width: 767px) {
  .wy-beta { padding-bottom: max(72px, 54svh - 376px); }
}
.wy-form { margin-top: 20px; }
.wy-form-row {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}
.wy-page .wy .wy-field {
  flex: 1 1 210px;
  min-width: 0;
  height: 50px;
  margin: 0;
  padding: 0 20px;
  border: 0;
  border-radius: 999px;
  background: rgb(255 255 255 / 0.07);
  box-shadow: inset 0 0 0 0.75px rgb(255 255 255 / 0.24), inset 0 1px 0 rgb(255 255 255 / 0.12);
  color: var(--wy-fg);
  font: 400 16px/1 var(--wy-sans);
  letter-spacing: -0.006em;
  outline: none;
  transition: box-shadow 0.2s ease, background-color 0.2s ease;
}
.wy-page .wy .wy-field::placeholder { color: rgb(250 250 249 / 0.6); opacity: 1; }
.wy-page .wy .wy-field:focus-visible {
  outline: none;
  background: rgb(255 255 255 / 0.1);
  box-shadow: inset 0 0 0 1.5px rgb(250 250 249 / 0.85);
}
.wy-page .wy .wy-field[aria-invalid="true"] { box-shadow: inset 0 0 0 1.5px rgb(250 250 249 / 0.85); }
.wy-page .wy .wy-submit { flex: 1 0 auto; }
.wy-form.is-busy .wy-submit { cursor: progress; }
.wy-form.is-busy .wy-submit::after {
  content: "";
  width: 14px;
  height: 14px;
  margin-left: 6px;
  border-radius: 50%;
  border: 2px solid currentColor;
  border-right-color: transparent;
  animation: wy-spin 0.8s linear infinite;
}
@keyframes wy-spin { to { transform: rotate(1turn); } }
.wy-turnstile:not(:empty) { margin-top: 12px; }
.wy-page .wy .wy-form-status {
  margin-top: 14px;
  padding: 11px 16px;
  border-radius: 18px;
  background: rgb(255 255 255 / 0.06);
  box-shadow: inset 0 0 0 0.75px rgb(255 255 255 / 0.14);
  color: var(--wy-fg);
  font-size: 16px;
  line-height: 1.5;
  overflow-wrap: anywhere;
}
.wy-form-status a, .wy-noscript a, .wy-beta-web a {
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
}
.wy-honeypot {
  position: absolute;
  left: -5000px;
  width: 1px;
  height: 1px;
  overflow: hidden;
  opacity: 0;
  pointer-events: none;
}
.wy-page .wy .wy-noscript {
  margin-top: 14px;
  color: var(--wy-card-muted);
  font-size: 16px;
  line-height: 1.5;
}
.wy-page .wy .wy-thanks {
  margin-top: 20px;
  font-size: 16px;
  line-height: 1.5;
  color: var(--wy-fg);
  overflow-wrap: anywhere;
  outline: none;
}
.wy-thanks-address { font-weight: 600; }
/* winyl.app's line: the body's size and muted white, its link underlined
   in the same colour (no arrow: the new tab is said to screen readers) */
.wy-page .wy .wy-beta-web {
  margin-top: 18px;
  font-size: 16px;
  line-height: 1.5;
  color: var(--wy-card-muted);
}
.wy-beta-web a { color: inherit !important; }
/* the sign-off: secondary, the card's own text style, close under it */
.wy-page .wy .wy-signoff {
  --wy-card-muted: rgb(250 250 249 / 0.76);
  margin-top: 20px;
  padding-inline: 14px;
  font: 400 16px/1.5 var(--wy-sans);
  letter-spacing: 0;
  color: var(--wy-card-muted);
}

/* ---------------------------------------------------------------- footer */

.wy-wrap { width: 88%; max-width: 1320px; margin-inline: auto; }
.wy-foot { border-top: 1px solid #1c1c1b; padding-block: 2.5rem; }
.wy-foot .wy-wrap { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 1.5rem; }
.wy-page .wy a.wy-foot-mark {
  font-family: var(--site-title-font-font-family, "Lily Script One"), cursive;
  font-size: 2rem;
  line-height: 1;
  letter-spacing: 0;
  color: var(--wy-fg);
  text-decoration: none;
}
.wy-social { list-style: none; margin: 0; padding: 0; display: flex; gap: 14px; }
.wy-social li { margin: 0; }
.wy-social li::before { content: none; }
/* grey at rest (#6d6d6d, 3.9:1 on black), the page's white under the
   pointer and on keyboard focus, as on every footer of the site */
.wy-page .wy .wy-social a { display: block; width: 24px; height: 24px; color: #6d6d6d; text-decoration: none; transition: color 0.15s ease; }
.wy-page .wy .wy-social a:hover, .wy-page .wy .wy-social a:focus-visible { color: var(--wy-fg); }
.wy-social svg { display: block; width: 100%; height: 100%; fill: currentColor; }
/* on a phone, one row as on the homepage: the wordmark at the size the
   site's footer draws it there (by the window's height, as the site does),
   the icons against the right margin, centred on each other. Under 375 the
   icons close up to 8px, the space before them to 1rem, and the wordmark
   stops at its size on a 568px-tall phone, so the row still fits at 320 (overrides.css does the same to the
   site's footer). */
@media (max-width: 767px) {
  .wy-foot .wy-wrap { flex-wrap: nowrap; }
  .wy-page .wy a.wy-foot-mark { font-size: calc(0.012 * min(100vh, 900px) + 1rem); white-space: nowrap; }
}
@media (max-width: 374px) {
  .wy-foot .wy-wrap { gap: 1rem; }
  .wy-social { gap: 8px; }
  .wy-page .wy a.wy-foot-mark { font-size: min(calc(0.012 * min(100vh, 900px) + 1rem), calc(0.012 * 568px + 1rem)); }
}

/* ---------------------------------------------------------- phone widths */

/* the narrowest phones: both buttons still on one line, above the crate */
@media (max-width: 359px) {
  .wy-arrival { --wy-mark: 56px; }
  .wy-page .wy .wy-tagline { font-size: 21px; }
  .wy-page .wy .wy-line { font-size: 15px; }
  .wy-page .wy .wy-btn { min-height: 44px; padding: 0 14px; font-size: 14px; }
  .wy-actions { gap: 8px; margin-top: 20px; }
}

/* --------------------------------------------------------- reduce motion */

/* Nothing moves; only opacity changes. */
@media (prefers-reduced-motion: reduce) {
  .wy-page .wy .wy-btn { transition: none; }
  .wy-form.is-busy .wy-submit::after { animation: none; border-right-color: currentColor; opacity: 0.5; }
}

/* ----------------------------------------------------------------- motion */

/* Two classes. html.wy-motion comes from a line in the head, before the
   first paint, and holds the hero in the arrival's own first frame: black,
   no crate, no wordmark, no words, no buttons, as the app opens. So a
   paint before winyl-motion.js runs is the intro's start, never a still
   hero it would have to hide again. If the script has not started 1.8 s
   after the first frame, that line puts html.wy-still on and takes
   html.wy-motion off, and the still hero fades in. html.wy-motion-live
   comes from winyl-motion.js once it has started without fault, and
   everything that makes room, hides or moves hangs on it; on any fault
   the script takes both off and the page is the still one. The script
   keeps what is on screen in place when the layout changes under it. */
html.wy-motion:not(.wy-motion-live) :is(.wy-wordmark, .wy-tagline, .wy-line, .wy-actions, .wy-crate-card) { opacity: 0; }
html.wy-motion:not(.wy-motion-live) .wy-actions:focus-within { opacity: 1; }
html.wy-still :is(.wy-wordmark, .wy-tagline, .wy-line, .wy-actions, .wy-crate-card) { transition: opacity 0.6s cubic-bezier(0.33, 1, 0.68, 1); }

/* The arrival starts black: the crate is dealt in, the wordmark and the
   words come in as it lands, then the buttons rise. After it the hero
   simply scrolls away. */
html.wy-motion-live:not(.wy-arrived) :is(.wy-wordmark, .wy-tagline, .wy-line, .wy-actions, .wy-crate-card) { opacity: 0; }
/* the intro's crate may be drawn smaller than the still's, from the top of
   its box (the script), which clips it as the app's screen does */
html.wy-motion-live :is(.wy-crate, .wy-crate-veil) { transform-origin: 50% 0; }
html.wy-motion-live .wy-crate { overflow: clip; }
html.wy-motion-live .wy-actions:focus-within { opacity: 1 !important; }

/* The gallery: one iPhone pinned beside the blocks (Adam's reference, the
   Apple TV 4K page), its screen cross-fading to each block's as the block
   reaches the middle of the window. The phone is drawn much smaller than
   1:1 (Adam: "the iPhone is DEFINITELY too big"): at most two thirds of
   the window's height (--wy-ph), never past its own 450 CSS px. The plain
   rows' phones are not drawn (nor fetched: they are lazy). Before the
   script has started they wait too, so nothing loads twice. */
html.wy-motion .wy-block-shot,
html.wy-motion-live .wy-block-shot { display: none; }
html.wy-motion-live .wy-stage { display: block; }
html.wy-motion-live .wy-gallery { transition: --wy-glow 0.8s ease; }
html.wy-motion-live .wy-gallery.is-playing { transition-duration: 0.3s; }
html.wy-motion-live .wy-block { --wy-glow: inherit; }
/* the phone comes in once its frame and first screen are there (the
   script names them only as the reader starts down the page), so it is
   never seen empty */
html.wy-motion-live .wy-stage-in { position: relative; opacity: 0; transition: opacity 0.35s ease; }
html.wy-motion-live .wy-stage.is-ready .wy-stage-in { opacity: 1; }
html.wy-motion-live .wy-glow { width: calc(var(--wy-ph) * 1.15); }

@media (min-width: 768px) {
  html.wy-motion-live .wy-gallery-in {
    display: grid;
    grid-template-columns: minmax(0, 30rem) auto;
    justify-content: space-between;
    column-gap: clamp(40px, 6vw, 120px);
  }
  html.wy-motion-live .wy-stage {
    grid-column: 2;
    grid-row: 1;
    align-self: start;
    position: sticky;
    top: calc((100svh - var(--wy-ph)) / 2);
    padding-inline: clamp(0px, 4vw, 72px);
  }
  /* the gallery starts with the phone, close under the hero */
  html.wy-motion-live .wy-gallery { padding-top: clamp(16px, 2vw, 32px); }
  /* each block 62% of a window tall (Adam, 2026-10-14: a window each left
     the words' side a long black stretch), its words centred; the first
     and last reach past the row by half the phone less half a block, so
     the first block's words stand level with the phone's middle as the
     phone pins, and the last's as it leaves */
  html.wy-motion-live .wy-gallery { --wy-bh: 62svh; }
  html.wy-motion-live .wy-blocks {
    grid-column: 1;
    grid-row: 1;
    margin-block: calc((var(--wy-ph) - var(--wy-bh)) / 2);
  }
  html.wy-motion-live .wy-blocks > .wy-block {
    display: flex;
    align-items: center;
    min-height: var(--wy-bh);
    padding-block: 0;
  }
}
/* Below 768 the phone pins at the top, smaller, and the words scroll up
   under it, over the page's black */
@media (max-width: 767px) {
  html.wy-motion-live .wy-gallery { --wy-ph: min(44svh, 380px); }
  html.wy-motion-live .wy-stage {
    position: sticky;
    top: 0;
    z-index: 2;
    padding: 14px 0 44px;
    margin-inline: calc(-1 * var(--wy-gutter));
    background: linear-gradient(#000 calc(100% - 44px), rgb(0 0 0 / 0));
  }
  html.wy-motion-live .wy-blocks > .wy-block {
    display: block;
    min-height: 62svh;
    padding-block: 4svh 0;
  }
  html.wy-motion-live .wy-blocks { padding-bottom: 12svh; }
}

/* The end: the covers bloom out onto the wall as soon as its top comes
   into the window, from the middle of the part of it on screen; then it
   settles, softened, drifting, and the beta card rises over it. The card
   comes in 0.95 of a window after the wall's top (Adam, 2026-10-14: a
   window and a half was a long black stretch), while the covers are
   landing, so the wall has settled by the time the card is centred. The
   black over the wall's top is short, so the bloom shows as it enters. */
html.wy-motion-live .wy-beta { padding-top: 95svh; }
html.wy-motion-live .wy-finale::before { height: 12svh; background: linear-gradient(#000, rgb(0 0 0 / 0)); }
html.wy-motion-live .wy-wall-view { perspective: none; filter: none; }
html.wy-motion-live .wy-wall-plane { left: 0; top: 0; transform: none; }
html.wy-motion-live .wy-wall-tile {
  left: calc(var(--wy-tile) * var(--wy-u) / -2);
  top: calc(var(--wy-tile) * var(--wy-u) / -2);
  opacity: 0;
  border-radius: calc(var(--wy-tile-radius) * var(--wy-u));
}
html.wy-motion-live .wy-ground.is-live .wy-wall-tile { will-change: transform, filter; }
html.wy-motion-live .wy-ground:not(.is-live) .wy-wall-view { visibility: hidden; }
html.wy-motion-live .wy-wall-edges { display: block; opacity: 0; }
html.wy-motion-live .wy-wall-vignette { opacity: 0; }
/* the settled wall: its picture on the wall's plane, sliding (one
   compositor animation), under its still fog */
html.wy-motion-live .wy-ground-view { position: absolute; inset: 0; opacity: 0; }
html.wy-motion-live .wy-ground-view > canvas {
  position: absolute;
  left: 0;
  top: 0;
  max-width: none;
  transform-origin: 0 0;
  backface-visibility: hidden;
}
html.wy-motion-live .wy-ground-tex { will-change: transform; }

/* The beta card rises as it comes in (.smooth 0.7, 40 points), by
   transform only: an opacity on a glass card would leave its glass nothing
   to see. The gallery's words, the web's picture and the questions come
   up and in (winyl-motion.js marks them as they reach the window). */
html.wy-motion-live .wy-rise {
  transform: translateY(56px);
  transition: transform 1.03s var(--wy-smooth);
}
html.wy-motion-live .wy-rise:is(.is-up, :focus-within) { transform: none; }
html.wy-motion-live .wy-reveal {
  opacity: 0;
  transform: translateY(32px);
  transition: opacity 0.8s cubic-bezier(0.33, 1, 0.68, 1), transform 1.03s var(--wy-smooth);
  transition-delay: var(--wy-delay, 0s);
}
html.wy-motion-live .wy-reveal:is(.is-up, :focus-within) { opacity: 1; transform: none; }

/* Reduce Motion, with script: the plain rows and the rest fade in as they
   come into view, and the card too (opacity only). */
@media (prefers-reduced-motion: reduce) {
  .wy-fade { opacity: 0; transition: opacity 0.4s ease-out; }
  .wy-fade:is(.is-in, :focus-within) { opacity: 1; }
  .wy-page .wy .wy-screen, .wy-qa-icon::after { transition: none; }
}
