/* Heaven8 — design system
 * =========================================================================
 * Self-contained. This file is the only stylesheet the site loads — every
 * page under this domain shares it.
 *
 * Direction — "dojo": warm paper, ink, and one vermilion accent (the sumo
 * ring), with a monospace layer for anything technical. Print-manual
 * calmness rather than SaaS gradient; the mono labels are what say
 * "written by someone who reads man pages".
 *
 * Both colour schemes are first-class: every colour is a token defined on
 * bare :root and redefined under prefers-color-scheme: dark. Never give a
 * colour its only definition inside the dark block.
 * ========================================================================= */

:root {
  /* Surfaces — warm paper, never pure white */
  --paper:        #F2EDE4;
  --surface:      #FBF8F2;
  --surface-sunk: #EAE3D6;

  /* Ink */
  --ink:      #1A1815;
  --ink-2:    #5C564C;
  --ink-3:    #8C8577;

  /* Rules */
  --line:        #DED6C7;
  --line-strong: #C6BCA8;

  /* Accent — vermilion, the sumo ring */
  --accent:       #D63B22;
  --accent-deep:  #A82C16;
  --accent-wash:  rgba(214, 59, 34, 0.09);
  --accent-ink:   #FFFFFF;

  /* Secondary — indigo. The system's other hue: "shipped/verified" states
     (checkmarks, success), and any neutral control that must read as a
     distinct, clickable thing without competing with the vermilion accent,
     which is reserved for the page's one call to action. */
  --indigo:      #2C477C;
  --indigo-wash: rgba(44, 71, 124, 0.10);

  /* Depth */
  --shadow-sm: 0 1px 2px rgba(60, 45, 25, 0.05);
  --shadow-md: 0 2px 4px rgba(60, 45, 25, 0.05), 0 8px 24px rgba(60, 45, 25, 0.07);
  --shadow-lg: 0 4px 8px rgba(60, 45, 25, 0.06), 0 20px 48px rgba(60, 45, 25, 0.11);

  /* Type */
  --font-ui: -apple-system, BlinkMacSystemFont, "SF Pro Text", system-ui, "Segoe UI", Roboto, sans-serif;
  --font-display: -apple-system, BlinkMacSystemFont, "SF Pro Display", system-ui, "Segoe UI", Roboto, sans-serif;
  --font-mono: ui-monospace, "SF Mono", SFMono-Regular, Menlo, "JetBrains Mono", Consolas, monospace;

  /* Geometry */
  --radius:    14px;
  --radius-sm: 9px;
  --radius-pill: 999px;

  /* Rhythm */
  --gap:  20px;
  --pad-section: clamp(56px, 9vw, 104px);

  /* Width */
  --page-max: 1080px;
  --page-narrow: 720px;
  --measure: 640px;
  --measure-display: 960px;
}

@media (prefers-color-scheme: dark) {
  :root {
    --paper:        #131109;
    --surface:      #1C1913;
    --surface-sunk: #24211A;

    --ink:      #F4EEE2;
    --ink-2:    #A79E8B;
    --ink-3:    #7A7261;

    --line:        #2F2B22;
    --line-strong: #47412F;

    --accent:       #FF5C3D;
    --accent-deep:  #E24523;
    --accent-wash:  rgba(255, 92, 61, 0.12);
    --accent-ink:   #1A1008;

    --indigo:      #8FA9E8;
    --indigo-wash: rgba(143, 169, 232, 0.14);

    --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.4);
    --shadow-md: 0 2px 4px rgba(0, 0, 0, 0.35), 0 8px 24px rgba(0, 0, 0, 0.4);
    --shadow-lg: 0 4px 8px rgba(0, 0, 0, 0.35), 0 20px 48px rgba(0, 0, 0, 0.5);
  }
}

/* -------------------------------------------------------------------------
 * Base
 * ---------------------------------------------------------------------- */

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

html {
  overflow-x: hidden;
  scroll-behavior: smooth;
}

body {
  margin: 0;
  max-width: 100%;
  overflow-x: hidden;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-ui);
  font-size: 17px;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  overflow-wrap: break-word;
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    transition-duration: 0.001ms !important;
  }
}

::selection { background: var(--accent-wash); color: var(--ink); }

a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; text-underline-offset: 3px; }

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

img { max-width: 100%; height: auto; }

code, kbd, samp {
  font-family: var(--font-mono);
  font-size: 0.88em;
}

