/* Molvi — public site.
   One stylesheet, no build step. The world is the product's own artifact: a take
   read back with the analysis marked over it. Paper ground, ink text, and the
   report's four measured highlight fills used at page scale.

   Tokens are lifted from mlv_frontend/src/styles.css, which documents the
   measured contrast behind each pair. What is dropped here: the Telegram theme
   variables. Inside the Mini App the client owns the palette; on the open web we
   do, so every value below is fixed. */

/* ---- Nunito, self-hosted ----
   Same reasoning as the app: fonts.gstatic.com is unreliable from Russia, and
   with `display: swap` the outcome there is no brand face at all rather than a
   slow one. One variable file per subset, 400-800 out of each. */
@font-face {
  font-family: "Nunito";
  font-style: normal;
  font-weight: 400 800;
  font-display: swap;
  src: url("/fonts/nunito-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "Nunito";
  font-style: normal;
  font-weight: 400 800;
  font-display: swap;
  src: url("/fonts/nunito-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

:root {
  /* ---- Ground and ink ----
     Paper, because the world is a marked-up transcript and a mark needs paper.
     --surface is the raised white of a phone screen sitting on that paper. */
  --paper: #f8f6f2;
  --surface: #ffffff;
  --ink: #0f2b40;
  /* Body-weight secondary. Measures 6.3:1 on --paper, 6.7:1 on --surface. The
     app's lesson: secondary text is tinted from the foreground, never greyed. */
  --ink-2: #4c5d6b;
  /* Decorative only — hairlines and dividers. Never carries words. */
  --line: #e3ded6;
  --line-strong: #cdc6bb;

  /* Molvi's accent, unchanged from the app. #1d6ca7 puts white-on-accent at
     5.59:1; the old #2ea6ff measured 2.62:1 on the primary CTA of every screen. */
  --accent: #1d6ca7;
  /* The accent AS TEXT, pulled toward the ink until it is readable on paper. */
  --accent-ink: #14527f;

  /* ---- The four highlight fills ----
     Straight from mlv_frontend/src/report/spans.tsx: one fill per span group,
     opaque rather than translucent so their contrast is knowable. These are the
     saturated material of this page, used as whole-region washes as well as
     inline marks. */
  --good-fg: #0b5730;
  --good-bg: #c3e9d2;
  --auth-fg: #5f2480;
  --auth-bg: #e7cff5;
  --info-fg: #0b4f86;
  --info-bg: #cfe4f7;
  --warn-fg: #6e3f00;
  --warn-bg: #fbe0a8;
  --mute-fg: #3f4954;
  --mute-bg: #dbe0e7;
  /* The one place red survives, and it is not a verdict: a filler word struck
     out. docs/feedback-tone.md — the verdict scale has no red. */
  --cut-fg: #97211b;
  --cut-bg: #f8cdc9;
  /* The app's «done» green, fixed in both themes there and here. */
  --done: #22c55e;

  /* ---- Type ----
     The app's six steps, plus the two display steps a page needs that a 390px
     Mini App never did. */
  --fs-xs: 0.75rem;
  --fs-sm: 0.875rem;
  --fs-md: 1rem;
  --fs-lg: 1.125rem;
  --fs-xl: 1.375rem;
  --fs-2xl: clamp(1.5rem, 1.1rem + 1.6vw, 1.875rem);
  --fs-3xl: clamp(1.875rem, 1.2rem + 3vw, 2.75rem);
  --fs-4xl: clamp(2.375rem, 1.2rem + 5.2vw, 4.25rem);

  /* ---- Radii ---- */
  --r-xs: 4px; /* inline marks over a transcript, as in the app */
  --r-sm: 8px;
  --r-md: 12px;
  --r-lg: 16px;
  --r-xl: 24px;
  --r-full: 999px;

  /* ---- Rhythm ----
     One scale. More space above a heading than below it, everywhere. */
  --s-1: 0.25rem;
  --s-2: 0.5rem;
  --s-3: 0.75rem;
  --s-4: 1rem;
  --s-5: 1.5rem;
  --s-6: 2rem;
  --s-7: 3rem;
  --s-8: 4.5rem;
  --s-9: 6.5rem;

  --measure: 66ch;
  --page: 1140px;

  /* ---- Motion ----
     The app's curves. ease-in is never used: it delays the first frame, the one
     the eye is on. */
  --ease-out: cubic-bezier(0.23, 1, 0.32, 1);
  --d-fast: 160ms;
  --d-base: 200ms;

  /* Offset and blur, never a zero-offset halo. */
  --lift: 0 1px 2px rgba(15, 43, 64, 0.05), 0 10px 28px rgba(15, 43, 64, 0.09);
  --lift-sm: 0 1px 2px rgba(15, 43, 64, 0.06), 0 4px 12px rgba(15, 43, 64, 0.07);
}

/* ---- Reset, kept to what this page actually uses ---- */
*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  /* The scroll target must clear the sticky header. */
  scroll-padding-top: 5rem;
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: "Nunito", ui-sans-serif, system-ui, sans-serif;
  font-size: var(--fs-lg);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

h1,
h2,
h3,
h4 {
  margin: 0;
  font-weight: 800;
  line-height: 1.08;
  letter-spacing: -0.025em;
  text-wrap: balance;
}

p {
  margin: 0;
}

ul,
ol {
  margin: 0;
  padding: 0;
}

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

/* ---- Browser surfaces: the parts we did not draw still carry the design ---- */
::selection {
  /* Selecting text on a page about marking up text should use the page's own
     highlighter. */
  background: var(--good-bg);
  color: var(--good-fg);
}

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

html {
  scrollbar-color: var(--line-strong) var(--paper);
  scrollbar-width: thin;
}

::-webkit-scrollbar {
  width: 12px;
  height: 12px;
}

::-webkit-scrollbar-track {
  background: var(--paper);
}

::-webkit-scrollbar-thumb {
  background: var(--line-strong);
  border: 3px solid var(--paper);
  border-radius: var(--r-full);
}

::-webkit-scrollbar-thumb:hover {
  background: var(--ink-2);
}

a {
  color: var(--accent-ink);
  text-decoration-thickness: 1.5px;
  text-underline-offset: 0.18em;
}

a:hover {
  text-decoration-thickness: 2px;
}

/* ---- The signature: a mark over the words ----
   Same construction as the app's spans — opaque fill, small radius, cloned
   across line breaks so a wrapped phrase stays one mark. */
.mk {
  --mk-fill: var(--good-bg);
  border-radius: var(--r-xs);
  /* Horizontal padding is pulled back out as negative margin: a mark that widens
     the line pushes the following full stop away from the word, and the gap reads
     as a typo. */
  padding: 0.06em 0.14em;
  margin: 0 -0.14em;
  -webkit-box-decoration-break: clone;
  box-decoration-break: clone;
  background-color: var(--mk-fill);
  color: var(--good-fg);
}

.mk--auth {
  --mk-fill: var(--auth-bg);
  color: var(--auth-fg);
}

.mk--info {
  --mk-fill: var(--info-bg);
  color: var(--info-fg);
}

.mk--warn {
  --mk-fill: var(--warn-bg);
  color: var(--warn-fg);
}

/* A word to delete. Not a verdict on the take — the one surviving red. */
.mk--cut {
  background: none;
  color: var(--cut-fg);
  text-decoration: line-through 2px;
  text-decoration-color: var(--cut-fg);
  padding: 0;
  margin: 0;
}

/* The authored moment: the marks paint themselves in, left to right, the way the
   analysis lands on a take. The word is legible before, during and after — only
   the fill grows, so nothing is hidden waiting for motion. */
@keyframes mark-in {
  from {
    background-position: 100% 0;
  }
  to {
    background-position: 0% 0;
  }
}

/* The fill is painted as a background IMAGE, not with an absolutely positioned
   pseudo-element: these marks wrap mid-sentence, and an inline box's abs-positioned
   child collapses to a sliver across line fragments. A gradient behind the text
   grows per fragment and needs no extra element. */
/* A gradient twice the box's width — fill on the left half, nothing on the right —
   slid into place. `background-position` is animated rather than `background-size`:
   Chromium finishes a percentage size animation without applying its forwards
   fill, so the mark ended the run unpainted. Position also makes the resting state
   the painted one, which is what a client with no animation support must get. */
.mk--anim {
  background-color: transparent;
  background-image: linear-gradient(
    to right,
    var(--mk-fill) 0 50%,
    transparent 50% 100%
  );
  background-repeat: no-repeat;
  background-size: 200% 100%;
  background-position: 0 0;
  animation: mark-in 620ms var(--ease-out) both;
  animation-delay: var(--mk-delay, 0ms);
}

/* One orchestrated moment across the first viewport: the headline's mark, then
   the take's three, in the order a reader gets to them. */
.mk--d1 {
  --mk-delay: 240ms;
}
.mk--d2 {
  --mk-delay: 760ms;
}
.mk--d3 {
  --mk-delay: 1000ms;
}
.mk--d4 {
  --mk-delay: 1240ms;
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
  .mk--anim {
    animation: none;
  }
}

/* ---- Layout ---- */
.band {
  padding: var(--s-8) var(--s-5);
}

.band--tight {
  padding: var(--s-7) var(--s-5);
}

.wrap {
  max-width: var(--page);
  margin: 0 auto;
}

.wrap--narrow {
  max-width: 760px;
  margin: 0 auto;
}

/* Whole-region washes. The colour owns the band, rather than being sprinkled as
   accents over a neutral page. */
.band--info {
  background: var(--info-bg);
}

.band--good {
  background: var(--good-bg);
}

.band--ink {
  background: var(--ink);
  color: var(--surface);
}

.band--ink h2,
.band--ink h3 {
  color: var(--surface);
}

/* On ink, secondary text is tinted from the ink's own hue, not greyed. */
.band--ink .lede,
.band--ink .note,
.band--ink li {
  color: #c3d3de;
}

.band--info .lede,
.band--good .lede {
  color: #2c4655;
}

.lede {
  max-width: var(--measure);
  color: var(--ink-2);
  font-size: var(--fs-lg);
}

.note {
  font-size: var(--fs-sm);
  color: var(--ink-2);
}

h2 {
  font-size: var(--fs-3xl);
  max-width: 26ch;
}

/* A reading column inside the full-width wrap, so prose and the FAQ start on the
   same left edge as every other section instead of floating to the middle. */
.col {
  max-width: 820px;
}

/* .col is always a child of .wrap, never a second class on it: sharing one element
   let its 820px win the max-width cascade while .wrap's `margin: 0 auto` stayed,
   which centred prose that has to start on the page's left edge. */

.pt-0 {
  padding-top: 0;
}

.mt-5 {
  margin-top: var(--s-5);
}

.mt-6 {
  margin-top: var(--s-6);
}

/* Matches an h2 wherever it sits in a band: the child-combinator version missed
   every section whose heading lives inside a .col reading column, and those
   headings sat flush against their own lede. */
.band h2 {
  margin-bottom: var(--s-4);
}

h3 {
  font-size: var(--fs-xl);
}

/* ---- Header ---- */
.top {
  position: sticky;
  top: 0;
  z-index: 20;
  padding: var(--s-3) var(--s-5);
  background: color-mix(in srgb, var(--paper) 88%, transparent);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--line);
}

/* The wordmark has to sit on the same left edge as the headline under it. Without
   its own wrap the header ran full-bleed while the page centred at --page, and the
   logo missed the H1 by 130px at 1440. */
.top-in {
  max-width: var(--page);
  margin: 0 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-4);
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-size: var(--fs-xl);
  font-weight: 800;
  letter-spacing: -0.03em;
  color: var(--ink);
  text-decoration: none;
}

/* The wordmark carries the page's own gesture: the product's name, marked. */
.brand > span {
  background: var(--good-bg);
  border-radius: var(--r-xs);
  padding: 0.02em 0.2em;
}

.top nav {
  display: flex;
  align-items: center;
  gap: var(--s-5);
}

.top nav a:not(.btn) {
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--ink-2);
  text-decoration: none;
}

