/* ============================================================
   Lekton — product layer over the Erasmus Labs design system.

   styles.css is the SHARED system and is copied here byte-identical, so it
   stays diffable against erasmuslabs-site. Everything Lekton-specific lives
   in this file: nothing below may be needed by the company site, and nothing
   above may be edited here. That split is what keeps the two sites looking
   like the same company a year from now.
   ============================================================ */

/* ============ system overrides ============
   These re-point tokens the shared system defines. They live here rather than in styles.css
   because styles.css must stay byte-identical with the company site — but every one of them
   is a fix the company site needs too, and should be lifted into the system next time both
   are being touched together.
   ============================================================ */
:root {
  /* Body was 15px with 10–13px fine print, the smallest type we ship. WCAG sets no floor,
     but Material's body-large is 16 and GOV.UK ships 19 at every screen size and deleted
     their 14px step on accessibility grounds. Every step moves up one notch. Measures are
     capped in em/ch, so the characters-per-line stay where they were. */
  --fs-body-l:  19px;
  --fs-body:    17px;
  --fs-body-s:  15px;
  --fs-caption: 13px;
  --fs-mono:    14px;

  /* Mono, uppercase, letterspaced: section marks, eyebrows, table keys, footer heads, the
     kbd chips. The system writes these as six separate declarations that had already drifted
     between 10px and 11px; one token means they can't drift again. */
  --fs-label:   12px;

  /* #7B8294 is 3.84:1 on white — a straight SC 1.4.3 failure, and it carries the section
     marks, the demo labels and the whole footer. This is 5.18:1 and still reads a step
     quieter than --fg-muted, which is the only job it has. */
  --fg-subtle:  #656C7E;
}
[data-theme="dark"] {
  /* #6B7285 measured 4.0:1 on the page and 3.3:1 inside the terminal card. This is 5.01:1
     on --bg and 4.81:1 on --bg-subtle, the worst backdrop it lands on. */
  --fg-subtle:  #7B8296;
}

/* The six label declarations the system hardcodes, re-pointed at the token. */
.entry-head,
.hero-eyebrow,
.eh-coord,
.era-meta .meta-row,
.foot-col h2,
.foot-bottom { font-size: var(--fs-label); }

/* 38px is a 10mm-wide finger aiming at a 6.7mm-tall target. Parhi et al. measured 9.2mm as
   the point where one-handed thumb accuracy stops degrading; 44px is 11.6mm and is also
   Apple's own minimum and WCAG 2.5.5. These are the two things anyone came here to press. */
.btn { height: 44px; padding: 0 20px; font-size: var(--fs-body-s); }
.eh-brand-name { font-size: var(--fs-body-s); }

/* The system leaves focus to the user agent everywhere except the email field. Safari's
   default ring is faint on a dark surface, and the header is sticky, so a tabbed-to link can
   end up behind it. This is one visible, high-contrast ring for everything, plus the scroll
   offset that keeps the header off whatever the ring is around (SC 2.4.11). */
a:focus-visible,
button:focus-visible,
summary:focus-visible,
[tabindex]:focus-visible {
  outline: 2px solid var(--border-focus);
  outline-offset: 3px;
  border-radius: var(--r-xs);
}
:target,
[id] { scroll-margin-top: 96px; }

/* The section marks are the one place --accent-warm carries text rather than a dot, and
   terracotta on white is 4.35:1 — a hair under AA. Two points darker clears it at 4.89:1 and
   is indistinguishable beside the dots that keep the original. Calibrated against --bg-subtle,
   not white: the alt sections are the darker backdrop and the binding constraint (4.70:1
   there, 5.13:1 on white). Dark mode's --terra-soft is already 7.4:1, so it is left alone. */