code {
  background: var(--surface-sunk);
  border: 1px solid var(--line);
  border-radius: 5px;
  padding: 1px 5px;
}

kbd {
  display: inline-block;
  background: var(--surface);
  border: 1px solid var(--line-strong);
  border-bottom-width: 2px;
  border-radius: 6px;
  padding: 1px 6px;
  font-size: 0.82em;
  color: var(--ink);
  white-space: nowrap;
}

hr {
  border: 0;
  border-top: 1px solid var(--line);
  margin: 40px 0;
}

/* -------------------------------------------------------------------------
 * Layout
 * ---------------------------------------------------------------------- */

.wrap {
  width: 100%;
  max-width: var(--page-max);
  margin: 0 auto;
  padding: 0 24px;
}

.wrap-narrow { max-width: var(--page-narrow); }

.section { padding: var(--pad-section) 0; }
.section + .section { padding-top: 0; }

/* The hero already carries its own bottom padding; without this the two stack
   into a gap that reads as a missing section. */
.hero + .section { padding-top: clamp(30px, 4.5vw, 58px); }

.section-rule { border-top: 1px solid var(--line); }

/* -------------------------------------------------------------------------
 * Typography
 * ---------------------------------------------------------------------- */

.display,
h1 {
  font-family: var(--font-display);
  font-size: clamp(38px, 6.4vw, 62px);
  font-weight: 780;
  letter-spacing: -0.035em;
  line-height: 1.03;
  margin: 0 0 18px;
  text-wrap: balance;
}

h2 {
  font-family: var(--font-display);
  font-size: clamp(25px, 3.3vw, 34px);
  font-weight: 700;
  letter-spacing: -0.024em;
  line-height: 1.15;
  margin: 0 0 14px;
  text-wrap: balance;
}

h3 {
  font-size: 19px;
  font-weight: 650;
  letter-spacing: -0.012em;
  line-height: 1.3;
  margin: 0 0 8px;
}

p { margin: 0 0 16px; }
p:last-child { margin-bottom: 0; }

.lead {
  font-size: clamp(18px, 2.1vw, 21px);
  line-height: 1.55;
  color: var(--ink-2);
  max-width: var(--measure);
}

/* Pairs a heading with the .lead (or .small) paragraph beneath it on one
   right edge. Add to an h1/h2 that is immediately followed by a lead
   paragraph, so the two wrap at the same point instead of the heading
   running full width while only the paragraph picks a narrower measure —
   that mismatch is what reads as an accidental line break. Whatever
   follows (buttons, grids, cards) is unaffected and keeps the section's
   full width. */
.measure {
  max-width: var(--measure);
}

/* A display headline (h1) needs a wider measure than body copy: at the h1
   clamp's top end (62px) the body .measure (640px) is only ~18ch, which
   breaks a hero headline into four lines and leaves a wide viewport's right
   half empty. Scoped to h1 specifically so h2/.lead/etc. keep the body
   measure — this selector hits only the ~7 hero <h1 class="measure">
   elements across the content tree, never the other 46 .measure uses. */
h1.measure {
  max-width: var(--measure-display);
}

.muted { color: var(--ink-2); }
.small { font-size: 14.5px; color: var(--ink-2); }

/* The mono label that runs above a heading. The leading rule is what makes
   it read as a section marker rather than as body text set small. */
.eyebrow {
  display: flex;
  align-items: center;
  gap: 10px;
  font-family: var(--font-mono);
  font-size: 11.5px;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--accent);
  margin: 0 0 14px;
}

.eyebrow::before {
  content: "";
  width: 22px;
  height: 1px;
  background: currentColor;
  flex: none;
}

.eyebrow-plain::before { display: none; }

/* -------------------------------------------------------------------------
 * Header
 * ---------------------------------------------------------------------- */

.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  background: color-mix(in srgb, var(--paper) 86%, transparent);
  -webkit-backdrop-filter: saturate(180%) blur(14px);
  backdrop-filter: saturate(180%) blur(14px);
  border-bottom: 1px solid var(--line);
}

.site-header .wrap {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  min-height: 60px;
  padding-top: 10px;
  padding-bottom: 10px;
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  color: var(--ink);
  font-weight: 650;
  letter-spacing: -0.02em;
  font-size: 16.5px;
  flex: none;
}
.brand:hover { text-decoration: none; }

.brand-sub {
  color: var(--ink-3);
  font-weight: 450;
}

