/* "Ink & paper". The site is a sibling of the app, not a copy of it: it borrows
   the warm paper and the seal mark, but a marketing page spreads colour over far
   more surface than a phone screen, so saturated red is not the right workhorse.

   Red is kept, but only on small surfaces and in two strengths — what made the
   earlier attempt aggressive was scale and repetition, not the hue itself.

     --color-ink          headings and body — carries the page's structure
     --color-primary      seal red, one single strength, on small areas only:
                          brand mark, buttons, first step marker, tile glyphs,
                          section labels, current nav item, open FAQ row, focus ring

   A desaturated red was tried for the text uses and rejected: it reads as washed
   out against cream, even though its measured contrast is higher. Vividness, not
   contrast ratio, is what makes a small red label legible here.

   Rule: red fills only small surfaces — brand mark, buttons, one step marker.
   Never a section background, never a coloured shadow, never a full-width panel. */
/* Inter variable, latin subset (48 KB) — self-hosted, so no third-party request
   and no consent question. The unicode-range stops it loading for the hanzi,
   which it does not contain: those fall through to the system CJK font.
   Variable, so the non-standard weights below (720, 760, 820, 850) render as
   asked instead of snapping to the nearest static cut. */
@font-face {
  font-family: "Inter var";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("/assets/fonts/inter-latin-var.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;
}

:root {
  /* warm paper, rendered as a fixed gradient canvas by body::before */
  --color-bg: #faf6ed;
  --color-surface: #ffffff;
  --color-surface-soft: #f3ece0;
  --color-line: #e9e1d4;

  --color-ink: #1c1a17;
  --color-ink-soft: #4a463f;
  --color-muted: #6f6961;

  --color-primary: #b3372b;
  --color-primary-dark: #8f2a20;

  --color-gold-ink: #8a6118;
  --shadow-soft: 0 18px 50px rgba(28, 26, 23, 0.06);
  --shadow-card: 0 1px 2px rgba(28, 26, 23, 0.04), 0 8px 24px rgba(28, 26, 23, 0.05);
  --radius-sm: 8px;
  --radius-md: 14px;
  --radius-lg: 22px;
  --container: 1160px;
  --nav-height: 72px;
  --font-main: "Inter var", Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
}

* {
  box-sizing: border-box;
}

html {
  scroll-behavior: smooth;
}

body {
  margin: 0;
  background: var(--color-bg);
  color: var(--color-ink);
  font-family: var(--font-main);
  font-size: 16px;
  line-height: 1.6;
  text-rendering: optimizeLegibility;
}

/* One fixed canvas behind the whole document rather than a gradient per section,
   so the warmth stays continuous while scrolling and never seams between blocks.
   Kept strictly neutral-warm: a red wash over cream turns muddy, not warmer. */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  background:
    radial-gradient(1100px 660px at 8% -18%, #fffefa 0%, rgba(255, 254, 250, 0) 52%),
    radial-gradient(1150px 720px at 96% -2%, #f7edde 0%, rgba(247, 237, 222, 0) 62%),
    linear-gradient(180deg, #fdfaf4 0%, #faf6ed 55%, #f7f1e5 100%);
}

body.nav-open {
  overflow: hidden;
}

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

img {
  height: auto;
}

a {
  color: inherit;
  text-decoration: none;
}

a:focus-visible,
button:focus-visible {
  outline: 3px solid rgba(179, 55, 43, 0.4);
  outline-offset: 3px;
}

button {
  font: inherit;
}

.site-header {
  position: fixed;
  inset: 0 0 auto;
  z-index: 50;
  height: var(--nav-height);
  border-bottom: 1px solid rgba(233, 225, 212, 0.9);
  background: rgba(253, 250, 244, 0.82);
  backdrop-filter: blur(18px);
}

.nav-shell {
  width: min(100% - 32px, var(--container));
  height: 100%;
  margin: 0 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-weight: 850;
  letter-spacing: 0;
}

.brand-mark {
  display: grid;
  place-items: center;
  width: 36px;
  height: 36px;
  border-radius: 10px;
  background: var(--color-primary);
  color: #fff;
  font-size: 22px;
  font-weight: 800;
}

.brand-text {
  white-space: nowrap;
}

.primary-nav {
  display: flex;
  align-items: center;
  gap: 6px;
}

.primary-nav a {
  padding: 10px 12px;
  border-radius: var(--radius-sm);
  color: var(--color-ink-soft);
  font-weight: 720;
  font-size: 0.94rem;
}

.primary-nav a:hover {
  color: var(--color-ink);
  background: var(--color-surface-soft);
}

/* Same treatment as the app's bottom tab bar: red label, no chip behind it. */
.primary-nav a[aria-current="page"] {
  color: var(--color-primary);
}

.nav-actions {
  display: flex;
  align-items: center;
  gap: 10px;
}

.lang-switch {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  padding: 3px;
  border: 1px solid var(--color-line);
  border-radius: 999px;
  background: var(--color-surface);
}

.lang-switch a {
  padding: 5px 9px;
  border-radius: 999px;
  color: var(--color-muted);
  font-size: 0.76rem;
  font-weight: 800;
  letter-spacing: 0.04em;
}

.lang-switch a:hover {
  color: var(--color-ink);
}

.lang-switch a[aria-current="true"] {
  background: var(--color-surface-soft);
  color: var(--color-primary);
}

.nav-toggle {
  display: none;
  width: 42px;
  height: 42px;
  border: 1px solid var(--color-line);
  border-radius: var(--radius-sm);
  background: var(--color-surface);
  color: var(--color-ink);
}

.nav-toggle span,
.nav-toggle span::before,
.nav-toggle span::after {
  display: block;
  width: 18px;
  height: 2px;
  margin: 0 auto;
  background: currentColor;
  border-radius: 99px;
  content: "";
}

.nav-toggle span::before {
  transform: translateY(-6px);
}

.nav-toggle span::after {
  transform: translateY(4px);
}

.button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  padding: 12px 18px;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  cursor: pointer;
  font-weight: 820;
  line-height: 1.1;
  transition: transform 0.2s ease, box-shadow 0.2s ease, background 0.2s ease;
}

.button:hover {
  transform: translateY(-1px);
}

/* Seal red returns on the action itself — small, purposeful surfaces. The shadow
   stays neutral: a red glow on light paper reads as a halo, not as depth. */
.button-primary {
  background: var(--color-primary);
  color: #fff;
  box-shadow: 0 6px 16px rgba(28, 26, 23, 0.1);
}

.button-primary:hover {
  background: var(--color-primary-dark);
}

.button-secondary {
  border-color: var(--color-line);
  background: var(--color-surface);
  color: var(--color-ink);
}

.button-ghost {
  color: var(--color-ink);
  background: var(--color-surface-soft);
}

main {
  padding-top: var(--nav-height);
}

.section {
  padding: 78px 0;
}

.section-tight {
  padding: 54px 0;
}

/* Just enough tint to set a section apart — 1.10:1 against the page, where the
   dark band that read as aggressive was 17:1. Translucent on purpose: the page
   background is a fixed gradient, and an opaque fill would mask it and drop a
   flat slab over it. This lets the gradient through, only deeper.
   The alpha is capped at 0.22: above that, --color-muted on the tinted area
   falls under 4.5:1. Deepening this tint means darkening that token too.

   Both edges are a short shadow rather than a long gradient: the separation
   resolves within 8px instead of smearing over a third of the block. Painted
   as background layers rather than `box-shadow: inset`, whose blur also bled a
   few pixels down the left and right edges of this full-bleed band.

   Both shadows now fall outside the band, each fading away from its boundary,
   so the section reads as raised off the page rather than sunk into it. That
   puts them on the neighbouring blocks, hence the two pseudo-elements. */
.section-tinted {
  position: relative;
  background: rgba(214, 194, 158, 0.22);
}

.section-tinted::before,
.section-tinted::after {
  content: "";
  position: absolute;
  right: 0;
  left: 0;
  height: 8px;
  pointer-events: none;
}

.section-tinted::before {
  bottom: 100%;
  background: linear-gradient(0deg, rgba(28, 26, 23, 0.08), rgba(28, 26, 23, 0) 8px);
}

.section-tinted::after {
  top: 100%;
  background: linear-gradient(180deg, rgba(28, 26, 23, 0.08), rgba(28, 26, 23, 0) 8px);
}

.container {
  width: min(100% - 32px, var(--container));
  margin: 0 auto;
}

.hero {
  position: relative;
  overflow: hidden;
  min-height: calc(100vh - var(--nav-height));
  display: flex;
  align-items: center;
  padding: 70px 0 46px;
}

.hero-grid {
  display: grid;
  grid-template-columns: minmax(0, 1.02fr) minmax(320px, 0.72fr);
  align-items: center;
  gap: clamp(32px, 6vw, 82px);
}

/* Full vermilion, but at weight 700 and tighter tracking. What made the first
   version shout was the 900 weight and the count, not the colour. */
.eyebrow {
  margin: 0 0 14px;
  color: var(--color-primary);
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

h1,
h2,
h3,
p {
  margin-top: 0;
}

h1 {
  max-width: 780px;
  margin-bottom: 18px;
  font-size: clamp(2.2rem, 5vw, 4rem);
  line-height: 1.04;
  letter-spacing: 0;
}

h2 {
  margin-bottom: 16px;
  font-size: clamp(1.65rem, 3.2vw, 2.55rem);
  line-height: 1.08;
  letter-spacing: 0;
}

h3 {
  margin-bottom: 8px;
  font-size: 1.22rem;
  line-height: 1.2;
}

.lead {
  max-width: 720px;
  color: var(--color-ink-soft);
  font-size: clamp(1.08rem, 2.3vw, 1.32rem);
}

.hero-actions,
.cta-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: 30px;
}

.hero-proof {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: 28px;
  color: var(--color-ink-soft);
  font-weight: 760;
}

.proof-pill {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 9px 12px;
  border: 1px solid var(--color-line);
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.72);
}

.phone-stage {
  display: grid;
  place-items: center;
}

.phone-frame {
  position: relative;
  width: min(100%, 390px);
  padding: 12px;
  border: 1px solid rgba(28, 26, 23, 0.08);
  border-radius: 36px;
  background: #1c1a17;
  box-shadow: 0 42px 90px rgba(28, 26, 23, 0.2);
}

.phone-frame img {
  width: 100%;
  border-radius: 26px;
}

.mini-stats {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 14px;
  margin-top: 36px;
}

.mini-stat {
  padding: 18px;
  border: 1px solid var(--color-line);
  border-radius: var(--radius-md);
  background: rgba(255, 255, 255, 0.72);
}

.mini-stat strong {
  display: block;
  color: var(--color-ink);
  font-size: 1.7rem;
  line-height: 1;
}

.mini-stat span {
  color: var(--color-muted);
  font-weight: 760;
  font-size: 0.82rem;
  text-transform: uppercase;
}

.section-heading {
  max-width: 760px;
  margin-bottom: 34px;
}

.section-heading.center {
  margin-inline: auto;
  text-align: center;
}

.muted {
  color: var(--color-muted);
}

.feature-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 16px;
}