.entry-num { color: #B25127; }
[data-theme="dark"] .entry-num { color: var(--accent-warm); }

/* Moving the email form out of the hero left the fold landing in dead space: the next section
   started 69px above it, but all 69px were its own top padding, so nothing INKED appeared
   below the hero and the first screen read as the whole page. Trimming the hero's bottom
   padding and the first section's top padding together puts the "EL — 003 / A" mark ~25px
   above a 900px fold — a cut-off line rather than a clean edge, which is the whole point.
   Nothing is being crammed in; it is a scroll signifier, and it costs one gap. */
.hero { padding-bottom: var(--s-10); }
/* The section's 80px top padding and the entry-head's 80px were stacking to a 160px gap
   before the first ink — two rules doing one job, which is also why the fold landed in
   nothing. The entry-head owns the space; the section keeps its bottom padding. */
#privacy { padding-top: 0; }
#privacy .entry-head { padding-top: var(--s-16); }

/* At 96px the system's 1.0 leading puts the hero's descenders into the caps of the line
   below it — visible on "Dictation that never / leaves your Mac." 1.06 is the smallest
   value that clears them and is still tighter than any of Material's display steps. */
.hero h1 { line-height: 1.06; }

/* ============ header additions ============ */
.eh-brand .lk-plate { width: 26px; height: 26px; border-radius: 6px; display: block; }
.eh-nav {
  font-size: var(--fs-body-s);
  color: var(--fg-muted);
  text-decoration: none;
  padding: 6px 2px;
  transition: color var(--dur-base) var(--ease-standard);
}
.eh-nav:hover { color: var(--fg-strong); }
.eh-actions { gap: var(--s-5); }
/* On a phone the header does not fit brand + three section links + language + theme, and it did not
   fit before the switcher existed either: at 375px the row overflowed the viewport and the theme
   toggle sat off-screen entirely. The section links go first — this is one scrolling page, so they
   are a convenience — leaving the two controls that have no other route: language and theme. The
   Korean and Chinese labels are what made it unmissable, wrapping one character per line. */
@media (max-width: 640px) {
  .eh-nav-wide { display: none; }
  .eh-actions .eh-nav[href^="#"] { display: none; }
  .eh-brand-name { white-space: nowrap; }
}

/* ============ hero ============ */
.hero-stack .lead { max-width: 30em; }

.cta-row { display: flex; flex-wrap: wrap; gap: var(--s-3); margin-top: var(--s-8); }
.cta-note {
  margin-top: var(--s-4);
  font-size: var(--fs-body-s);
  color: var(--fg-muted);
  max-width: 34em;
}

/* The demo card: what was heard above what was typed.
   This is the product's entire pitch in one glance, so it earns hero space that
   the company site gives to the animated mark. */
.hero-demo { display: flex; flex-direction: column; gap: var(--s-4); }
.demo-card {
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  padding: var(--s-5) var(--s-6) var(--s-6);
  box-shadow: var(--shadow-lg);
}
.demo-head {
  display: flex; align-items: center; gap: var(--s-3);
  padding-bottom: var(--s-4);
  margin-bottom: var(--s-5);
  border-bottom: 1px solid var(--border);
}
.demo-dot {
  width: 8px; height: 8px; border-radius: var(--r-full);
  background: var(--terra);
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--terra) 18%, transparent);
  flex: none;
}
[data-theme="dark"] .demo-dot { background: var(--terra-soft); }
.demo-title { font-size: var(--fs-body-s); color: var(--fg-muted); }
.demo-title kbd {
  font-family: var(--font-mono);
  font-size: var(--fs-label);
  border: 1px solid var(--border-strong);
  border-bottom-width: 2px;
  border-radius: var(--r-xs);
  padding: 1px 5px;
  color: var(--fg);
}

/* Seven bars, staggered — a listening indicator, not a real level meter.
   Honest as decoration because it is plainly stylised; a fake waveform that
   pretended to track audio would be a small lie in the shop window. */
