/* ============================================================================
   wird - marketing site
   ----------------------------------------------------------------------------
   Both palettes are the app's own shipped colours (DESIGN.md), converted to
   OKLCH so they are identical rather than approximated. The app ships light
   and dark and defaults to light; this page defaults to dark and offers the
   same switch.

   Two of the app's rules carry over, because they're what a generic landing
   page would get wrong:
     1. Ember is never a button fill. Buttons are monochrome; ember is for
        streak numerals, active states and small link-style affordances.
     2. No boxed cards around plain stat numbers.
   ========================================================================== */

/* Font loading itself lives in index.html's <head> as a real <link>, not a
   CSS @import here - @import can only be discovered after the browser has
   already fetched and parsed this whole file, which pushes the Arabic
   glyph fonts' fetch far enough behind styles.css's own arrival that the
   hero's Arabic word painted in a fallback serif before Amiri arrived,
   with fallback-serif metrics tall enough to look like a layout bug rather
   than a font swap. A <link> in the head is discovered immediately and
   fetched in parallel with this file instead of after it. */

/* The three script specimens use the app's own bundled font files, not a
   same-name substitute from Google Fonts - "Amiri Quran" and especially
   "Noto Nastaliq Urdu" are visibly different letterforms from what the app
   actually renders, and the Tajweed specimen used hand-picked colours on
   three hardcoded spans standing in for a font that already colour-codes
   every rule itself. Copied verbatim from Wird/assets/fonts/. */
@font-face {
  font-family: 'AlQuranIndoPakWBW';
  src: url('assets/fonts/AlQuranIndoPakWBW.ttf') format('truetype');
  font-display: swap;
}
@font-face {
  font-family: 'AmiriQuranApp';
  src: url('assets/fonts/AmiriQuran.ttf') format('truetype');
  font-display: swap;
}
@font-face {
  font-family: 'AmiriQuranColored';
  src: url('assets/fonts/AmiriQuranColored.ttf') format('truetype');
  font-display: swap;
}

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

:root {
  color-scheme: dark;

  --bg:          oklch(14.1% 0.0030 69.4);   /* #0A0908 */
  --surface:     oklch(19.7% 0.0067 78.2);   /* #171512 */
  --ink:         oklch(95.9% 0.0103 81.8);   /* #F5F1EA */
  --muted:       oklch(62.2% 0.0202 70.1);   /* #8F857A */
  --divider:     oklch(27.1% 0.0108 73.5);   /* #2A2621 */
  --ember:       oklch(72.7% 0.1757 41.2);   /* #FF7A45, the shipped accent - used as running text */

  /* Fill/icon/border variant. In dark mode the shipped ember is already vivid
     enough to serve both roles, so this just aliases it; light mode gives it
     its own brighter value below. --on-fill is the ink colour placed ON TOP
     of an --ember-fill block (a calendar day, a playing button) - near-black
     here because the fill is already bright. */
  --ember-fill: var(--ember);
  --on-fill: var(--bg);

  /* Ink used on top of the drenched .download section, which uses
     --ember-fill as its background. */
  --on-ember:      oklch(20% 0.045 45);
  --on-ember-dim:  oklch(30% 0.065 45);
  --ember-ink-inv: oklch(17% 0.035 45);

  --ink-dim: color-mix(in oklch, var(--ink) 74%, var(--bg));
  --shadow: 0 24px 60px -22px oklch(0% 0 0 / 0.85);
}