.feature-grid-simple {
  grid-template-columns: repeat(3, minmax(0, 1fr));
}

.feature-card,
.info-card,
.testimonial,
.article-card,
.legal-card {
  border: 1px solid var(--color-line);
  border-radius: var(--radius-md);
  background: var(--color-surface);
  box-shadow: var(--shadow-card);
}

.feature-card {
  padding: 22px;
}

.icon-tile {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  margin-bottom: 18px;
  border-radius: 12px;
  background: var(--color-surface-soft);
  color: var(--color-primary);
  font-weight: 800;
}

.split {
  display: grid;
  grid-template-columns: minmax(0, 0.95fr) minmax(0, 1.05fr);
  gap: 34px;
  align-items: center;
}

.info-card {
  padding: 28px;
}

.reason-list {
  display: grid;
  gap: 14px;
}

.reason-item {
  padding-left: 18px;
  border-left: 3px solid var(--color-line);
}

.compare-wrap {
  overflow-x: auto;
  border: 1px solid var(--color-line);
  border-radius: var(--radius-md);
  background: #fff;
  box-shadow: var(--shadow-card);
}

.compare-table {
  width: 100%;
  min-width: 720px;
  border-collapse: collapse;
}

.compare-table th,
.compare-table td {
  padding: 18px;
  border-bottom: 1px solid var(--color-line);
  text-align: left;
  vertical-align: top;
}

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