.demo-wave { margin-left: auto; display: flex; align-items: center; gap: 3px; height: 18px; }
.demo-wave i {
  display: block; width: 3px; height: 30%;
  border-radius: var(--r-full);
  background: var(--accent);
  opacity: 0.85;
  animation: lk-bar 1100ms var(--ease-standard) infinite;
}
.demo-wave i:nth-child(1) { animation-delay: 0ms; }
.demo-wave i:nth-child(2) { animation-delay: 90ms; }
.demo-wave i:nth-child(3) { animation-delay: 180ms; }
.demo-wave i:nth-child(4) { animation-delay: 270ms; }
.demo-wave i:nth-child(5) { animation-delay: 360ms; }
.demo-wave i:nth-child(6) { animation-delay: 450ms; }
.demo-wave i:nth-child(7) { animation-delay: 540ms; }
@keyframes lk-bar {
  0%, 100% { height: 25%; }
  50%      { height: 100%; }
}
@media (prefers-reduced-motion: reduce) {
  .demo-wave i { animation: none; height: 60%; }
}

.demo-label {
  font-family: var(--font-mono);
  font-size: var(--fs-label);
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
  color: var(--fg-subtle);
  margin: 0 0 var(--s-2);
}
.demo-raw {
  color: var(--fg-muted);
  font-size: var(--fs-body);
  margin: 0 0 var(--s-5);
}
.demo-strike { text-decoration: line-through; opacity: 0.55; }
.demo-clean {
  color: var(--fg-strong);
  font-size: var(--fs-body-l);
  margin: 0;
}
.demo-clean code {
  font-family: var(--font-mono);
  font-size: 0.88em;
  background: var(--bg-muted);
  border-radius: var(--r-xs);
  padding: 1px 4px;
  margin: 0 -1px;
}
.demo-caption { font-size: var(--fs-caption); color: var(--fg-muted); margin: 0; max-width: 40em; }

/* ============ sections ============ */
.section { padding: var(--s-20) 0; }
.section-alt {
  background: var(--bg-subtle);
  border-block: 1px solid var(--border);
}
.section > .container-wide > h2 {
  font-family: var(--font-display);
  font-size: clamp(34px, 4.2vw, 56px);
  font-weight: 500;
  letter-spacing: -0.026em;
  line-height: 1.03;
  margin: 0 0 var(--s-4);
}
.dek-wide {
  font-size: var(--fs-body-l);
  color: var(--fg-muted);
  max-width: 34em;
  margin: 0 0 var(--s-10);
}
.prose-wide { max-width: 36em; color: var(--fg-muted); margin-top: var(--s-10); }

/* Right-hand column of a work-grid. The system defines .work-art for imagery;
   this is its text sibling. */
.work-aside { display: flex; flex-direction: column; gap: var(--s-5); }

/* ============ privacy claims ============ */
.claim-list { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s-1); }
.claim-list li {
  display: flex; align-items: flex-start; gap: var(--s-3);
  padding: var(--s-3) 0;
  border-bottom: 1px solid var(--border);
  font-size: var(--fs-body);
  color: var(--fg);
}
.claim-list li:last-child { border-bottom: none; }
.claim-list li::before {
  flex: none;
  width: 18px; height: 18px;
  margin-top: 2px;
  border-radius: var(--r-full);
  display: grid; place-items: center;
  font-size: 11px; font-weight: 700; line-height: 1;
}
/* Runs on your Mac. */
.claim-yes::before {
  content: "✓";
  background: color-mix(in srgb, var(--accent) 16%, transparent);
  color: var(--accent);
}
/* Does not happen at all — the more important half of the list. */
.claim-no::before {
  content: "✕";
  background: color-mix(in srgb, var(--terra) 15%, transparent);
  color: var(--terra);
}
[data-theme="dark"] .claim-no::before { color: var(--terra-soft); }
/* The Pro Voice download caveat, attached to the ONE claim it qualifies.
   It used to sit under the whole list, where it read as a footnote on all seven items —
   including the four about collection, which it has nothing to do with. The exception is
   only to "works with no network at all", so it lives there and nowhere else. */