.top nav a:not(.btn):hover {
  color: var(--ink);
}

/* Below this the two text links and the button fight for the same 340px and all
   three wrap. The button is the one that has to survive. */
@media (max-width: 640px) {
  .top nav a:not(.btn) {
    display: none;
  }
  .top .btn {
    white-space: nowrap;
  }
}

/* ---- Buttons ---- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  padding: 0.75rem 1.375rem;
  border-radius: var(--r-full);
  border: 1.5px solid transparent;
  font: inherit;
  font-size: var(--fs-md);
  font-weight: 700;
  line-height: 1.2;
  text-decoration: none;
  cursor: pointer;
  transition: transform var(--d-fast) var(--ease-out),
    box-shadow var(--d-fast) var(--ease-out),
    background-color var(--d-fast) var(--ease-out);
}

.btn--primary {
  background: var(--ink);
  color: var(--surface);
  box-shadow: var(--lift-sm);
}

.btn--primary:hover {
  background: #16394f;
  box-shadow: var(--lift);
  transform: translateY(-1px);
}

.btn--primary:active {
  transform: translateY(0);
  box-shadow: var(--lift-sm);
}

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

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

/* Inverted, for the ink bands. */
.band--ink .btn--primary {
  background: var(--surface);
  color: var(--ink);
}