:root[data-theme='light'] {
  color-scheme: light;

  --bg:          oklch(97.7% 0.0074 80.7);   /* #FAF7F2 */
  --surface:     oklch(95.1% 0.0119 79.8);   /* #F3EEE6 */
  --ink:         oklch(27.3% 0.0104 61.0);   /* #2B2622 */
  --muted:       oklch(50.2% 0.0181 67.4);   /* #6B6259 */
  --divider:     oklch(89.7% 0.0179 81.3);   /* #E3DCD0 */

  /* The shipped app's light-mode clay (#A8562E) reads as brown rather than
     orange once it's the ONLY orange on a cream page - there's no dark UI
     around it to read it against. Brightened and pushed toward true orange
     while still clearing 4.5:1 on --surface (measured 4.52, verified). */
  --ember: oklch(55% 0.16 40);

  /* A genuinely vivid "sparkling" orange for fills/icons/borders - the
     calendar's filled days, the playing button, the download section's own
     background. Paired with dark ink (--on-fill), not white: at this
     lightness white text/icons would fail contrast, dark ink clears it with
     room to spare (measured 5.4+). */
  --ember-fill: oklch(78% 0.24 46);
  --on-fill: var(--ink);

  --on-ember:      oklch(22% 0.05 45);
  /* 34% measured at 4.46:1 against the vivid fill - short of 4.5. Dropped to
     30% for margin (measured 5.17:1). */
  --on-ember-dim:  oklch(30% 0.06 45);
  --ember-ink-inv: oklch(18% 0.04 45);

  --shadow: 0 22px 50px -24px oklch(40% 0.03 60 / 0.28);
}

:root {
  --sans: 'Inter', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif;
  /* Uthmani naskh: upright, the shape most mushafs use - the app's own
     bundled Amiri Quran file, with the Google Fonts copy only as a fallback
     for the instant before the self-hosted file finishes loading. */
  --naskh: 'AmiriQuranApp', 'Amiri Quran', 'Amiri', serif;
  /* Indo-Pak: genuinely Nastaleeq, diagonal and stacked - specifically the
     app's specially-matched font, not a generic Nastaliq substitute (Noto
     Nastaliq Urdu is a real, different typeface, not a stand-in for this). */
  --nastaliq: 'AlQuranIndoPakWBW', 'Amiri Quran', serif;
  /* Same Uthmani text as --naskh, but this font colour-codes every tajweed
     rule in its own glyphs - the three hardcoded span colours it replaced
     covered three rules; this covers all of them, the same as the app. */
  --tajweed: 'AmiriQuranColored', 'Amiri Quran', serif;

  --t-xs:   clamp(0.72rem, 0.70rem + 0.10vw, 0.78rem);
  --t-sm:   clamp(0.84rem, 0.81rem + 0.14vw, 0.94rem);
  --t-base: clamp(1rem, 0.96rem + 0.20vw, 1.14rem);
  --t-md:   clamp(1.22rem, 1.12rem + 0.45vw, 1.5rem);
  --t-lg:   clamp(1.6rem, 1.35rem + 1.1vw, 2.4rem);
  --t-xl:   clamp(2.2rem, 1.6rem + 2.6vw, 4rem);
  --t-2xl:  clamp(3rem, 1.8rem + 5.2vw, 6.6rem);

  --gutter: clamp(1.25rem, 4vw, 3rem);
  --sec-y:  clamp(5rem, 11vh, 10rem);
  --sec-y-tight: clamp(3rem, 6vh, 5rem);
  --measure: 62ch;
  --maxw: 1240px;

  --ease: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-quart: cubic-bezier(0.25, 1, 0.5, 1);
  --tap: 180ms;
}

/* ------------------------------------------------------------------ reset - */

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--sans);
  font-size: var(--t-base);
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
  transition: background-color 320ms var(--ease), color 320ms var(--ease);
}

h1, h2, h3, h4 {
  margin: 0;
  font-weight: 800;
  letter-spacing: -0.035em;
  line-height: 1.04;
  text-wrap: balance;
}
p { margin: 0; }
img { display: block; max-width: 100%; height: auto; }
a { color: inherit; }

:focus-visible { outline: 2px solid var(--ember); outline-offset: 3px; border-radius: 4px; }
::selection { background: var(--ember); color: var(--bg); }

/* --------------------------------------------------------------- utilities - */

.wrap { width: 100%; max-width: var(--maxw); margin-inline: auto; padding-inline: var(--gutter); }
.measure { max-width: var(--measure); }

.prose > * + * { margin-top: 1.25rem; }
.prose .kicker + h2 { margin-top: 0.9rem; }

.h2-tight { font-size: var(--t-xl); max-width: 22ch; }

.kicker {
  font-size: var(--t-xs);
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted);
}

