@font-face {
  font-family: "Newsreader";
  src: url("/assets/full-stop/web/enuva-display-medium-latin-ext.woff2") format("woff2");
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  unicode-range: U+0020-007E, U+00A0-0131, U+0134-0148, U+014A-017E, U+018F, U+0192, U+01A0-01A1, U+01AF-01B0, U+01C4-01CC, U+01E6-01E7, U+01EA-01EB, U+01FA-021B, U+022A-022D, U+0230-0233, U+0237, U+0300-0304, U+0306-030C, U+030F, U+0311-0312, U+031B, U+0323-0324, U+0326-0328, U+032E, U+0331, U+0335, U+1E80-1E85, U+1E9E, U+1EA0-1EF9, U+2010, U+2013-2014, U+2018-201A, U+201C-201E, U+2020-2022, U+2026, U+2030, U+2032-2033, U+2039-203A, U+2044, U+2052, U+20A1, U+20A3-20A4, U+20A6-20A7, U+20A9, U+20AB-20AD, U+20B1-20B2, U+20B5, U+20B9-20BA, U+20BC-20BD, U+2116, U+2122, U+2212;
}
@font-face {
  font-family: "Plex";
  src: url("/assets/full-stop/web/enuva-serif-medium-period.woff2") format("woff2");
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  unicode-range: U+002E;
}
/* Georgia Regular width fit across the four-language display copy; vertical
   overrides derive from Newsreader 1470/-530/0 at 2000 units per em. */
@font-face {
  font-family: "Newsreader Fallback";
  src: local("Georgia");
  font-style: normal;
  font-weight: 400;
  size-adjust: 95.8197%;
  ascent-override: 76.7066%;
  descent-override: 27.6561%;
  line-gap-override: 0%;
}
/* Day colors. The listening dusk swaps the page's color tokens (--paper, --ink, --muted,
   --rule, --stage); the --day-* colors never change, for the few things that stay in day
   colors on the dusk. */
:root {
  --day-paper: #f5f2e9; --day-ink: #3a2a1f; --day-rule: #d5cfc1; --day-stage: #ebe4d6;
  --paper: var(--day-paper); --ink: var(--day-ink); --muted: #746355; --amber: #e29a45;
  /* The invite band's lighter amber keeps ink focus rings about 6.3:1 on it; the hover amber is
     the play buttons' lift; the error ink passes 4.5:1 on the band and on its pale field. */
  --amber-band: #e6a153; --amber-hover: #edac62; --error: #632c1d; --error-field: #f9d6c8;
  --dusk: #594738; --dusk-ink: #f5f2e9; --dusk-muted: #d8c8b5;
  --font-display: "Newsreader", "Newsreader Fallback", Georgia, serif;
  --font-text: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --font-mono: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  --step-display: clamp(4.5rem, 2.9rem + 6.6vw, 9rem);
  --step-h2: clamp(2.5rem, 2.05rem + 1.9vw, 3.5rem);
  --step-h3: clamp(1.5rem, 1.39rem + 0.47vw, 1.75rem);
  --step-lede: clamp(1.125rem, 1.07rem + 0.24vw, 1.25rem);
  --step-body: clamp(1rem, 0.97rem + 0.12vw, 1.0625rem);
  --step-small: 0.875rem; --step-legal: 0.75rem;
  --space-1: 0.5rem; --space-2: 1rem; --space-3: 1.5rem; --space-4: 2rem;
  --space-6: 3rem; --space-8: 4rem; --space-12: 6rem; --space-16: 8rem;
  --section-pad: clamp(5rem, 3.6rem + 5.8vw, 8rem);
  --radius-control: 10px; --radius-device: 36px; --radius-pill: 999px;
  /* The captures' whole iPhone screen in pixels (402 × 874 pt at 3x); see .whole-screen. */
  --screen-w: 1206; --screen-h: 2622;
}
/* Hairlines and the product stage keep their own colors. The header height is shared
   with the language suggestion, which hangs from the header's lower edge. */
:root {
  --rule: var(--day-rule);
  --stage: var(--day-stage);
  --header-height: 119px;
}
* {
  box-sizing: border-box;
}
html {
  scroll-behavior: smooth;
  scroll-padding-top: var(--space-4);
}
body {
  margin: 0;
  font-family: var(--font-text);
  font-size: var(--step-body);
  line-height: 1.55;
  color: var(--ink);
  background: var(--paper);
  -webkit-font-smoothing: antialiased;
}
h1, h2, h3 { text-wrap: balance; }
p, li, dd { text-wrap: pretty; }
::selection {
  background: var(--amber);
  color: var(--ink);
}
a {
  color: inherit;
  text-underline-offset: 5px;
}
button,
input,
select {
  font: inherit;
  color: inherit;
}
button,
summary,
select {
  cursor: pointer;
}
button,
a,
input,
select {
  -webkit-tap-highlight-color: transparent;
}
button,
a {
  touch-action: manipulation;
}
:focus-visible { outline: 3px solid var(--ink); outline-offset: 3px; }
/* Focus the page moves itself after a tap or a click shows no ring; after a key it keeps it (homepage.js). */
[data-quiet-focus]:focus-visible { outline: none; }
/* Ink rings on the amber band (about 6.3:1) and around the floating invitation. */
.beta :focus-visible, .mobile-waitlist-cta :focus-visible { outline-color: var(--ink); }
button:disabled {
  cursor: default;
  opacity: 0.4;
}
button {
  border: 0;
}
svg {
  width: 24px;
  height: 24px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.5;
}
p,
h1,
h2,
h3,
figure {
  margin: 0;
}
[hidden] {
  display: none !important;
}
.button { display: inline-flex; align-items: center; justify-content: center; gap: var(--space-1);
  min-height: 48px; padding: 0 var(--space-3); border-radius: var(--radius-control);
  font: 600 var(--step-body)/1.2 var(--font-text); text-decoration: none; cursor: pointer; }