/* Everything right of the brand: the language chip, the nav-toggle
   disclosure, and the nav itself. A single flex item so .site-header .wrap
   keeps its two-child space-between layout (brand left, controls right)
   regardless of what's inside. position:relative anchors .site-nav's
   mobile dropdown (below), the same way .lang-switcher anchors its own
   menu. */
.header-controls {
  position: relative;
  display: flex;
  align-items: center;
  gap: 4px;
}

/* .nav-toggle is a <details> holding nothing but the burger <summary> — no
   panel lives inside it. Closed <details> content gets hidden by the
   browser in ways that resist a plain CSS override (Chromium wraps it in
   an internal ::details-content box), so rather than fight that, .site-nav
   sits as .nav-toggle's plain sibling and is shown/hidden with an ordinary
   sibling selector keyed off the disclosure's [open] state — see the
   mobile media query below. Desktop never looks at [open] at all: .site-nav
   is just an unconditional inline row and the burger is hidden. order:1
   keeps the links to the left of the switcher chip, matching the row's
   long-standing appearance. */
.nav-toggle { order: 1; }

.nav-toggle-btn { display: none; }

.site-nav {
  order: 1;
  display: flex;
  align-items: center;
  gap: 4px;
  flex-wrap: wrap;
  justify-content: flex-end;
}

.site-nav a {
  color: var(--ink-2);
  font-size: 14.5px;
  font-weight: 500;
  padding: 6px 10px;
  border-radius: var(--radius-sm);
  white-space: nowrap;
}

.site-nav a:hover {
  color: var(--ink);
  background: var(--surface-sunk);
  text-decoration: none;
}

.site-nav a.current {
  color: var(--ink);
  background: var(--surface-sunk);
}

/* Language switcher — a details/summary disclosure, styled as a small
   coloured control (indigo — the system's secondary hue, never touched by
   the vermilion accent that the hero's own call-to-action pill already
   owns) rather than a seventh plain nav link. order:2 keeps it to the
   right of the nav links on desktop; the mobile media query below flips
   both orders so the chip sits left of the burger instead. */
.lang-switcher {
  position: relative;
  flex: none;
  order: 2;
  margin-left: 10px;
  padding-left: 10px;
}

/* The divider that separates the chip from the nav links (or, on mobile,
   from the burger) — a hairline, not a second border on the chip itself. */
.lang-switcher::before {
  content: "";
  position: absolute;
  left: 0;
  top: 50%;
  transform: translateY(-50%);
  width: 1px;
  height: 20px;
  background: var(--line);
}

.lang-switcher summary {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  list-style: none;
  cursor: pointer;
  color: var(--indigo);
  background: var(--indigo-wash);
  border: 1px solid var(--indigo);
  font-size: 14.5px;
  font-weight: 500;
  padding: 5px 10px;
  border-radius: var(--radius-sm);
  white-space: nowrap;
}

.lang-switcher-icon {
  width: 14px;
  height: 14px;
  flex: none;
  stroke: currentColor;
  stroke-width: 1.3;
  stroke-linecap: round;
  fill: none;
}

.lang-switcher summary::-webkit-details-marker { display: none; }

.lang-switcher summary::after {
  content: " ▾";
  font-size: 11px;
  color: currentColor;
  opacity: 0.75;
}

/* Deepen the same two tokens rather than reach for a third colour. */
.lang-switcher:hover summary,
.lang-switcher[open] summary {
  background: color-mix(in srgb, var(--indigo) 18%, var(--indigo-wash));
  border-color: var(--indigo);
}

.lang-switcher-menu {
  position: absolute;
  right: 0;
  top: calc(100% + 4px);
  margin: 0;
  padding: 6px;
  list-style: none;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-md);
  min-width: 11em;
  max-width: calc(100vw - 48px);
  z-index: 60;
}

.lang-switcher-menu a,
.lang-switcher-menu span[aria-current] {
  display: block;
  color: var(--ink-2);
  font-size: 14.5px;
  font-weight: 500;
  padding: 6px 10px;
  border-radius: var(--radius-sm);
  white-space: nowrap;
}

.lang-switcher-menu a:hover {
  color: var(--ink);
  background: var(--surface-sunk);
  text-decoration: none;
}

.lang-switcher-menu span[aria-current] {
  color: var(--ink);
  background: var(--surface-sunk);
}