.lede { font-size: var(--t-md); line-height: 1.5; color: var(--ink-dim); letter-spacing: -0.012em; }
.body-dim { color: var(--muted); }
.rule { height: 1px; border: 0; margin: 0; background: var(--divider); }

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

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

.btn {
  --btn-pad-y: 0.95rem;
  display: inline-flex; align-items: center; justify-content: center;
  gap: 0.6rem;
  padding: var(--btn-pad-y) 1.6rem;
  border-radius: 999px;
  border: 1px solid transparent;
  font: inherit; font-size: var(--t-sm); font-weight: 600;
  letter-spacing: -0.005em; text-decoration: none; cursor: pointer;
  transition: transform var(--tap) var(--ease), background-color var(--tap) var(--ease),
              border-color var(--tap) var(--ease), color var(--tap) var(--ease);
}
.btn:active { transform: scale(0.975); }
.btn svg { flex: none; }

.btn--primary { background: var(--ink); color: var(--bg); }
.btn--primary:hover { background: color-mix(in oklch, var(--ink) 88%, var(--ember)); }

.btn--ghost {
  background: transparent; color: var(--ink);
  border-color: color-mix(in oklch, var(--ink) 32%, transparent);
}
.btn--ghost:hover { border-color: var(--ink); background: color-mix(in oklch, var(--ink) 7%, transparent); }

/* --------------------------------------------------------------------- nav - */

.nav {
  position: fixed; inset: 0 0 auto 0; z-index: 60;
  display: flex; align-items: center; gap: 1rem;
  padding: 0.85rem var(--gutter);
  background: transparent;
  border-bottom: 1px solid transparent;
  transition: background-color 280ms var(--ease), border-color 280ms var(--ease);
}
.nav[data-stuck='true'] {
  background: color-mix(in oklch, var(--bg) 92%, transparent);
  backdrop-filter: saturate(140%) blur(10px);
  border-bottom-color: var(--divider);
}

/* Wordmark is type, not an image. */
.nav__mark {
  margin-right: auto; text-decoration: none;
  font-weight: 900; font-size: 1.45rem; letter-spacing: -0.055em;
  padding-block: 0.35rem;
}
.nav__mark i { color: var(--ember); font-style: normal; }

.nav__links { display: flex; align-items: center; gap: clamp(1rem, 2.4vw, 1.9rem); font-size: var(--t-sm); }
.nav__links a {
  color: var(--muted); text-decoration: none; font-weight: 500;
  padding-block: 0.6rem;
  transition: color var(--tap) var(--ease);
}
.nav__links a:hover { color: var(--ink); }

.nav .btn { --btn-pad-y: 0.6rem; padding-inline: 1.1rem; }

/* Theme switch */
.themebtn {
  display: inline-grid; place-items: center;
  width: 40px; height: 40px;
  border-radius: 999px;
  border: 1px solid var(--divider);
  background: transparent; color: var(--muted);
  cursor: pointer;
  transition: color var(--tap) var(--ease), border-color var(--tap) var(--ease),
              background-color var(--tap) var(--ease);
}
.themebtn:hover { color: var(--ink); border-color: var(--ink); }
.themebtn svg { width: 17px; height: 17px; }
.themebtn .i-sun { display: none; }
:root[data-theme='light'] .themebtn .i-sun { display: block; }
:root[data-theme='light'] .themebtn .i-moon { display: none; }

@media (max-width: 820px) { .nav__links { display: none; } }

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

.hero { position: relative; padding-block: clamp(7rem, 16vh, 11rem) var(--sec-y); overflow: hidden; }

/* ورد, the word the app is named after, at the largest scale on the page. */
.hero__glyph {
  position: absolute; top: 50%;
  right: clamp(-11rem, -7vw, -2rem);
  translate: 0 -50%;
  font-family: var(--naskh);
  font-size: clamp(15rem, 38vw, 31rem);
  line-height: 1; color: var(--ember);
  opacity: 0.1;
  pointer-events: none; user-select: none; z-index: 0;
  will-change: transform;
}
:root[data-theme='light'] .hero__glyph { opacity: 0.11; }

.hero__inner { position: relative; z-index: 1; }

.hero h1 {
  font-size: var(--t-2xl); font-weight: 900;
  letter-spacing: -0.055em; max-width: 17ch;
  margin-block: 1.4rem 0;
}