.button-primary { background: var(--ink); color: var(--paper); border: 0; }
.button-primary:hover { background: #2b1c13; }
.button:active { transform: translateY(1px); }
/* .text-cta on a <button> drops the native button look. Zero specificity, so the
   .text-cta color and weight still apply; links are not matched. The underline is
   declared on .text-cta itself, so a button reads exactly like the link version. */
:where(button.text-cta) { background: none; border: 0; padding: 0; font: inherit; color: inherit; cursor: pointer; }
.text-cta { font-weight: 600; color: var(--ink); text-decoration: underline; text-underline-offset: 5px; }
.device-frame { border-radius: var(--radius-device); overflow: hidden; background: #221a15; box-shadow: 0 18px 44px rgb(58 42 31 / 0.18); }
/* A frame that shows a capture's whole screen, at the capture's own aspect: the empty status
   bar at the top, the app's tab bar and the inset below it at the bottom. Nothing is cropped,
   so no row or control meets the frame's edge; a layout with less room makes the whole phone
   smaller. The corners are 10% of the frame's width (the vertical radius is the same length),
   36 px on a 360 px frame, well clear of the tab bar's rounded ends. */
.whole-screen {
  aspect-ratio: var(--screen-w) / var(--screen-h);
  border-radius: 10% / calc(10% * var(--screen-w) / var(--screen-h));
}
.whole-screen img { display: block; width: 100%; height: auto; margin: 0; }
.wrap {
  max-width: 1600px;
  margin-inline: auto;
  padding-inline: var(--space-8);
}
.sr-only,
.ea-honeypot {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}
.skip {
  position: fixed;
  top: -100px;
  left: 20px;
  z-index: 10;
  padding: var(--space-2);
  background: var(--paper);
  color: var(--ink);
}
.skip:focus {
  top: 12px;
}
/* locale.js can show this line after the page has painted. It sits out of flow just
   below the header, so nothing moves when it appears. It stacks above the header (z 2),
   whose empty lower edge it overlaps; an open language menu lifts the header above it.
   Its bottom edge keeps the header's row spacing (--space-1) above the headline, which
   starts the hero's top padding (--space-4) below the header. */
.language-suggestion {
  position: absolute;
  z-index: 3;
  top: calc(var(--header-height) + var(--space-4) - var(--space-1));
  transform: translateY(-100%);
  right: max(var(--space-8), calc(50% - 736px));
  display: flex;
  align-items: center;
  max-width: calc(100% - 2 * var(--space-3));
  padding-left: var(--space-2);
  border: 1px solid var(--rule);
  border-radius: var(--radius-pill);
  background: var(--stage);
  color: var(--ink);
  font-size: var(--step-small);
  line-height: 1.2;
}
.language-suggestion a {
  padding-block: var(--space-1);
}
.language-suggestion button {
  width: 32px;
  height: 32px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: transparent;
  color: var(--muted);
  font-size: 22px;
  line-height: 1;
}
.header {
  min-height: var(--header-height);
  display: flex;
  align-items: center;
  gap: var(--space-4);
}
.wordmark {
  stroke: none;
  width: 155px;
  height: auto;
  display: block;
}
.beta-status {
  font-size: var(--step-small);
  color: var(--muted);
}
.header-actions {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: var(--space-4);
}
.language-menu {
  position: relative;
}
.language-menu summary {
  white-space: nowrap;
  display: flex;
  align-items: center;
  gap: var(--space-1);
  padding: var(--space-1);
  font-size: var(--step-small);
  list-style: none;
}
.language-menu summary::-webkit-details-marker,
.intro-transcript summary::-webkit-details-marker {
  display: none;
}
/* The chevron of every disclosure and select: the language menu, "Transcript and
   sources" and the form's "How did you hear" select. It turns up while open. */
.language-menu summary::after,
.intro-transcript summary::after,
.select-field::after {
  content: "";
  width: 6px;
  height: 6px;
  margin-top: -4px;
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  transform: rotate(45deg);
}
.language-menu[open] summary::after,
.intro-transcript[open] summary::after {
  margin-top: 3px;
  transform: rotate(225deg);
}
/* Day colors: the panel stays paper-colored while the header turns dusk, and so
   do the focus rings inside it. */
.language-menu ul {
  --ink: var(--day-ink);
  position: absolute;
  top: 100%;
  right: 0;
  min-width: 176px;
  margin: 0;
  padding: var(--space-1);
  list-style: none;
  background: var(--day-paper);
  color: var(--day-ink);
  border: 1px solid var(--day-rule);
  border-radius: var(--radius-control);
  box-shadow: 0 6px 16px rgb(58 42 31 / 0.08);
}
.language-menu a {
  display: block;
  padding: var(--space-1) var(--space-2);
  border-radius: 6px;
  font-size: var(--step-small);
  text-decoration: none;
}
.language-menu a:hover {
  background: var(--day-stage);
}
.language-menu a:focus-visible {
  outline-offset: -2px;
}
.language-menu a[aria-current="true"] {
  font-weight: 700;
}
/* The header's controls never wrap: below 1151 px their gaps tighten instead, so the
   longest set (Slovak) keeps one line from 761 px. */
.join-link {
  white-space: nowrap;
  font-size: var(--step-small);
  display: flex;
  align-items: center;
  gap: var(--space-3);
  text-decoration: none;
  border-bottom: 1px solid var(--ink);
  padding: var(--space-2) 0;
}
.join-link svg {
  transition: transform 0.2s;
}
.join-link:hover svg {
  transform: translateX(4px);
}
/* Section rhythm: half of --section-pad on each side of a plain section, so adjacent
   sections sit a full --section-pad (128/80 px) apart. The hero keeps a short top
   offset under the header; the amber band keeps the full padding inside its color. */
.hero {
  padding-top: var(--space-4);
  padding-bottom: calc(var(--section-pad) / 2);
}
.hero-composition {
  display: grid;
  grid-template-columns: minmax(0, 1.5fr) minmax(340px, 1fr);
  gap: var(--space-8);
  align-items: start;
}
.hero-editorial { min-width: 0; }
/* One h1 carries both lines: the muted kicker, then the display line. Words may break
   rather than overflow when readers widen letter spacing (WCAG 1.4.12). */
.hero-headline {
  font-family: var(--font-display);
  font-weight: 500;
  hyphens: manual;
  overflow-wrap: anywhere;
}
.not-more {
  display: block;
  font-size: clamp(2.5rem, 4.1vw, 4rem);
  line-height: 1.05;
  letter-spacing: -0.035em;
  color: var(--muted);
}
/* When the German kicker wraps, it breaks before "Nachrichten.": Chrome's balance would
   split "Nicht noch mehr Nachrichten." after "noch", leaving the shorter line on top. */
html[lang="de"] .not-more { text-wrap: pretty; }
/* The display step, held at 9.1vw below 1582 px; the longer German, Czech and Slovak lines
   start smaller. */
.enough {
  display: block;
  margin-top: var(--space-1);
  font-size: min(var(--step-display), 9.1vw);
  line-height: .98;
  letter-spacing: -0.04em;
}
html[lang="de"] .enough,
html[lang="sk"] .enough,
html[lang="cs"] .enough {
  font-size: clamp(76px, 7.5vw, 116px);
}
/* Beside the capture the display line keeps one line in every language: it never grows past
   the headline's width (cqi). Each cap is that line's width in em (Enough news. 5.54,
   Dosť správ. 4.40, Tak akorát zpráv. 6.73, Genug Nachrichten. 7.89) with 2.5% to spare;
   measure again when the copy changes. The German kicker stays clearly the smaller line.
   Phones keep the spec's display sizes (the 760px block). */
@supports (width: 1cqi) {
  .hero-headline { container-type: inline-size; }
  .enough { --fit: 17.6cqi; font-size: min(var(--step-display), 9.1vw, var(--fit)); }
  html[lang="sk"] .enough { --fit: 22cqi; }
  html[lang="cs"] .enough { --fit: 14.5cqi; }
  html[lang="de"] .enough { --fit: 12.3cqi; }
  html:is([lang="de"], [lang="sk"], [lang="cs"]) .enough { font-size: min(clamp(76px, 7.5vw, 116px), var(--fit)); }
  html[lang="de"] .not-more { font-size: min(clamp(2.5rem, 4.1vw, 4rem), 8.8cqi); }
}
.period {
  color: var(--amber);
  font-family: Plex, Georgia, serif;
  letter-spacing: -0.01em;
}
.hero-copy { margin-top: var(--space-4); }
.hero-copy > p {
  font-size: var(--step-lede);
  line-height: 1.65;
  max-width: 510px;
  margin-top: 0;
  color: var(--hero-body, #675547);
}
.hero-actions { margin-top: var(--space-3); }
.listen-invite { width: 100%; }
.listen-start {
  background: transparent;
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: 0;
  text-align: left;
}
/* An amber halo marks the circle as a control, not a dot. Until the sample is first played
   (.was-played, homepage.js), a ring leaves the circle every four seconds, slow as a breath, and
   rests while the button is off screen (.is-offscreen); hover widens the halo and underlines
   the title. */
.play-icon {
  position: relative;
  width: 60px;
  height: 60px;
  border-radius: 50%;
  background: var(--amber);
  box-shadow: 0 0 0 7px rgb(226 154 69 / .28);
  display: grid;
  place-items: center;
  flex-shrink: 0;
  transition: background 0.2s, box-shadow 0.2s;
}
.play-icon::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  border: 3px solid var(--amber);
  opacity: 0;
  pointer-events: none;
  animation: play-ripple 4s cubic-bezier(.2, .6, .3, 1) .8s infinite;
}
@keyframes play-ripple {
  0% { transform: scale(1); opacity: .85; }
  55%, 100% { transform: scale(1.8); opacity: 0; }
}
.is-offscreen .play-icon::after { animation-play-state: paused; }
.was-played .play-icon::after { animation: none; }
@media (prefers-reduced-motion: reduce) { .play-icon::after { animation: none; } }
.play-icon svg {
  fill: var(--ink);
  stroke: none;
  width: 27px;
  height: 27px;
}
@media (hover: hover) and (pointer: fine) {
  .listen-start:hover .play-icon { background: var(--amber-hover); box-shadow: 0 0 0 10px rgb(226 154 69 / .34); }
  .listen-start:hover strong { text-decoration-color: currentColor; }
}
.listen-start strong {
  font: 500 var(--step-h3)/1.1 var(--font-display);
  letter-spacing: -0.02em;
  text-decoration: underline 1px transparent;
  text-underline-offset: .18em;
  transition: text-decoration-color 0.2s;
}
/* The start title keeps its no-break pair ("sample briefing") on one line, so where the column is
   narrower than that pair at full size (large text on small phones), the title scales down with
   the column: the column less the 60 px play icon and the gap. The cap is the widest pair, German
   "Briefing anhören" at 7.01 em, with 4% to spare; with text-spacing overrides it may still break
   inside a word rather than widen the page. Measure again when the copy changes. */
@supports (width: 1cqi) {
  .listen-default { container-type: inline-size; }
  .listen-start strong {
    font-size: min(var(--step-h3), (100cqi - 60px - var(--space-2)) * .137);
    overflow-wrap: anywhere;
  }
}
.listen-start small {
  display: block;
  margin-top: var(--space-1);
  color: var(--muted);
  font-size: var(--step-small);
  line-height: 1.5;
  max-width: 320px;
}
/* The invitation never shrinks, so its label stays on one line. */
.hero-invite { flex: none; }
/* Transcript and sources: a reading surface, so body-size text in ink. */
.intro-transcript { margin-top: var(--space-1); max-width: 560px; }
.intro-transcript summary { display: flex; align-items: center; gap: var(--space-1); list-style: none; color: var(--muted); font-size: var(--step-small); padding-block: var(--space-1); width: fit-content; }
.intro-transcript small { display: block; margin-top: var(--space-1); color: var(--muted); font-size: var(--step-small); line-height: 1.6; }
.intro-transcript h2 { margin-top: var(--space-3); font: 500 var(--step-lede)/1.3 var(--font-display); letter-spacing: -.01em; color: var(--ink); }
#sample-transcript { margin-top: var(--space-1); color: var(--ink); font-size: var(--step-body); line-height: 1.6; }
#sample-transcript p + p { margin-top: var(--space-2); }
.intro-transcript .speaker { font-weight: 700; }
.intro-transcript .speaker-note { color: var(--muted); }
.sample-sources { list-style: none; padding: 0; margin: var(--space-1) 0 0; font-size: var(--step-body); line-height: 1.6; }
.sample-sources li { display: flex; flex-wrap: wrap; column-gap: var(--space-2); margin-top: var(--space-1); }
.sample-sources time { color: var(--muted); }
.intro-transcript .ai-disclosure { margin-top: var(--space-3); font-size: var(--step-small); }
.audio-error { margin-top: var(--space-2); font-size: var(--step-small); line-height: 1.6; }
.hero-proof { --frame-w: 360px; min-width: 0; padding-top: var(--space-1); }
/* On shorter desktop screens the phone narrows (not below 250 px) so that the whole screen and
   its caption stay in the first viewport under the header. */
@supports (height: 100svh) {
  .hero-proof { --frame-w: min(360px, max(250px, (100svh - var(--header-height) - var(--space-12)) * var(--screen-w) / var(--screen-h))); }
}
/* The phone frame (.whole-screen) holds the screenshot's whole screen and, while the sample plays,
   the live Spine in the same box, point for point, so nothing moves at the swap. The screenshot
   and its play hotspot share one box (.hero-capture). */
/* The caption keeps one line: the figure takes the wider of the phone (--frame-w) and the
   caption's one line, within its column, and the phone fills the figure. So a longer caption
   (German) widens the phone a little rather than wrapping under it. Only where even the whole
   column is narrower than the caption (German at 320 px) does it wrap. */
.hero-proof { width: max-content; max-width: 100%; margin-inline: auto; }
.hero-frame {
  position: relative;
  isolation: isolate;
  width: var(--frame-w);
  min-width: 100%;
  max-width: 100%;
}
.hero-capture { position: relative; }
/* The capture's own play button starts the sample, exactly like Play (homepage.js). It is pointer
   only, aria-hidden and not focusable: the hero's buttons are the accessible player. It sits on the
   circle in the capture's own coordinates, so a new crop keeps it aligned: all four captures draw the
   circle 192 px wide, centered at 603 x 2097 of 1206 x 2622. */
.hero-play {
  position: absolute;
  left: 50%;
  top: 79.977%;
  width: 15.92%;
  aspect-ratio: 1;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  cursor: pointer;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
  transition: background-color .2s;
}
/* Lighter on hover, like the hero's own play button; darker while pressed. */
@media (hover: hover) {
  .hero-play:hover { background: rgb(255 255 255 / .16); }
}
.hero-play:active { background: rgb(35 23 14 / .16); }
body.is-listening .hero-play { visibility: hidden; }
.hero-frame > .live-spine { position: absolute; inset: 0; }
.hero-proof figcaption { font-size: var(--step-small); line-height: 1.6; color: var(--muted); padding-block: var(--space-1); text-wrap: pretty; }
/* How it works: three tabs over one fixed-height stage, so choosing a view never moves
   the page. data-view follows the chosen tab at once; data-shown names the view whose
   captures the stage shows, and moves once the new captures are decoded (homepage.js).
   The narrower layouts are in the @media blocks at the end of this section. */
.product {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.06fr);
  grid-template-areas: "copy proof" "details proof" "cta proof";
  grid-template-rows: auto auto 1fr;
  column-gap: 8%;
  padding-block: calc(var(--section-pad) / 2);
}
.product-copy {
  grid-area: copy;
  padding-top: var(--space-4);
}
/* Section headings: the tour and "Before you ask". */
.product h2,
.answers h2 {
  font: 500 var(--step-h2)/1.04 var(--font-display);
  letter-spacing: -0.025em;
}
.section-intro {
  font-size: var(--step-lede);
  line-height: 1.7;
  color: var(--muted);
  margin-top: var(--space-3);
  max-width: 395px;
}
.product-tabs {
  margin-top: var(--space-4);
  max-width: 425px;
}
.product-tabs button {
  display: flex;
  align-items: center;
  border: 0;
  border-bottom: 1px solid var(--rule);
  width: 100%;
  min-height: 50px;
  padding: var(--space-1) 0;
  background: transparent;
  text-align: left;
  font: 500 var(--step-lede)/1.2 var(--font-display);
  color: var(--muted);
}
/* A text underline, unlike a color or a border, survives forced-colors mode. */
.product-tabs button[aria-selected="true"] {
  color: var(--ink);
  text-decoration-line: underline;
  text-decoration-thickness: 2px;
  text-underline-offset: 6px;
}
/* With a mouse, a tab darkens as the pointer arrives, and its view follows after a short rest
   (homepage.js). On touch, a tapped tab does not keep a hover color. */
@media (hover: hover) and (pointer: fine) {
  .product-tabs button {
    transition: color .2s ease;
  }
  .product-tabs button:hover {
    color: var(--ink);
  }
}
/* The copy under the tabs keeps the height of the tallest view's copy: an invisible sizer
   per view (aria-hidden) shares the live copy's grid cell, so choosing a view never moves
   the invitation link or the sections below. */
.view-description {
  grid-area: details;
  display: grid;
  max-width: 410px;
  margin-top: var(--space-3);
}
.view-description > * {
  grid-area: 1 / 1;
}
.view-sizer {
  visibility: hidden;
}
.view-description h3,
.view-title {
  font: 500 var(--step-h3)/1.15 var(--font-display);
  text-wrap: balance;
}
.view-description p {
  font-size: var(--step-body);
  line-height: 1.7;
  color: var(--muted);
  margin-top: var(--space-1);
}
.product > .text-cta {
  grid-area: cta;
  justify-self: start;
  align-self: start;
  margin-top: var(--space-2);
  padding-block: var(--space-1);
}
/* The counter and arrows are for phones; wider screens show every tab at once. */
.stage-controls {
  grid-area: navigation;
  display: none;
  gap: var(--space-2);
  align-items: center;
  font-size: var(--step-small);
  color: var(--muted);
}
.stage-controls button {
  width: 44px;
  height: 44px;
  background: transparent;
  display: grid;
  place-items: center;
}
#previous svg {
  transform: rotate(180deg);
}
.product-stage {
  grid-area: proof;
  height: 680px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  padding: var(--space-4) var(--space-3) var(--space-3);
  background: var(--stage);
  touch-action: pan-y pinch-zoom;
}
.stage-media {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: var(--space-3);
  width: 100%;
}
/* A shot is one capture's whole screen in its phone frame (.whole-screen), then its label.
   The phone is as tall as the stage allows: 587 px of the 680 px stage remain once its
   padding, the gap and the caption are taken, so the shot is 270 px wide. */