.band--ink .btn--primary:hover {
  background: #eef2f5;
}

.band--ink .btn--ghost {
  border-color: #47637a;
  color: var(--surface);
}

.band--ink .btn--ghost:hover {
  border-color: var(--surface);
  background: rgba(255, 255, 255, 0.08);
}

.btn--sm {
  padding: 0.5rem 1rem;
  font-size: var(--fs-sm);
}

.btn-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-3);
  align-items: center;
}

/* ---- Hero ---- */
.hero {
  padding: var(--s-6) var(--s-5) var(--s-7);
}

@media (min-width: 700px) {
  .hero {
    padding-top: var(--s-8);
  }
}

.hero-grid {
  max-width: var(--page);
  margin: 0 auto;
  display: grid;
  /* Explicit even in the one-column case: an implicit auto column takes its width
     from the phone's fixed 320px and stops being able to shrink, which pushed the
     whole section past a 320px viewport. minmax(0, 1fr) lets it. */
  grid-template-columns: minmax(0, 1fr);
  gap: var(--s-6);
  align-items: start;
}

@media (min-width: 900px) {
  .hero-grid {
    grid-template-columns: minmax(0, 1fr) minmax(0, 0.85fr);
    gap: var(--s-6);
    align-items: center;
  }
}

.hero h1 {
  font-size: var(--fs-4xl);
  max-width: 18ch;
  /* Looser than the global 1.08: a filled mark on one line is a solid block, and
     at 1.08 its top edge cut through the descenders of the line above. */
  line-height: 1.16;
}