.hero p.lede { margin-top: 1.6rem; max-width: 54ch; }
.hero__cta { display: flex; flex-wrap: wrap; gap: 0.8rem; margin-top: 2.4rem; }

.hero__meta {
  margin-top: 1.5rem;
  display: flex; flex-wrap: wrap; gap: 0.4rem 1.1rem;
  font-size: var(--t-xs); color: var(--muted);
  font-variant-numeric: tabular-nums;
}
.hero__meta span { display: inline-flex; gap: 0.45rem; align-items: center; }
.hero__meta span::before {
  content: ''; width: 3px; height: 3px; border-radius: 50%; background: var(--muted);
}
.hero__meta span:first-child::before { display: none; }

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

.sec { padding-block: var(--sec-y); }
.sec--tight { padding-block: var(--sec-y-tight); }
.sec--bordered { border-top: 1px solid var(--divider); }

.sec__head { max-width: 46ch; }
.sec__head h2 { font-size: var(--t-xl); }

.split {
  display: grid; gap: clamp(2.5rem, 6vw, 5rem);
  align-items: center;
  grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
}
.split--top { align-items: start; }
.split--flip > :first-child { order: 2; }
@media (max-width: 900px) {
  .split { grid-template-columns: 1fr; }
  .split--flip > :first-child { order: 0; }
}

/* ------------------------------------------------------------ device frame - */
/* One large device rather than a cramped filmstrip of five - room enough for
   a corner radius and bezel that actually read as an iPhone instead of a
   rounded rectangle. The screenshot is an Android capture, so the screen
   crops it to the device aspect via object-fit rather than squashing it. */

.showcase {
  display: flex;
  justify-content: center;
  position: relative;
  padding: clamp(2rem, 6vh, 3.5rem) 1rem;
  perspective: 1600px;
}
/* A dark radial glow behind the device, independent of the page theme - the
   same dramatic-render energy as a studio product shot, in both themes. */
.showcase::before {
  content: '';
  position: absolute; inset: -10% -10%;
  z-index: 0;
  background: radial-gradient(closest-side, oklch(10% 0.01 60 / 0.9), transparent 72%);
  border-radius: 50%;
}
:root[data-theme='light'] .showcase::before {
  background: radial-gradient(closest-side, oklch(88% 0.02 60 / 0.9), transparent 72%);
}

/* A single rendered shot, tilt and shadow already baked into the image
   itself - no CSS device frame drawn around it. */
.showcase__shot {
  position: relative;
  z-index: 1;
  width: clamp(220px, 28vw, 340px);
  height: auto;
  display: block;
  /* A little left of dead-centre in its column - purely a placement
     preference, not tied to anything the flip layout requires. */
  margin-right: clamp(0px, 4vw, 28px);
  transition: transform 500ms var(--ease);
  /* Deters the casual right-click-save/drag-to-desktop copy - see the
     matching draggable/oncontextmenu attributes in the markup. Doesn't (and
     can't) stop devtools or a screenshot; nothing rendered in a browser can. */
  -webkit-user-drag: none;
  user-select: none;
  -webkit-touch-callout: none;
}
.showcase:hover .showcase__shot { transform: translateY(-6px); }

.showcase__label {
  margin-top: 1.3rem; text-align: center;
  font-size: var(--t-xs); color: var(--muted);
}
.showcase__label b { color: var(--ink); font-weight: 600; }

/* -------------------------------------------------------------- calendar -- */
/* A real month grid: weekday header, dates, and the streak drawn through it,
   so the grace-day rule is legible at a glance instead of abstract. */

.cal {
  border: 1px solid var(--divider);
  border-radius: 18px;
  padding: clamp(1rem, 2.4vw, 1.5rem);
  background: var(--surface);
  max-width: 420px;
}

.cal__top {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 1rem; margin-bottom: 1.1rem;
}
.cal__month { font-size: var(--t-sm); font-weight: 700; letter-spacing: -0.01em; }
/* A small filled badge rather than coloured text on the page background -
   that's what lets it use the same vivid orange as the download section
   while still passing contrast (the pairing that matters is icon+text
   against the badge's own fill, not against the page). */