.stage-shot {
  flex: none;
  width: min(100%, 587px * var(--screen-w) / var(--screen-h));
}
.product-stage:not(:is([data-shown="listen"], [data-shown="feedback"])) .stage-second {
  display: none;
}
/* A label shows only while its shot stands beside the other one. */
.frame-label {
  display: none;
  margin-top: var(--space-1);
  font-size: var(--step-small);
  line-height: 1.5;
  color: var(--muted);
  text-align: center;
}
.stage-caption {
  font-size: var(--step-small);
  line-height: 1.5;
  color: var(--muted);
  text-align: center;
}
/* Where one capture of a pair shows at a time, the switch mirrors the app's own segmented
   control. Its pressed segment is lighter than the app's, so the choice reads at 3.2:1
   against the track (WCAG 1.4.11), with its label at 4.7:1; the transparent outline shows
   it in forced-colors mode, where backgrounds are dropped. */
.pair-switch {
  display: flex;
  padding: 4px;
  border-radius: 10px;
  background: #30241d;
}
.pair-switch button {
  min-width: 96px;
  min-height: 36px;
  padding: 0 var(--space-2);
  border-radius: 8px;
  background: transparent;
  color: #a59d94;
  font: 500 var(--step-small)/1 var(--font-text);
}
.pair-switch button[aria-pressed="true"] {
  background: #817165;
  color: #fff;
  font-weight: 600;
  outline: 2px solid transparent;
  outline-offset: -2px;
}
.pair-switch button:focus-visible {
  outline: 3px solid #f4eee7;
  outline-offset: -3px;
}
/* A pair of captures, side by side and labelled, from where both phones are 236 px or wider.
   The label takes 29 px of the phone's height. */
@media (min-width: 1280px) {
  .product-stage:is([data-shown="listen"], [data-shown="feedback"]) .stage-shot {
    width: min((100% - var(--space-3)) / 2, 558px * var(--screen-w) / var(--screen-h));
  }
  .product-stage:is([data-shown="listen"], [data-shown="feedback"]) .frame-label {
    display: block;
  }
}
/* Up to 1279 px one capture of a pair shows at a time (homepage.js), with the pair's
   switch under the phone and its caption: the view's controls stay together, and on phones the
   switch sits right above the pager. The switch keeps its row in every view, so the phone never
   moves; the phone keeps 527 px of the stage's height. The one column spans the stage, so a
   shot's width follows its own rule rather than the image's sizes attribute. */
