/*
 * Afinora — afinora.app
 *
 * Every colour here comes from the app itself: surfaces and text from
 * tunerSettings.ts (dark theme), state colours from semanticColors.ts. Nothing
 * was invented for the web, so a player who opens the site and then the app
 * sees one product.
 */

/* ---------------------------------------------------------------- tokens */

:root {
  /* Surfaces and text — tunerSettings.ts, dark */
  --bg: #050505;
  --surface: #101114;
  --elevated: #0e0f12;
  --border: #1c1d22;
  --ink: #fafaf9;
  --ink-dim: #a8a29e;
  --accent: #2dd4bf;
  --accent-muted: #0c2018;
  --on-accent: #04211d;

  /* Forest — the technique-training and download grounds */
  --forest-bg: #06130f;
  --forest-surface: #10231d;
  --forest-elevated: #0a1a15;
  --forest-border: #245447;

  /* State — semanticColors.ts, dark */
  --in-tune: #34d399;
  --close: #fbbf24;
  --far: #fb7185;
  --on-state: #141110;
  --pro-surface: #1a1205;
  --pro-border: #5c4a20;
  --pro-caption: #c9a860;

  /* Verdicts and the string ramp, shared with the mockups */
  --verdict-perfect: #5ee7f0;
  --verdict-hit: #8fbf5a;
  --verdict-miss: #e0554a;

  --display: 'Space Grotesk', system-ui, sans-serif;
  --body: 'IBM Plex Sans', system-ui, sans-serif;
  --mono: 'IBM Plex Mono', ui-monospace, monospace;

  --maxw: 1200px;
  --gutter: 20px;
  --section-y: clamp(44px, 9vw, 88px);
}

/* ------------------------------------------------------------------ base */

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

html {
  scroll-behavior: smooth;
  /* The header is sticky, so an anchored heading would land underneath it. */
  scroll-padding-top: 84px;
  /* clip, not hidden, and on html rather than body.
     `overflow-x: hidden` on the body forces overflow-y to auto, which makes the
     body its own scroll container — and a nested scroller silently breaks every
     jump to an anchor on the page: the hash changes and nothing moves. `clip`
     contains a stray wide element without creating a scroll container at all. */
  overflow-x: clip;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font: 400 18px/1.6 var(--body);
  -webkit-font-smoothing: antialiased;
}

/* Declared on purpose: without it a link added later renders browser-default
   blue on a near-black ground. */
a { color: var(--in-tune); text-decoration: none; }
a:hover { color: var(--accent); }

::selection { background: var(--in-tune); color: var(--forest-bg); }

img, svg { max-width: 100%; }

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 4px;
}

.skip {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 100;
  background: var(--in-tune);
  color: var(--forest-bg);
  padding: 10px 16px;
  border-radius: 0 0 9px 0;
  font: 600 15px/1 var(--display);
}
.skip:focus { left: 0; }

.wrap {
  max-width: var(--maxw);
  margin: 0 auto;
  padding-left: var(--gutter);
  padding-right: var(--gutter);
}

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

/* ------------------------------------------------------------ typography */

h1, h2, h3 {
  font-family: var(--display);
  color: var(--ink);
  margin: 0;
  text-wrap: balance;
}

h1 {
  font-weight: 700;
  /* Capped low on purpose: this column is ~45% of the viewport, so a higher
     coefficient crushes the headline into eight-character lines on a tablet. */
  font-size: clamp(32px, 3.6vw, 52px);
  line-height: 1.05;
  letter-spacing: -.03em;
}

h2 {
  font-weight: 700;
  font-size: clamp(28px, 4.2vw, 46px);
  line-height: 1.12;
  letter-spacing: -.03em;
}

h2.block-h2 { font-size: clamp(26px, 3.4vw, 38px); letter-spacing: -.028em; }
h2.sub-h2 { font-size: clamp(24px, 3.2vw, 34px); letter-spacing: -.025em; }

h3 { font-weight: 600; font-size: 18.5px; line-height: 1.3; }

p { margin: 0; text-wrap: pretty; }

.eyebrow {
  font: 500 12px/1.4 var(--mono);
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--in-tune);
}

.lead {
  font-size: clamp(17px, 1.9vw, 20px);
  line-height: 1.6;
  color: var(--ink-dim);
  max-width: 60ch;
}