.cal__streak {
  display: inline-flex; align-items: center; gap: 0.35rem;
  padding: 0.3rem 0.6rem;
  border-radius: 999px;
  background: var(--ember-fill);
  font-size: var(--t-xs); font-weight: 700; color: var(--on-fill);
  font-variant-numeric: tabular-nums;
}

.cal__dows, .cal__grid {
  display: grid; grid-template-columns: repeat(7, minmax(0, 1fr));
  gap: clamp(4px, 0.9vw, 7px);
}
.cal__dows {
  margin-bottom: 0.5rem;
  font-size: 0.62rem; font-weight: 600; letter-spacing: 0.1em;
  color: var(--muted); text-align: center;
}

.cal__day {
  position: relative;
  aspect-ratio: 1;
  display: grid; place-items: center;
  border-radius: 8px;
  /* Floor raised from 0.62rem: at 390px the vw term bottoms out, and dates
     were rendering at ~10px inside a 44px cell. */
  font-size: clamp(0.72rem, 1.4vw, 0.78rem);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--muted);
  border: 1px solid transparent;
  transition: opacity 380ms var(--ease), transform 460ms var(--ease);
  transition-delay: calc(var(--i, 0) * 16ms);
}
.cal__day[data-pad] { opacity: 0.22; }

/* a day that was read - filled with the vivid orange, ink on top */
.cal__day[data-state='read'] {
  background: var(--ember-fill);
  border-color: var(--ember-fill);
  color: var(--on-fill);
}

/* the forgiven miss - dashed outline, kept in the chain */
.cal__day[data-state='grace'] {
  border: 1px dashed var(--ember);
  color: var(--ember);
  background: color-mix(in oklch, var(--ember) 10%, transparent);
}

/* the day that actually broke it */
.cal__day[data-state='miss'] {
  border: 1px solid var(--divider);
  color: color-mix(in oklch, var(--muted) 70%, transparent);
}

/* today - open, outlined in ink */
.cal__day[data-state='today'] {
  border: 2px solid var(--ink);
  color: var(--ink);
  font-weight: 800;
}

.cal__note {
  margin-top: 1.1rem; padding-top: 1rem;
  border-top: 1px solid var(--divider);
  font-size: var(--t-xs); color: var(--muted); line-height: 1.55;
}
.cal__note b { color: var(--ember); font-weight: 700; }

.legend { list-style: none; margin: 1.4rem 0 0; padding: 0; display: grid; gap: 0.6rem; font-size: var(--t-xs); color: var(--muted); }
.legend li { display: flex; align-items: center; gap: 0.65rem; }
.legend i { flex: none; width: 14px; height: 14px; border-radius: 4px; }
.legend i[data-swatch='read']  { background: var(--ember-fill); border: 1px solid var(--ember-fill); }
.legend i[data-swatch='grace'] { border: 1px dashed var(--ember); background: color-mix(in oklch, var(--ember) 10%, transparent); }
.legend i[data-swatch='today'] { border: 2px solid var(--ink); }

/* ------------------------------------------------------- script specimens - */
/* Each script is set in its own family against its own text edition, so the
   three genuinely look like three different mushafs. */

.scripts {
  display: grid;
  gap: clamp(1rem, 2vw, 1.4rem);
  grid-template-columns: repeat(auto-fit, minmax(290px, 1fr));
  margin-top: clamp(2.2rem, 5vh, 3.4rem);
}

.script {
  display: flex; flex-direction: column;
  border: 1px solid var(--divider);
  border-radius: 18px;
  overflow: hidden;
  background: var(--surface);
}

.script__specimen {
  display: grid; place-items: center;
  min-height: clamp(150px, 20vh, 200px);
  padding: clamp(1.4rem, 3vw, 2.2rem) 1.2rem;
  background: var(--bg);
  border-bottom: 1px solid var(--divider);
  direction: rtl;
  text-align: center;
}
/* Direct child only. Matching every descendant span turned the tajweed
   specimen's inline tint runs into stacked blocks (a 789px-tall line) and
   overrode their colours on specificity. */
.script__specimen > span { display: block; color: var(--ink); }