@media (max-width: 1279px) {
  .product-stage {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: minmax(0, 1fr) auto 44px;
    justify-items: center;
    row-gap: var(--space-2);
  }
  .stage-media {
    grid-row: 1;
  }
  .stage-caption {
    grid-row: 2;
  }
  .pair-switch {
    grid-row: 3;
  }
  .stage-shot {
    width: min(100%, 527px * var(--screen-w) / var(--screen-h));
  }
}
@media (max-width: 760px) {
  .product {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas: "copy" "proof" "navigation" "details" "cta";
    grid-template-rows: auto;
    row-gap: var(--space-2);
  }
  .product-copy {
    padding-top: 0;
  }
  .section-intro {
    margin-top: var(--space-2);
  }
  /* One row of tabs that runs edge to edge, the first label in line with the copy. All three
     labels stay whole in view: where they do not fit on one line (with Apple's system font,
     below 357 px in English, 366 px in Czech, 383 px in Slovak and 386 px in German), the
     longest label wraps to two lines inside the row's 44 px height, spaced for the chosen
     tab's underline. Each tab is a grid column as wide as its label, and homepage.js narrows
     a wrapped label's column to its longer line, so the gaps stay even. The padding keeps
     the focus rings inside the row. Only if even the wrapped labels are too wide (very large
     text) does the row scroll sideways; homepage.js then keeps the chosen tab in view, and
     an edge fades while labels are scrolled past it. */
  .product-tabs {
    position: relative;
    display: grid;
    grid-auto-flow: column;
    justify-content: start;
    column-gap: 12px;
    max-width: none;
    margin: var(--space-1) calc(-1 * var(--space-3)) 0;
    padding: var(--space-1) var(--space-1) var(--space-1) var(--space-3);
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scrollbar-width: none;
  }
  .product-tabs::-webkit-scrollbar {
    display: none;
  }
  .product-tabs.has-more-end {
    mask-image: linear-gradient(to right, #000 calc(100% - var(--space-6)), transparent);
  }
  .product-tabs.has-more-start {
    mask-image: linear-gradient(to left, #000 calc(100% - var(--space-6)), transparent);
  }
  .product-tabs.has-more-start.has-more-end {
    mask-image: linear-gradient(to right, transparent, #000 var(--space-6), #000 calc(100% - var(--space-6)), transparent);
  }
  .product-tabs button {
    width: auto;
    min-height: 44px;
    border-bottom: 0;
    text-wrap: balance;
    font: 400 var(--step-small)/1.4 var(--font-text);
  }
  .view-description {
    margin-top: 0;
  }
  .product > .text-cta {
    margin-top: 0;
  }
  .stage-controls {
    display: flex;
    justify-content: space-between;
  }
  /* The phone keeps 493 px of the 630 px stage, so it is 227 px wide. */
  .product-stage {
    height: 630px;
    padding: var(--space-3) var(--space-2) var(--space-2);
  }
  .stage-shot {
    width: min(100%, 493px * var(--screen-w) / var(--screen-h));
  }
}
/* Language samples: a two-column grid (copy and players | voice picker) on desktop,
   stacked on mobile. R14: half of --section-pad on each side, like every plain section.
   Kept as one block (with its own nested @media rules below) so this section's CSS
   stays easy to cherry-pick while the hero (a separate, concurrently edited section)
   keeps its own rules elsewhere. */
.languages {
  padding-block: calc(var(--section-pad) / 2);
  display: grid;
  grid-template-columns: 1fr 1.06fr;
  gap: 8%;
}
.languages h2 {
  font: 500 var(--step-h2)/1.04 var(--font-display);
  letter-spacing: -0.025em;
}
.languages-copy > p {
  max-width: 420px;
  font-size: var(--step-lede);
  line-height: 1.7;
  color: var(--muted);
  margin-top: var(--space-3);
}
/* The four players stay a 2x2 grid at every width, so no endonym or voice pair is ever cut: a tile needs
   about 143 px ("Slovenčina" is 111 px at 24 px), and four in a row do not get that below 1560 px. The
   tiles in a row share one height. */
.sample-players {
  list-style: none;
  margin: var(--space-4) 0 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-2);
}
/* Each tile is a size container: in a narrower tile (below a 360 px screen) the endonyms scale down
   with it, so the longest keeps a 4% margin. */
.sample-players > li {
  display: flex;
  container-type: inline-size;
}
/* The name, the voices, then the duration with the play or pause icon in the corner. */
.sample-player {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  grid-template-areas: "lang lang" "voices voices" "time icon";
  align-items: center;
  column-gap: var(--space-1);
  width: 100%;
  padding: var(--space-2) var(--space-2) calc(var(--space-2) + 4px);
  border: 1px solid rgb(58 42 31 / 0.18);
  border-radius: var(--radius-control);
  background: transparent;
  text-align: left;
  overflow: hidden;
  transition: background 0.2s ease, color 0.2s ease, border-color 0.2s ease;
}
/* Hover only with a mouse: on touch, a tapped tile keeps no darker border or lighter icon. */
@media (hover: hover) and (pointer: fine) {
  .sample-player:not([aria-pressed="true"]):hover {
    border-color: var(--ink);
  }
  .sample-player:hover .sample-icon {
    background: var(--amber-hover);
    box-shadow: 0 0 0 6px rgb(226 154 69 / .32);
  }
}
.sample-lang {
  grid-area: lang;
  margin-bottom: 2px;
  font: 500 clamp(18px, (100cqi - 2 * var(--space-2)) / 4.8, 24px)/1.15 var(--font-display);
  letter-spacing: -0.01em;
  white-space: nowrap;
}
.sample-voices,
.sample-time {
  font-size: var(--step-small);
  color: var(--muted);
  white-space: nowrap;
}
.sample-voices {
  grid-area: voices;
}
.sample-time {
  grid-area: time;
  margin-top: 2px;
}
/* The corner icon echoes the amber play buttons of the voice picker beside the tiles: play at rest,
   pause while that sample plays. Its glyph stays espresso in the dusk. */
.sample-icon {
  grid-area: icon;
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  margin-top: 2px;
  border-radius: 50%;
  position: relative;
  background: var(--amber);
  box-shadow: 0 0 0 4px rgb(226 154 69 / .24);
  color: var(--day-ink);
  transition: background 0.2s, box-shadow 0.2s;
}
/* Until a language sample is first played (data-sample-played, samples.js), a ring leaves each
   icon in turn, English to Slovak, a quieter echo of the hero's play button. It rests while the
   tiles are off screen (.is-offscreen, samples.js). The tile's padding holds it. */
.sample-icon::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  border: 2px solid var(--amber);
  opacity: 0;
  pointer-events: none;
  animation: sample-ripple 5.2s cubic-bezier(.2, .6, .3, 1) .3s infinite;
}
.sample-players > li:nth-child(2) .sample-icon::after { animation-delay: 1.6s; }
.sample-players > li:nth-child(3) .sample-icon::after { animation-delay: 2.9s; }
.sample-players > li:nth-child(4) .sample-icon::after { animation-delay: 4.2s; }
@keyframes sample-ripple {
  0% { transform: scale(1); opacity: .85; }
  35%, 100% { transform: scale(1.75); opacity: 0; }
}
.sample-players.is-offscreen .sample-icon::after { animation-play-state: paused; }
body[data-sample-played] .sample-players .sample-icon::after { animation: none; }
@media (prefers-reduced-motion: reduce) { .sample-players .sample-icon::after { animation: none; } }
.sample-player[aria-pressed="true"] .sample-icon { box-shadow: none; }
.sample-icon svg {
  width: 14px;
  height: 14px;
  fill: currentColor;
  stroke: none;
}
.sample-player[aria-pressed="true"] .sample-glyph-play,
.sample-player:not([aria-pressed="true"]) .sample-glyph-pause {
  display: none;
}
.sample-progress {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 2px;
  background: rgb(58 42 31 / 0.14);
}
.sample-progress span {
  display: block;
  width: 100%;
  height: 100%;
  background: var(--ink);
  transform-origin: left;
  transform: scaleX(0);
  transition: transform 0.1s linear;
}
/* Day colors: a playing sample never shows in the listening dusk, and a player that
   takes over from the hero sample must not follow the page's dusk as it fades out. Its focus
   ring stays the page's ink ring outside the tile, 12.25:1 on paper. */
.sample-player[aria-pressed="true"] {
  background: var(--day-ink);
  color: var(--day-paper);
  border-color: var(--day-ink);
  --muted: var(--dusk-muted);
}
.sample-player[aria-pressed="true"] .sample-progress {
  background: color-mix(in srgb, var(--day-paper) 25%, transparent);
}
.sample-player[aria-pressed="true"] .sample-progress span {
  background: var(--day-paper);
}
.languages-proof {
  align-self: center;
  min-width: 0;
}
/* The voice picker, cropped on purpose: below its list the screen is empty, so the frame shows the
   top 500 of its 874 pt. It ends in that empty area, 47 pt below the lowest row in any language
   (German's list ends at 453 pt), with the same rounded corners at the bottom as at the top. At
   320 px wide the list's smallest text (15 pt) is 12 px. */
.voices-frame {
  width: 100%;
  max-width: 320px;
  margin-inline: auto;
  aspect-ratio: 402 / 500;
  border-radius: 10% / calc(10% * 402 / 500);
}
.voices-frame img { display: block; width: 100%; height: auto; }
.languages-proof figcaption {
  max-width: 320px;
  margin-inline: auto;
  margin-top: var(--space-1);
  font-size: var(--step-small);
  line-height: 1.6;
  color: var(--muted);
  text-align: center;
}
/* The tour and this section share one narrower column gap below 1150 px. */
@media (max-width: 1150px) {
  .product,
  .languages {
    column-gap: 6%;
  }
}
@media (max-width: 760px) {
  .languages {
    grid-template-columns: 1fr;
    gap: var(--space-4);
  }
  .languages-copy > p {
    margin-top: var(--space-2);
  }
}
.answers {
  /* R14: adjacent sections share one --section-pad between them. */
  padding-block: calc(var(--section-pad) / 2);
}
.answers-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-8) var(--space-12);
  margin-top: var(--space-6);
}
.answer h3 {
  font: 500 var(--step-h3)/1.15 var(--font-display);
}
.answer p {
  max-width: 46ch;
  font-size: var(--step-body);
  color: var(--muted);
  margin-top: var(--space-1);
}
.beta {
  background: var(--amber-band);
}
/* The heading's column fits the longest first line on one line: Slovak "Desať pokojných
   minút." (9.4 em) from 1025 px up. */