/* At display size a 4px radius reads as a square corner. The mark keeps its
   proportion instead of its pixel value. */
.hero h1 .mk {
  border-radius: var(--r-sm);
  padding-block: 0.01em;
}

.hero-price {
  margin-top: var(--s-4);
  font-size: var(--fs-2xl);
  font-weight: 700;
  line-height: 1.25;
  letter-spacing: -0.02em;
  color: var(--accent-ink);
  max-width: 24ch;
}

.hero .lede {
  margin-top: var(--s-4);
}

.hero .btn-row {
  margin-top: var(--s-5);
}

.hero-fine {
  margin-top: var(--s-4);
  font-size: var(--fs-sm);
  color: var(--ink-2);
  max-width: 46ch;
}

/* ---- The take: the product's own artifact, at page scale ----
   Not a screenshot and not a device photo. The thing Molvi makes is a take read
   back with marks over it, so the page shows exactly that, in the app's own
   type and fills. */
.take {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-xl);
  box-shadow: var(--lift);
  padding: var(--s-5);
  overflow: hidden;
}

.take-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-3);
  padding-bottom: var(--s-3);
  border-bottom: 1px solid var(--line);
  margin-bottom: var(--s-4);
}

.take-title {
  display: flex;
  align-items: center;
  gap: 0.625rem;
  font-size: var(--fs-md);
  font-weight: 700;
}

.take-emoji {
  width: 2rem;
  height: 2rem;
  border-radius: var(--r-sm);
  background: var(--info-bg);
  display: grid;
  place-items: center;
  font-size: 1rem;
  line-height: 1;
}

.take-when {
  flex: none;
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--ink-2);
  font-variant-numeric: tabular-nums;
}

.take-body {
  font-size: var(--fs-md);
  line-height: 1.75;
}

.take-body p + p {
  margin-top: var(--s-3);
}

/* A pause, measured. The app prints the seconds rather than a metaphor. */
.pause {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  vertical-align: baseline;
  font-size: var(--fs-xs);
  font-weight: 700;
  padding: 0.05em 0.4em;
  border-radius: var(--r-full);
  background: var(--mute-bg);
  color: var(--mute-fg);
  font-variant-numeric: tabular-nums;
}

.take-foot {
  margin-top: var(--s-4);
  padding-top: var(--s-4);
  border-top: 1px solid var(--line);
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2);
}

/* The legend, which is also the chip vocabulary of the whole page. */
.chip {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  font-size: var(--fs-xs);
  font-weight: 600;
  padding: 0.25rem 0.625rem;
  border-radius: var(--r-sm);
  background: var(--mute-bg);
  color: var(--mute-fg);
}

.chip--good {
  background: var(--good-bg);
  color: var(--good-fg);
}
.chip--auth {
  background: var(--auth-bg);
  color: var(--auth-fg);
}
.chip--info {
  background: var(--info-bg);
  color: var(--info-fg);
}
.chip--warn {
  background: var(--warn-bg);
  color: var(--warn-fg);
}
.chip--accent {
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  color: var(--accent-ink);
}

/* ---- Facts: a line of them, hairline-separated, not four identical cards ---- */
.facts {
  max-width: var(--page);
  margin: 0 auto;
  display: grid;
  gap: 0;
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
}

@media (min-width: 700px) {
  .facts {
    grid-auto-flow: column;
    grid-auto-columns: 1fr;
  }
}

.fact {
  padding: var(--s-4) var(--s-4);
  border-bottom: 1px solid var(--line);
}

.fact:last-child {
  border-bottom: none;
}

@media (min-width: 700px) {
  .fact {
    border-bottom: none;
    border-left: 1px solid var(--line);
  }
  .fact:first-child {
    border-left: none;
    padding-left: 0;
  }
}

.fact b {
  display: block;
  font-size: var(--fs-md);
  font-weight: 800;
  letter-spacing: -0.01em;
}

.fact span {
  font-size: var(--fs-sm);
  color: var(--ink-2);
}

/* ---- Plain prose: the paragraph that says what this is ---- */
.plain {
  font-size: var(--fs-lg);
  max-width: var(--measure);
}

.plain + .plain {
  margin-top: var(--s-4);
}

/* ---- The report, opened up ---- */
.report {
  background: var(--surface);
  border-radius: var(--r-xl);
  border: 1px solid var(--line);
  box-shadow: var(--lift);
  overflow: hidden;
}

.report-tabs {
  display: flex;
  gap: var(--s-1);
  padding: var(--s-3) var(--s-4) 0;
  overflow-x: auto;
  border-bottom: 1px solid var(--line);
  scrollbar-width: none;
}

.report-tabs::-webkit-scrollbar {
  display: none;
}

.report-tab {
  flex: none;
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--ink-2);
  padding: 0.5rem 0.75rem;
  border-bottom: 2px solid transparent;
  white-space: nowrap;
}

.report-tab--on {
  color: var(--ink);
  border-bottom-color: var(--accent);
}

.report-panes {
  display: grid;
  gap: 0;
}

@media (min-width: 860px) {
  .report-panes {
    grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr);
  }
}