/* Nastaliq needs far more vertical room: it stacks on a diagonal baseline. */
.script--nastaliq .script__specimen > span {
  font-family: var(--nastaliq);
  font-size: clamp(1.5rem, 3.4vw, 2.05rem);
  line-height: 2.5;
}
.script--naskh .script__specimen > span {
  font-family: var(--naskh);
  font-size: clamp(1.7rem, 3.8vw, 2.3rem);
  line-height: 1.95;
}
/* Tajweed: the app's own AmiriQuranColored font colours every recitation
   rule in its glyphs - the same plain Uthmani text as .script--naskh above,
   just set in that font, rather than a few rules hand-tinted on spans to
   approximate it. */
.script--tajweed .script__specimen > span {
  font-family: var(--tajweed);
  font-size: clamp(1.7rem, 3.8vw, 2.3rem);
  line-height: 1.95;
}

.script__body { padding: clamp(1.1rem, 2.4vw, 1.5rem); display: grid; gap: 0.5rem; }
.script__name { font-size: var(--t-md); font-weight: 700; letter-spacing: -0.025em; line-height: 1.2; }
/* Same reasoning as .cal__streak above: a filled vivid-orange badge, not
   orange text on the surface. */
.script__meta {
  /* .script__body is a grid, which stretches block-level children to the
     full column width by default - justify-self keeps this a compact pill. */
  justify-self: start;
  font-size: 0.62rem; font-weight: 700; letter-spacing: 0.09em; text-transform: uppercase;
  padding: 0.28rem 0.55rem;
  border-radius: 999px;
  background: var(--ember-fill); color: var(--on-fill);
}
.script__desc { font-size: var(--t-sm); color: var(--muted); line-height: 1.6; }

/* --------------------------------------------------------------- reciters - */

.reciters { margin-top: clamp(1.6rem, 4vh, 2.2rem); border-top: 1px solid var(--divider); }

.reciter {
  display: flex; align-items: center; gap: clamp(0.8rem, 2vw, 1.2rem);
  padding-block: 0.9rem;
  border-bottom: 1px solid var(--divider);
}

.reciter__play {
  flex: none;
  width: 44px; height: 44px;
  display: grid; place-items: center;
  border-radius: 999px;
  border: 1px solid var(--divider);
  background: transparent; color: var(--ink);
  cursor: pointer;
  transition: background-color var(--tap) var(--ease), border-color var(--tap) var(--ease),
              color var(--tap) var(--ease), transform var(--tap) var(--ease);
}
.reciter__play:hover { border-color: var(--ink); }
.reciter__play:active { transform: scale(0.94); }
.reciter__play svg { width: 15px; height: 15px; }
.reciter__play .i-pause, .reciter__play .i-load { display: none; }

.reciter[data-play='loading'] .reciter__play .i-play { display: none; }
.reciter[data-play='loading'] .reciter__play .i-load { display: block; animation: spin 800ms linear infinite; }

.reciter[data-play='playing'] .reciter__play {
  background: var(--ember-fill); border-color: var(--ember-fill); color: var(--on-fill);
}
.reciter[data-play='playing'] .reciter__play .i-play { display: none; }
.reciter[data-play='playing'] .reciter__play .i-pause { display: block; }

@keyframes spin { to { rotate: 360deg; } }

.reciter__who { min-width: 0; }
.reciter__name { font-size: var(--t-base); font-weight: 600; letter-spacing: -0.015em; }
.reciter__note { font-size: var(--t-xs); color: var(--muted); }

.reciter__wave {
  margin-left: auto; flex: none;
  display: flex; align-items: flex-end; gap: 3px;
  height: 20px; width: 46px;
  opacity: 0; transition: opacity 220ms var(--ease);
}
.reciter[data-play='playing'] .reciter__wave { opacity: 1; }
.reciter__wave i {
  display: block; width: 3px; border-radius: 2px;
  background: var(--ember-fill); height: 25%;
}
.reciter[data-play='playing'] .reciter__wave i {
  animation: bar 900ms var(--ease-quart) infinite alternate;
  animation-delay: calc(var(--i, 0) * 110ms);
}
@keyframes bar { from { height: 20%; } to { height: 100%; } }