.compare-table th {
  color: var(--color-ink-soft);
  background: var(--color-surface-soft);
  font-size: 0.86rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.compare-table strong {
  color: var(--color-ink);
  font-weight: 700;
}

.slider-head {
  display: flex;
  align-items: end;
  justify-content: space-between;
  gap: 18px;
  margin-bottom: 24px;
}

.slider-actions {
  display: flex;
  gap: 8px;
}

.slider-button {
  width: 44px;
  height: 44px;
  border: 1px solid var(--color-line);
  border-radius: var(--radius-sm);
  background: #fff;
  color: var(--color-ink);
  cursor: pointer;
  font-size: 1.3rem;
}

/* Custom properties are not animatable until registered; without these the
   transition below is silently a no-op and the fades snap. */
@property --fade-l {
  syntax: "<length>";
  inherits: false;
  initial-value: 0px;
}

@property --fade-r {
  syntax: "<length>";
  inherits: false;
  initial-value: 0px;
}

.screenshot-track {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(238px, 292px);
  gap: 30px;
  overflow-x: auto;
  /* A scroll container clips at its padding box, so the frame shadow was sliced
     into a vertical seam at the last card. The negative margin pushes the clip
     16px outside the container while the matching padding keeps the first card
     aligned with the heading. 16px is exactly `.container`'s own side gutter, so
     the track reaches the viewport edge at most and never overflows the page. */
  margin-inline: -16px;
  padding: 6px 16px 22px;
  /* `proximity`, not `mandatory`: snapping assists free scrolling instead of
     overriding it, which matters here because the arrows scroll by 85% of the
     viewport rather than card by card. */
  scroll-snap-type: x proximity;
  /* Must track padding-left. Any mismatch puts the first card's snap position
     at (padding - scroll-padding), so the track settles part-scrolled on load
     instead of at 0. */
  scroll-padding-left: 16px;

  /* The arrows and the edge fade already signal that the row scrolls, so the
     bar is redundant and it cut a grey line across the tinted band. Scrolling
     by wheel, touch, keyboard and the arrow buttons is unaffected. */
  scrollbar-width: none;
  -ms-overflow-style: none;

  /* A screenshot sliced mid-device by the scroll edge reads as a cut rather than
     as "more to come", so each edge fades — but only on the side that actually
     has hidden content. Both widths start at 0 and main.js raises them from the
     scroll position; a permanent fade would dim the first card on load, when
     there is nothing to its left. Kept short: over a long distance the fade
     stops looking like an edge treatment and starts looking like a blur. */
  --fade-l: 0px;
  --fade-r: 0px;
  -webkit-mask-image: linear-gradient(
    90deg,
    transparent 0,
    #000 var(--fade-l),
    #000 calc(100% - var(--fade-r)),
    transparent 100%
  );
  mask-image: linear-gradient(
    90deg,
    transparent 0,
    #000 var(--fade-l),
    #000 calc(100% - var(--fade-r)),
    transparent 100%
  );
  transition: --fade-l 0.2s linear, --fade-r 0.2s linear;
}

.screenshot-track.has-before {
  --fade-l: 26px;
}

.screenshot-track.has-after {
  --fade-r: 26px;
}

/* <figure> carries a UA margin of `1em 40px`. Unreset, it pushed the first card
   40px into the scroll content — so the track could never rest at 0 — and ate
   80px of every column, leaving the screenshots needlessly narrow. */
/* Chrome, Safari and Edge ignore scrollbar-width and need this instead. */
.screenshot-track::-webkit-scrollbar {
  display: none;
}

.screenshot-card {
  margin: 0;
  scroll-snap-align: start;
  cursor: zoom-in;
}

/* The screenshots are cream and so is the page, so a pale border could never
   separate them. The same device bezel as the hero does it instead: the dark
   stays confined to a thin frame rather than taking over the whole section. */
.shot-frame {
  padding: 8px;
  border: 1px solid rgba(28, 26, 23, 0.08);
  border-radius: 28px;
  background: #1c1a17;
  /* The negative spread keeps the sideways reach to ~3px. The track is a scroll
     container and clips at its padding box, so a wide blur got sliced flat at
     the last card and showed as a vertical seam against the tint. Depth is
     carried downward, where there is padding to hold it. */
  box-shadow: 0 14px 26px -10px rgba(28, 26, 23, 0.3);
}

.screenshot-card img {
  width: 100%;
  border-radius: 20px;
  background: #fff;
}

.screenshot-card figcaption {
  margin-top: 10px;
  color: var(--color-ink-soft);
  font-weight: 760;
  text-align: center;
}

.screenshot-lightbox {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: none;
  grid-template-columns: 64px minmax(0, 1fr) 64px;
  align-items: center;
  gap: 14px;
  padding: 22px;
  background: rgba(28, 26, 23, 0.82);
  backdrop-filter: blur(14px);
}

.screenshot-lightbox.is-open {
  display: grid;
}

.screenshot-lightbox__figure {
  display: grid;
  justify-items: center;
  gap: 12px;
  min-width: 0;
  margin: 0;
}

.screenshot-lightbox__image {
  width: auto;
  max-width: min(92vw, 460px);
  max-height: calc(100vh - 120px);
  border: 1px solid rgba(255, 255, 255, 0.28);
  border-radius: 30px;
  background: #fff;
  box-shadow: 0 32px 90px rgba(0, 0, 0, 0.42);
}

.screenshot-lightbox__caption {
  color: #fff;
  font-weight: 820;
  text-align: center;
}

.screenshot-lightbox__button {
  display: grid;
  place-items: center;
  width: 48px;
  height: 48px;
  border: 1px solid rgba(255, 255, 255, 0.24);
  border-radius: var(--radius-sm);
  background: rgba(255, 255, 255, 0.12);
  color: #fff;
  cursor: pointer;
  font-size: 1.45rem;
  line-height: 1;
}

.screenshot-lightbox__button:hover {
  background: rgba(255, 255, 255, 0.2);
}

.screenshot-lightbox__close {
  position: absolute;
  top: 18px;
  right: 18px;
}

.timeline {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 14px;
  counter-reset: step;
}

.timeline-simple {
  grid-template-columns: repeat(3, 1fr);
  max-width: 900px;
  margin: 0 auto;
}

.timeline-step {
  position: relative;
  padding: 24px;
  border: 1px solid var(--color-line);
  border-radius: var(--radius-md);
  background: #fff;
  box-shadow: var(--shadow-card);
}

.timeline-step::before {
  counter-increment: step;
  content: counter(step);
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  margin-bottom: 18px;
  border-radius: 50%;
  background: var(--color-surface-soft);
  color: var(--color-ink);
  font-weight: 800;
}

/* Only the entry point of the sequence is filled, so the three steps don't
   read as a repeating dotted line across the grid. */
.timeline-step:first-child::before {
  background: var(--color-primary);
  color: #fff;
}

.testimonial-grid,
.article-grid,
.hsk-grid,
.two-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 16px;
}