.report-pane {
  padding: var(--s-5);
}

@media (min-width: 860px) {
  .report-pane + .report-pane {
    border-left: 1px solid var(--line);
  }
}

@media (max-width: 859px) {
  .report-pane + .report-pane {
    border-top: 1px solid var(--line);
  }
}

.pane-label {
  font-size: var(--fs-xs);
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-2);
  margin-bottom: var(--s-3);
}

.pane-label + * {
  margin-top: 0;
}

.feedback-list {
  list-style: none;
  display: grid;
  gap: var(--s-3);
  font-size: var(--fs-md);
  line-height: 1.55;
}

.feedback-list li {
  display: grid;
  grid-template-columns: 1.25rem 1fr;
  gap: 0.625rem;
  align-items: start;
}

.feedback-list svg {
  margin-top: 0.3em;
  flex: none;
}

.tick {
  color: var(--good-fg);
}

.arrow {
  color: var(--accent-ink);
}

/* «Say it better» — was / better, the pair the app puts side by side. */
.better {
  margin-top: var(--s-5);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  overflow: hidden;
  font-size: var(--fs-md);
}

.better-row {
  padding: var(--s-3) var(--s-4);
}

.better-row + .better-row {
  border-top: 1px solid var(--line);
}

.better-row--was {
  background: color-mix(in srgb, var(--mute-bg) 45%, var(--surface));
}

.better-row--to {
  background: color-mix(in srgb, var(--good-bg) 40%, var(--surface));
}

.better-row b {
  display: block;
  font-size: var(--fs-xs);
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-2);
  margin-bottom: var(--s-1);
}

/* ---- The catalog, as the app draws it ----
   These rows are the app's `.ex-card`: emoji tile, name, hook, metric chips,
   duration. Reproduced rather than reinvented, so what the page promises and
   what opens in Telegram are the same object. */
.cards {
  list-style: none;
  display: grid;
  gap: var(--s-3);
  margin-top: var(--s-6);
}

@media (min-width: 800px) {
  .cards {
    grid-template-columns: 1fr 1fr;
    gap: var(--s-4);
  }
}

.card {
  display: flex;
  align-items: flex-start;
  gap: var(--s-3);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  padding: var(--s-4);
  box-shadow: var(--lift-sm);
}

.card-tile {
  width: 3.5rem;
  height: 3.5rem;
  flex: none;
  border-radius: var(--r-md);
  display: grid;
  place-items: center;
  font-size: 1.75rem;
  line-height: 1;
}

.card-body {
  min-width: 0;
  display: grid;
  gap: var(--s-2);
}

.card-body h3 {
  font-size: var(--fs-lg);
  font-weight: 700;
  letter-spacing: -0.015em;
}

.card-body p {
  font-size: var(--fs-sm);
  color: var(--ink-2);
  line-height: 1.5;
}

.card-meta {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2);
  align-items: center;
}

/* ---- Steps: numbered because the order is the information ---- */
.steps {
  list-style: none;
  counter-reset: step;
  display: grid;
  gap: var(--s-5);
  margin-top: var(--s-6);
}

@media (min-width: 820px) {
  .steps {
    grid-template-columns: repeat(3, 1fr);
    gap: var(--s-6);
  }
}

.steps li {
  counter-increment: step;
  padding-top: var(--s-4);
  border-top: 2px solid var(--ink);
}

.steps li::before {
  content: counter(step);
  display: block;
  font-size: var(--fs-xl);
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  line-height: 1;
  margin-bottom: var(--s-3);
}

.steps h3 {
  font-size: var(--fs-lg);
  margin-bottom: var(--s-2);
}

.steps p {
  font-size: var(--fs-md);
  color: var(--ink-2);
  line-height: 1.55;
}

.band--ink .steps p {
  color: #c3d3de;
}

/* ---- Price ---- */
.plans {
  display: grid;
  gap: var(--s-4);
  margin-top: var(--s-6);
}

@media (min-width: 760px) {
  .plans {
    grid-template-columns: 1fr 1fr;
    gap: var(--s-5);
  }
}

.plan {
  border: 1px solid #37536a;
  border-radius: var(--r-lg);
  padding: var(--s-5);
  display: grid;
  gap: var(--s-2);
  align-content: start;
}

.plan--pick {
  border-color: var(--surface);
  background: rgba(255, 255, 255, 0.06);
}

.plan-name {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  font-size: var(--fs-md);
  font-weight: 700;
  letter-spacing: 0.02em;
  text-transform: uppercase;
}

.plan-amount {
  font-size: var(--fs-3xl);
  font-weight: 800;
  letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;
  line-height: 1.1;
}

.plan-amount small {
  font-size: var(--fs-lg);
  font-weight: 700;
  letter-spacing: -0.01em;
  color: #c3d3de;
}

.plan-sub {
  font-size: var(--fs-sm);
  color: #c3d3de;
  font-variant-numeric: tabular-nums;
}

.terms {
  list-style: none;
  display: grid;
  gap: var(--s-3);
  margin-top: var(--s-6);
  font-size: var(--fs-md);
}