.body-dim { color: var(--ink-dim); }
.small { font-size: 16px; line-height: 1.55; color: var(--ink-dim); }

.fine {
  font: 400 13px/1.75 var(--mono);
  color: #94a09b;
}

/* ---------------------------------------------------------------- header */

.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  background: rgba(5, 5, 5, .9);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border-bottom: 1px solid var(--border);
}

/* Fixed height with border-box, not min-height plus padding: the latter lets
   the row grow to two lines on a narrow phone. */
.site-header .inner {
  max-width: var(--maxw);
  margin: 0 auto;
  height: 70px;
  padding: 0 var(--gutter);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}

.brand {
  display: flex;
  align-items: center;
  gap: 10px;
  color: var(--ink);
}
.brand:hover { color: var(--ink); }
.brand svg { width: 30px; height: 30px; flex: 0 0 auto; }
.brand .name {
  font: 700 21px/1 var(--display);
  letter-spacing: -.01em;
}

.header-right {
  display: flex;
  align-items: center;
  gap: 10px;
}

/* Language menu: a native disclosure, so it works with JavaScript off. */
.lang { position: relative; }
.lang > summary {
  list-style: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 6px;
  font: 400 12px/1 var(--mono);
  letter-spacing: .08em;
  color: var(--ink-dim);
  border: 1px solid var(--border);
  border-radius: 7px;
  padding: 7px 10px;
  white-space: nowrap;
}
.lang > summary::-webkit-details-marker { display: none; }
.lang > summary:hover { color: var(--ink); }
.lang-panel {
  position: absolute;
  right: 0;
  top: calc(100% + 9px);
  min-width: 170px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 11px;
  padding: 6px;
  box-shadow: 0 20px 44px rgba(0, 0, 0, .65);
  display: flex;
  flex-direction: column;
  gap: 1px;
}
.lang-panel a,
.lang-panel span {
  display: block;
  font: 400 14px/1.3 var(--body);
  padding: 8px 11px;
  border-radius: 7px;
  color: var(--ink-dim);
}
.lang-panel a:hover { background: var(--elevated); color: var(--ink); }
.lang-panel .current { background: var(--forest-surface); color: var(--in-tune); }

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--in-tune);
  color: var(--forest-bg);
  font: 600 clamp(14px, 3.4vw, 15px)/1 var(--display);
  padding: 9px 15px;
  border-radius: 9px;
  white-space: nowrap;
}
.btn:hover { background: var(--accent); color: var(--forest-bg); }

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

.hero {
  position: relative;
  padding-top: clamp(40px, 7vw, 76px);
  padding-bottom: var(--section-y);
  overflow: hidden;
}

/* Alphas tuned for the drawn field behind them. Swapping in a photograph means
   raising these back to roughly .85 / .65 / .95 for legibility. */
.hero-scrim {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(180deg,
    rgba(5, 5, 5, .30) 0%,
    rgba(5, 5, 5, .15) 42%,
    rgba(5, 5, 5, .45) 100%);
}

.hero .wrap { position: relative; }

/* The vibrating strings, as their own layer over the hero's ground. Positioned
   from the stylesheet rather than inline so the phone rules below can move it. */
.string-field { position: absolute; inset: 0; }

.hero-grid {
  display: grid;
  /* min() matters: a bare minmax(460px, 1fr) makes 460px a hard floor and
     overflows a 360px phone. */
  grid-template-columns: repeat(auto-fit, minmax(min(460px, 100%), 1fr));
  gap: clamp(32px, 4vw, 60px);
  align-items: center;
}

/* The hero is one column now: the highway runs the full width beneath the
   words rather than a phone standing beside them. A note travelling along a
   neck needs the width to read as movement. */
/*
 * The hero: the claim on the left, what backs it on the right.
 *
 * Stacked in one column the headline and the paragraph fought for the same
 * eye, and the headline could not grow without pushing the buttons down the
 * page. Apart, the headline can be as large as it deserves to be and the
 * paragraph reads as support rather than as the next thing to get through.
 *
 * Both collapse to one column below 900px, in the order they are written.
 */
.hero-split {
  display: grid;
  gap: clamp(26px, 4vw, 56px);
  align-items: start;
}
@media (min-width: 900px) {
  .hero-split { grid-template-columns: 1.08fr 1fr; }
}