.testimonial,
.article-card,
.legal-card {
  padding: 24px;
}

.stars {
  color: var(--color-gold-ink);
  font-weight: 900;
  letter-spacing: 0.1em;
}

.faq-list {
  display: grid;
  gap: 10px;
  max-width: 900px;
  margin: 0 auto;
}

.faq-item {
  border: 1px solid var(--color-line);
  border-radius: var(--radius-md);
  background: #fff;
  overflow: hidden;
}

.faq-question {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  padding: 18px 20px;
  border: 0;
  background: transparent;
  color: var(--color-ink);
  cursor: pointer;
  font-weight: 850;
  text-align: left;
}

.faq-question::after {
  content: "+";
  margin-left: 16px;
  color: var(--color-muted);
  font-size: 1.4rem;
}

.faq-question[aria-expanded="true"]::after {
  content: "-";
  color: var(--color-primary);
}

.faq-answer {
  padding: 0 20px 20px;
  color: var(--color-ink-soft);
}

/* The closing card earns attention through size and whitespace, not colour —
   its ink button is already the strongest contrast on the page. */
.cta-band {
  border: 1px solid var(--color-line);
  border-radius: var(--radius-lg);
  background: var(--color-surface);
  padding: clamp(30px, 7vw, 64px);
  box-shadow: var(--shadow-soft);
}