@media (min-width: 760px) {
  .terms {
    grid-template-columns: 1fr 1fr;
    column-gap: var(--s-7);
  }
}

.terms li {
  display: grid;
  grid-template-columns: 1.25rem 1fr;
  gap: 0.625rem;
  align-items: start;
  line-height: 1.5;
}

.terms svg {
  margin-top: 0.32em;
  flex: none;
  color: #7fd1a2;
}

/* ---- FAQ ---- */
.faq {
  margin-top: var(--s-6);
  border-top: 1px solid var(--line);
}

.faq details {
  border-bottom: 1px solid var(--line);
}

.faq summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-4);
  padding: var(--s-4) 0;
  font-size: var(--fs-lg);
  font-weight: 700;
  letter-spacing: -0.015em;
  cursor: pointer;
  list-style: none;
}

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

.faq summary::after {
  content: "";
  flex: none;
  width: 0.75rem;
  height: 0.75rem;
  border-right: 2px solid var(--ink-2);
  border-bottom: 2px solid var(--ink-2);
  transform: rotate(45deg) translateY(-2px);
  transition: transform var(--d-base) var(--ease-out);
}

.faq details[open] summary::after {
  transform: rotate(225deg) translateY(-2px);
}

.faq summary:hover {
  color: var(--accent-ink);
}

.faq-answer {
  padding: 0 0 var(--s-5);
  max-width: var(--measure);
  font-size: var(--fs-md);
  color: var(--ink-2);
  line-height: 1.6;
}

.faq-answer p + p {
  margin-top: var(--s-3);
}

/* ---- Close ---- */
.close {
  text-align: center;
}

.close h2 {
  max-width: 26ch;
  margin: 0 auto var(--s-4);
  font-size: var(--fs-3xl);
}

.close .lede {
  margin: 0 auto;
}

.close .btn-row {
  justify-content: center;
  margin-top: var(--s-5);
}

.close .note {
  margin: var(--s-5) auto 0;
  max-width: 56ch;
}

/* ---- Footer ---- */
.foot {
  background: var(--ink);
  color: #c3d3de;
  padding: var(--s-7) var(--s-5) var(--s-6);
  font-size: var(--fs-sm);
}

.foot a {
  color: var(--surface);
  text-decoration: none;
}

.foot a:hover {
  text-decoration: underline;
}

.foot-grid {
  max-width: var(--page);
  margin: 0 auto;
  display: grid;
  gap: var(--s-5);
}

@media (min-width: 760px) {
  .foot-grid {
    grid-template-columns: minmax(0, 1.2fr) repeat(2, minmax(0, 1fr));
    gap: var(--s-6);
  }
}

.foot .brand {
  color: var(--surface);
  margin-bottom: var(--s-3);
}

.foot .brand > span {
  background: rgba(255, 255, 255, 0.16);
  color: var(--surface);
}

.foot h4 {
  font-size: var(--fs-xs);
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: #8ba6b8;
  margin-bottom: var(--s-3);
}

.foot ul {
  list-style: none;
  display: grid;
  gap: var(--s-2);
}

.foot-legal {
  max-width: var(--page);
  margin: var(--s-6) auto 0;
  padding-top: var(--s-4);
  border-top: 1px solid #2b4a60;
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2) var(--s-5);
  justify-content: space-between;
  font-size: var(--fs-xs);
  color: #8ba6b8;
}

/* A value the founder must replace before this site goes live. Loud on purpose:
   a placeholder that reads like copy is a placeholder that ships. */
.todo {
  background: var(--warn-bg);
  color: var(--warn-fg);
  border-radius: var(--r-xs);
  padding: 0.05em 0.35em;
  font-weight: 700;
  font-size: 0.95em;
}

.foot .todo {
  background: #ffd166;
  color: #4a2c00;
}

/* ---- Legal pages ---- */
/* The reading column is capped at 760px, but the page box stays --page wide so the
   text starts on the same left edge as the wordmark in the header above it. A
   centred 760px column put the two ~150px apart. */
.doc {
  /* --page plus its own gutters, so the content edge lands where .top-in's does
     rather than 24px inside it. */
  max-width: calc(var(--page) + var(--s-5) * 2);
  margin: 0 auto;
  padding: var(--s-7) var(--s-5) var(--s-8);
}

.doc > * {
  max-width: 760px;
}

.doc h1 {
  font-size: var(--fs-3xl);
  max-width: 24ch;
}

.doc-meta {
  margin-top: var(--s-3);
  font-size: var(--fs-sm);
  color: var(--ink-2);
}

.doc h2 {
  font-size: var(--fs-xl);
  max-width: 34ch;
  margin-top: var(--s-7);
  margin-bottom: var(--s-3);
}

.doc h3 {
  font-size: var(--fs-lg);
  margin-top: var(--s-5);
  margin-bottom: var(--s-2);
}

.doc p,
.doc li {
  font-size: var(--fs-md);
  line-height: 1.65;
  max-width: var(--measure);
}