.beta-inner {
  display: grid;
  grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr);
  gap: 8%;
  padding-block: var(--section-pad);
  align-items: start;
}
.beta h2 {
  font: 500 var(--step-h2)/0.99 var(--font-display);
  letter-spacing: -0.035em;
}
.get-on {
  font-size: 0.74em;
  display: inline-block;
  max-width: 500px;
  margin-top: var(--space-1);
}
/* The sub-copy's measure breaks it between sentences: "…For iPhone." / "Free during the
   beta." That needs 23.5 to 24.8 em in English, Czech and Slovak, and 26 to 30 em for
   German's longer first sentence. */
.beta-heading > p {
  max-width: 24.2em;
  font-size: var(--step-lede);
  margin-top: var(--space-3);
}
html[lang="de"] .beta-heading > p {
  max-width: 28em;
}
/* Beside the heading, the form starts so that the Email label's cap line sits on the
   heading's: the heading's first capital starts about 5 px higher in its line than the
   label's does. */
.hero-panel {
  margin-top: -5px;
}
.hero-signup-row {
  display: flex;
  gap: var(--space-1);
  align-items: center;
}
.hero-email-field {
  flex: 1;
  min-width: 0;
}
.form-field {
  margin-bottom: var(--space-2);
}
.hero-email-field {
  margin-bottom: 0;
}
input[type="email"],
select#ea-hear-from {
  width: 100%;
  min-height: 48px;
  padding: 0 var(--space-2);
  border: 1px solid #7a542f;
  background: #f7ecd9;
  border-radius: var(--radius-control);
  font-size: var(--step-body);
}
/* The select draws the shared chevron (see .language-menu), inset like the text. */
select#ea-hear-from {
  appearance: none;
  padding-right: var(--space-6);
}
.select-field {
  position: relative;
}
.select-field::after {
  position: absolute;
  top: 50%;
  right: var(--space-2);
  margin-top: -6px;
  pointer-events: none;
}
input::placeholder {
  color: #746355;
  opacity: 1;
}
.signup-hint {
  font-size: var(--step-small);
  line-height: 1.6;
  margin-top: var(--space-2);
}
.verification-note {
  font: 500 var(--step-h3)/1.2 var(--font-display);
  margin: var(--space-3) 0;
}
.field-label,
.form-field > label {
  display: block;
  font-size: var(--step-small);
  margin-bottom: var(--space-1);
}
.form-consent .consent-label {
  display: flex;
  align-items: start;
  gap: var(--space-1);
  font-size: var(--step-legal);
  line-height: 1.6;
}
.consent-label input {
  accent-color: var(--ink);
  width: 17px;
  height: 17px;
  flex-shrink: 0;
  margin-top: 2px;
}
.cf-turnstile {
  margin-block: var(--space-2);
  min-height: 65px;
}
/* The form's one error box (placed next to its field by the page script): the control
   radius, and balanced lines, so no word (such as an example address) ends up alone. */
.form-error {
  background: #fff2e3;
  color: var(--error);
  padding: var(--space-2);
  margin-top: var(--space-2);
  border-radius: var(--radius-control);
  font-size: var(--step-small);
  line-height: 1.5;
  text-wrap: balance;
}
.form-consent .form-error {
  margin-top: var(--space-1);
}
/* A field the form marks invalid takes the error color (4.5:1 on the band). The checkbox
   gets an error ring, which a keyboard focus ring replaces. */
#ea-email[aria-invalid="true"] {
  border-color: var(--error);
  box-shadow: inset 0 0 0 1px var(--error);
  background: var(--error-field);
}
.consent-label input[aria-invalid="true"]:not(:focus-visible) {
  outline: 2px solid var(--error);
  outline-offset: 2px;
}
.ea-success-title {
  font: 500 var(--step-h2)/1.1 var(--font-display);
}
/* The Enuva symbol marks a sent request, as tall as the heading's type. It sits on a
   paper disc: its amber full stop would vanish on the amber band, and the bare ring
   would read as a spinner. */
.ea-success-mark {
  display: block;
  width: var(--step-h2);
  height: var(--step-h2);
  margin-bottom: var(--space-2);
  border-radius: 50%;
  background: var(--day-paper);
}
.ea-success-note {
  font-size: var(--step-body);
  margin-top: var(--space-2);
}
.ea-success-actions {
  margin-top: var(--space-3);
}
/* The share line reads as a sentence; its button and the replay link keep 44px targets. */
.ea-success-actions .text-cta,
.ea-share .text-cta {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
}
#ea-share-status {
  font-size: var(--step-small);
}
.ai-disclosure {
  max-width: 720px;
  color: var(--muted);
  font-size: var(--step-legal);
  line-height: 1.6;
}
.site-footer {
  max-width: 1600px;
  margin-inline: auto;
  padding: var(--space-4) var(--space-8);
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  justify-content: space-between;
  align-items: center;
  font-size: var(--step-small);
  line-height: 1.7;
}
.site-footer .footer-grant {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}
.footer-grant img {
  width: 136px;
  height: 12px;
  object-fit: contain;
}
/* The footer's links and "Contact: email us" never break inside; lines break after a
   separator, which the page glues to the item before it. */
#contact a,
.footer-contact {
  white-space: nowrap;
}
.site-footer .built {
  width: 100%;
  color: var(--muted);
}
.mobile-waitlist-cta {
  display: none;
}
.listen-invite { position: relative; display: grid; }
/* A row: the play button, then the invitation centered on it. Where the column is too
   narrow for both, the invitation wraps under the play button, flush left. */
.listen-default {
  grid-area: 1 / 1;
  min-height: 160px;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  align-content: center;
  gap: var(--space-2) var(--space-4);
  transition: opacity .25s ease, visibility 0s;
}
.is-listening .listen-default { opacity: 0; visibility: hidden; transition: opacity .25s ease, visibility 0s .25s; }
/* The listening panel: the mark, and beside it the playing block (the title, the controls and, on
   phones, Follow along) centered on it. The end block stacks in the same rows and stays laid out,
   invisible, until the sample ends, so the panel keeps one height from rest to the end: the hero never
   grows and nothing below it moves. */
#listening {
  container: listening / inline-size;
  position: relative;
  grid-area: 1 / 1;
  min-height: 160px;
  display: grid;
  grid-template-columns: 144px minmax(0, 1fr);
  grid-template-rows: 1fr auto auto auto 1fr;
  column-gap: var(--space-2);
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity .3s ease, visibility 0s .3s;
}
.is-listening #listening {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
  transition: opacity .55s ease, visibility 0s;
}
/* At rest the mark waits, scaled down, on the play icon. homepage.js measures the offset
   (--mark-x, --mark-y) as the sample opens, so the mark grows out of the play button at any width. */
.listening-mark {
  grid-area: 1 / 1 / -1 / 2;
  align-self: center;
  position: relative;
  width: 144px;
  height: 144px;
  transform: translate(var(--mark-x, 0px), var(--mark-y, 0px)) scale(.48);
  transition: transform .4s cubic-bezier(.16, 1, .3, 1);
  isolation: isolate;
}
.is-listening .listening-mark {
  transform: none;
  transition-duration: .7s;
}
.listening-symbol { display: block; width: 100%; height: 100%; position: relative; }
/* While the sample plays, the full stop smoulders like an ember. A warm halo breathes around the
   dot (.ember, under the symbol), and a hot core flickers on the dot itself (.ember-core, over it).
   The ring stays still. Two uneven cycles (5.3 s and 3.1 s) never line up, so the light reads as
   fire, not as a loading indicator's regular pulse. On pause and at the end, the glow fades back
   to the plain dot. The containers fade; their ::before layers flicker. The dot sits at (48, 50)
   in the symbol's 100-unit box. */
.ember,
.ember-core {
  position: absolute;
  left: 48%;
  top: 50%;
  aspect-ratio: 1;
  translate: -50% -50%;
  opacity: 0;
  transition: opacity .6s ease;
  animation-play-state: paused;
  pointer-events: none;
}
.ember { width: 84%; }
.ember-core { width: 20%; mix-blend-mode: screen; }
.is-playing .ember,
.is-playing .ember-core {
  opacity: 1;
  transition-duration: .9s;
  animation-play-state: running;
}
.ember::before,
.ember-core::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
}
.ember::before {
  background: radial-gradient(circle, rgb(255 206 140 / .95) 0%, rgb(236 150 70 / .7) 14%,
    rgb(214 104 52 / .32) 34%, rgb(190 80 40 / .1) 52%, transparent 70%);
  opacity: .62;
  scale: .92;
  animation: ember-breathe 5.3s ease-in-out infinite;
  animation-play-state: inherit;
}
.ember-core::before {
  background: radial-gradient(circle, rgb(255 240 205) 0%, rgb(255 200 120 / .85) 40%, rgb(240 140 60 / 0) 72%);
  opacity: .55;
  animation: ember-flicker 3.1s linear infinite;
  animation-play-state: inherit;
}
@keyframes ember-breathe {
  0%, 100% { opacity: .62; scale: .92; }
  18% { opacity: .9; scale: 1.02; }
  34% { opacity: .7; scale: .96; }
  52% { opacity: 1; scale: 1.08; }
  71% { opacity: .78; scale: .98; }
  86% { opacity: .95; scale: 1.04; }
}
@keyframes ember-flicker {
  0%, 100% { opacity: .55; }
  7% { opacity: .9; }
  13% { opacity: .6; }
  24% { opacity: 1; }
  31% { opacity: .7; }
  45% { opacity: .95; }
  53% { opacity: .5; }
  64% { opacity: .85; }
  72% { opacity: .65; }
  83% { opacity: 1; }
  91% { opacity: .6; }
}
/* The detail column is narrow on small phones: long words wrap rather than overflow. Its children
   sit in #listening's grid. */
