/* Kansei Link: night and day glass */

:root {
  --font-display: 'Archivo', system-ui, sans-serif;
  --font-body: 'Barlow Semi Condensed', system-ui, sans-serif;
  --font-num: 'Oxanium', system-ui, sans-serif;
  /* Zen Kaku is loaded as a text= subset (カンセイ夜昼 only); the system Japanese fonts cover anything else */
  --font-jp: 'Zen Kaku Gothic New', 'Hiragino Sans', 'Yu Gothic', YuGothic, 'Meiryo', 'Noto Sans JP', sans-serif;
  /* the banner decal and the tach: the same satin red at night and by day */
  --decal-red: #E3283F;
  --decal-red-mid: #C8102E;
  --decal-red-low: #8E0B20;
  /* words straight on the scene by day (see the day halo rules further down) */
  --on-video: #F4F6F8;
  --on-video-2: rgba(244, 246, 248, 0.9);
  --red-day: var(--decal-red-mid);
  --red-night: #E8344A;
  --r-lg: 24px;
  --r-md: 16px;
  --r-sm: 10px;
  /* one side padding for every pane, so text edges line up from pane to pane (20px on phones) */
  --pad: 28px;
  --ease: cubic-bezier(0.2, 0.7, 0.2, 1);
  --phase: 0.9s;
  --shade: 0;
}

html[data-phase="night"] {
  color-scheme: dark;
  --ink: #E8E8E8;
  --ink-2: rgba(232, 232, 232, 0.78);
  --ink-3: rgba(232, 232, 232, 0.6);
  --red: var(--red-night);
  --glass-bg: rgba(14, 18, 34, 0.52);
  --glass-line: rgba(255, 255, 255, 0.14);
  --glass-top: rgba(255, 255, 255, 0.2);
  --glass-shadow: 0 24px 48px rgba(0, 0, 0, 0.45);
  --shade-rgb: 6, 8, 16;
  --shade-max: 0.58;
  --solid-bg: #ECE8E1;
  --solid-ink: #14171C;
  --hair: rgba(255, 255, 255, 0.12);
  --btn-hover: rgba(0, 0, 0, 0.08); /* the solid button's hover overlay: a shade on the light button */
}

html[data-phase="day"] {
  color-scheme: light;
  --ink: #14171C;
  /* darker than the night pair: by day these sit on light, tinted glass and tracks and must
     still hold 4.5:1 (the theme numbers are 13px) */
  --ink-2: rgba(20, 23, 28, 0.88);
  --ink-3: rgba(20, 23, 28, 0.8);
  --red: var(--red-day);
  --glass-bg: rgba(255, 255, 255, 0.55);
  --glass-line: rgba(255, 255, 255, 0.7);
  --glass-top: rgba(255, 255, 255, 0.95);
  --glass-shadow: 0 20px 44px rgba(10, 30, 50, 0.28);
  --shade-rgb: 16, 34, 52;
  --shade-max: 0.3;
  --solid-bg: #14171C;
  --solid-ink: #F3F6F8;
  --hair: rgba(20, 23, 28, 0.12);
  --btn-hover: rgba(255, 255, 255, 0.16); /* a lift on the dark button (brightness alone barely shows on near-black) */
}

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

html { scroll-behavior: smooth; }
/* under the loader a link to a section (#editor) jumps straight there: a smooth jump kept going to
   where the section was when it started, and the reel above it grows a little as its glass settles
   (refract.js), so the page stopped short of the section's top */
html.loading { scroll-behavior: auto; }
/* no grey tap flash on the glass controls; their own hover and press states show the touch
   (inherited, so it also covers taps caught by delegated containers) */
html { -webkit-tap-highlight-color: transparent; }
/* the page is never wider than the screen (the slanted banner used to poke out on phones, so a
   sideways swipe panned the page instead of reaching the carousel) */
html, body { overflow-x: hidden; }
@supports (overflow: clip) { html, body { overflow-x: clip; } }
/* touch screens: the browser snaps one section per swipe, with its own momentum */
html.touch-snap { scroll-snap-type: y mandatory; }
html.touch-snap main > section { scroll-snap-align: start; scroll-snap-stop: always; }
html.touch-snap .footer { scroll-snap-align: end; }
/* the reel is taller than the screen: its end is always a stop, and so are the rows main.js marks
   is-stop (see placeStops there), each just under the nav */
html.touch-snap .reel .tile { scroll-margin-top: 84px; }
html.touch-snap .reel .tile.is-stop { scroll-snap-align: start; }
html.touch-snap .reel .tile.is-catch { scroll-snap-stop: always; } /* short phones: see placeStops */
html.touch-snap .reel__grid { scroll-snap-align: end; scroll-snap-stop: always; }
/* tablets held upright, where the reel is all but one screen (placeStops): one stop for the reel, the
   grid's end (end-only) or the section's top (no-end) */
html.touch-snap .reel__grid.no-end { scroll-snap-align: none; }
html.touch-snap main > .reel.end-only { scroll-snap-align: none; }
/* desktop: a control that focus scrolls into view stops below the fixed nav (16px top + 60px
   high + 16px gap). Not scroll-padding on html, which would also push #fragment jumps down */
html:not(.touch-snap) main :is(a, button) { scroll-margin-top: 92px; }

body {
  margin: 0;
  /* the backdrop's own base colour in both phases: landscape iPhone letterbox bars and
     overscroll read as the phone's black bezel, not a pale band by day */
  background: #070912;
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 18px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  transition: color var(--phase) var(--ease);
}

img, video, svg { display: block; max-width: 100%; }
h1, h2, h3, p, ul, ol, figure { margin: 0; }
ul, ol { padding: 0; list-style: none; }
a { color: inherit; }

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

.skip {
  position: fixed; left: 16px; top: -64px; z-index: 100;
  padding: 10px 16px; border-radius: var(--r-sm);
  background: var(--solid-bg); color: var(--solid-ink); text-decoration: none; font-weight: 600;
}
.skip:focus { top: 16px; }
/* the keyboard-only "Pause motion" button: the same off-screen pill as the skip link */
.skip--motion { border: 0; font: inherit; font-weight: 600; cursor: pointer; }

:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 3px;
}
/* a section takes focus after an in-page jump so Tab carries on inside it; no ring round a whole screen */
main > section:focus { outline: none; }

.jp { font-family: var(--font-jp); font-weight: 700; }

/* ---------- glass, the main material */
.glass {
  background: var(--glass-bg);
  border: 1px solid var(--glass-line);
  box-shadow: inset 0 1px 0 var(--glass-top), var(--glass-shadow);
  -webkit-backdrop-filter: blur(22px) saturate(150%);
  backdrop-filter: blur(22px) saturate(150%);
  border-radius: var(--r-md);
  transition: background-color var(--phase) var(--ease), border-color var(--phase) var(--ease),
    box-shadow var(--phase) var(--ease), color var(--phase) var(--ease);
}

/* ---------- lens glass (where refraction is supported): one even sheet of frosted glass, edge
   to edge. The frost is the same everywhere; the edge bends the scene behind it like a lens;
   a crisp highlight traces the rim. No inner box, no fades. */
html[data-phase="night"] { --spec: rgba(255, 255, 255, 0.3); --spec-low: rgba(255, 255, 255, 0.07); }
html[data-phase="day"] { --spec: rgba(255, 255, 255, 0.95); --spec-low: rgba(255, 255, 255, 0.4); }
.showcase__controls, .tile, .shot, .section-head,
.fine, .tier, .footer__row, .title__pane { position: relative; }
html.has-refraction [data-refract] {
  --frost: 10px;
  -webkit-backdrop-filter: blur(var(--frost)) var(--lens, blur(0)) saturate(150%);
  backdrop-filter: blur(var(--frost)) var(--lens, blur(0)) saturate(150%);
  box-shadow: inset 0 1px 0 var(--spec), inset 0 -1px 0 var(--spec-low), inset 0 0 0 1px var(--spec-low), var(--glass-shadow);
}
html.has-refraction [data-refract="clear"] { --frost: 5px; }
/* the reel's tiles keep the frost and the rim but not the lens: a refracting pane over a picture that
   changes every frame cost the background video a quarter of its frames (data-refract stays, for
   the bezel and screen corner refract.js measures) */
html.has-refraction .reel .tile { -webkit-backdrop-filter: blur(var(--frost)) saturate(150%); backdrop-filter: blur(var(--frost)) saturate(150%); }