.cta-band h2 {
  max-width: 760px;
}

.download-note {
  margin-top: 16px;
  color: var(--color-ink-soft);
  font-size: 0.95rem;
}

.page-hero {
  padding: 56px 0 28px;
}

.page-hero .lead {
  max-width: 820px;
}

.hsk-card {
  padding: 22px;
  border: 1px solid var(--color-line);
  border-radius: var(--radius-md);
  background: #fff;
}

.hsk-card strong {
  display: block;
  color: var(--color-ink);
  font-size: 1.4rem;
}

.blog-list {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.blog-list li {
  padding: 16px 18px;
  border: 1px solid var(--color-line);
  border-radius: var(--radius-sm);
  background: #fff;
  font-weight: 760;
}

.legal-content {
  max-width: 860px;
}

.legal-content h2 {
  margin-top: 34px;
  font-size: 1.7rem;
}

.site-footer {
  padding: 54px 0 28px;
  border-top: 1px solid var(--color-line);
}

.footer-grid {
  display: grid;
  grid-template-columns: 1.4fr repeat(3, 1fr);
  gap: 24px;
}

.footer-links {
  display: grid;
  gap: 9px;
}

.footer-links a {
  color: var(--color-ink-soft);
  font-weight: 680;
}

.footer-bottom {
  display: flex;
  justify-content: space-between;
  gap: 20px;
  margin-top: 36px;
  padding-top: 20px;
  border-top: 1px solid var(--color-line);
  color: var(--color-muted);
  font-size: 0.92rem;
}

.back-to-top {
  position: fixed;
  right: 18px;
  bottom: 18px;
  z-index: 40;
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border: 1px solid var(--color-line);
  border-radius: var(--radius-sm);
  background: #fff;
  box-shadow: var(--shadow-card);
  opacity: 0;
  pointer-events: none;
  transform: translateY(10px);
  transition: opacity 0.2s ease, transform 0.2s ease;
}

.back-to-top.is-visible {
  opacity: 1;
  pointer-events: auto;
  transform: translateY(0);
}

[data-reveal] {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity 0.55s ease, transform 0.55s ease;
}

[data-reveal].is-visible {
  opacity: 1;
  transform: translateY(0);
}

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

@media (max-width: 980px) {
  .hero-grid,
  .split {
    grid-template-columns: 1fr;
  }

  .phone-stage {
    order: -1;
  }

  .phone-frame {
    width: min(82vw, 330px);
  }

  .feature-grid,
  .feature-grid-simple,
  .timeline,
  .timeline-simple,
  .testimonial-grid,
  .article-grid,
  .hsk-grid,
  .two-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .mini-stats {
    grid-template-columns: repeat(2, 1fr);
  }

  .footer-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (max-width: 760px) {
  :root {
    --nav-height: 66px;
  }

  .brand-text {
    max-width: 154px;
    overflow: hidden;
    text-overflow: ellipsis;
  }

  .primary-nav {
    position: fixed;
    inset: var(--nav-height) 0 auto 0;
    display: grid;
    gap: 4px;
    padding: 18px 16px 22px;
    border-bottom: 1px solid var(--color-line);
    background: rgba(252, 250, 246, 0.98);
    transform: translateY(-120%);
    transition: transform 0.22s ease;
  }

  .primary-nav.is-open {
    transform: translateY(0);
  }

  .primary-nav a {
    padding: 14px 12px;
  }

  .nav-toggle {
    display: grid;
    place-items: center;
  }

  .nav-actions .button {
    min-height: 40px;
    padding: 10px 12px;
    font-size: 0.9rem;
  }

  .lang-switch a {
    padding: 5px 7px;
    font-size: 0.72rem;
  }

  .hero {
    min-height: auto;
    padding-top: 30px;
  }

  .section,
  .section-tight {
    padding: 52px 0;
  }

  .hero-actions,
  .cta-actions {
    display: grid;
  }

  .button {
    width: 100%;
  }

  .feature-grid,
  .feature-grid-simple,
  .timeline,
  .timeline-simple,
  .testimonial-grid,
  .article-grid,
  .hsk-grid,
  .two-grid,
  .blog-list {
    grid-template-columns: 1fr;
  }

  .slider-head {
    align-items: start;
    flex-direction: column;
  }

  .screenshot-track {
    grid-auto-columns: minmax(230px, 78vw);
  }

  .screenshot-lightbox {
    grid-template-columns: 44px minmax(0, 1fr) 44px;
    gap: 8px;
    padding: 14px;
  }

  .screenshot-lightbox__image {
    max-width: min(82vw, 430px);
    max-height: calc(100vh - 112px);
    border-radius: 24px;
  }

  .screenshot-lightbox__button {
    width: 40px;
    height: 40px;
  }

  .footer-grid,
  .footer-bottom {
    grid-template-columns: 1fr;
    flex-direction: column;
  }
}

/* The language switcher costs ~104px in the header, and localised CTA labels run
   longer than "Download". Drop the wordmark before the row can overflow — the
   seal keeps the branding. */
@media (max-width: 480px) {
  .brand-text {
    display: none;
  }
}

@media (max-width: 420px) {
  .nav-shell {
    width: min(100% - 20px, var(--container));
  }

  .container {
    width: min(100% - 28px, var(--container));
  }

  .lang-switch a {
    padding: 5px 6px;
    font-size: 0.7rem;
  }

  h1 {
    font-size: 2.1rem;
  }
}