.reciter__err { font-size: var(--t-xs); color: var(--muted); margin-left: auto; }

/* ----------------------------------------------------------------- numbers - */
/* Four figures on one ruled line. Decluttered from the previous six-up grid,
   which read as a wall. */

.nums {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  margin-top: clamp(2rem, 5vh, 3rem);
  border-top: 1px solid var(--divider);
}
@media (min-width: 620px)  { .nums { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (min-width: 1040px) { .nums { grid-template-columns: repeat(5, minmax(0, 1fr)); } }

.num {
  padding: clamp(1.5rem, 3.5vh, 2.4rem) 1.5rem clamp(1.5rem, 3.5vh, 2.4rem) 0;
  border-bottom: 1px solid var(--divider);
}
/* The offline/zero figure - same accent treatment as the privacy section's
   zeros, kept visually distinct from the plain ink figures beside it. */
.num[data-accent] b { color: var(--ember); }

.num b {
  display: block;
  font-size: clamp(2.4rem, 5vw, 3.6rem);
  font-weight: 800; letter-spacing: -0.055em; line-height: 1;
  font-variant-numeric: tabular-nums;
}
.num span { display: block; margin-top: 0.55rem; font-size: var(--t-sm); color: var(--muted); }

/* ----------------------------------------------------------------- privacy - */
/* Typography only. No stock image: nothing photographic honestly illustrates
   "the data stays on the device". */

.privacy { background: var(--surface); border-block: 1px solid var(--divider); }

.privacy__statement {
  font-size: clamp(1.5rem, 3.4vw, 2.5rem);
  font-weight: 700; letter-spacing: -0.035em; line-height: 1.25;
  max-width: 30ch; text-wrap: balance;
}
.privacy__statement em { font-style: normal; color: var(--ember); }

.facts { list-style: none; margin: 0; padding: 0; display: grid; gap: 0; }
.facts li {
  display: flex; align-items: baseline; gap: 0.9rem;
  padding-block: 0.85rem;
  border-bottom: 1px solid var(--divider);
  font-size: var(--t-sm);
}
.facts li:first-child { border-top: 1px solid var(--divider); }
.facts li b { flex: none; width: 4.2ch; font-weight: 700; color: var(--ember); font-variant-numeric: tabular-nums; }
.facts li span { color: var(--muted); }

/* ---------------------------------------------------------------- releases - */

.rel { margin-top: clamp(2rem, 5vh, 3rem); border-top: 1px solid var(--divider); }

.rel__row {
  display: grid;
  grid-template-columns: auto 1fr auto;
  gap: clamp(0.9rem, 2.5vw, 2rem);
  align-items: center;
  padding-block: clamp(1.1rem, 2.6vh, 1.6rem);
  border-bottom: 1px solid var(--divider);
}

.rel__ver {
  font-size: var(--t-md); font-weight: 800; letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;
}
.rel__ver small {
  display: block; margin-top: 0.15rem;
  font-size: var(--t-xs); font-weight: 500; letter-spacing: 0;
  color: var(--muted);
}
.rel__what { font-size: var(--t-sm); color: var(--muted); line-height: 1.55; min-width: 0; }
.rel__row[data-latest] .rel__what { color: var(--ink); }

.rel__tag {
  display: inline-block; margin-bottom: 0.35rem;
  font-size: 0.6rem; font-weight: 700; letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--ember);
}

.rel__get {
  flex: none;
  display: inline-flex; align-items: center; gap: 0.45rem;
  font-size: var(--t-sm); font-weight: 600;
  text-decoration: none; color: var(--ink);
  padding: 0.6rem 1.1rem;
  border: 1px solid var(--divider); border-radius: 999px;
  transition: border-color var(--tap) var(--ease), background-color var(--tap) var(--ease);
}
.rel__get:hover { border-color: var(--ink); background: color-mix(in oklch, var(--ink) 6%, transparent); }
.rel__get svg { width: 13px; height: 13px; }

@media (max-width: 720px) {
  .rel__row { grid-template-columns: 1fr auto; }
  .rel__what { grid-column: 1 / -1; grid-row: 2; }
}

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

.download {
  background: var(--ember-fill);
  color: var(--on-ember);
  padding-block: clamp(4.5rem, 10vh, 8rem);
}
.download h2 { font-size: var(--t-2xl); font-weight: 900; letter-spacing: -0.055em; max-width: 15ch; }
.download .lede, .download p { color: var(--on-ember-dim); }
.download .kicker { color: var(--on-ember-dim); }

.download .btn--primary { background: var(--ember-ink-inv); color: var(--ember-fill); }
.download .btn--primary:hover { filter: brightness(0.9); }
.download .btn--ghost { color: var(--on-ember); border-color: color-mix(in oklch, var(--on-ember) 40%, transparent); }
.download .btn--ghost:hover { border-color: var(--on-ember); background: color-mix(in oklch, var(--on-ember) 8%, transparent); }

.download__meta { margin-top: 1.6rem; font-size: var(--t-xs); font-variant-numeric: tabular-nums; }

/* Always a dark panel, in both themes. It sits on the ember surface either
   way, and inheriting the theme's inverted ink flipped it to near-white on
   near-white in light mode (measured at 1.87:1). An alert is the last thing
   that should be hard to read. */
.warn {
  display: none;
  margin-top: 1.8rem; padding: 1.1rem 1.3rem;
  border-radius: 14px;
  background: oklch(21% 0.042 45);
  color: oklch(89% 0.085 60);
  font-size: var(--t-sm); line-height: 1.55; max-width: 52ch;
}
.warn[data-show='true'] { display: block; }
.warn b { color: oklch(99% 0.01 80); }
.warn__row { display: flex; flex-wrap: wrap; gap: 0.6rem; margin-top: 0.9rem; }
.warn__row button {
  font: inherit; font-weight: 600; font-size: var(--t-xs);
  padding: 0.55rem 0.95rem; border-radius: 999px; cursor: pointer;
  border: 1px solid oklch(89% 0.085 60 / 0.45);
  background: transparent; color: oklch(89% 0.085 60);
  transition: background-color var(--tap) var(--ease), border-color var(--tap) var(--ease);
}
.warn__row button:hover {
  background: oklch(89% 0.085 60 / 0.14);
  border-color: oklch(89% 0.085 60);
}

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

.foot { padding-block: clamp(3rem, 7vh, 5rem); font-size: var(--t-sm); color: var(--muted); }
.foot__grid {
  display: grid; gap: 2.5rem;
  grid-template-columns: minmax(0, 1.4fr) repeat(auto-fit, minmax(140px, 1fr));
}
.foot h3 {
  font-size: var(--t-xs); letter-spacing: 0.16em; text-transform: uppercase;
  font-weight: 600; color: var(--muted); margin-bottom: 1rem;
}
.foot ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.6rem; }
.foot a { text-decoration: none; transition: color var(--tap) var(--ease); }
.foot a:hover { color: var(--ink); }