/* phones and tablets: a lighter frost (a smaller blur, no colour boost) with a little more tint
   to make up for it. A wide live blur over 60 fps video is the costliest thing a phone browser
   draws, and every pane re-blurs on every video frame. */
html.touch-snap .glass { -webkit-backdrop-filter: blur(12px); backdrop-filter: blur(12px); }
html.touch-snap[data-phase="night"] { --glass-bg: rgba(14, 18, 34, 0.64); }
html.touch-snap[data-phase="day"] { --glass-bg: rgba(255, 255, 255, 0.64); }
/* phones and tablets: the screenshot panes are almost all opaque picture; only the 10px bezel
   would show frost, so skip the live blur there and tint the bezel a little more instead */
html.touch-snap .shot { -webkit-backdrop-filter: none; backdrop-filter: none; }
html.touch-snap[data-phase="night"] .shot { background: rgba(14, 18, 34, 0.82); }
html.touch-snap[data-phase="day"] .shot { background: rgba(255, 255, 255, 0.8); }
/* the reel's tiles likewise: picture with a rim and a caption */
html.touch-snap .tile { -webkit-backdrop-filter: none; backdrop-filter: none; }
html.touch-snap[data-phase="night"] .tile { background: rgba(14, 18, 34, 0.82); }
html.touch-snap[data-phase="day"] .tile { background: rgba(255, 255, 255, 0.8); }

/* the fallbacks are the plain-glass sizes: refract.js sets --bezel and --screen-r only once a
   pane's map is built, in idle time, and without them the padding and corners would drop to 0 */
html.has-refraction .shot { padding: var(--bezel, 10px); }
html.has-refraction .shot img { border-radius: var(--screen-r, 14px); }

/* clearer glass for big type and controls: less tint, so the refracted light shows */
html[data-phase="night"] .glass--clear { --glass-bg: rgba(14, 18, 34, 0.26); --glass-line: rgba(255, 255, 255, 0.22); --glass-top: rgba(255, 255, 255, 0.3); }
html[data-phase="day"] .glass--clear { --glass-bg: rgba(255, 255, 255, 0.34); }