.hero-claim {
  display: flex;
  flex-direction: column;
  gap: 18px;
}
/* Bigger than the stacked version allowed: it has a column to itself now. */
@media (min-width: 900px) {
  .hero-claim h1 { font-size: clamp(38px, 4.4vw, 60px); }
}

.hero-detail {
  display: flex;
  flex-direction: column;
  gap: 22px;
}
/* Optically level with the headline rather than with the eyebrow above it. */
@media (min-width: 900px) {
  .hero-detail { padding-top: 34px; }
}

.hero .highway-card { margin-top: clamp(30px, 4vw, 48px); }

.hero-copy {
  display: flex;
  flex-direction: column;
  gap: 22px;
}

.store-row {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
}

.store-btn {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 11px 22px;
  border-radius: 10px;
}

.store-lines {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

/* Sized to the cap height of the label beside it, so the glyph reads as part of
   the type rather than as a picture stuck next to it. */
.store-glyph {
  width: 26px;
  height: 26px;
  flex: 0 0 auto;
}
.store-btn .top {
  font: 400 10.5px/1 var(--mono);
  letter-spacing: .14em;
  text-transform: uppercase;
  /* Without this the label wraps and collides with the line below. */
  white-space: nowrap;
}
.store-btn .name { font: 600 17px/1.2 var(--display); white-space: nowrap; }

/* Both stores share one dark ground.
   Play's glyph is four colours and needs somewhere dark to sit; on a mint
   button its own green disappeared into the background. Matching the two also
   stops them reading as a primary and a secondary choice — the visitor's phone
   decides which one they need, not us. */
.store-btn.play,
.store-btn.apple {
  border: 1px solid rgba(250, 250, 249, .3);
  background: rgba(5, 5, 5, .55);
  color: var(--ink);
}
.store-btn.play:hover,
.store-btn.apple:hover { border-color: var(--in-tune); color: var(--ink); }
.store-btn.play .top,
.store-btn.apple .top { color: var(--ink-dim); }

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

.phone {
  width: min(300px, 74vw);
  border: 10px solid var(--border);
  border-radius: 38px;
  background: var(--surface);
  overflow: hidden;
  box-shadow: 0 40px 100px rgba(0, 0, 0, .8);
  margin: 0 auto;
  /* A closed frame on all four sides: an open bottom reads as clipped content
     when the screen inside is animating. */
  height: clamp(530px, 168vw, 580px);
}

.phone-sm {
  width: min(280px, 76vw);
  box-shadow: 0 30px 70px rgba(0, 0, 0, .7);
  height: clamp(480px, 78vw, 552px);
}
.phone-violin { height: clamp(500px, 132vw, 560px); }

.screen {
  position: relative;
  background: #0a0a0a;
  padding: 18px 16px 12px;
  display: flex;
  flex-direction: column;
  height: 100%;
}

/* -------------------------------------------------------------- sections */

section { padding: var(--section-y) 0; }

.stats {
  background: var(--elevated);
  border-bottom: 1px solid var(--border);
  padding: 0;
}
.stats .grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 0 20px;
}
.stats .cell { padding: 26px 0; }
.stats .figure {
  font: 700 30px/1.1 var(--display);
  color: var(--ink);
}
.stats .label {
  font: 400 12px/1.4 var(--mono);
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--ink-dim);
  margin-top: 4px;
}

.pill-row {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: 26px;
}
.pill {
  font-size: 15.5px;
  color: #e9e6df;
  border: 1px solid var(--border);
  border-radius: 99px;
  padding: 10px 20px;
}
a.pill:hover { border-color: var(--in-tune); color: var(--in-tune); }

/* --------------------------------------------------- technique training */

.technique {
  background: var(--forest-bg);
  border-top: 1px solid var(--forest-border);
  border-bottom: 1px solid var(--forest-border);
}
.technique .eyebrow { letter-spacing: .18em; }
.technique .lead { font-size: 19px; max-width: 72ch; }

.highway-card {
  border: 1px solid var(--forest-border);
  border-radius: 14px;
  background: var(--forest-elevated);
  overflow: hidden;
  margin-top: 30px;
}