.claim-note {
  display: block;
  margin-top: var(--s-2);
  padding: var(--s-3);
  font-size: var(--fs-caption);
  line-height: 1.5;
  color: var(--fg-muted);
  background: var(--bg-muted);
  border-radius: var(--r-sm);
}

/* ============ measured numbers ============ */
.stat-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--s-6);
  margin-bottom: var(--s-6);
}
@media (max-width: 860px) { .stat-grid { grid-template-columns: 1fr; } }
.stat {
  border-top: 2px solid var(--fg-strong);
  padding-top: var(--s-4);
}
.stat-num {
  font-family: var(--font-display);
  font-size: clamp(34px, 4.2vw, 56px);
  font-weight: 500;
  letter-spacing: -0.03em;
  line-height: 1;
  color: var(--fg-strong);
  margin: 0 0 var(--s-2);
}
.stat-num span { font-size: 0.42em; color: var(--fg-muted); margin-left: 2px; letter-spacing: 0; }
/* Two of these read as short phrases ("3 in 4", "8 in 10") rather than single numerals, so
   the scale is set by the longest of them and shared by all three. Sizing them individually
   — which an earlier pass did via :has() — gave one card a 44px figure beside a 30px one,
   and a stat grid where the numbers disagree about their own importance reads as a mistake. */
.stat-num { text-wrap: balance; white-space: nowrap; }
.stat-label { font-size: var(--fs-body); color: var(--fg-strong); margin: 0 0 var(--s-2); }
.stat-note { font-size: var(--fs-body-s); color: var(--fg-muted); margin: 0; }

/* ============ features ============ */
.feature-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--s-10) var(--s-12);
  margin-top: var(--s-10);
}
/* An odd number of cards otherwise leaves the last one stranded in a half-width row, which
   reads as a missing card rather than a deliberate end. Spanning it closes the block: the
   rule above the heading runs the full measure and the section ends on a line, not a gap.
   The paragraph keeps its 32em cap, so nothing stretches to an unreadable measure. */
.feature-grid > .feature:last-child:nth-child(odd) { grid-column: 1 / -1; }
@media (max-width: 820px) { .feature-grid { grid-template-columns: 1fr; gap: var(--s-8); } }
.feature h3 {
  font-size: var(--fs-h4);
  font-weight: var(--fw-medium);
  margin: 0 0 var(--s-2);
  padding-top: var(--s-4);
  border-top: 1px solid var(--border-strong);
}
.feature p { font-size: var(--fs-body); color: var(--fg-muted); margin: 0; max-width: 32em; }

/* ============ spec list ============ */
.meta { margin: 0; }
.meta-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--s-4);
  padding: var(--s-3) 0;
  border-bottom: 1px solid var(--border);
}
.meta-row:last-child { border-bottom: none; }
.meta-row dt {
  font-family: var(--font-mono);
  font-size: var(--fs-caption);
  letter-spacing: var(--tracking-mono);
  text-transform: uppercase;
  color: var(--fg-subtle);
}
.meta-row dd { margin: 0; font-size: var(--fs-body); color: var(--fg-strong); text-align: right; }