/* Mobile header: one row (brand, chip, burger) below this width, instead of
   a THIRD nav row (the defect this fixes was four rows on a 390px phone).
   Above it, .site-nav wraps exactly as it always has, up to two rows in
   the worst case — a two-row nav on a narrow desktop window is ordinary
   and not what the burger exists to prevent. 800px is measured, not
   guessed: with the nav's own flex-wrap:wrap left alone (not forced
   nowrap) and the row's real width binary-searched in headless Chrome
   (this machine's -apple-system stack), the eight-item Russian row this is
   sized for (apps, product name, faq, changelog, support, features,
   feedback, plus the chip — the count once finsumo's features page lands,
   not the seven that exist today) needed 775px to still fit in two rows;
   774px and narrower needs a third. Rounded up to 800px. See chat-ai.md
   for the measurement. */
@media (max-width: 800px) {
  .nav-toggle { order: 2; }
  .lang-switcher { order: 1; margin-left: 0; padding-left: 0; }
  .lang-switcher::before { display: none; }

  .nav-toggle-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    color: var(--ink-2);
    border-radius: var(--radius-sm);
    cursor: pointer;
    list-style: none;
  }
  .nav-toggle-btn::-webkit-details-marker { display: none; }

  .nav-toggle:hover .nav-toggle-btn,
  .nav-toggle[open] .nav-toggle-btn {
    color: var(--ink);
    background: var(--surface-sunk);
  }

  .nav-toggle-icon { width: 19px; height: 19px; }

  /* Closed by default; shown when the nav-toggle disclosure is [open] (the
     sibling selector, not native <details> content hiding — see the note
     above .nav-toggle). Overlays the page the same way .lang-switcher-menu
     does (same anchor, background, border and shadow), rather than pushing
     content down. */
  .site-nav {
    display: none;
    flex-direction: column;
    align-items: stretch;
    position: absolute;
    right: 0;
    top: calc(100% + 4px);
    min-width: 15em;
    max-width: calc(100vw - 48px);
    padding: 6px;
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--radius-sm);
    box-shadow: var(--shadow-md);
    z-index: 60;
  }

  .nav-toggle[open] ~ .site-nav { display: flex; }

  .site-nav a { padding: 11px 12px; }
}

/* The endonym label was checked against a 390px mobile row (brand + chip +
   burger) and comfortably fits — Russian "Русский", the widest locale name
   on the site, leaves ~107px to spare there — so no two-letter fallback is
   needed. See chat-ai.md for the measurement. */

/* -------------------------------------------------------------------------
 * Hero
 * ---------------------------------------------------------------------- */

.hero {
  position: relative;
  padding: clamp(52px, 8vw, 92px) 0 clamp(40px, 6vw, 64px);
  overflow: hidden;
}

/* The dohyo: a large, very faint ring behind the hero copy. Pure decoration,
   aria-hidden at the markup level. */
.hero-ring {
  position: absolute;
  top: -18%;
  right: -14%;
  width: min(560px, 78vw);
  aspect-ratio: 1;
  border-radius: 50%;
  border: 1px solid var(--line-strong);
  opacity: 0.55;
  pointer-events: none;
}

.hero-ring::after {
  content: "";
  position: absolute;
  inset: 11%;
  border-radius: 50%;
  border: 1px dashed var(--line);
}

.hero > .wrap { position: relative; }

.hero-icon {
  width: 84px;
  height: 84px;
  border-radius: 19px;
  box-shadow: var(--shadow-md);
  margin-bottom: 22px;
  display: block;
}

.hero-cta {
  display: flex;
  align-items: center;
  gap: 14px;
  flex-wrap: wrap;
  margin-top: 30px;
}

/* -------------------------------------------------------------------------
 * Buttons
 * ---------------------------------------------------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  font-family: inherit;
  font-size: 15.5px;
  font-weight: 600;
  letter-spacing: -0.01em;
  padding: 11px 20px;
  border-radius: var(--radius-sm);
  border: 1px solid transparent;
  cursor: pointer;
  transition: transform 0.12s ease, background-color 0.12s ease, border-color 0.12s ease;
}
.btn:hover { text-decoration: none; }
.btn:active { transform: translateY(1px); }

.btn-primary {
  background: var(--accent);
  color: var(--accent-ink);
  box-shadow: var(--shadow-sm);
}
.btn-primary:hover { background: var(--accent-deep); }

.btn-ghost {
  background: transparent;
  color: var(--ink);
  border-color: var(--line-strong);
}
.btn-ghost:hover { background: var(--surface-sunk); }

.btn[disabled] { opacity: 0.55; cursor: not-allowed; }

/* App Store badge — the dark pill Apple's own badge uses, rebuilt so it
   inherits the page's radius and needs no image. */