.legend {
  background: var(--forest-surface);
  border-top: 1px solid var(--forest-border);
  padding: 20px 26px;
  display: flex;
  flex-wrap: wrap;
  gap: 18px 30px;
}
.legend div {
  display: flex;
  align-items: center;
  gap: 9px;
  font: 400 13px/1.4 var(--mono);
  color: var(--ink);
}
.legend .dot {
  width: 11px;
  height: 11px;
  border-radius: 50%;
  flex: 0 0 auto;
}

.trio {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 26px;
  margin-top: 38px;
}
.trio h3 { margin-bottom: 8px; }

/* -------------------------------------------------------- feature blocks */

.blocks {
  display: flex;
  flex-direction: column;
  gap: clamp(52px, 9vw, 88px);
}

.block {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: clamp(32px, 5vw, 72px);
  align-items: center;
}

/* Blocks 2 and 4 put the image on the left on wide screens. Done with
   direction, not order: `order` has no width condition, so when the grid
   collapses to one column the reversal survives and the reader meets an
   unlabelled screenshot before its heading. rtl swaps two columns and does
   nothing to one. */
.block.mirrored { direction: rtl; }
.block.mirrored > * { direction: ltr; }

.block-copy {
  display: flex;
  flex-direction: column;
  gap: 18px;
}
.block .eyebrow { letter-spacing: .18em; }

/* ------------------------------------------------------- how it listens */

.listens { background: var(--elevated); }
/* Amber, not green: this section is the honest caveat about signal quality,
   not a feature. */
.listens .eyebrow { color: var(--close); }

/* Two routes in, so two columns — not auto-fit, which would let a third card
   slot in beside them and read as another option. */
.listen-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 24px;
  margin-top: 34px;
}
@media (min-width: 700px) {
  .listen-grid { grid-template-columns: 1fr 1fr; }
}

/*
 * What happens to the sound once it is in.
 *
 * Deliberately not a card: it is an answer to a question the two cards raise,
 * not a third thing to pick. Lying on its side, with a smaller figure and no
 * shared border colour, it reads as a footnote to the row above.
 */
.listen-note {
  display: grid;
  grid-template-columns: 200px 1fr;
  align-items: center;
  gap: 22px;
  margin-top: 20px;
  padding: 4px 22px 4px 4px;
  border: 1px solid var(--border);
  border-radius: 12px;
  background: linear-gradient(90deg, rgba(16, 35, 29, .5) 0%, transparent 60%);
}
.listen-note-figure {
  position: relative;
  height: 124px;
  border-radius: 10px;
  overflow: hidden;
  background: radial-gradient(120% 100% at 30% 50%, var(--forest-surface) 0%, #0a0c0b 72%);
}
.listen-note-body h3 { margin-bottom: 7px; }
.listen-note-body p { color: var(--ink-dim); font-size: 16px; line-height: 1.55; }

@media (max-width: 640px) {
  .listen-note {
    grid-template-columns: 1fr;
    gap: 0;
    padding: 4px 4px 18px;
    background: none;
  }
  .listen-note-body { padding: 16px 18px 0; }
}
.listen-card {
  border: 1px solid var(--border);
  border-radius: 12px;
  overflow: hidden;
  background: var(--bg);
}
.listen-card.usb {
  border-color: var(--pro-border);
  background: #120d04;
}
.listen-card.usb .listen-body p { color: var(--pro-caption); }
.listen-figure {
  position: relative;
  height: 170px;
  overflow: hidden;
  background: radial-gradient(120% 100% at 22% 50%, var(--forest-surface) 0%, #0a0c0b 70%);
}
.listen-body { padding: 20px 22px; }
.listen-body h3 { margin-bottom: 8px; }
.listen-body p { font-size: 16px; line-height: 1.55; color: var(--ink-dim); }

.trademark {
  margin-top: 28px;
  font-size: 14.5px;
  line-height: 1.6;
  color: var(--ink-dim);
  max-width: 90ch;
}

/* --------------------------------------------------------------- privacy */

.two-col {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(340px, 100%), 1fr));
  gap: clamp(28px, 4vw, 56px);
}
.link-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-top: 20px;
}
.link-list a { text-decoration: underline; }

/* ------------------------------------------------------------ free / pro */

.pricing { background: var(--elevated); }
.price-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 22px;
  margin-top: 34px;
}
.price-card {
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 26px 24px;
  background: var(--bg);
}
.price-card h3 { margin-bottom: 10px; }
.price-card p { font-size: 16px; line-height: 1.55; color: var(--ink-dim); }
.price-card.pro {
  border-color: var(--pro-border);
  background: var(--pro-surface);
}
.price-card.pro .price {
  margin-top: 14px;
  font: 500 14px/1.4 var(--mono);
  color: var(--pro-caption);
}