/* ============ questions ============ */
.faq { margin-top: var(--s-8); border-top: 1px solid var(--border); }
.faq details { border-bottom: 1px solid var(--border); }
.faq summary {
  cursor: pointer;
  padding: var(--s-5) var(--s-8) var(--s-5) 0;
  font-size: var(--fs-h4);
  font-weight: var(--fw-medium);
  color: var(--fg-strong);
  list-style: none;
  position: relative;
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after {
  content: "";
  position: absolute; right: 4px; top: 50%;
  width: 9px; height: 9px;
  margin-top: -6px;
  border-right: 1.5px solid var(--fg-subtle);
  border-bottom: 1.5px solid var(--fg-subtle);
  transform: rotate(45deg);
  transition: transform var(--dur-base) var(--ease-standard);
}
.faq details[open] summary::after { transform: rotate(-135deg); margin-top: -2px; }
.faq p {
  margin: 0 0 var(--s-5);
  /* 55ch, not the 66ch the measure rule suggests, and the difference is the face: Geist's
     "0" — which is what ch measures — is 1.31x its average lowercase advance, so a ch cap
     over-reports the real measure by about a third. 55ch renders as ~72 characters here.
     Measured, not assumed; re-measure if the typeface ever changes. */
  max-width: 55ch;
  color: var(--fg-muted);
}

.contact-card {
  margin-top: var(--s-12);
  padding: var(--s-6);
  border-radius: var(--r-lg);
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--s-6); flex-wrap: wrap;
}
.contact-card h3 { font-size: var(--fs-h4); font-weight: var(--fw-medium); margin: 0 0 var(--s-1); }
.contact-card p { margin: 0; font-size: var(--fs-body-s); color: var(--fg-muted); max-width: 34em; }

/* ============ share ============
   Placed after the contact card, which is after the FAQ, which is after the download — the
   last thing on the page rather than a second control competing with the one action anyone
   came for. Quieter than .contact-card by design: no elevated surface, just a rule, because
   this is an offer and not an ask. */
.share-card {
  margin-top: var(--s-8);
  padding-top: var(--s-6);
  border-top: 1px solid var(--border);
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--s-5); flex-wrap: wrap;
}
.share-copy h3 { font-size: var(--fs-h4); font-weight: var(--fw-medium); margin: 0 0 var(--s-1); }
.share-copy p { margin: 0; font-size: var(--fs-body-s); color: var(--fg-muted); max-width: 34em; }
.share-actions { display: flex; gap: var(--s-2); flex-wrap: wrap; }
.share-icon { width: 1em; height: 1em; flex: none; }

/* The status line owns a fixed row whether or not it has text, so confirming a copy does not
   shift the footer up and down under the reader's cursor. */
.share-status {
  flex-basis: 100%;
  margin: var(--s-3) 0 0;
  min-height: 1.5em;
  font-size: var(--fs-body-s);
  color: var(--fg-muted);
}
@media (max-width: 560px) {
  /* Stacked, and the buttons go full width — at this size they are thumb targets. */
  .share-card { flex-direction: column; align-items: stretch; }
  .share-actions { flex-direction: column; }
}

/* ============ footer ============ */
.foot-col a { display: block; }

/* ============ coding-agent demo ============
   The primary use case, shown rather than asserted. It is an ILLUSTRATION in the site's
   own visual language, not a mocked-up screenshot of someone else's app — a fabricated
   screenshot is a small lie, and this page's entire argument is that we can be taken at
   our word. The caption says so plainly, and every transformation it shows is one the
   pipeline actually performs. */
.term {
  /* Capped, because a terminal stretched to a 1180px container reads as a banner rather
     than a window — and the line lengths inside it stop looking like something a person
     would type. */
  max-width: 860px;
  margin-top: var(--s-10);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  background: var(--ink-950);
  box-shadow: var(--shadow-xl);
  overflow: hidden;
}
[data-theme="light"] .term { background: var(--ink-900); }

.term-bar {
  display: flex; align-items: center; gap: var(--s-3);
  padding: var(--s-3) var(--s-4);
  background: rgba(255, 255, 255, 0.03);
  border-bottom: 1px solid rgba(255, 255, 255, 0.07);
}
.term-dots { display: flex; gap: 6px; flex: none; }
.term-dots i { width: 10px; height: 10px; border-radius: var(--r-full); background: rgba(255,255,255,0.16); }
.term-title {
  font-family: var(--font-mono);
  font-size: var(--fs-caption);
  color: var(--ink-400);
  letter-spacing: var(--tracking-mono);
}
.term-badge {
  margin-left: auto;
  display: flex; align-items: center; gap: var(--s-2);
  font-size: var(--fs-caption);
  color: var(--ink-300);
}
.term-key {
  font-family: var(--font-mono);
  font-size: var(--fs-label);
  border: 1px solid rgba(255,255,255,0.2);
  border-bottom-width: 2px;
  border-radius: var(--r-xs);
  padding: 1px 5px;
  color: var(--ink-50);
}
.term-badge .demo-wave i { background: var(--blue-light); }