.doc p + p,
.doc ul + p,
.doc ol + p,
.doc table + p,
.doc .doc-scroll + p {
  margin-top: var(--s-4);
}

.doc ul,
.doc ol {
  margin-top: var(--s-3);
  padding-left: 1.25rem;
  display: grid;
  gap: var(--s-2);
}

.doc ul {
  list-style: disc;
}

.doc ol {
  list-style: decimal;
}

.doc table {
  width: 100%;
  margin-top: var(--s-4);
  border-collapse: collapse;
  font-size: var(--fs-sm);
  font-variant-numeric: tabular-nums;
}

.doc caption {
  text-align: left;
  font-size: var(--fs-sm);
  color: var(--ink-2);
  padding-bottom: var(--s-2);
}

.doc th,
.doc td {
  text-align: left;
  padding: var(--s-3) var(--s-3) var(--s-3) 0;
  border-bottom: 1px solid var(--line);
  vertical-align: top;
}

.doc th {
  font-weight: 800;
  font-size: var(--fs-xs);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-2);
}

.doc-scroll {
  overflow-x: auto;
}

/* The one thing a legal page must never bury. */
.callout {
  margin-top: var(--s-5);
  padding: var(--s-4) var(--s-5);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-md);
  background: var(--surface);
}

.callout p {
  max-width: none;
}

.back {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  font-size: var(--fs-sm);
  font-weight: 700;
  color: var(--ink-2);
  text-decoration: none;
  margin-bottom: var(--s-5);
}

.back:hover {
  color: var(--ink);
}

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

/* ---- What most apps train vs what this trains ----
   One light half, one ink half. The dark side is the claim, so it carries the
   page's only inverted panel outside the ink bands. */
.versus {
  display: grid;
  gap: var(--s-4);
  margin-top: var(--s-6);
}

@media (min-width: 860px) {
  .versus {
    grid-template-columns: 1fr 1fr;
    gap: var(--s-5);
  }
}

.versus > div {
  border-radius: var(--r-lg);
  padding: var(--s-5);
}

.versus-them {
  background: color-mix(in srgb, var(--mute-bg) 40%, var(--surface));
  border: 1px solid var(--line);
}

.versus-us {
  background: var(--ink);
  color: var(--surface);
}

.versus h3 {
  font-size: var(--fs-md);
  font-weight: 800;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  margin-bottom: var(--s-4);
}

.versus-us h3 {
  color: var(--surface);
}

.versus ul {
  list-style: none;
  display: grid;
  gap: var(--s-4);
  font-size: var(--fs-md);
  line-height: 1.5;
}

.versus-them li {
  color: var(--ink-2);
}

.versus-us li {
  color: #dce7ef;
}

.versus li b {
  color: var(--ink);
  font-weight: 700;
}

.versus-us li b {
  color: var(--surface);
}

/* ---- What the research supports ----
   Citations at reading size, not fine print: a claim hidden in 12px is a claim
   nobody checks. The caveat that follows them is the same size as they are. */
.research {
  list-style: none;
  margin-top: var(--s-5);
  max-width: var(--measure);
  display: grid;
  gap: var(--s-4);
  font-size: var(--fs-md);
  line-height: 1.55;
}

.research li {
  padding-left: var(--s-4);
  border-left: 1px solid var(--line-strong);
}

.research cite {
  display: block;
  margin-top: var(--s-1);
  font-style: normal;
  font-size: var(--fs-sm);
  color: var(--ink-2);
}

/* ---- Image slots ----
   Reserved dimensions, so dropping a real file in never shifts the layout. */
.shot {
  margin: 0;
  border-radius: var(--r-lg);
  overflow: hidden;
  background: var(--mute-bg);
  border: 1px solid var(--line);
}

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

.shot figcaption {
  padding: var(--s-3) var(--s-4);
  font-size: var(--fs-sm);
  color: var(--ink-2);
  background: var(--surface);
  border-top: 1px solid var(--line);
}

/* ---- The phone ----
   Construction mirrored from the pinned reference: one element, `overflow: hidden`,
   and the bezel drawn entirely with layered box-shadow spreads. No extra wrapper,
   no image of a device. The ink replaces the reference's warm brown, so the frame
   belongs to this palette rather than to theirs. */
.phone {
  width: 320px;
  max-width: 100%;
  margin: 0 auto;
  border-radius: 36px;
  overflow: hidden;
  background: var(--surface);
  box-shadow:
    0 2px 0 0 rgba(15, 43, 64, 0.04),
    0 32px 70px -28px rgba(15, 43, 64, 0.32),
    0 0 0 6px var(--ink),
    0 0 0 8px rgba(15, 43, 64, 0.12);
}

/* Inside, the app's own screen at its own scale: 14px base, the way a 390px
   viewport reads it, not the page's 18px. */
.scr {
  font-size: var(--fs-sm);
  line-height: 1.45;
  display: flex;
  flex-direction: column;
  /* 600px left a void under the third card that read as a bug rather than as screen
     space. 560 with the streak row fills it. */
  height: 560px;
}