/* -------------------------------------------------------------- download */

.download {
  background: var(--forest-bg);
  border-top: 1px solid var(--forest-border);
  text-align: center;
}
.download .store-row { justify-content: center; margin-top: 30px; }
.download .mark { width: 48px; height: 48px; margin: 0 auto 22px; display: block; }
.download h2 { margin-bottom: 14px; }
.download .lead { margin: 0 auto; }

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

.site-footer {
  border-top: 1px solid var(--border);
  padding: clamp(40px, 6vw, 64px) 0 34px;
}
.footer-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 32px;
}
.footer-grid h4 {
  margin: 0 0 14px;
  font: 500 12px/1 var(--mono);
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--ink-dim);
}
.footer-grid ul { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 9px; }
.footer-grid li a { font-size: 15.5px; color: var(--ink-dim); }
.footer-grid li a:hover { color: var(--in-tune); }
.footer-brand .name { font: 700 21px/1 var(--display); letter-spacing: -.01em; color: var(--ink); }
.footer-brand p { margin-top: 10px; font-size: 15.5px; color: var(--ink-dim); max-width: 32ch; }

.footer-bottom {
  margin-top: 40px;
  padding-top: 24px;
  border-top: 1px solid var(--border);
  display: flex;
  flex-wrap: wrap;
  gap: 10px 24px;
  justify-content: space-between;
  font: 400 12.5px/1.6 var(--mono);
  color: var(--ink-dim);
}

/* ------------------------------------------------- support / legal pages */

.doc { max-width: 820px; }
.doc-narrow { max-width: 800px; }

.qa {
  border-top: 1px solid var(--border);
  padding: 30px 0;
}
.qa:last-of-type { border-bottom: 1px solid var(--border); }
.qa h2 { font-size: clamp(20px, 2.6vw, 26px); letter-spacing: -.02em; margin-bottom: 12px; }
.qa p, .qa li { color: var(--ink-dim); font-size: 17px; line-height: 1.65; }
.qa ul { margin: 12px 0 0; padding-left: 22px; display: flex; flex-direction: column; gap: 8px; }

.callout {
  background: #241c07;
  border: 1px solid var(--pro-border);
  border-radius: 12px;
  padding: 26px 24px;
  margin: 30px 0;
}
.callout h2 { color: var(--close); }