.term-body { padding: var(--s-6); }
.term-caption {
  font-family: var(--font-mono);
  font-size: var(--fs-label);
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
  color: var(--fg-subtle);
  margin: 0 0 var(--s-3);
}
.term-said {
  color: var(--ink-300);
  font-size: var(--fs-body);
  line-height: 1.6;
  margin: 0 0 var(--s-6);
  max-width: 60ch;
}
/* The spoken form of the things that come out written differently — the whole trick, so
   it should be visible which words did the work. */
.term-said-id {
  color: var(--ink-200);
  border-bottom: 1px dashed rgba(255,255,255,0.28);
}
.term-prompt {
  display: flex; gap: var(--s-3);
  padding: var(--s-4) var(--s-5);
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: var(--r-md);
}
.term-caret { font-family: var(--font-mono); color: var(--blue-light); flex: none; line-height: 1.6; }
.term-prompt p {
  margin: 0;
  color: var(--ink-50);
  font-size: var(--fs-body-l);
  line-height: 1.6;
  max-width: 58ch;
}
.term-prompt code, .feature code, .term-note code {
  font-family: var(--font-mono);
  font-size: 0.86em;
  background: rgba(255, 255, 255, 0.09);
  border-radius: var(--r-xs);
  padding: 1px 5px;
}
.feature code, .term-note code { background: var(--bg-muted); }

/* Matches the card above it. An earlier 62ch cap was still in play and won on source
   order, so the caption wrapped into a narrow column under a wide window. */
.term-note {
  max-width: 860px;
  margin: var(--s-4) 0 0;
  font-size: var(--fs-caption);
  color: var(--fg-muted);
}
.feature-grid-tight { margin-top: var(--s-10); }

@media (max-width: 640px) {
  .term-body { padding: var(--s-4); }
  .term-title { display: none; }
}

/* ============ signup ============ */
.cta-input {
  flex: 1 1 15em;
  min-width: 0;
  height: 44px;
  padding: 0 14px;
  font: inherit;
  font-size: 15px;
  color: var(--fg-strong);
  background: var(--bg-elevated);
  border: 1px solid var(--border-strong);
  border-radius: 6px;
}
.cta-input::placeholder { color: var(--fg-subtle); }
.cta-input:focus-visible { outline: none; border-color: var(--border-focus); box-shadow: var(--focus-ring); }
.cta-done { margin: 0; font-size: var(--fs-body); color: var(--fg-strong); }
@media (max-width: 560px) { .cta-row { flex-direction: column; align-items: stretch; } }

.signup-inline { display: flex; gap: var(--s-2); margin-top: var(--s-8); max-width: 26em; }
.signup-inline .cta-input { flex: 1 1 auto; }
@media (max-width: 560px) { .signup-inline { flex-direction: column; } }

/* ============ policy page ============ */
/* 44em rendered as 87 characters, past the 80 ceiling — em assumes an average character is
   half the type size and Geist's is nearer 0.42. 55ch is the same measure the FAQ uses,
   ~72 characters. Applies to the privacy page too, which shares this block. */
.policy { max-width: 55ch; margin-top: var(--s-8); }
.policy h3 {
  font-size: var(--fs-h3);
  font-weight: var(--fw-medium);
  margin: var(--s-10) 0 var(--s-3);
  padding-top: var(--s-4);
  border-top: 1px solid var(--border);
}
.policy h3:first-child { margin-top: 0; border-top: none; padding-top: 0; }
/* The release date sits on the version heading rather than on its own line: the two are one
   fact, and a changelog is scanned by date at least as often as by number. Mono and quiet so
   the version stays the thing the eye lands on. */