.listening-detail { display: contents; overflow-wrap: anywhere; }
/* The title's last two words share a no-break space (copy.js), so no word is left alone on its last
   line. Where the column is narrower than that pair at full size (below 384 px screens), the title
   scales down with the column. */
.listening-title {
  grid-area: 2 / 2;
  font: 500 min(var(--step-h3), (100cqi - 160px) * .132)/1.12 var(--font-display);
  letter-spacing: -.02em;
}
/* Phones only (see the 760px block): the live Spine sits below the hero text there. */
.follow-along {
  grid-area: 4 / 2;
  justify-self: start;
  display: none;
  align-items: center;
  gap: var(--space-1);
  min-height: 44px;
  font-size: var(--step-small);
  font-weight: 600;
  text-underline-offset: 5px;
}
/* The turned chevron reaches 1.6 px past its box: the margin keeps it inside the link. */
.follow-along::after {
  content: "";
  width: 6px;
  height: 6px;
  margin: -4px 2px 0 0;
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  transform: rotate(45deg);
}
/* The end block: in the detail column beside the mark, from the panel's top. homepage.js still sets
   its hidden attribute; here that only makes it invisible, so it keeps its place in the layout. It
   only ever shows in the listening dusk, so its button keeps dusk colors whichever element carries
   the listening state. */
.listen-end { container: end / inline-size; grid-area: 1 / 2 / -1 / 3; align-self: start; }
#listen-end[hidden] { display: block !important; visibility: hidden; }
/* Room for Close, which sits at the block's top right corner. */
.listen-end-title { padding-right: 52px; font: 500 var(--step-h3)/1.12 var(--font-display); letter-spacing: -.02em; }
.listen-end-title + p { max-width: 440px; margin-top: var(--space-1); color: var(--muted); }
.listen-end-actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2) var(--space-4); margin-top: var(--space-3); }
.listen-end .button-primary { background: var(--dusk-ink); color: var(--dusk); }
.listen-end .button-primary:hover { background: #fff; }
.listen-end .text-cta { min-height: 44px; }
/* A narrower end block keeps within the playing panel's height: smaller body text, and both actions
   in one row (the longest pair, German, needs 342 px). */
@container end (max-width: 439px) {
  .listen-end-title + p { font-size: var(--step-small); }
  .listen-end-actions { gap: var(--space-1) var(--space-2); margin-top: var(--space-2); }
  .listen-end .button { padding-inline: var(--space-2); }
  .listen-end .text-cta { font-size: var(--step-small); }
}
.listening-controls { grid-area: 3 / 2; display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-1) var(--space-2); margin-top: var(--space-1); }
.listening-controls button { background: transparent; min-height: 44px; padding: 0; font-size: var(--step-small); }
#listen-pause { display: flex; align-items: center; gap: var(--space-1); }
#listen-pause svg { width: 14px; height: 14px; stroke-width: 2; }
#listen-pause.paused svg { display: none; }
#listen-remaining { font-size: var(--step-small); font-variant-numeric: tabular-nums; color: var(--muted); }
#listen-close { width: 44px; display: grid; place-items: center; color: var(--muted); }
#listen-close svg { width: 17px; height: 17px; }
/* The end state: the playing block turns invisible in place and the end block appears. Close moves
   to the end block's top right corner, centered on the title's first line: right after the body's
   440 px measure, or at the panel's edge where the block is narrower. */