.appstore {
  display: inline-flex;
  align-items: center;
  gap: 11px;
  background: #000;
  color: #fff;
  padding: 9px 18px 9px 15px;
  border-radius: 11px;
  border: 1px solid #000;
  box-shadow: var(--shadow-sm);
  transition: transform 0.12s ease, opacity 0.12s ease;
}
.appstore:hover { text-decoration: none; opacity: 0.88; }
.appstore:active { transform: translateY(1px); }
.appstore svg { width: 26px; height: 26px; fill: #fff; flex: none; }
.appstore-text { display: flex; flex-direction: column; line-height: 1.15; }
.appstore-text small { font-size: 10.5px; letter-spacing: 0.02em; opacity: 0.82; }
.appstore-text strong { font-size: 17px; font-weight: 600; letter-spacing: -0.02em; }

@media (prefers-color-scheme: dark) {
  .appstore { background: #fff; color: #000; border-color: #d8d2c6; }
  .appstore svg { fill: #000; }
}

/* -------------------------------------------------------------------------
 * Spec strip — the mono key/value row under a hero
 * ---------------------------------------------------------------------- */

.specs {
  display: flex;
  flex-wrap: wrap;
  gap: 0;
  margin-top: 34px;
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
}

.spec {
  flex: 1 1 150px;
  padding: 14px 18px 14px 0;
  border-right: 1px solid var(--line);
}
.spec:last-child { border-right: 0; }

.spec dt {
  font-family: var(--font-mono);
  font-size: 10.5px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-bottom: 3px;
}

.spec dd {
  margin: 0;
  font-size: 15.5px;
  font-weight: 600;
  letter-spacing: -0.01em;
}

@media (max-width: 720px) {
  .spec { flex-basis: 45%; border-right: 0; }
}

/* -------------------------------------------------------------------------
 * Spec table — a small comparison table (e.g. format sizes). Scrolls inside
 * its own wrapper on a narrow viewport rather than the page.
 * ---------------------------------------------------------------------- */

.table-wrap {
  overflow-x: auto;
  margin-top: 28px;
}

.spec-table {
  width: 100%;
  min-width: 460px;
  border-collapse: collapse;
  font-size: 15px;
}

.spec-table th,
.spec-table td {
  padding: 10px 14px;
  border-bottom: 1px solid var(--line);
  text-align: left;
  white-space: nowrap;
}

.spec-table th {
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-3);
}

.spec-table td { color: var(--ink-2); }
.spec-table td:first-child { color: var(--ink); font-weight: 600; }

.spec-table th:not(:first-child),
.spec-table td:not(:first-child) {
  text-align: right;
  font-variant-numeric: tabular-nums;
}

.spec-table tbody tr:last-child td { border-bottom: 0; }

/* -------------------------------------------------------------------------
 * Cards & grids
 * ---------------------------------------------------------------------- */

.grid {
  display: grid;
  gap: var(--gap);
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
}

.grid-2 { grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); }

.card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 24px 24px 26px;
}

.card-link {
  display: block;
  color: inherit;
  transition: border-color 0.15s ease, transform 0.15s ease, box-shadow 0.15s ease;
}
.card-link:hover {
  text-decoration: none;
  border-color: var(--line-strong);
  transform: translateY(-2px);
  box-shadow: var(--shadow-md);
}

.card h3 { margin-bottom: 6px; }
.card p { color: var(--ink-2); font-size: 15.5px; }

/* The numbered step: a mono ordinal in the accent, not a coloured circle. */
.step-num {
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.1em;
  color: var(--accent);
  display: block;
  margin-bottom: 10px;
}

/* Small square glyph slot at the top of a feature card */
.card-mark {
  width: 34px;
  height: 34px;
  border-radius: 9px;
  background: var(--accent-wash);
  color: var(--accent);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 14px;
}
.card-mark svg { width: 19px; height: 19px; stroke: currentColor; fill: none; stroke-width: 1.7; }

/* -------------------------------------------------------------------------
 * Claims list — what the app does not do
 * ---------------------------------------------------------------------- */

.claims {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 2px;
}