.summary-card {
  background: var(--forest-surface);
  border: 1px solid var(--forest-border);
  border-radius: 12px;
  padding: 26px 24px;
  margin-bottom: 40px;
}
.summary-card p { color: #cfe6dd; }

.legal h2 {
  font-size: clamp(19px, 2.4vw, 24px);
  letter-spacing: -.02em;
  margin: 40px 0 12px;
}
.legal p, .legal li { color: var(--ink-dim); font-size: 17px; line-height: 1.7; }
.legal p + p { margin-top: 14px; }
.legal ul, .legal ol { margin: 14px 0 0; padding-left: 22px; display: flex; flex-direction: column; gap: 10px; }
.legal strong { color: var(--ink); font-weight: 600; }

.contact-band {
  background: var(--elevated);
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
  padding: 40px 0;
  margin-top: 50px;
}
.contact-band .btn { margin-top: 20px; }

.page-nav {
  display: flex;
  gap: 20px;
  align-items: center;
}
.page-nav a { font-size: 15px; color: var(--ink-dim); }
.page-nav a:hover { color: var(--in-tune); }

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

/* Sections start hidden only when script confirms it can reveal them, so a
   failed observer never leaves the page blank. See afinora.js. */
.js-reveal section.pending {
  opacity: 0;
  transform: translateY(22px);
  transition: opacity .7s ease, transform .7s cubic-bezier(.2, .7, .3, 1);
}
.js-reveal section.shown { opacity: 1; transform: none; }

/* ---------------------------------------------------------------- phones */

/*
 * The layout is fluid everywhere else — every size is a clamp() and every grid
 * is auto-fit — so this is not a breakpoint the design hangs off. It tightens
 * the one place the fluid version reads badly: on a 360px screen the hero ran
 * to 1.77 screenfuls before the phone mockup appeared, which is a long way to
 * scroll past prose to reach the thing being sold.
 */
@media (max-width: 560px) {
  :root { --section-y: clamp(36px, 8vw, 56px); }

  .hero { padding-top: 26px; }
  .hero-copy { gap: 16px; }
  .hero .lead { font-size: 16.5px; line-height: 1.52; }
  .hero .fine { font-size: 12px; line-height: 1.6; }

  /* Full width and stacked. Two buttons side by side at this width leave each
     one too narrow for its two lines of label, and a full-width target is
     easier to hit with a thumb. */
  .store-row { flex-direction: column; }
  .store-btn { justify-content: center; padding: 13px 18px; }

  /*
   * The vibrating strings drop to the lower half of the hero.
   *
   * At this width the copy runs the full width of the section, so six
   * horizontal lines cross right through it and the headline reads as struck
   * out. Below the text they are scenery again — and they sit behind the phone,
   * which is where a string field belongs anyway. Fainter too: there is far
   * less room here for something that is only atmosphere.
   */
  .string-field { inset: 46% 0 0; opacity: .6; }

  /* The hero phone is the point of the section, so it keeps its size while the
     words around it give way. The floor is what the tuner screen actually needs
     once its labels start wrapping at this width — measured, not guessed. */
  .phone { height: clamp(516px, 160vw, 560px); }
  .phone-sm { height: clamp(500px, 155vw, 552px); }
  .phone-violin { height: clamp(516px, 160vw, 560px); }

  .stats .cell { padding: 18px 0; }
  .stats .figure { font-size: 26px; }

  .legend { padding: 16px 18px; gap: 12px 20px; }
  .listen-body, .price-card, .callout, .summary-card { padding: 20px 18px; }
  .pill { font-size: 14.5px; padding: 9px 16px; }

  .footer-grid { gap: 26px; }
  .footer-bottom { margin-top: 30px; }
}

/*
 * The narrowest phones still in use, where the header is the tight part: the
 * mark, the language control and a Download label that is "Herunterladen" in
 * German do not fit one 320px row at full size. The row must stay one row — a
 * header that wraps to two lines pushes the whole page down and looks broken —
 * so the controls shrink instead.
 */
@media (max-width: 400px) {
  .site-header .inner { padding: 0 14px; gap: 8px; }
  .brand svg { width: 26px; height: 26px; }
  .brand .name { font-size: 18px; }
  .btn { padding: 8px 12px; font-size: 13.5px; }
  .lang > summary { padding: 6px 8px; font-size: 11px; gap: 4px; }
  :root { --gutter: 16px; }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .js-reveal section.pending { opacity: 1; transform: none; transition: none; }
  * { animation-duration: .001ms !important; animation-iteration-count: 1 !important; }
}

/* The training section: the three points on one side, the report on the other.
   Stacked, the points read as a list to get through; beside the screen they
   read as captions to it. */
/* Words beside the screen, the three points in a row underneath — the shape
   the feature blocks below already use. Centring three short paragraphs against
   a tall phone left a hole above them the height of the phone. */
.technique-grid {
  display: grid;
  gap: clamp(28px, 4vw, 52px);
  align-items: center;
}
@media (min-width: 900px) {
  .technique-grid { grid-template-columns: 1fr minmax(240px, 300px); }
}
.technique-figure { display: flex; justify-content: center; }
.technique .trio { margin-top: clamp(30px, 4vw, 48px); }



/* ------------------------------------------------------------ instruments */

/* A frieze rather than a wall of cards, and near the foot of the page: by here
   the reader knows what the app does, and this is the closing statement about
   how far it reaches. */
.instruments {
  padding-top: var(--section-y);
  padding-bottom: var(--section-y);
  border-top: 1px solid var(--border);
}

.inst-frieze {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(96px, 1fr));
  gap: 22px 12px;
  margin-top: 34px;
}

.inst {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  text-align: center;
  color: var(--ink-dim);
  transition: color .18s;
}
.inst:hover { color: var(--accent); }
.inst svg { width: 100%; max-width: 62px; height: auto; }
.inst span {
  font: 400 12.5px/1.35 var(--body);
  color: inherit;
}

@media (max-width: 560px) {
  .inst-frieze { grid-template-columns: repeat(auto-fit, minmax(78px, 1fr)); gap: 18px 8px; }
  .inst svg { max-width: 50px; }
  .inst span { font-size: 11.5px; }
}