.is-ended :is(.listening-title, #listen-pause, #listen-remaining, .follow-along) { visibility: hidden; }
.is-ended #listen-close { position: absolute; top: calc(var(--step-h3) * .56 - 22px); left: min(160px + 440px, 100cqi - 44px); }
.is-ended .listen-end { animation: listen-end-in .4s ease; }
@keyframes listen-end-in { from { opacity: 0; } }
/* Beside the mark the end block gets the panel's width minus 160 px. A panel too narrow for the
   German actions in one row there (below 521 px, screens below about 990 px) gives the end block
   the whole panel, as on phones. */
@container listening (max-width: 520px) {
  .listen-end { grid-column: 1 / -1; }
  .is-ended .listening-mark { visibility: hidden; }
  .is-ended #listen-close { left: min(440px, 100cqi - 44px); }
}
/* Listening. While the sample panel is open the whole page turns dusk (spec 4.1 and 9):
   the body carries the dusk background and text, and every region except the amber band
   swaps its color tokens. The tokens are registered, so they fade with the body over 700 ms
   and every color built from them follows. With reduced motion the change is instant. */
@property --ink { syntax: "<color>"; inherits: true; initial-value: #3a2a1f; }
@property --muted { syntax: "<color>"; inherits: true; initial-value: #746355; }
@property --paper { syntax: "<color>"; inherits: true; initial-value: #f5f2e9; }
@property --rule { syntax: "<color>"; inherits: true; initial-value: #d5cfc1; }
@property --stage { syntax: "<color>"; inherits: true; initial-value: #ebe4d6; }
@property --hero-body { syntax: "<color>"; inherits: true; initial-value: #675547; }
body { transition: background-color .7s ease, color .7s ease; }
body.is-listening { background: var(--dusk); color: var(--dusk-ink); transition: background-color 0.7s ease, color 0.7s ease; }
#site-shell > :not(main), main > :not(.beta) {
  transition: --ink .7s ease, --muted .7s ease, --paper .7s ease, --rule .7s ease, --stage .7s ease, --hero-body .7s ease;
}
body.is-listening :is(#site-shell > :not(main), main > :not(.beta)) {
  --ink: var(--dusk-ink); --muted: var(--dusk-muted); --paper: var(--dusk);
  --rule: #897360; --stage: #4f3f32; --hero-body: var(--dusk-muted);
}
/* The amber band keeps its colors, and its ink text, while the page around it turns. */
.beta { color: var(--ink); }
body.is-listening .sample-player { border-color: var(--rule); }
/* The grant logo is black: it turns white on dusk. */
.footer-grant img { transition: filter .7s ease; }
body.is-listening .footer-grant img { filter: invert(1); }
@media (prefers-reduced-motion: reduce) { body.is-listening { transition: none; } }
/* The screenshot crossfades into the live Spine, which fades in over the same 300 ms. */
.hero-frame img { transition: opacity .3s ease; }
body.is-listening .hero-frame img { opacity: 0; }
@media (max-width: 1150px) {
  .hero-composition { grid-template-columns: minmax(0, 1.4fr) minmax(310px, 1fr); gap: var(--space-4); }
  .enough { font-size: clamp(70px, calc(10vw - 12px), 90px); }
  html[lang="de"] .enough, html[lang="sk"] .enough, html[lang="cs"] .enough { font-size: clamp(54px, calc(9vw - 12px), 80px); }
  @supports (width: 1cqi) {
    .enough { font-size: min(clamp(70px, calc(10vw - 12px), 90px), var(--fit)); }
    html:is([lang="de"], [lang="sk"], [lang="cs"]) .enough { font-size: min(clamp(54px, calc(9vw - 12px), 80px), var(--fit)); }
  }
  .wrap {
    padding-inline: var(--space-4);
  }
  .language-suggestion {
    right: var(--space-4);
  }
  .header,
  .header-actions,
  .join-link {
    gap: var(--space-2);
  }
  .hero-signup-row {
    flex-wrap: wrap;
  }
  .hero-email-field {
    flex-basis: 100%;
  }
  .hero-signup-row .button,
  .hero-submit-row .button {
    width: 100%;
  }
  .site-footer {
    padding-inline: var(--space-4);
  }
}
/* Up to 1024 px the band stacks, as on phones: beside the form, its heading's column is
   too narrow for "Ten quiet minutes." and its translations on one line. The form keeps
   the desktop column's width, with the email and its button on one row. */
@media (max-width: 1024px) {
  .beta-inner {
    display: block;
  }
  .hero-panel {
    max-width: 36rem;
    margin-top: 0;
    padding-top: var(--space-4);
  }
  .hero-signup-row {
    flex-wrap: nowrap;
    align-items: stretch;
  }
  .hero-email-field {
    flex-basis: auto;
  }
  .hero-signup-row .button {
    width: auto;
    max-width: 46%;
  }
  .hero-submit-row .button {
    width: auto;
  }
}
@media (max-width: 760px) {
  :root {
    --header-height: 108px;
  }
  .wrap {
    padding-inline: var(--space-3);
  }
  .language-suggestion {
    right: var(--space-3);
  }
  .header {
    gap: var(--space-1) var(--space-2);
    flex-wrap: wrap;
    padding-block: var(--space-2);
    align-content: center;
  }
  .wordmark {
    width: 128px;
  }
  .beta-status {
    order: 3;
    width: 100%;
    padding-left: 5px;
  }
  .header-actions {
    gap: var(--space-2);
  }
  .language-menu summary {
    padding-inline: 2px;
  }
  .join-link {
    display: none;
  }
  .join-link span {
    display: none;
  }
  .join-link svg {
    width: 22px;
  }
  .hero-composition { grid-template-columns: minmax(0, 1fr); gap: 0; }
  .enough { font-size: var(--step-display); line-height: 1; }
  html[lang="sk"] .enough, html[lang="cs"] .enough, html[lang="de"] .enough { font-size: clamp(52px, 16.4vw, 76px); }
  /* "Nicht noch mehr Nachrichten." (11.91 em) keeps one line at 40 px from 525 px.
     Narrower, it wraps into two lines before "Nachrichten." (text-wrap: pretty, above). */
  html[lang="de"] .not-more { font-size: clamp(2rem, 10vw - 5px, 2.5rem); }
  .hero-copy { margin-top: var(--space-3); }
  .hero-copy > p { margin-top: var(--space-2); }
  /* Stacked: the play button, then the invitation at full width, both flush left. */
  .listen-default { flex-direction: column; flex-wrap: nowrap; align-items: flex-start; justify-content: center; gap: var(--space-3); }
  .hero-invite { align-self: stretch; }
  .follow-along { display: inline-flex; }
  /* The title, the controls and Follow along stay beside the mark. The end block takes the whole
     panel in their place. Its invitation fills the row beside Listen again, or the whole row when
     Listen again wraps under it. */
  .listen-end { grid-column: 1 / -1; }
  .is-ended .listening-mark { visibility: hidden; }
  .is-ended #listen-close { left: min(440px, 100cqi - 44px); }
  .listen-end-actions .button { flex: 1 0 auto; }
  /* The whole screen at 70% of a 390 px phone's width (270 px), so the live Spine, with its
     caption, fits the screen when Follow along brings it into view. */
  .hero-proof { --frame-w: min(270px, 70vw); margin-top: var(--space-4); padding-top: 0; }
  .beta-inner {
    display: block;
  }
  .get-on {
    font-size: 0.76em;
  }
  .hero-panel {
    padding-top: var(--space-3);
  }
  .answers-grid {
    grid-template-columns: 1fr;
  }
  .site-footer {
    padding-inline: var(--space-3);
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--space-3);
  }
  .listening-controls { gap: var(--space-1); }

}
/* The longest suggestion ("Enuva gibt es auch auf Deutsch") keeps one line. */
@media (max-width: 359px) {
  .language-suggestion {
    left: var(--space-2);
    right: var(--space-2);
    max-width: none;
    justify-content: space-between;
  }
}
/* Keep Pause and the longer Resume label in the same reserved row. */
@media (max-width: 420px) {
  .listening-controls {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 44px;
    grid-template-rows: 44px 44px;
    grid-template-areas: "pause pause" "remaining close";
    gap: var(--space-1);
  }
  #listen-pause { grid-area: pause; justify-self: start; }
  #listen-remaining { grid-area: remaining; justify-self: start; }
  #listen-close { grid-area: close; }
}
@media (max-width: 760px) {
  /* A paper strip along the bottom edge, fading in at its top, so the page's copy passes
     behind it rather than through it. It sits in #site-shell, so the dusk tokens reach it. */
  .mobile-waitlist-cta.is-visible {
    display: flex;
    position: fixed;
    z-index: 3;
    bottom: 0;
    left: 0;
    right: 0;
    align-items: center;
    gap: var(--space-1);
    padding: var(--space-2) var(--space-3);
    background: var(--paper);
  }
  .mobile-waitlist-cta.is-visible::before {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    bottom: 100%;
    height: var(--space-4);
    background: linear-gradient(to top, var(--paper), transparent);
    pointer-events: none;
  }
  /* Keyboard focus scrolled into view stays clear of the strip. */
  html:has(.mobile-waitlist-cta.is-visible) {
    scroll-padding-bottom: calc(80px + var(--space-4));
  }
  .mobile-waitlist-link {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 48px;
    padding: 0 var(--space-3);
    background: var(--ink);
    color: var(--paper);
    text-decoration: none;
    border-radius: var(--radius-control);
    font-size: var(--step-body);
    font-weight: 600;
  }
  .mobile-waitlist-dismiss {
    width: 36px;
    height: 36px;
    display: grid;
    place-items: center;
    background: var(--paper);
    border: 1px solid var(--rule);
    border-radius: 50%;
  }
  .mobile-waitlist-dismiss svg {
    width: 16px;
    height: 16px;
  }
}
@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
  *,
  *::before,
  *::after {
    animation: none !important;
    transition: none !important;
  }
}

.no-script-capture { display: block; max-width: 100%; height: auto; }
/* The invitation button needs its full label beside the field, so it takes its own row;
   Send request, in step 2, spans the column the same way. */
@media (max-width: 560px) {
  .hero-signup-row { flex-wrap: wrap; }
  .hero-email-field { flex-basis: 100%; }
  .hero-signup-row .button, .hero-submit-row .button { width: 100%; max-width: none; }
}

/* z-index keeps the open language menu above the hero and above the language
   suggestion (z 3) while the menu is open. */
.header { position: relative; z-index: 2; }
.header:has(.language-menu[open]) { z-index: 4; }
/* No suggestion while the sample plays; out of flow, so hiding it moves nothing. */
body.is-listening .language-suggestion { display: none; }

/* Live Spine */
/* The app's Spine screen (402 x 874 pt), scaled to the frame: --pt is one iPhone point.
   Colors are sampled from the captures; sizes follow the app's ReelMetrics and card layout. */
.live-spine { container-type: inline-size; opacity: 0; transition: opacity .3s ease; }
.live-spine.is-visible { opacity: 1; }
.ls-screen {
  --pt: 0.8955px;
  /* The system font tracks wider as it gets smaller (about .059 px per px of size, per character);
     this cancels it, so text keeps the width the app renders at full size in any frame. */
  --ls-track: calc(.059 * (var(--pt) - 1px));
  --ls-amber: #e8a34e; --ls-glow: rgb(232 163 78 / .55);
  position: relative; width: 100%; height: calc(874 * var(--pt));
  overflow: hidden; background: #241812; color: #f4eee7;
  font: calc(12 * var(--pt)) / 1.2 var(--font-text); -webkit-font-smoothing: antialiased; user-select: none;
}
@supports (width: 1cqw) { .ls-screen { --pt: calc(100cqw / 402); } }
.ls-screen svg { display: block; fill: currentColor; flex: none; }
.ls-top { position: absolute; top: calc(66 * var(--pt)); left: calc(24 * var(--pt)); right: calc(24 * var(--pt)); height: calc(44 * var(--pt)); display: flex; justify-content: flex-end; align-items: center; }
.ls-date { position: absolute; left: 0; top: calc(7 * var(--pt)); display: flex; align-items: center; gap: calc(5 * var(--pt)); font: calc(11 * var(--pt)) / calc(14 * var(--pt)) var(--font-mono); color: #a59d94; }
.ls-date svg { width: calc(11 * var(--pt)); height: calc(11 * var(--pt)); margin-top: calc(-1 * var(--pt)); }
.ls-remaining { position: absolute; left: 0; top: calc(23 * var(--pt)); font: 500 calc(13 * var(--pt)) / calc(17 * var(--pt)) var(--font-mono); color: #beb6ad; font-variant-numeric: tabular-nums; }
.ls-segment { display: flex; height: calc(43 * var(--pt)); background: #30241d; border-radius: calc(10 * var(--pt)); }
.ls-segment > span { display: flex; align-items: center; justify-content: center; gap: calc(5 * var(--pt)); min-width: calc(74 * var(--pt)); padding: 0 calc(10 * var(--pt)); border-radius: calc(8 * var(--pt)); color: #a59d94; letter-spacing: calc(12 * var(--ls-track)); }
.ls-segment > .is-on { background: #42362f; color: #f4eee7; font-weight: 600; }
.ls-segment svg { width: calc(12 * var(--pt)); height: calc(12 * var(--pt)); }
.ls-segment .ls-mark { width: calc(16 * var(--pt)); height: calc(16 * var(--pt)); }
.ls-rows { list-style: none; margin: calc(136 * var(--pt)) calc(24 * var(--pt)) 0; padding: 0; display: flex; flex-direction: column; gap: calc(6 * var(--pt)); }
.ls-row { position: relative; border-radius: calc(12 * var(--pt)); background: #382b23; }
.ls-row.is-played { background: #2b1f19; }
.ls-row.is-current { background: #423424; }
.ls-row time, .ls-intro .ls-title, .ls-closing .ls-title { position: relative; top: calc(1.6 * var(--pt)); font: 500 calc(12 * var(--pt)) / 1.3 var(--font-mono); color: #a59d94; font-variant-numeric: tabular-nums; white-space: nowrap; }
.ls-intro .ls-title, .ls-closing .ls-title { font-weight: 400; }
.ls-intro, .ls-closing { display: flex; align-items: center; justify-content: space-between; gap: calc(10 * var(--pt)); height: calc(var(--ls-h) * var(--pt)); padding: 0 calc(16 * var(--pt)); }
.ls-story { display: grid; grid-template-columns: 100%; grid-template-rows: calc(4 * var(--pt)) calc((var(--ls-h) - 52) * var(--pt)) calc(44 * var(--pt)) calc(4 * var(--pt)) auto; }
.ls-story::before { content: ""; position: absolute; left: 0; top: calc(8 * var(--pt)); width: calc(3 * var(--pt)); height: calc((var(--ls-h) - 16) * var(--pt)); border-radius: calc(1.5 * var(--pt)); background: rgb(229 205 173 / .4); }
.ls-story.is-current::before { background: var(--ls-amber); }
.ls-lead { grid-row: 2; align-self: center; display: flex; align-items: flex-start; gap: calc(10 * var(--pt)); padding: 0 calc(16 * var(--pt)); min-width: 0; }
/* Titles break as the app breaks them: no single word left on the last line. */
.ls-lead .ls-title { flex: 1 1 auto; min-width: 0; font: 600 calc(16 * var(--pt)) / calc(21 * var(--pt)) var(--font-text); letter-spacing: calc(16 * var(--ls-track) - .06 * var(--pt)); text-wrap: pretty; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.ls-lead time { letter-spacing: calc(-.3 * var(--pt)); }
.ls-story.is-played .ls-title { color: #a59d94; }
/* On the current row, the times and the intro and closing titles take the same lighter step as the
   publisher line below, for 4.6:1 on #423424 (4.49:1 before). */
.ls-row.is-current time, .ls-intro.is-current .ls-title, .ls-closing.is-current .ls-title { color: #a79f96; }
/* The publisher line is one step lighter than the captures' #a59d94, so it keeps 4.6:1 on the current row's
   #423424 in the dusk (4.49:1 before). */
.ls-source { grid-row: 3; position: relative; top: calc(3.5 * var(--pt)); display: flex; align-items: center; gap: calc(8 * var(--pt)); padding: 0 calc(16 * var(--pt)); color: #a79f96; min-width: 0; letter-spacing: calc(12 * var(--ls-track)); }
.ls-source svg { width: calc(16 * var(--pt)); height: calc(16 * var(--pt)); }
.ls-source > span { flex: 1 1 auto; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ls-source .ls-caret { width: calc(16 * var(--pt)); height: calc(16 * var(--pt)); color: rgb(165 157 148 / .6); }
.ls-story.is-current .ls-caret { color: #beb6ad; transform: rotate(180deg); }
.ls-detail { grid-row: 5; display: none; margin: 0 calc(16 * var(--pt)); padding: calc(8.6 * var(--pt)) 0 calc(12 * var(--pt)); border-top: calc(1 * var(--pt)) solid #594c3e; }
.ls-story.is-current .ls-detail { display: block; }
.ls-chips { display: grid; grid-template-columns: 1fr 1fr; column-gap: calc(12 * var(--pt)); margin-bottom: calc(11.4 * var(--pt)); }
.ls-chip { display: grid; grid-template-columns: calc(44 * var(--pt)) calc(44 * var(--pt)) minmax(0, 1fr); row-gap: calc(4 * var(--pt)); }
.ls-chip-label { grid-column: 1 / -1; font: 500 calc(13 * var(--pt)) / 1.25 var(--font-text); letter-spacing: calc(13 * var(--ls-track)); color: #beb6ad; }
.ls-chip b { position: relative; display: grid; place-items: center; width: calc(44 * var(--pt)); height: calc(44 * var(--pt)); padding-bottom: calc(3.6 * var(--pt)); font: 300 calc(26 * var(--pt)) / 1 var(--font-text); }
.ls-chip b::before { content: ""; position: absolute; inset: calc(6 * var(--pt)) calc(4 * var(--pt)); border: calc(1 * var(--pt)) solid #594c3e; border-radius: calc(8 * var(--pt)); }
.ls-chip .ls-less { color: #d6998a; }
.ls-chip .ls-more { color: #a8c198; }
.ls-hint { margin: 0; color: #a59d94; letter-spacing: calc(12 * var(--ls-track)); }
.ls-playhead {
  position: absolute; left: 0; right: 0; top: calc(-1 * var(--pt)); height: calc(2 * var(--pt)); background: var(--ls-amber);
  box-shadow: 0 0 calc(14 * var(--pt)) var(--ls-glow); transition: transform .25s linear; pointer-events: none;
}
.ls-playhead::after { content: ""; position: absolute; right: calc(7 * var(--pt)); top: 50%; width: calc(9 * var(--pt)); height: calc(9 * var(--pt)); border-radius: 50%; background: var(--ls-amber); box-shadow: 0 0 calc(14 * var(--pt)) var(--ls-glow); transform: translateY(-50%); }
.ls-pill {
  position: absolute; left: calc(10 * var(--pt)); top: 50%; transform: translateY(-50%); height: calc(24 * var(--pt)); padding: 0 calc(9 * var(--pt));
  border: calc(1 * var(--pt)) solid var(--ls-amber); border-radius: 999px; background: #241812; color: var(--ls-amber);
  font: 500 calc(12 * var(--pt)) / calc(22 * var(--pt)) var(--font-mono); letter-spacing: calc(.12 * var(--pt)); font-variant-numeric: tabular-nums;
  box-shadow: 0 0 calc(14 * var(--pt)) var(--ls-glow);
}
.ls-pill[hidden] { display: none; }
/* The final full stop keeps the rows' rhythm: its ink starts 18 pt below the last row, three row gaps, with the
   parked playhead line in the first. A zero line height keeps the glyph out of the flow. With Plex's metrics
   (ascent 1.025 em, descent .275 em) the baseline sits 75 pt below the box and the dot's top 41.6 pt below it. */
.ls-end { display: block; margin-top: calc(-23.6 * var(--pt)); text-align: center; font: 500 calc(200 * var(--pt)) / 0 Plex, Georgia, serif; color: var(--ls-amber); }
.ls-controls { position: absolute; top: calc(667 * var(--pt)); left: calc(24 * var(--pt)); right: calc(24 * var(--pt)); height: calc(64 * var(--pt)); margin: 0; display: flex; align-items: center; justify-content: space-between; }
.ls-controls > span { position: relative; display: grid; place-items: center; width: calc(56 * var(--pt)); height: calc(56 * var(--pt)); color: #beb6ad; }
.ls-skip svg { width: calc(34 * var(--pt)); height: calc(34 * var(--pt)); transform: scale(1.15, .8); }
.ls-skip .is-back { transform: scale(-1.15, .8); }
/* The arrow's head turns to twelve o'clock, where the app's gobackward.10 and goforward.10 have theirs. */
.ls-back svg, .ls-fwd svg { width: calc(34 * var(--pt)); height: calc(34 * var(--pt)); transform: rotate(-45deg); }
.ls-back b, .ls-fwd b { position: absolute; font: 700 calc(12 * var(--pt)) / 1 var(--font-text); letter-spacing: calc(-.3 * var(--pt)); }
.ls-back .is-back { transform: scaleX(-1) rotate(-45deg); }
.ls-play { display: grid; place-items: center; width: calc(64 * var(--pt)); height: calc(64 * var(--pt)); padding: 0; border: 0; border-radius: 50%; background: var(--ls-amber); color: #23170e; box-shadow: 0 calc(6 * var(--pt)) calc(9 * var(--pt)) rgb(232 163 78 / .22); cursor: pointer; }
.ls-play svg { width: calc(24 * var(--pt)); height: calc(24 * var(--pt)); }
.ls-play .ls-icon-pause, .ls-play.is-playing .ls-icon-play { display: none; }
.ls-play.is-playing .ls-icon-pause { display: block; }
.ls-utility { position: absolute; top: calc(743 * var(--pt)); left: calc(24 * var(--pt)); right: calc(24 * var(--pt)); height: calc(44 * var(--pt)); display: flex; align-items: center; justify-content: space-between; color: #beb6ad; font: calc(14 * var(--pt)) / 1 var(--font-mono); }
.ls-utility .ls-doc { width: calc(24 * var(--pt)); height: calc(24 * var(--pt)); margin-right: calc(10 * var(--pt)); }
.ls-tabs { position: absolute; top: calc(791 * var(--pt)); left: calc(21 * var(--pt)); right: calc(21 * var(--pt)); height: calc(62 * var(--pt)); display: grid; grid-template-columns: repeat(4, 1fr); align-items: center; padding: 0 calc(10 * var(--pt)); background: #201813; border: calc(1 * var(--pt)) solid #2c2019; border-radius: 999px; }
.ls-tabs > span { position: relative; isolation: isolate; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: calc(2 * var(--pt)); height: calc(48 * var(--pt)); font: 500 calc(12 * var(--pt)) / 1.2 var(--font-text); letter-spacing: calc(12 * var(--ls-track)); color: #fbf3ee; }
.ls-tabs > .is-on { color: #fff; }
.ls-tabs > .is-on::before { content: ""; position: absolute; inset: 0 calc(-6 * var(--pt)); border-radius: 999px; background: #423934; z-index: -1; }
.ls-tabs svg { width: calc(28 * var(--pt)); height: calc(28 * var(--pt)); }
@media (prefers-reduced-motion: reduce) {
  .live-spine, .ls-playhead { transition: none; }
}