/* Wordmark, set as type. */
.foot__mark {
  font-weight: 900; font-size: 1.5rem; letter-spacing: -0.055em; color: var(--ink);
}
.foot__mark i { color: var(--ember); font-style: normal; }
.foot__note { margin-top: 0.9rem; max-width: 32ch; line-height: 1.6; }

.foot__bottom {
  margin-top: 3rem; padding-top: 1.5rem; border-top: 1px solid var(--divider);
  display: flex; flex-wrap: wrap; gap: 0.6rem 1.5rem; font-size: var(--t-xs);
}

/* ------------------------------------------------------- reveal on scroll - */

.js [data-reveal] {
  opacity: 0; transform: translateY(18px);
  transition: opacity 760ms var(--ease), transform 860ms var(--ease);
  transition-delay: calc(var(--d, 0) * 1ms);
}
.js [data-reveal].is-in { opacity: 1; transform: none; }

.js .cal__day { opacity: 0; transform: scale(0.6); }
.js .cal.is-in .cal__day { opacity: 1; transform: none; }
.js .cal.is-in .cal__day[data-pad] { opacity: 0.22; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
  .js [data-reveal] { opacity: 1; transform: none; }
  .js .cal__day { opacity: 1; transform: none; }
  .hero__glyph { transform: none !important; }
}