.claims li {
  display: flex;
  align-items: baseline;
  gap: 12px;
  padding: 11px 0;
  border-bottom: 1px solid var(--line);
  font-size: 16px;
}
.claims li:last-child { border-bottom: 0; }

.claims .mark {
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.06em;
  color: var(--accent);
  flex: none;
  min-width: 34px;
}

.claims .mark-yes { color: var(--indigo); }

.claims strong { font-weight: 620; }
.claims span.detail { color: var(--ink-2); }

/* A panel for the one honest caveat. Deliberately not styled as a warning —
   it is a statement of fact, and dressing it as an alert would read as an
   apology for it. */
.note {
  background: var(--surface-sunk);
  border: 1px solid var(--line);
  border-left: 3px solid var(--accent);
  border-radius: var(--radius-sm);
  padding: 18px 20px;
  font-size: 15.5px;
  color: var(--ink-2);
}
.note strong { color: var(--ink); font-weight: 620; }

/* -------------------------------------------------------------------------
 * Status pills
 * ---------------------------------------------------------------------- */

.pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: var(--font-mono);
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  padding: 4px 10px;
  border-radius: var(--radius-pill);
  border: 1px solid var(--line-strong);
  color: var(--ink-2);
  white-space: nowrap;
}

.pill-shipped { color: var(--indigo); border-color: var(--indigo); background: var(--indigo-wash); }
.pill-next    { color: var(--accent); border-color: var(--accent); background: var(--accent-wash); }
.pill-later   { color: var(--ink-3); }

/* -------------------------------------------------------------------------
 * Roadmap — checklist
 * A real checkbox glyph per item rather than markdown "- [ ]" text. Every
 * item here is unchecked by definition: the moment something ships it moves
 * to the features page instead of gaining a checkmark. The box's colour is
 * what carries lane meaning (soon vs. someday), not a fill state.
 * ---------------------------------------------------------------------- */

.lane { margin-bottom: 44px; }
.lane:last-child { margin-bottom: 0; }

.lane-head {
  display: flex;
  align-items: center;
  gap: 14px;
  margin-bottom: 6px;
}
.lane-head h2 { margin: 0; }

/* No max-width here: the lane's h2 is short by design (two or three
   words), so there is no companion heading edge for a capped paragraph to
   match — a narrow measure here only reads as a stray gap in front of the
   full-width checklist that follows it. */
.lane > p.small { margin-bottom: 20px; }

.checklist {
  list-style: none;
  margin: 0;
  padding: 0;
  border-top: 1px solid var(--line);
}

.checklist li {
  position: relative;
  padding: 18px 0 18px 36px;
  border-bottom: 1px solid var(--line);
}

.checklist li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 21px;
  width: 17px;
  height: 17px;
  border: 2px solid var(--line-strong);
  border-radius: 5px;
  background: var(--surface);
}

.lane-next .checklist li::before { border-color: var(--accent); }
.lane-later .checklist li::before { border-color: var(--ink-3); }

.checklist h3 { margin-bottom: 4px; }
.checklist p { color: var(--ink-2); font-size: 15.5px; margin: 0; }

/* -------------------------------------------------------------------------
 * Changelog
 * ---------------------------------------------------------------------- */

.release {
  display: grid;
  grid-template-columns: 168px 1fr;
  gap: 28px;
  padding: 30px 0;
  border-top: 1px solid var(--line);
}
.release:last-of-type { border-bottom: 1px solid var(--line); }

.release-meta { padding-top: 2px; }

.release-version {
  font-family: var(--font-display);
  font-size: 24px;
  font-weight: 720;
  letter-spacing: -0.025em;
  margin: 0 0 4px;
  line-height: 1.1;
}

.release-date {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.08em;
  color: var(--ink-3);
  text-transform: uppercase;
}

.release h3 {
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin: 20px 0 8px;
}
.release h3:first-child { margin-top: 0; }

.release ul { margin: 0; padding-left: 20px; }
.release li { margin-bottom: 8px; color: var(--ink-2); }
.release li:last-child { margin-bottom: 0; }
.release li strong { color: var(--ink); font-weight: 600; }

@media (max-width: 700px) {
  .release { grid-template-columns: 1fr; gap: 14px; }
}

/* -------------------------------------------------------------------------
 * FAQ — native <details>/<summary>, no JS
 * ---------------------------------------------------------------------- */

.faq-list { border-top: 1px solid var(--line); }