.scr-top {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.875rem 0.875rem 0.5rem;
}

.scr-av {
  width: 2rem;
  height: 2rem;
  border-radius: var(--r-full);
  background: var(--info-bg);
  flex: none;
}

.scr-hi {
  flex: 1;
  min-width: 0;
  font-size: var(--fs-xs);
  color: var(--ink-2);
  line-height: 1.25;
}

.scr-hi b {
  display: block;
  font-size: var(--fs-sm);
  color: var(--ink);
}

.scr-lang {
  flex: none;
  font-size: var(--fs-xs);
  font-weight: 700;
  padding: 0.2rem 0.5rem;
  border-radius: var(--r-full);
  border: 1px solid var(--line);
  color: var(--ink-2);
}

.scr-body {
  flex: 1;
  min-height: 0;
  overflow: hidden;
  padding: 0.5rem 0.875rem 0;
}

.scr-h1 {
  font-size: var(--fs-xl);
  font-weight: 800;
  letter-spacing: -0.02em;
}

.scr-sub {
  display: flex;
  align-items: center;
  gap: 0.375rem;
  font-size: var(--fs-xs);
  color: var(--ink-2);
  margin-top: 0.125rem;
}

/* The streak, as the app draws it: a flame and a digit, nothing more. */
.scr-streak {
  display: inline-flex;
  align-items: center;
  gap: 0.15rem;
  font-weight: 700;
  padding: 0.1rem 0.4rem;
  border-radius: var(--r-full);
  background: var(--warn-bg);
  color: var(--warn-fg);
  font-variant-numeric: tabular-nums;
}

/* The day is a sequence, so the cards hang off a rail. Straight from the app's
   «Today» screen, where the rail is what makes three cards read as one plan. */
.scr-rail {
  position: relative;
  margin-top: 0.875rem;
  padding-left: 1.125rem;
  display: grid;
  gap: 0.5rem;
}

.scr-rail::before {
  content: "";
  position: absolute;
  left: 0.28rem;
  top: 1.4rem;
  bottom: 1.4rem;
  width: 2px;
  border-radius: 2px;
  background: var(--line);
}

.scr-card {
  position: relative;
  display: flex;
  gap: 0.5rem;
  align-items: flex-start;
  background: var(--paper);
  border-radius: var(--r-md);
  padding: 0.625rem;
}

/* The rail's node: done is filled, the rest are hollow. */
.scr-card::before {
  content: "";
  position: absolute;
  left: -1.125rem;
  top: 1rem;
  width: 0.625rem;
  height: 0.625rem;
  border-radius: var(--r-full);
  background: var(--surface);
  box-shadow: 0 0 0 2px var(--line-strong);
}

.scr-card--done::before {
  background: var(--done);
  box-shadow: 0 0 0 2px var(--done);
}

.scr-card--next::before {
  background: var(--accent);
  box-shadow: 0 0 0 2px var(--accent);
}

.scr-card--done {
  opacity: 0.62;
}

.scr-tile {
  width: 2.25rem;
  height: 2.25rem;
  flex: none;
  border-radius: var(--r-sm);
  display: grid;
  place-items: center;
  font-size: 1.125rem;
  line-height: 1;
}

.scr-cb {
  min-width: 0;
  display: grid;
  gap: 0.25rem;
}

.scr-name {
  font-size: var(--fs-sm);
  font-weight: 700;
  letter-spacing: -0.01em;
}

.scr-hook {
  font-size: var(--fs-xs);
  color: var(--ink-2);
  line-height: 1.35;
}

.scr-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem;
}

.scr-chip {
  font-size: 0.625rem;
  font-weight: 600;
  padding: 0.1rem 0.35rem;
  border-radius: var(--r-xs);
  background: var(--mute-bg);
  color: var(--mute-fg);
}

.scr-chip--primary {
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  color: var(--accent-ink);
}

/* «Next» rides the top edge of the first unfinished card, as it does in the app. */
.scr-next {
  position: absolute;
  top: -0.45rem;
  left: 0.625rem;
  font-size: 0.5625rem;
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 0.1rem 0.35rem;
  border-radius: var(--r-xs);
  background: var(--accent);
  color: #fff;
}

.scr-go {
  flex: none;
  align-self: center;
  font-size: var(--fs-xs);
  font-weight: 700;
  color: var(--accent-ink);
}

/* The tab bar, frosted, the way the client draws it over the list. */
.scr-tabs {
  flex: none;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 0.25rem;
  padding: 0.5rem 0.75rem 0.75rem;
  border-top: 1px solid var(--line);
  background: color-mix(in srgb, var(--surface) 88%, transparent);
  backdrop-filter: blur(8px);
}

.scr-tab {
  text-align: center;
  font-size: 0.625rem;
  font-weight: 600;
  color: var(--ink-2);
  display: grid;
  gap: 0.125rem;
}

.scr-tab span:first-child {
  font-size: 1rem;
  line-height: 1;
}

.scr-tab--on {
  color: var(--accent-ink);
}