/* ---------- backdrop: night and day videos, crossfaded by phase */
.backdrop { position: fixed; inset: 0; z-index: -1; overflow: hidden; background: #070912; }
.backdrop__video {
  position: absolute; inset: 0; width: 100%; height: 100%; max-width: none;
  object-fit: cover; object-position: 50% 50%;
}
/* the day grade (a touch less glare, a little more colour) is baked into day-720.mp4 and
   day-video.jpg, so the browser no longer filters a full-screen video on every frame */
.backdrop__video--day { opacity: 0; transition: opacity var(--phase) var(--ease); }
html[data-phase="day"] .backdrop__video--day { opacity: 1; }
/* on the title the whole scene is blurred and dimmed; it clears as the page moves to the carousel */
.backdrop__blur {
  position: absolute; inset: 0;
  background: rgba(6, 8, 16, 0.22);
  -webkit-backdrop-filter: blur(18px) saturate(120%);
  backdrop-filter: blur(18px) saturate(120%);
  opacity: 1;
  transition: opacity 0.9s var(--ease);
}
/* clears as the screens arrive, then switches off entirely: an invisible backdrop blur is still
   recomputed on every video frame (Safari), which alone made phones stutter */
html.title-gone .backdrop__blur, html.scene-clear .backdrop__blur {
  opacity: 0; visibility: hidden;
  transition: opacity 0.9s var(--ease), visibility 0s linear 0.9s;
}
.backdrop__shade {
  position: absolute; inset: 0;
  background:
    linear-gradient(to bottom, rgba(var(--shade-rgb), 0.45), rgba(var(--shade-rgb), 0) 22%, rgba(var(--shade-rgb), 0) 70%, rgba(var(--shade-rgb), 0.55)),
    rgba(var(--shade-rgb), calc(0.12 + var(--shade) * var(--shade-max)));
  transition: background-color var(--phase) var(--ease);
}
/* the designer's frost: heavy blur and a mist over the whole scene (bright by day, deep by night),
   so the app window is the only sharp thing on screen. It is one fixed sheet that fades in as the
   designer arrives and out as it leaves (main.js, html.studio-frost), never an edge sliding across
   the video. Off, it is hidden as well as clear: an invisible backdrop blur still costs every frame */
.backdrop__frost {
  position: absolute; inset: 0;
  background: var(--band);
  -webkit-backdrop-filter: blur(30px) saturate(140%);
  backdrop-filter: blur(30px) saturate(140%);
  opacity: 0; visibility: hidden;
  transition: opacity 0.7s var(--ease), visibility 0s linear 0.7s, background-color var(--phase) var(--ease);
}
html[data-phase="night"] .backdrop__frost { --band: rgba(24, 31, 50, 0.46); }
html[data-phase="day"] .backdrop__frost { --band: rgba(238, 243, 247, 0.5); }
html.studio-frost .backdrop__frost {
  opacity: 1; visibility: visible;
  transition: opacity 0.7s var(--ease), visibility 0s, background-color var(--phase) var(--ease);
}
/* phones and tablets: no live blur over the video (see .glass), a deeper mist instead */
html.touch-snap .backdrop__frost { -webkit-backdrop-filter: none; backdrop-filter: none; }
html.touch-snap[data-phase="night"] .backdrop__frost { --band: rgba(8, 10, 18, 0.9); }
html.touch-snap[data-phase="day"] .backdrop__frost { --band: rgba(232, 238, 243, 0.9); }

/* ---------- nav */
.nav {
  position: fixed; z-index: 20; top: 16px; left: 50%;
  transform: translateX(-50%);
  width: min(1240px, calc(100% - 32px));
  height: 60px;
  padding: 0 10px 0 18px;
  border-radius: 30px;
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
}
.brand { display: flex; align-items: center; gap: 10px; text-decoration: none; min-height: 44px; }
.nav__links { display: flex; align-items: center; gap: 4px; }
.nav__links a:not(.btn) {
  padding: 10px 14px; border-radius: 22px; text-decoration: none;
  font-size: 17px; font-weight: 500; color: var(--ink-2);
  transition: color 0.2s var(--ease), background-color 0.2s var(--ease);
}
@media (hover: hover) {
  .nav__links a:not(.btn):hover { color: var(--ink); background: var(--hair); }
}
/* the section on screen (main.js marks its link) */
.nav__links a:not(.btn)[aria-current] { color: var(--ink); background: var(--hair); }

/* ---------- the logo: the tuner banner. A decal, so it is the same satin black and red at night
   and by day. Everything scales from --bh, the banner's height. */
.banner {
  --bh: 34px;
  display: inline-flex; align-items: stretch; height: var(--bh);
  transform: skewX(-12deg);
  filter: drop-shadow(0 calc(var(--bh) * 0.12) calc(var(--bh) * 0.24) rgba(0, 0, 0, 0.4));
  line-height: 1; white-space: nowrap;
}
.banner__body {
  display: flex; align-items: center; gap: calc(var(--bh) * 0.19);
  padding: 0 calc(var(--bh) * 0.36) 0 calc(var(--bh) * 0.28);
  background: linear-gradient(180deg, #2A2F3A 0%, #12151C 38%, #07080C 100%);
  border-radius: calc(var(--bh) * 0.07) 0 0 calc(var(--bh) * 0.07);
  color: #E8E8E8;
}
.banner__mark { width: calc(var(--bh) * 0.69); height: calc(var(--bh) * 0.69); flex-shrink: 0; }
.banner__mark circle { fill: var(--decal-red); } /* the K's red dot (its fill attribute stays as the no-CSS fallback) */
.banner__word { font-family: var(--font-display); font-stretch: 125%; font-size: calc(var(--bh) * 0.45); letter-spacing: 0.03em; }
.banner__word b { font-weight: 900; }
.banner__word span { font-weight: 300; margin-left: 0.26em; color: rgba(232, 232, 232, 0.7); }
.banner__end {
  display: flex; align-items: center; padding: 0 calc(var(--bh) * 0.26);
  background: linear-gradient(180deg, var(--decal-red) 0%, var(--decal-red-mid) 45%, var(--decal-red-low) 100%);
  border-radius: 0 calc(var(--bh) * 0.07) calc(var(--bh) * 0.07) 0;
  font-family: var(--font-jp);
  font-weight: 900; font-size: calc(var(--bh) * 0.38); letter-spacing: 0.04em; color: #F6F1EA;
}
.banner--nav { --bh: 34px; }
.banner--xl { --bh: clamp(36px, min(11vw, 12svh), 84px); }
.banner--lg { --bh: clamp(32px, 7vw, 64px); }
.title__banner, .get__banner { margin: 0; display: flex; justify-content: center; }
/* title lockup: the banner (the toggle sits under it; the two are centred together) */
.lockup {
  --bh: clamp(36px, min(11vw, 12svh), 84px); /* as wide as a phone allows, and no taller than a landscape phone can spare */
  position: relative; display: inline-flex;
  transform: skewX(-12deg);
}
.lockup .banner { transform: none; }

/* ---------- the tach around the K (title logo and loading screen): solid gauge segments ending
   in red at the redline dot. While revving, unlit segments drop to a dim trace. */
.tach__seg { fill: #E8E8E8; }
.tach__seg--red { fill: var(--decal-red); }
.tach.is-revving .tach__seg:not(.is-lit) { fill: rgba(255, 255, 255, 0.13); }
.tach__dot { transform-box: fill-box; transform-origin: center; }
.tach.is-redline .tach__dot { animation: kl-dot 0.4s ease-out; }
@keyframes kl-dot { 40% { transform: scale(1.5); filter: brightness(1.5); } }
.lockup .banner__mark { width: calc(var(--bh) * 0.86); height: calc(var(--bh) * 0.86); }

/* ---------- loading: the title logo itself is the loading bar, at its final size and place.
   A dark ground covers the page; the logo sits above it as a plain slanted bar that fills with
   satin black. When the page is ready the ground fades and, all at once, the K, the text and the
   red slice come in while the tach revs. (If the script never runs, the ground gives way after
   12 s and the logo shows as normal.) */
.loader {
  position: fixed; inset: 0; z-index: 200;
  background: #0B0D14;
  transition: opacity 0.6s var(--ease), visibility 0s linear 0.6s;
  animation: kl-failsafe 0s linear 12s forwards;
}
html.loaded .loader { opacity: 0; visibility: hidden; }
html.loading { overflow: hidden; }
html.title-up .title { z-index: 201; } /* the logo shows above the dark ground until it has faded */
@keyframes kl-failsafe { to { opacity: 0; visibility: hidden; } }
html.loading .loader { animation: none; } /* the script is running: it decides when to reveal */
html.loading .ribbon { pointer-events: none; } /* no grab cursor or drag on the screens while the loader covers them */

/* bar state, while loading */
html.intro-pending .lockup .banner { filter: none; }
/* the empty bar is a faint outline, so the satin fill reads as filling it */
html.intro-pending .lockup .banner__body,
html.intro-pending .lockup .banner__end { background: rgba(255, 255, 255, 0.025); box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.1); }
.lockup .banner__body { position: relative; }
.lockup .banner__body::before {
  content: ""; position: absolute; inset: 0; border-radius: inherit;
  background: linear-gradient(180deg, #2A2F3A 0%, #12151C 38%, #07080C 100%);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.14);
  transform-origin: left center; transform: scaleX(1);
  transition: transform 0.4s var(--ease);
}
html.intro-pending .lockup .banner__body::before { transform: scaleX(var(--load, 0)); }
.lockup .banner__body > * { position: relative; }
html.intro-pending .lockup .banner__body > * { opacity: 0; transform: translateX(-10px); }
/* the red slice keeps its place as a faint track (so the bar is the whole logo's width and sits
   centred), then its red wipes in */
.lockup .banner__end { position: relative; isolation: isolate; background: none; }
.lockup .banner__end::before {
  content: ""; position: absolute; inset: 0; z-index: -1; border-radius: inherit;
  background: linear-gradient(180deg, var(--decal-red) 0%, var(--decal-red-mid) 45%, var(--decal-red-low) 100%);
  clip-path: inset(0 0 0 0); /* the resting value must be inset(), not none, or the wipe from inset(0 100% 0 0) snaps */
}
html.intro-pending .lockup .banner__end { color: transparent; }
html.intro-pending .lockup .banner__end::before { clip-path: inset(0 100% 0 0); }

/* reveal: everything together, quickly */
html.intro-play .lockup .banner__body > * { transition: opacity 0.4s var(--ease), transform 0.45s var(--ease); }
html.intro-play .lockup .banner__end { transition: color 0.35s var(--ease) 0.1s, background-color 0.3s var(--ease); }
html.intro-play .lockup .banner__end::before { transition: clip-path 0.45s cubic-bezier(0.2, 0.8, 0.2, 1); }
html.intro-play .lockup .banner { transition: filter 0.4s var(--ease); }

/* ---------- buttons */
.btn {
  display: inline-flex; align-items: center; justify-content: center;
  height: 48px; padding: 0 24px; border-radius: 24px;
  font-family: var(--font-body); font-size: 17px; font-weight: 600;
  text-decoration: none; cursor: pointer; touch-action: manipulation;
  transition: transform 0.2s var(--ease), box-shadow 0.2s var(--ease), background-color var(--phase) var(--ease), color var(--phase) var(--ease);
}
.btn:active { transform: scale(0.97); }
.btn--sm { height: 44px; padding: 0 18px; font-size: 16px; }
/* hover lays a tint over the button (a shade on the light night button, a lift on the dark day
   one) from a resting transparent overlay, so it fades instead of popping. Real hover only: on
   touch a :hover sticks after the tap. The press (.btn:active) applies everywhere. */
.btn--solid { background: var(--solid-bg); color: var(--solid-ink); border: 0; box-shadow: inset 0 0 0 999px transparent; }
@media (hover: hover) {
  .btn--solid:hover { box-shadow: inset 0 0 0 999px var(--btn-hover); }
}
/* the quieter of two buttons side by side: an outline in the text colour */
.btn--line { background: transparent; color: var(--ink); border: 0; box-shadow: inset 0 0 0 1.5px var(--ink-2); }
@media (hover: hover) {
  .btn--line:hover { background: var(--hair); }
}
/* the nav CTA steps aside while the Get section (which has the same button) is on screen; main.js
   sets html.at-get. Its space stays, so the toggle beside it never moves. */
.nav .btn--solid {
  transition: transform 0.2s var(--ease), box-shadow 0.2s var(--ease), background-color var(--phase) var(--ease), color var(--phase) var(--ease),
    opacity 0.3s var(--ease), visibility 0s linear 0s;
}
html.at-get .nav .btn--solid {
  opacity: 0; visibility: hidden; pointer-events: none;
  transition: transform 0.2s var(--ease), box-shadow 0.2s var(--ease), background-color var(--phase) var(--ease), color var(--phase) var(--ease),
    opacity 0.3s var(--ease), visibility 0s linear 0.3s;
}

/* ---------- title screen: the logo between two drifting rows of screens */
/* the padding is the room the intro keeps clear: the fixed nav (16 px from the top, 60 px tall)
   plus a gap above, a margin below. The logo and toggle centre in what is left, and the rows of
   screens fill it around them (ribbon.js reads these). */
.title {
  position: relative; min-height: 100vh; min-height: 100svh; height: 100svh;
  display: grid; place-items: center;
  padding: 92px 16px calc(20px + env(safe-area-inset-bottom, 0px));
}
/* the title sits straight on the blurred scene: no box */
/* the logo and the night/day toggle under it, centred together between the rows of screens */
.title__pane {
  width: min(880px, 100%);
  display: flex; flex-direction: column; align-items: center; text-align: center; gap: clamp(18px, 2.4vw, 28px);
}
/* one scroll down: the logo dissolves (lifts, swells, blurs away); scrolling back re-forms it.
   Only the logo: the toggle has its own glide into the nav and back, which a fading, swelling
   parent would hide (and throw off where the glide starts) */
.title__banner { transition: opacity 0.7s var(--ease), transform 0.8s var(--ease), filter 0.7s var(--ease); }
html.title-gone .title__banner { opacity: 0; transform: translateY(-48px) scale(1.1); filter: blur(14px); }

/* ---------- night/day toggle: the only thing that changes the page between night and day. A
   glass pill under the logo on the intro; once the page moves on, it glides up into the nav bar
   (and back down on return; main.js moves it). Wide screens show the kanji with their English;
   phones, with no room for both, say it in English. */
/* its place under the logo keeps the toggle's height after it has moved to the nav, so the logo
   never jumps when the page moves on or comes back */
.title__toggle { height: 54px; display: flex; align-items: center; justify-content: center; }
.phase-toggle {
  position: relative; pointer-events: auto;
  display: grid; grid-template-columns: 1fr 1fr;
  padding: 4px; border-radius: 999px;
  touch-action: manipulation; /* no double-tap zoom from a tap that lands between the options */
}
.phase-toggle::after {
  content: ""; position: absolute; left: 4px; top: 4px; bottom: 4px; width: calc(50% - 4px);
  border-radius: 999px; background: var(--solid-bg);
  transition: transform 0.45s cubic-bezier(0.3, 0.7, 0.2, 1), background-color var(--phase) var(--ease);
}
.phase-toggle[data-active="day"]::after { transform: translateX(100%); }
.phase-toggle__opt {
  position: relative; z-index: 1;
  height: 44px; padding: 0 18px;
  display: flex; align-items: center; justify-content: center; gap: 8px;
  border: 0; border-radius: 999px; background: none; cursor: pointer; touch-action: manipulation;
  color: var(--ink-2); transition: color 0.3s var(--ease), background-color 0.2s var(--ease);
}
.phase-toggle__opt .jp { font-size: 18px; line-height: 1; }
.phase-toggle__label { font-family: var(--font-body); font-size: 12px; font-weight: 600; letter-spacing: 0.16em; text-transform: uppercase; line-height: 1; }
.phase-toggle__opt[aria-pressed="true"] { color: var(--solid-ink); }
/* focus ring drawn inside each option in its own text colour: dark on the clear half, light on
   the dark thumb (any phase, on the intro or in the nav) */
.phase-toggle__opt:focus-visible { outline-color: currentColor; outline-offset: -4px; }
/* while it travels between the intro and the bar */
.phase-toggle.is-moving { transition: transform 0.6s cubic-bezier(0.3, 0.7, 0.2, 1); }
/* on the intro it comes in with the logo */
.title__toggle { transition: opacity 0.5s var(--ease) 0.25s; }
/* hidden, not just clear, while the loader shows: no taps or Tab stops on it; its slot keeps the
   logo in place, and visibility comes back at once on reveal while the opacity fades in */
html.intro-pending .title__toggle { opacity: 0; visibility: hidden; transition: none; }
/* in the nav bar: a smaller switch sitting before the links */
.nav .phase-toggle {
  padding: 3px; margin: 0 8px 0 auto;
  background: var(--hair); border: 0; box-shadow: none;
  -webkit-backdrop-filter: none; backdrop-filter: none;
}
.nav .phase-toggle::after { left: 3px; top: 3px; bottom: 3px; width: calc(50% - 3px); }
.nav .phase-toggle__opt { height: 38px; padding: 0 13px; gap: 6px; }
/* the switch looks smaller in the bar, but each option still takes a 44px+ tap: the hit area
   reaches 6px above and below, inside the 60px bar (never sideways, so the two never overlap) */
.nav .phase-toggle__opt::before { content: ""; position: absolute; inset: -6px 0; }
.nav .phase-toggle__opt .jp { font-size: 16px; }
.nav .phase-toggle__label { font-size: 12px; letter-spacing: 0.12em; }
@media (max-width: 720px) {
  .phase-toggle__opt .jp { display: none; }
  .phase-toggle__label { font-size: 15px; letter-spacing: 0.01em; text-transform: none; }
  .nav .phase-toggle { margin-right: 6px; }
  .nav .phase-toggle__opt { padding: 0 11px; }
  .nav .phase-toggle__label { font-size: 14px; letter-spacing: 0.01em; }
}
.btn { white-space: nowrap; }
@media (max-width: 560px) {
  :root { --pad: 20px; }
}
@media (max-width: 420px) {
  .nav .banner--nav { --bh: 27px; } /* beats the 720px size further down */
  .nav .phase-toggle__opt { height: 36px; padding: 0 9px; }
  .nav .phase-toggle__label { font-size: 13px; }
  .nav .btn--sm { padding: 0 14px; }
  .nav { gap: 8px; padding: 0 6px 0 10px; }
  .nav .phase-toggle { margin-right: 0; }
}

/* words straight on the scene (not on a pane) stay light by day too, with a dark halo: dark type
   over a busy, sunlit video does not read */
html[data-phase="day"] .title__pane,
html[data-phase="day"] .intro__grid {
  --ink: var(--on-video); --ink-2: var(--on-video-2);
  color: var(--ink);
}
html[data-phase="day"] .intro__grid > * { text-shadow: 0 1px 2px rgba(8, 14, 22, 0.45), 0 2px 22px rgba(8, 14, 22, 0.55); }
/* the readout is a glass pane, not bare scene: dark ink on it by day, no halo */
html[data-phase="day"] .intro__grid .readout { --ink: #14171C; --ink-2: rgba(20, 23, 28, 0.88); text-shadow: none; }
/* the night/day pill is glass, not bare scene: dark ink on it by day, like other day glass (the
   selected half keeps --solid-ink on the dark thumb) */
html[data-phase="day"] .title__pane .phase-toggle { --ink: #14171C; --ink-2: rgba(20, 23, 28, 0.92); }

/* ---------- the screens around the title logo: dials drifting left to right along the top,
   motorsport right to left along the bottom. Drag a row to move it; scrolling moves on. */
.title__stage { position: absolute; inset: 0; overflow: hidden; }
.ribbon {
  position: absolute; inset: 0; width: 100%; height: 100%;
  cursor: grab; touch-action: pan-y pinch-zoom; /* sideways drags move a row; vertical swipes scroll, pinches zoom */
}
.title__stage.is-dragging .ribbon { cursor: grabbing; }
/* phones: the centre screens' live clips, real video elements fitted over the canvas by ribbon.js */
.ribbon-live { position: absolute; inset: 0; overflow: hidden; pointer-events: none; }
.ribbon-live video {
  position: absolute; left: 0; top: 0; width: 800px; height: 480px; max-width: none;
  transform-origin: 0 0; object-fit: fill; opacity: 0;
  transition: opacity 0.3s var(--ease);
  will-change: transform, opacity; backface-visibility: hidden;
}
/* the logo sits over the screens but lets drags through to them */
.title__pane { position: relative; z-index: 1; pointer-events: none; }

/* the list holds the clip and poster data the ribbon reads, and doubles as the no-WebGL fallback
   (a strip along the bottom). It is decorative and aria-hidden: the showcase names the themes */
.screens { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }
html.no-webgl .screens {
  position: absolute; left: 0; right: 0; bottom: 24px; width: auto; height: auto; clip: auto;
  display: flex; gap: 16px; padding: 0 24px; overflow-x: auto; scroll-snap-type: x mandatory;
}
html.no-webgl .screens li { flex: 0 0 min(320px, 70vw); scroll-snap-align: center; }
html.no-webgl .screens video { width: 100%; aspect-ratio: 5 / 3; border-radius: var(--r-md); background: #000; border: 1px solid var(--glass-line); }
/* the strip shows screens only, no captions (the ribbon has none either) */
html.no-webgl .screens figcaption { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
html.no-webgl .ribbon { display: none; }

/* ---------- sections */
/* every section is at least one screen: each is a stop the page moves between */
.section {
  position: relative; padding: 112px 24px 96px;
  min-height: 100vh; min-height: 100svh; box-sizing: border-box;
  display: flex; flex-direction: column; justify-content: center;
}
.section > .wrap { width: 100%; }
.wrap { max-width: 1200px; margin: 0 auto; }
.display {
  font-family: var(--font-display);
  font-stretch: 112%;
  font-weight: 750;
  font-size: clamp(36px, 5.2vw, 68px);
  line-height: 1.04;
  letter-spacing: -0.01em;
  text-wrap: balance;
  max-width: 16ch;
}
/* a heading's quieter second line (Features) */
.display__more { display: block; margin-top: 0.22em; font-size: 0.56em; font-weight: 500; font-stretch: 100%; line-height: 1.15; color: var(--ink-2); }
.lead { font-size: 21px; line-height: 1.55; color: var(--ink-2); max-width: 46ch; }
p { text-wrap: pretty; } /* no one-word last lines where the browser can avoid them */
h3 { font-size: 21px; font-weight: 600; line-height: 1.3; }

.intro__grid { display: grid; grid-template-columns: 1.2fr 1fr; gap: 48px; align-items: end; }
/* the opening's readout: what the car's screen shows, ticking through a short drive (main.js) */
.readout {
  display: flex; flex-wrap: wrap; align-items: flex-end; gap: 12px 26px;
  padding: 20px var(--pad); border-radius: var(--r-lg);
}
.readout__item { display: flex; flex-direction: column; gap: 4px; }
.readout__item b {
  font-family: var(--font-num); font-weight: 700; font-size: 40px; line-height: 1;
  font-variant-numeric: tabular-nums; color: var(--ink);
}
.readout__item b i { font-style: normal; }
.readout__item b small { font-size: 0.5em; font-weight: 600; margin-left: 2px; }
.readout__item--big b { font-size: 54px; }
.readout__item span { font-size: 13px; font-weight: 600; letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink-2); }
/* phones: a tidy grid, speed / revs / gear over the two temperatures */
@media (max-width: 560px) {
  .readout { display: grid; grid-template-columns: auto auto 1fr; gap: 14px 24px; padding: 18px var(--pad); }
  .readout__item b { font-size: 32px; }
  .readout__item--big b { font-size: 42px; }
  .readout__item span { font-size: 12px; }
}

/* ---------- the reel: the features as a wall of the car's own screens (looping clips) and the lap
   data they record, each in a glass bezel with a few words under it. main.js loads them last, plays
   only the clips in view and swaps night and day. Wide screens: two mirrored bands, a big screen
   beside a column (a screen over the lap chart that fills the rest of the height), then a column of
   two screens beside a big screen that fills theirs. Phones: two columns, a screen across both
   between each pair (see the 699px block) */
/* the opening: the page's statement and its live readout, straight on the scene, above the screens */
.reel__head { margin-bottom: 40px; }
.reel__grid { display: flex; flex-direction: column; gap: 16px; }
.reel__band { display: flex; gap: 16px; }
.reel__col { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; gap: 16px; }
.reel__band > .tile { flex: 1 1 0; }
.reel__col > .tile--fill { flex: 1 1 auto; }
.reel__band > .tile--xl { flex: 0 0 calc((100% - 16px) * 0.68); }
.tile { margin: 0; min-width: 0; display: flex; flex-direction: column; padding: 10px; border-radius: var(--r-lg); }
html.has-refraction .tile { padding: var(--bezel, 10px); }
/* the screen: 5:3 like the head unit, so a clip is never cropped. Its ground (until the first
   picture arrives) is dark at night and light by day, like the themes */
.tile__media {
  position: relative; flex: none; aspect-ratio: 5 / 3; border-radius: 14px; overflow: hidden;
  background: #06080E; transition: background-color var(--phase) var(--ease);
}
html[data-phase="day"] .tile__media { background: #C9D2DB; }
html.has-refraction .tile__media { border-radius: var(--screen-r, 14px); }
/* an app shot in a column takes whatever height the big screen beside it leaves */
.tile--fill .tile__media { flex: 1 1 0; aspect-ratio: auto; min-height: 96px; }
/* the second band turns it round: two screens in the column set the height, and the big screen
   fills it (a few per cent of its sides go; the clip's middle is what matters) */
.tile--stretch .tile__media { flex: 1 1 0; aspect-ratio: auto; min-height: 0; }
/* its column a little narrower than the first band's, so the two screens and their words come to
   about the big screen's own 5:3 height */
.reel__band > .tile--stretch { flex-basis: calc((100% - 16px) * 0.71); }
/* night and day sit stacked; main.js says which is on show (data-show), once it is ready */
.tile__m {
  position: absolute; inset: 0; width: 100%; height: 100%; max-width: none;
  object-fit: cover; object-position: 50% 50%;
  transition: opacity var(--phase) var(--ease);
}
.tile__m--day { opacity: 0; }
.tile[data-show="day"] .tile__m--day { opacity: 1; }
/* a clip plays unseen under the canvas that draws it (main.js: shown as a video it cost the
   backdrop a third of its frames); where drawing is off the clip shows itself and the canvas goes */
.reel__grid.is-drawn .tile__media > video.tile__m { opacity: 0; transition: none; }
.reel__grid:not(.is-drawn) canvas.tile__m { display: none; }
/* an app shot not yet in draws nothing (Chromium outlines an img with no src) */
img.tile__m:not([src]) { visibility: hidden; }
/* where a tile is a different shape from its shot, the part that matters stays: the lap chart shows
   whole, on its own panel's colour */
.tile--laps .tile__m { object-fit: contain; }
.tile--laps .tile__media { background: #10141A; }
html[data-phase="day"] .tile--laps .tile__media { background: #EDF0F2; }
.tile__cap {
  padding: 12px 8px 4px;
  font-family: var(--font-display); font-stretch: 112%; font-weight: 700;
  font-size: clamp(17px, 1.5vw, 21px); line-height: 1.15; letter-spacing: -0.005em; text-wrap: balance;
}
.tile--xl .tile__cap { font-size: clamp(20px, 1.9vw, 27px); padding-top: 14px; }
/* tablets: the big screens take a little more of the band, so the column beside them (a screen
   over an app shot) still fits their height */
@media (min-width: 700px) and (max-width: 900px) {
  .reel__band > .tile--xl { flex-basis: calc((100% - 16px) * 0.7); }
  /* the first band's column (two captions on two lines each) a little narrower, so the lap chart
     under its screen keeps a fair height (at 0.7 it was a thin strip); the second band's column of
     two screens likewise, so the big screen beside them stays close to its own 5:3 */
  .reel__band:first-child > .tile--xl, .reel__band > .tile--stretch { flex-basis: calc((100% - 16px) * 0.72); }
  .tile--fill .tile__media { min-height: 64px; }
  /* the column's words set a touch narrower, so the longer captions hold two lines */
  .reel__col .tile__cap { font-stretch: 100%; }
}
@media (min-width: 700px) and (max-width: 767px) {
  .reel__band:first-child > .tile--xl, .reel__band > .tile--stretch { flex-basis: calc((100% - 16px) * 0.73); }
  /* and the columns' words narrower still, so the rules caption keeps to two lines */
  .reel__col .tile__cap { font-stretch: 84%; }
}

/* day headings and text sit on their own refracting glass, not on the video. Every content pane
   shares one corner (--r-lg) and one side padding (--pad); pills stay round */
.section-head {
  display: inline-flex; flex-direction: column;
  padding: 28px var(--pad) 32px; border-radius: var(--r-lg); margin-bottom: 32px;
}
/* ---------- theme showcase: one big screen in a glass bezel (night or day, with the page toggle)
   beside a numbered theme list, like the car's own menu, and a Dial / Motorsport switch */
.showcase { display: grid; grid-template-columns: minmax(0, 1fr) 280px; gap: 20px; align-items: stretch; }
.showcase__screen { margin: 0; align-self: center; }
/* 14px: concentric with the 24px bezel round its 10px padding. The background holds the picture
   on show while a new one fades in over it (main.js) */
.showcase__frame { position: relative; aspect-ratio: 5 / 3; border-radius: 14px; overflow: hidden; background: #000 center / cover no-repeat; }
html.has-refraction .showcase__frame { border-radius: var(--screen-r, 14px); }
.showcase__img {
  position: absolute; inset: 0; width: 100%; height: 100%; border-radius: 0;
  transition: opacity 0.6s var(--ease);
}
.showcase__img--day { opacity: 0; }
html[data-phase="day"] .showcase__img--day { opacity: 1; }
/* changing theme or layout: the picture on show stays under the frame (main.js) and the new one
   fades in over it, never over black. By day the night still stays hidden while it settles */
.showcase__frame.is-swapping .showcase__img { opacity: 0; transition: none; }
.showcase__frame.is-settling .showcase__img { transition-duration: 0.25s; }
html[data-phase="day"] .showcase__frame.is-settling .showcase__img--night { opacity: 0; transition: none; }
.showcase__controls {
  padding: 16px; border-radius: var(--r-lg); display: flex; flex-direction: column; gap: 12px; min-width: 0;
  touch-action: manipulation; /* no double-tap zoom in the gaps between the controls (the chip row still scrolls) */
}
.seg { display: grid; grid-template-columns: 1fr 1fr; padding: 4px; border-radius: 999px; background: var(--hair); }
.seg button, .showcase__themes button {
  border: 0; background: none; cursor: pointer; touch-action: manipulation;
  font-family: var(--font-body); font-weight: 600; color: var(--ink-2);
  transition: background-color 0.25s var(--ease), color 0.25s var(--ease);
}
.seg button { height: 40px; border-radius: 999px; font-size: 15px; }
.seg button[aria-pressed="true"] { background: var(--solid-bg); color: var(--solid-ink); }
.showcase__themes { display: flex; flex-direction: column; gap: 2px; }
/* the number sits on the name's baseline (wrap lets align-content centre that line in the row) */
.showcase__themes button {
  display: flex; flex-wrap: wrap; align-content: center; align-items: baseline; gap: 14px;
  min-height: 40px; padding: 0 14px; border-radius: 12px; text-align: left; font-size: 17px;
}
@media (hover: hover) {
  .showcase__themes button:hover { color: var(--ink); background: var(--hair); }
}
.showcase__themes button[aria-pressed="true"] { color: var(--ink); background: var(--hair); }
.showcase__themes button[aria-pressed="true"]::after {
  content: ""; width: 8px; height: 8px; margin-left: auto; align-self: center; border-radius: 50%; background: var(--red);
}
.showcase__n { font-family: var(--font-num); font-size: 13px; font-weight: 600; color: var(--ink-3); font-variant-numeric: tabular-nums; }
/* hover and press on the small controls: a tint on the unselected half (by day on the intro the
   two inks are close, so colour alone would not show), and a dip while pressed */
@media (hover: hover) {
  .phase-toggle__opt[aria-pressed="false"]:hover,
  .seg button[aria-pressed="false"]:hover { color: var(--ink); background: var(--hair); }
}
.phase-toggle__opt:active, .seg button:active, .showcase__themes button:active { opacity: 0.7; }
/* touch screens: 44px targets for the layout switch and the theme chips */
@media (pointer: coarse) {
  .seg button { height: 44px; }
  .showcase__themes button { min-height: 44px; }
}

.shot { padding: 10px; border-radius: var(--r-lg); }
.shot img { width: 100%; height: auto; border-radius: 14px; } /* concentric with the bezel: 24 less the 10px padding */

/* ---------- the designer: the real PC app, shown big, its features named on it. While it is on
   screen the whole scene behind goes soft under the frost (.backdrop__frost), so the window is the
   only sharp thing on screen. The window is the app as it is: dark at night, light by day. Each name
   is a red dot on the part it names, with a glass pill; showing a feature folds the other pills back
   into their dots. main.js swaps the pictures and walks the tour */
/* at night the mist is a blue-grey a step lighter than the app, so the near-black window reads as
   a solid thing lit at its rim */
html[data-phase="night"] .studio {
  --pill-bg: rgba(242, 239, 233, 0.9); --pill-ink: #14171C; --pill-rim: rgba(255, 255, 255, 0.95);
  --win-ground: #0B0E13;
  --win-edge: 0 0 0 1px rgba(255, 255, 255, 0.16), 0 0 120px rgba(110, 150, 230, 0.16), 0 40px 90px rgba(0, 0, 0, 0.55);
  --win-rim: inset 0 1px 0 rgba(255, 255, 255, 0.22), inset 0 0 0 1px rgba(255, 255, 255, 0.06);
}
html[data-phase="day"] .studio {
  --pill-bg: rgba(18, 21, 27, 0.86); --pill-ink: #F3F6F8; --pill-rim: rgba(255, 255, 255, 0.22);
  --win-ground: #E6E9ED;
  --win-edge: 0 0 0 1px rgba(255, 255, 255, 0.9), 0 36px 80px rgba(16, 36, 56, 0.32), 0 10px 26px rgba(16, 36, 56, 0.16);
  --win-rim: inset 0 0 0 1px rgba(16, 36, 56, 0.08);
}
.studio__title { max-width: none; }
.studio__stage { position: relative; }

/* the window: the app's own pictures, 1440 x 900, stacked; the one on show fades in over the last */
.win {
  position: relative; aspect-ratio: 1440 / 900; overflow: hidden; isolation: isolate;
  border-radius: 14px; background: var(--win-ground); box-shadow: var(--win-edge);
  transition: background-color var(--phase) var(--ease), box-shadow var(--phase) var(--ease);
}
/* the rim light sits over the pictures */
.win::after { content: ""; position: absolute; inset: 0; z-index: 4; border-radius: inherit; box-shadow: var(--win-rim); pointer-events: none; }
.win__shots { position: absolute; inset: 0; transform-origin: 0 0; transition: transform 0.7s var(--ease); }
.win__shot {
  position: absolute; inset: 0; width: 100%; height: 100%; max-width: none;
  opacity: 0; transition: opacity 0.45s var(--ease);
}
.win__shot.is-on { opacity: 1; z-index: 2; }
.win__shot.is-prev { opacity: 1; z-index: 1; transition: none; }
.win__shot:not([src]) { visibility: hidden; }

/* the names, laid over the window where the parts are */
.callouts { position: absolute; inset: 0; z-index: 3; pointer-events: none; }
.callout {
  position: absolute; left: var(--x); top: var(--y);
  display: flex; align-items: center; gap: 8px;
  margin: 0; padding: 0; border: 0; background: none; color: inherit; font: inherit;
  cursor: pointer; pointer-events: auto; touch-action: manipulation;
  transform: translate(-7px, -50%);
  transition: opacity 0.3s var(--ease);
}
/* the pill to the left of its dot: the dot stays on its part whatever the pill's width */
.callout[data-side="left"] { flex-direction: row-reverse; transform: translate(calc(-100% + 7px), -50%); }
.callout::before { content: ""; position: absolute; inset: -8px; } /* a dot alone still takes a good-sized hover */
.callout__dot {
  position: relative; flex: none; width: 14px; height: 14px; border-radius: 50%;
  background: var(--decal-red);
  box-shadow: 0 0 0 2.5px #FFFFFF, 0 2px 6px rgba(0, 0, 0, 0.45), 0 0 22px 6px rgba(227, 40, 63, 0.32);
  transition: transform 0.45s cubic-bezier(0.3, 1.6, 0.5, 1), box-shadow 0.3s var(--ease);
}
.callout__name {
  display: flex; align-items: center; height: 34px; max-width: 16em; padding: 0 13px;
  overflow: hidden; white-space: nowrap; border-radius: 999px;
  font-family: var(--font-display); font-stretch: 106%; font-weight: 650; font-size: 15px; line-height: 1; letter-spacing: 0;
  background: var(--pill-bg); color: var(--pill-ink);
  -webkit-backdrop-filter: blur(10px) saturate(150%); backdrop-filter: blur(10px) saturate(150%);
  box-shadow: inset 0 1px 0 var(--pill-rim), 0 10px 28px rgba(0, 0, 0, 0.3);
  transition: max-width 0.42s var(--ease), padding 0.42s var(--ease), opacity 0.3s var(--ease),
    background-color var(--phase) var(--ease), color var(--phase) var(--ease);
}
/* the one on show glows a little brighter */
.callout.is-active .callout__dot { animation: callout-glow 1.6s ease-in-out infinite; }
@keyframes callout-glow {
  50% { box-shadow: 0 0 0 2.5px #FFFFFF, 0 2px 6px rgba(0, 0, 0, 0.45), 0 0 30px 11px rgba(227, 40, 63, 0.5); }
}
html.motion-off .callout.is-active .callout__dot { animation: none; } /* Pause motion: it holds still */
@media (hover: hover) {
  .callout:hover .callout__dot { transform: scale(1.18); }
}
.callout:focus-visible { outline: none; }
.callout:focus-visible .callout__name { outline: 2px solid var(--pill-ink); outline-offset: -4px; }

@media (min-width: 901px) {
  /* one screen: the heading, then a window as big as the screen allows, down to just past its
     drive bar; the rest of it runs under the bottom edge and fades out */
  .studio {
    height: 100vh; height: 100svh; justify-content: flex-start;
    padding: 92px 32px 0; overflow: clip;
  }
  .studio__inner {
    --win: min(1320px, 100vw - 64px, (100svh - 254px) * 1.946);
    width: var(--win); margin: 0 auto; height: 100%;
    display: flex; flex-direction: column; gap: 22px;
    -webkit-mask-image: linear-gradient(to bottom, #000 calc(100% - 56px), transparent);
    mask-image: linear-gradient(to bottom, #000 calc(100% - 56px), transparent);
  }
  .studio__title { font-size: clamp(36px, min(4vw, 6.4vh), 58px); }
  /* the names keep their size to the window's: smaller windows (short screens) get smaller pills */
  .callout__name { --f: clamp(12.5px, var(--win) * 0.0118, 15px); font-size: var(--f); height: calc(var(--f) * 2.27); padding: 0 calc(var(--f) * 0.87); }
  /* the arrival: the dots land one after another, each pill opening out of its dot */
  .studio:not(.is-shown) .callout { opacity: 0; }
  .studio:not(.is-shown) .callout__dot { transform: scale(0); }
  .studio:not(.is-shown) .callout__name,
  .studio.is-focused .callout:not(.is-active) .callout__name { max-width: 0; padding-left: 0; padding-right: 0; opacity: 0; }
  .studio.is-shown:not(.is-settled) .callout,
  .studio.is-shown:not(.is-settled) .callout__dot { transition-delay: calc(450ms + var(--i) * 120ms); }
  .studio.is-shown:not(.is-settled) .callout__name { transition-delay: calc(560ms + var(--i) * 120ms); }
  /* while one feature is on show the other dots wait a size smaller; a feature that fills the window (the install window) has it to itself */
  .studio.is-focused .callout:not(.is-active) .callout__dot { transform: scale(0.78); }
  .studio.is-solo .callout:not(.is-active), .callout.is-hidden { opacity: 0; pointer-events: none; }
}

/* tablets and phones: the window across the width, the names a short list under it; picking one
   (or the tour) zooms the window to its part */
@media (max-width: 900px) {
  .studio__stage { display: flex; flex-direction: column; gap: 14px; }
  .studio__title { margin-bottom: 22px; }
  .callouts { position: static; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; pointer-events: auto; }
  .callout, .callout[data-side="left"] {
    position: static; transform: none; flex-direction: row; justify-content: flex-start; gap: 10px;
    min-height: 44px; padding: 0 14px; border-radius: 999px; background: var(--hair);
    transition: background-color 0.25s var(--ease);
  }
  .callout::before { display: none; }
  .callout__dot { width: 9px; height: 9px; box-shadow: none; }
  .callout.is-active .callout__dot { animation: none; }
  .callout__name {
    height: auto; max-width: none; padding: 0; overflow: visible; white-space: normal;
    background: none; box-shadow: none; -webkit-backdrop-filter: none; backdrop-filter: none;
    /* the body face here: narrow enough that every name holds one line in half a phone */
    font-family: var(--font-body); font-size: 16px; font-weight: 600; font-stretch: 100%; line-height: 1.15;
    text-align: left; color: var(--ink-2);
  }
  .callout.is-active { background: var(--solid-bg); }
  .callout.is-active .callout__name { color: var(--solid-ink); }
  .callout:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
  .callout:focus-visible .callout__name { outline: none; }
}
@media (max-width: 560px) {
  /* phones: the window runs edge to edge, the one picture on the page that does */
  .win { margin: 0 -16px; border-radius: 0; box-shadow: none; }
  .studio .callouts { gap: 6px; }
  .callout, .callout[data-side="left"] { padding: 0 10px 0 12px; gap: 8px; }
  .callout__dot { width: 8px; height: 8px; }
}
/* narrow phones: one name a row, so none breaks over two lines */
@media (max-width: 374px) {
  .studio .callouts { grid-template-columns: minmax(0, 1fr); }
}
/* under 360px the designer's heading follows the width, so "Layout Designer." keeps one line */
@media (max-width: 359px) {
  .studio__title { font-size: calc((100vw - 32px) * 0.104); }
}
/* 375-389px phones: two a row still, a size smaller, so "Your own background" holds one line too */
@media (min-width: 375px) and (max-width: 389px) {
  .callout__name { font-size: 15px; }
}

.note { margin-top: 28px; font-size: 16px; color: var(--ink-2); max-width: 70ch; }

/* the small print: one pane of label / line rows, like the back of the box. Its heading takes one
   line where it fits, and both panes run the full width, so their edges line up */
.small-print .display { max-width: none; }
.small-print .section-head { display: flex; }
.fine { margin: 0; padding: 6px var(--pad); border-radius: var(--r-lg); }
.fine > div { position: relative; display: grid; grid-template-columns: 11rem minmax(0, 1fr); gap: 4px 24px; align-items: baseline; padding: 20px 0; }
.fine > div + div::before { content: ""; position: absolute; left: 0; right: 0; top: 0; height: 1px; background: var(--hair); }
.fine dt { font-size: 13px; font-weight: 600; letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink-2); }
.fine dd { margin: 0; font-size: 19px; line-height: 1.45; color: var(--ink); text-wrap: pretty; }

/* Buy: the logo, then the two tiers side by side (one above the other on phones). Pro's button is
   the solid one; Basic's is drawn as an outline, so the eye lands on Pro without a "best value" label */
.get .wrap { display: flex; flex-direction: column; align-items: center; gap: 28px; }
.tiers { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 20px; width: 100%; max-width: 860px; }
.tier { display: flex; flex-direction: column; gap: 16px; padding: 32px var(--pad); border-radius: var(--r-lg); }
.tier__name { margin: 0; font-family: var(--font-display); font-stretch: 112%; font-weight: 750; font-size: 30px; line-height: 1; }
.price { margin: 0; font-family: var(--font-num); font-weight: 700; font-size: 44px; line-height: 1; }
/* the list takes the spare height, so both buttons sit on one line */
.tier__list { margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 10px; flex: 1; }
.tier__list li { position: relative; padding-left: 20px; font-size: 18px; line-height: 1.35; color: var(--ink); }
.tier__list li::before { content: ""; position: absolute; left: 2px; top: 0.5em; width: 7px; height: 7px; border-radius: 50%; background: var(--ink-2); }
.tier--pro .tier__list li::before { background: var(--decal-red); }
.tier .btn { align-self: stretch; margin-top: 8px; }
/* the line under the cards sits on its own strip of glass: by day the track behind is too busy for bare text */
.get .note { margin: 0; padding: 12px 22px; border-radius: 18px; text-align: center; }
/* phones: one card above the other, each with its name and price on one row, so both cards and
   the line under them fit one screen */
@media (max-width: 640px) {
  .get .wrap { gap: 18px; }
  .tiers { grid-template-columns: minmax(0, 1fr); gap: 12px; }
  .tier { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: baseline; gap: 10px 12px; padding: var(--pad); }
  .tier__list, .tier .btn { grid-column: 1 / -1; }
  .tier__name { font-size: 26px; }
  .price { font-size: 30px; }
  .tier__list { gap: 6px; }
  .tier__list li { font-size: 16px; }
  .tier .btn { height: 44px; margin-top: 4px; }
}
/* the tag on a Pro-only feature: a small red pill after its name, the red of the logo's dot */
.pro {
  display: inline-flex; align-items: center; vertical-align: 0.12em; margin-left: 0.25em;
  padding: 0.22em 0.6em 0.18em; border-radius: 999px;
  background: var(--decal-red); color: #FFFFFF;
  font-family: var(--font-num); font-weight: 700; font-stretch: 100%; font-size: 0.62em; line-height: 1;
  letter-spacing: 0.08em; text-transform: uppercase; white-space: nowrap;
}
.display .pro { font-size: 0.3em; vertical-align: 0.55em; }

/* a short bottom: the footer is the last snap, so a deep margin under it is only dead space */
.footer { padding: 32px 24px 48px; }
.footer__row { display: flex; justify-content: space-between; gap: 24px; padding: 20px var(--pad); border-radius: var(--r-lg); font-size: 14px; color: var(--ink-2); }
.footer__row p:first-child { flex: none; white-space: nowrap; } /* the copyright never breaks in two */
.footer__row p:last-child { max-width: 62ch; text-align: right; }

/* ---------- section moves: panes fly in from the direction of travel, one after another, and
   dissipate (lift or sink away and fade) when the page moves on */
.anim {
  transition: opacity 0.5s var(--ease), transform 0.6s var(--ease),
    background-color var(--phase) var(--ease), border-color var(--phase) var(--ease),
    box-shadow var(--phase) var(--ease), color var(--phase) var(--ease);
  transition-delay: calc(var(--i, 0) * 50ms), calc(var(--i, 0) * 50ms), 0s, 0s, 0s, 0s;
}
main > section:not(.is-shown) .anim {
  opacity: 0;
  transform: translateY(calc(var(--from, 1) * 64px)) scale(0.96);
}
main > section.is-leaving .anim {
  opacity: 0;
  transform: translateY(calc(var(--to, -1) * 48px)) scale(1.04);
  transition-duration: 0.3s, 0.35s, var(--phase), var(--phase), var(--phase), var(--phase);
  transition-delay: calc(var(--i, 0) * 25ms), calc(var(--i, 0) * 25ms), 0s, 0s, 0s, 0s;
}

/* ---------- small screens */
@media (max-width: 900px) {
  .intro__grid { grid-template-columns: 1fr; gap: 28px; }
  /* the screen on top; the themes become a sideways row of chips under the layout switch */
  .showcase { grid-template-columns: minmax(0, 1fr); }
  .showcase__themes {
    flex-direction: row; overflow-x: auto; gap: 8px; scrollbar-width: none; scroll-snap-type: x proximity;
    /* the row runs out to the pane's rim (16px = .showcase__controls' padding; change both
       together) and 6px above and below, so chips are not cut 16px inside the pane and a chip's
       focus ring is not clipped. The margins cancel the padding, so nothing else moves, and the
       scroll padding keeps the start snap on the 16px line */
    margin: -6px -16px; padding: 6px 16px; scroll-padding-inline: 16px;
    /* a fade exactly as wide as that padding: nothing is faded at rest or at either end, and a chip
       passing the rim dissolves instead of being sliced */
    -webkit-mask-image: linear-gradient(90deg, transparent, #000 16px, #000 calc(100% - 16px), transparent);
    mask-image: linear-gradient(90deg, transparent, #000 16px, #000 calc(100% - 16px), transparent);
  }
  .showcase__themes::-webkit-scrollbar { display: none; }
  .showcase__themes button { flex: 0 0 auto; gap: 8px; border-radius: 999px; background: var(--hair); scroll-snap-align: start; }
  .showcase__themes button[aria-pressed="true"] { background: var(--solid-bg); color: var(--solid-ink); }
  .showcase__themes button[aria-pressed="true"]::after { display: none; }
  .showcase__themes button[aria-pressed="true"] .showcase__n { color: inherit; opacity: 0.6; }
  .seg { max-width: 320px; }
  .section { padding: 96px 16px; }
  /* the same 16px gutter as the sections, and a bottom that just clears the home indicator */
  .footer { padding: 24px 16px calc(24px + env(safe-area-inset-bottom, 0px)); }
}
/* once the night/day toggle docks in the bar there is no room left for the text links below
   about 900px (920 leaves room for a desktop scrollbar): tablets get the phone set of logo,
   toggle and the one CTA */
@media (max-width: 920px) {
  .nav__links a:not(.btn) { display: none; }
}
/* phones: the reel in two columns. The bands and columns step aside (display: contents), so every
   tile is a cell and the lap chart takes the screens' 5:3. One screen across both, then a pair, in
   turn: backgrounds, best lap + lap data, the layouts, the rules + launch */
@media (max-width: 699px) {
  .reel__head { margin-bottom: 24px; }
  .reel__grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
  .reel__band, .reel__col { display: contents; }
  .tile, html.has-refraction .tile { padding: 6px; border-radius: 16px; }
  .tile__media, html.has-refraction .tile__media { border-radius: 10px; }
  .tile--xl { grid-column: 1 / -1; }
  .tile--layouts { order: 1; }
  .tile--rules, .tile--launch { order: 2; }
  .tile--fill .tile__media, .tile--stretch .tile__media { flex: none; aspect-ratio: 5 / 3; min-height: 0; }
  /* a touch narrower here, so the longest words in a half-width tile hold a line (two lines at most) */
  .tile__cap { padding: 8px 4px 2px; font-size: 16px; font-stretch: 100%; }
  .tile--xl .tile__cap { font-size: 19px; padding-top: 9px; }
}
@media (max-width: 359px) {
  .tile__cap { font-size: 14px; }
  .tile--xl .tile__cap { font-size: 17px; }
}
/* narrow phones: the half-width captions a little narrower again, so "Custom rules based on your
   car's data." keeps to two lines beside its pair (at 100% it took three) */
@media (max-width: 379px) { .tile:not(.tile--xl) .tile__cap { font-stretch: 88%; } }
@media (max-width: 339px) { .tile:not(.tile--xl) .tile__cap { font-stretch: 80%; } }
@media (max-width: 720px) {
  .nav { padding: 0 8px 0 14px; }
  .banner--nav { --bh: 30px; }
  .banner--nav .banner__end { display: none; }
  .nav .brand { flex-shrink: 0; } /* the logo never gets squeezed */
  .footer__row { flex-direction: column; }
  .footer__row p:last-child { text-align: left; }
}
/* 320px phones: the bar tightens a little more so the CTA still ends inside it (after the 720px
   and 420px rules, which it has to beat) */
@media (max-width: 359px) {
  .nav { gap: 4px; padding: 0 6px 0 10px; }
  .nav .banner--nav { --bh: 24px; }
  .nav .phase-toggle__opt { padding: 0 7px; }
  .nav .btn--sm { padding: 0 12px; }
}
/* phones: one spacing scale. A tight bottom (the next section's top already clears the nav) and one
   pane padding all round (--pad, 20px here) so text edges line up. After the 900px block, which it
   has to beat */
@media (max-width: 560px) {
  .section { padding: 92px 16px 24px; }
  .section-head { padding: var(--pad); }
  .section-head { display: flex; margin-bottom: 16px; } /* full width, like the panes under it */
  /* the small print's label sits over its line */
  .fine > div { grid-template-columns: minmax(0, 1fr); padding: 16px 0; }
  .fine dd { font-size: 17px; }
}
/* short phones (iPhone SE and the like): the small print's rows a little closer, so its pane fits
   the screen whole */
@media (max-width: 560px) and (max-height: 700px) {
  .small-print .fine > div { padding: 11px 0; }
  .small-print .section-head { margin-bottom: 12px; }
}
/* desktop: every section, Features included, fits one screen, so one wheel notch is one whole
   section. Headings and gaps follow the window's height as well as its width */
@media (min-width: 901px) {
  .section { padding-top: 92px; padding-bottom: clamp(24px, 6vh, 96px); }
  .display { font-size: clamp(36px, min(5.2vw, 7.5vh), 68px); }
  .section-head { padding: 20px var(--pad) 24px; margin-bottom: 20px; }
  /* only the showcase is held down to fit the height; the heading stays on the shared left edge,
     so the text edge does not jump sideways from section to section */
  .features .showcase { max-width: min(1200px, calc(130vh + 20px)); }
}
/* a mouse needs less than a finger: on short windows the theme rows close up */
@media (min-width: 901px) and (pointer: fine) {
  .showcase__themes button { min-height: clamp(28px, calc(7.8vh - 27px), 40px); }
}
/* landscape phones: little height, so less padding round the intro and the sections and smaller
   headings (the logo's size also follows the height, see --bh), and the screen rows keep their room */
@media (max-height: 500px) and (orientation: landscape) {
  .title { padding-top: 84px; padding-bottom: 8px; }
  .title__pane { gap: 10px; }
  .section { padding-top: 84px; padding-bottom: 16px; }
  .display { font-size: clamp(28px, 4.2vw, 40px); }
}

@media (prefers-reduced-motion: reduce) {
  :root { --phase: 0.01s; }
  html { scroll-behavior: auto; }
  .backdrop__video--day, .backdrop__blur, .backdrop__frost, html.studio-frost .backdrop__frost { transition: none; }
  html.intro-play .lockup .banner__body > *, html.intro-play .lockup .banner__end, html.intro-play .lockup .banner__end::before, .lockup .banner__body::before { transition: none !important; }
  .loader { transition-duration: 0.01s; }
  .title__banner { transition: opacity 0.01s; }
  html.title-gone .title__banner { transform: none; filter: none; }
  .phase-toggle::after, .phase-toggle__opt { transition-duration: 0.01s !important; } /* the thumb jumps instead of sliding */
  .anim { transition: none !important; }
  .win__shots, .win__shot, .callout, .callout__dot, .callout__name { transition: none !important; }
  .callout.is-active .callout__dot { animation: none; }
  main > section .anim { opacity: 1 !important; transform: none !important; }
}