.faq-item {
  border-bottom: 1px solid var(--line);
  padding: 4px 0;
}

.faq-item summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  cursor: pointer;
  list-style: none;
  padding: 16px 0;
  font-weight: 650;
  font-size: 17px;
  letter-spacing: -0.012em;
  color: var(--ink);
}
.faq-item summary::-webkit-details-marker { display: none; }

.faq-item summary::after {
  content: "+";
  flex: none;
  font-family: var(--font-mono);
  font-size: 19px;
  font-weight: 400;
  color: var(--ink-3);
  transition: transform 0.15s ease;
}
.faq-item[open] summary::after { content: "\2212"; }

.faq-item .faq-a {
  padding: 0 0 20px;
  color: var(--ink-2);
  max-width: 66ch;
}
.faq-item .faq-a p:last-child { margin-bottom: 0; }

/* -------------------------------------------------------------------------
 * Brand mark — the Heaven8 family mark, drawn once in CSS/SVG so every
 * product under the family shares it instead of a per-app icon standing in
 * for the umbrella. currentColor + tokens keep it theme-aware for free.
 * ---------------------------------------------------------------------- */

.brand-mark { flex: none; display: block; }
.brand-mark .mark-ring {
  fill: none;
  stroke: var(--line-strong);
}
.brand-mark .mark-accent {
  fill: var(--accent);
  stroke: none;
}

.brand .brand-mark { width: 22px; height: 22px; }

.hero-mark {
  width: 72px;
  height: 72px;
  margin-bottom: 22px;
  display: block;
}

/* -------------------------------------------------------------------------
 * Long-form documents (legal, support)
 * ---------------------------------------------------------------------- */

/* Capped to the same measure as .lead/.doc-meta, and on the header
   itself rather than just the h1 — so the rule below it (the border-bottom)
   shares that right edge too. A short single-word h1 ("Roadmap", "FAQ") never
   establishes a visible edge on its own; without this the intro paragraph
   still wrapped at the measure while the rule ran the full container width,
   stranding a gutter under it. */
.doc-header {
  max-width: var(--measure);
  padding: clamp(44px, 6vw, 68px) 0 26px;
  border-bottom: 1px solid var(--line);
  margin-bottom: 36px;
}
.doc-header h1 { font-size: clamp(32px, 4.6vw, 46px); margin-bottom: 10px; }

/* Opt-in exemption for a page whose intro is a single short sentence: at that
   length there's no risk of an over-long line, so the measure above is
   only an artificial narrowing that leaves the header column short of the
   content below it. Letting both the header and its lead paragraph run the
   full container width puts every element — eyebrow, heading, intro, rule,
   and whatever's below — back on one right edge. Most .doc-header pages keep
   the measure cap because their intros are long enough to need it. */
.doc-header--full,
.doc-header--full .lead {
  max-width: none;
}

/* Opt-in for a page whose header is a heading and nothing else: with no intro
   paragraph there is nothing for the rule below the heading to close off, and
   the first section's own top border already separates the two. Two rules 36px
   apart read as a mistake, so this drops the header's. */
.doc-header--bare {
  border-bottom: 0;
  padding-bottom: 8px;
}

.doc-meta {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin: 0;
}

.doc section { margin-bottom: 34px; }
.doc section:last-child { margin-bottom: 0; }
.doc h2 { font-size: 21px; letter-spacing: -0.015em; margin-bottom: 10px; }
.doc p { color: var(--ink-2); }
.doc p strong, .doc li strong { color: var(--ink); font-weight: 620; }
.doc ul { color: var(--ink-2); padding-left: 22px; }
.doc li { margin-bottom: 8px; }

/* -------------------------------------------------------------------------
 * Forms
 * ---------------------------------------------------------------------- */

.form-card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 26px;
}

.field { margin-bottom: 16px; }

.field label {
  display: block;
  font-size: 14px;
  font-weight: 600;
  color: var(--ink);
  margin-bottom: 6px;
}

.field .hint {
  font-size: 13.5px;
  color: var(--ink-3);
  margin: 6px 0 0;
}

.field input[type="text"],
.field input[type="email"],
.field select,
.field textarea {
  width: 100%;
  font-family: inherit;
  font-size: 16px;
  line-height: 1.5;
  color: var(--ink);
  background: var(--paper);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  padding: 11px 13px;
  transition: border-color 0.12s ease, box-shadow 0.12s ease;
}

.field textarea { min-height: 168px; resize: vertical; }