/* Two plans, four lines each, one number per line. */
.price-grid { grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); }

.price-card dl {
  margin: 16px 0 0;
  display: grid;
  gap: 11px;
}
.price-card dl > div {
  display: grid;
  grid-template-columns: 42px 1fr;
  align-items: baseline;
  gap: 12px;
}
.price-card dt {
  font: 700 22px/1 var(--display);
  color: var(--ink);
  text-align: right;
}
.price-card dd {
  margin: 0;
  font-size: 16px;
  line-height: 1.4;
  color: var(--ink-dim);
}
.price-card.pro dt { color: var(--close); }

/* The promises: a line under both plans, not a plan of their own. */
.never {
  margin-top: 26px;
  padding-top: 22px;
  border-top: 1px solid var(--border);
  font: 400 14.5px/1.7 var(--mono);
  color: var(--ink-dim);
  text-align: center;
}

@media (max-width: 560px) {
  .price-card dl > div { grid-template-columns: 34px 1fr; gap: 10px; }
  .price-card dt { font-size: 19px; }
  .price-card dd { font-size: 15px; }
  .never { font-size: 13px; text-align: left; }
}


/* Three claims, three demonstrations. */
.tri-cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(258px, 1fr));
  gap: clamp(22px, 3vw, 34px);
  margin-top: clamp(32px, 4vw, 46px);
}
.tri-card { display: flex; flex-direction: column; gap: 14px; }
.tri-card h3 { margin-bottom: -6px; }


/* Free is a narrow column; Pro is what the section is about. */
@media (min-width: 860px) {
  .price-grid { grid-template-columns: minmax(240px, 0.62fr) 1.38fr; }
}

.pro-head {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: 14px;
}
.pro-mark {
  width: 54px;
  height: 54px;
  border-radius: 13px;
  background: var(--forest-surface);
  border: 1px solid var(--forest-border);
  display: flex;
  align-items: center;
  justify-content: center;
}
.pro-mark svg { width: 34px; height: 34px; }
.pro-name h3 { font-size: 20px; }
.pro-kind {
  margin-top: 3px;
  font: 400 10px/1.3 var(--mono);
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--pro-caption);
}
.pro-price { text-align: right; }
.pro-price .amount {
  display: block;
  font: 700 clamp(28px, 3.4vw, 40px)/1 var(--display);
  color: var(--close);
  letter-spacing: -.02em;
}
.pro-price .note {
  display: block;
  margin-top: 4px;
  font: 400 11px/1.4 var(--mono);
  color: var(--pro-caption);
}

/* Three across, so the fourth line — the one with the infinity — lands on its
   own row where it reads as the punchline rather than as a fourth of four. */
.price-card .pro-items { margin-top: 22px; }
@media (min-width: 700px) {
  .price-card .pro-items { grid-template-columns: repeat(3, 1fr); }
}

.paid-once {
  margin-top: 20px;
  padding-top: 18px;
  border-top: 1px solid var(--pro-border);
  font-size: 16px;
  line-height: 1.5;
  color: var(--ink);
}
.price-card .never {
  margin-top: 8px;
  padding-top: 0;
  border-top: 0;
  text-align: left;
  font-size: 12.5px;
  color: var(--pro-caption);
}

@media (max-width: 560px) {
  .pro-head { grid-template-columns: auto 1fr; gap: 12px; }
  .pro-price { grid-column: 1 / -1; text-align: left; margin-top: 6px; }
  .pro-mark { width: 44px; height: 44px; border-radius: 11px; }
  .pro-mark svg { width: 28px; height: 28px; }
}


/* No figure here any more, so the kind of purchase carries the corner the
   price used to hold. */
.pro-head { grid-template-columns: auto 1fr; }
.pro-name h3 { font-size: clamp(20px, 2.4vw, 26px); }
.pro-kind { font-size: 11px; letter-spacing: .18em; }


/* The approximate price is a fact to judge by, not the headline of the card:
   smaller than the product name, and the note under it carries as much weight
   as the figure. */
.pro-head { grid-template-columns: auto 1fr auto; }
.pro-price .amount { font: 700 clamp(19px, 2vw, 24px)/1.1 var(--display); }
.pro-price .note { max-width: 20ch; }