.rel-date {
  float: right;
  font-family: var(--font-mono);
  font-size: var(--fs-label);
  font-weight: var(--fw-regular);
  letter-spacing: 0.06em;
  color: var(--fg-subtle);
  padding-top: 0.55em;
}
@media (max-width: 560px) {
  /* Floated beside a wrapping heading it collides; below 560px it becomes its own line. */
  .rel-date { float: none; display: block; padding-top: var(--s-1); }
}
.policy ul { padding-left: 1.2em; margin: 0 0 var(--s-4); }
.policy p, .policy li { color: var(--fg-muted); }
.policy strong { color: var(--fg-strong); font-weight: var(--fw-medium); }
.policy ol { padding-left: 1.2em; margin: 0 0 var(--s-4); }
.policy li { margin-bottom: var(--s-3); }
.policy code {
  font-family: var(--font-mono); font-size: 0.88em;
  background: var(--bg-muted); border-radius: var(--r-xs); padding: 1px 5px;
}

/* Inline SVG rather than the  glyph: that character lives in a private-use codepoint and
   renders as a blank box on anything that is not an Apple platform — including, ironically, the
   Linux and Windows machines of people reading about a Mac app. Sized to the cap height and
   nudged up a hair, because the mark's optical centre sits below its bounding box. */
.btn-apple {
  width: 1em;
  height: 1em;
  margin-right: 2px;
  margin-top: -2px;
  flex: none;
}

/* The asterisk applies to all three figures, so it is stated once under the row rather than
   repeated three times in small grey text. */
.stat-foot {
  margin: 0 0 var(--s-6);
  font-size: var(--fs-caption);
  color: var(--fg-subtle);
  max-width: 56ch;   /* ~73 characters — see the note on .faq p */
}
.stat-label sup { color: var(--fg-subtle); font-size: 0.8em; }

/* Language switcher — one control that names the current language and opens the rest.
   A <details>, so it works with no JavaScript and is keyboard-reachable; three separate links
   crowded the header and would have wrapped it onto two lines at the fourth language.
   The tokens here are the site's own — --fg-muted, --bg-elevated, --border. The first draft invented
   --muted/--surface/--rule, none of which exist, so every declaration fell through to its hardcoded
   dark fallback and the menu stayed near-black on the light theme. */
.eh-lang { position: relative; }
.eh-lang > summary {
  list-style: none; cursor: pointer; user-select: none;
  font: inherit; color: var(--fg-muted);
  padding: 0.35rem 0.6rem; border-radius: 8px;
  display: inline-flex; align-items: center; gap: 0.35rem;
  transition: color var(--dur-base) var(--ease-standard);
}
.eh-lang > summary::-webkit-details-marker { display: none; }
.eh-lang > summary::after {
  content: ""; width: 0.4rem; height: 0.4rem; margin-top: -0.2rem;
  border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor;
  transform: rotate(45deg); opacity: 0.7;
}
.eh-lang > summary:hover,
.eh-lang[open] > summary { color: var(--fg-strong); }
.eh-lang-menu {
  position: absolute; right: 0; top: calc(100% + 0.35rem); z-index: 40;
  min-width: 8.5rem; padding: 0.3rem;
  background: var(--bg-elevated);
  border: 1px solid var(--border-strong);
  border-radius: 10px; box-shadow: 0 12px 32px rgba(0, 0, 0, 0.18);
  display: flex; flex-direction: column;
}
.eh-lang-menu a {
  padding: 0.45rem 0.6rem; border-radius: 7px;
  color: var(--fg-muted); text-decoration: none; white-space: nowrap;
}
.eh-lang-menu a:hover { background: var(--bg-subtle); color: var(--fg-strong); }
.eh-lang-menu a[aria-current="true"] { color: var(--fg-strong); font-weight: var(--fw-medium); }