.field input:focus,
.field select:focus,
.field textarea:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-wash);
}

.field input::placeholder,
.field textarea::placeholder { color: var(--ink-3); }

/* Honeypot: off-screen for humans, still fillable by a bot. */
.hp {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.form-status {
  margin-top: 14px;
  font-size: 15px;
  min-height: 24px;
}
.form-status[data-state="ok"]  { color: var(--indigo); }
.form-status[data-state="err"] { color: var(--accent); }

/* -------------------------------------------------------------------------
 * Product row (umbrella index)
 * ---------------------------------------------------------------------- */

.product {
  display: flex;
  gap: 20px;
  align-items: flex-start;
}

.product-icon {
  width: 64px;
  height: 64px;
  border-radius: 15px;
  flex: none;
  box-shadow: var(--shadow-sm);
}

.product-icon-placeholder {
  background: var(--surface-sunk);
  border: 1px dashed var(--line-strong);
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-mono);
  font-size: 21px;
  color: var(--ink-3);
  box-shadow: none;
}

.product-body { flex: 1; min-width: 0; }

.product-head {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 6px;
}
.product-head h3 { margin: 0; font-size: 20px; }

.product-links {
  margin-top: 12px;
  display: flex;
  gap: 16px;
  flex-wrap: wrap;
  font-size: 14.5px;
}

@media (max-width: 560px) {
  .product { flex-direction: column; }
}

/* -------------------------------------------------------------------------
 * Footer
 * ---------------------------------------------------------------------- */

.site-footer {
  margin-top: var(--pad-section);
  border-top: 1px solid var(--line);
  padding: 34px 0 56px;
  font-size: 14px;
  color: var(--ink-3);
}

.site-footer .wrap {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 24px;
  flex-wrap: wrap;
}

.site-footer nav {
  display: flex;
  gap: 18px;
  flex-wrap: wrap;
}

.site-footer nav a { color: var(--ink-2); }
.site-footer nav a:hover { color: var(--ink); }

.footer-note { max-width: 40ch; }

.version {
  font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
  font-size: 12px;
  margin: 12px 0 0;
  color: var(--ink-3);
}

@media (max-width: 620px) {
  .site-footer .wrap { flex-direction: column; gap: 18px; }
}

/* -------------------------------------------------------------------------
 * Utilities
 * ---------------------------------------------------------------------- */

.stack-sm > * + * { margin-top: 10px; }
.mt-32 { margin-top: 32px; }
.mt-44 { margin-top: 44px; }
.center { text-align: center; }

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

/* -------------------------------------------------------------------------
 * Screenshots
 * These are the same images the App Store listing uses, so what the page
 * shows and what the store shows can never drift apart.
 * ---------------------------------------------------------------------- */

.shot {
  margin: 44px 0 0;
  border-radius: var(--radius);
  overflow: hidden;
  border: 1px solid var(--line-strong);
  background: var(--surface-sunk);
  box-shadow: var(--shadow-lg);
  line-height: 0;
}

.shot img { width: 100%; display: block; }

.shot figcaption {
  line-height: 1.5;
  font-family: var(--font-mono);
  font-size: 11.5px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-3);
  background: var(--surface);
  border-top: 1px solid var(--line);
  padding: 11px 16px;
}

.gallery {
  display: grid;
  gap: var(--gap);
  grid-template-columns: repeat(2, minmax(0, 1fr));
  margin-top: 32px;
}

@media (max-width: 720px) {
  .gallery { grid-template-columns: 1fr; }
}

.gallery .shot { margin: 0; box-shadow: var(--shadow-md); }

/* Three-up variant: caps at ~980px so three portrait phone shots stay a sensible
   size on desktop (~310px each), drops to two columns before .gallery's own
   720px breakpoint would otherwise cram three into too little space. */
.gallery-3 {
  max-width: 980px;
  grid-template-columns: repeat(3, minmax(0, 1fr));
}

@media (max-width: 900px) {
  .gallery-3 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 720px) {
  .gallery-3 { grid-template-columns: 1fr; }
}

/* -------------------------------------------------------------------------
 * Wide viewports
 * ---------------------------------------------------------------------- */

@media (min-width: 1280px) {
  :root { --page-max: 1180px; }
}

@media (min-width: 1680px) {
  :root { --page-max: 1360px; }
}

@media (min-width: 2200px) {
  :root { --page-max: 1520px; }
}
