/*
 * Z-Maps Car — instrument-cluster styling.
 *
 * The app's own colours — the #0E1116 surface, the four speed levels, the
 * white-on-red speed sign — are reused here so the site and the app read as one
 * thing. The theme SHIPS dark as its default (`colorModes.default`), but light is
 * the CSS base; see the colour-mode block below for why those are not the same
 * statement.
 *
 * Both modes are declared with the same token names, so every rule after that
 * block is written once and never branches. Neither does the MARKUP: the server
 * does not know which mode the visitor is in, so a theme that rendered different
 * elements per mode would be guessing, and wrong for the first frame.
 *
 * One exception, deliberate: the instrument cluster is painted in fixed dark
 * values rather than tokens. It is a picture of a device screen, and that screen
 * is dark in a light room too.
 */

/* -------------------------------------------------------------------------
 * Colour modes — three blocks, and the order of them is the whole mechanism.
 *
 * The runtime sets `data-theme` on <html> from an inline script in <head>, before
 * first paint. What it does NOT do is set it on the SERVER: the HTML ships as
 * plain `<html lang="vi" dir="ltr">`, because the visitor's preference lives in
 * their browser and the server has never seen it.
 *
 * So a theme is asked what to do when the attribute is ABSENT, and the first
 * version of this file answered "be dark", full stop. That was wrong twice over:
 * a visitor whose OS is set to light got a dark site with JavaScript disabled,
 * and every light-mode visitor got a dark flash in the moment before the script
 * ran. The runtime's own notes say a theme is expected to honour
 * `prefers-color-scheme` for exactly this gap.
 *
 *   1. `:root`                     — LIGHT, the base. Applies when nothing else does.
 *   2. `prefers-color-scheme: dark` — the OS speaking, honoured only while the
 *                                     visitor has not explicitly chosen light.
 *   3. `[data-theme="dark"]`       — an explicit choice, which beats the OS.
 *
 * The dark tokens are written twice, in 2 and 3, and there is no way around it:
 * plain CSS cannot name a block of declarations and apply it under two different
 * conditions. Keep the two lists identical.
 * ---------------------------------------------------------------------- */

:root {
  /* Mode-independent. The brand orange gets three tokens rather than one,
     because a single accent cannot be legible in both roles: orange is bright
     enough to carry a BUTTON but too bright to be small TEXT on white, and white
     is unreadable ON orange.
       --zmc-accent      the colour of accent surfaces (buttons, rules, marks)
       --zmc-on-accent   what sits on top of one — near-black, as on the icon
       --zmc-accent-text accent used as text on the page; darker in light mode */
  --zmc-accent: #f87800;
  --zmc-on-accent: #14181f;

  /* The app's speed-level colours, unchanged. */
  --zmc-ok: #3dd68c;
  --zmc-margin: #f2c14e;
  --zmc-warn: #f2913d;
  --zmc-severe: #e5484d;

  /* A road sign is a road sign in both modes. */
  --zmc-sign-bg: #ffffff;
  --zmc-sign-border: #d32029;
  --zmc-sign-ink: #15181d;

  --zmc-radius: 14px;
  --zmc-radius-sm: 10px;
  --zmc-radius-lg: 20px;
  --zmc-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;

  /* ---- Rhythm ----
     One band height for the whole site, so a page is a stack of equal beats
     rather than a set of sections that each guessed their own padding. The old
     file used `clamp(56px, 8vw, 104px)` per section; at a desktop width two
     adjacent bands put 208px of nothing between two sentences, and the page
     read as a series of unrelated screens with the content pushed to the top
     of each. These are the beats everything now measures against. */
  --zmc-band: clamp(48px, 5.2vw, 80px);
  --zmc-band-sm: clamp(28px, 3vw, 44px);
  --zmc-head-gap: clamp(26px, 2.8vw, 38px);

  /* ---- LIGHT (base) ---- */
  --zmc-bg: #eef2f8;
  --zmc-surface: #ffffff;
  --zmc-panel: #ffffff;
  --zmc-panel-2: #e9eef6;
  /* A band one step off the page background. Defined in ALL THREE token blocks:
     leaving it out of one means the tinted sections vanish in that mode only. */
  --zmc-tint: #e3e9f2;
  --zmc-line: #d2dae6;
  --zmc-ink: #101620;
  --zmc-muted: #59636f;
  --zmc-shadow: 0 22px 54px rgba(15, 25, 45, 0.11);
  /* #f87800 is only ~2.9:1 on white — fine as a surface, unreadable as small
     text. This is the same hue taken down to ~7:1. */
  --zmc-accent-text: #a94300;
  /* The instrument-panel texture: the faint ruled grid behind the hero, the
     number strip and the closing band. Per mode, because a graticule that reads
     as etched glass on a dark panel reads as dirt on a white one. */
  --zmc-hud: rgba(16, 30, 54, 0.055);
}

/* ---- DARK, from the OS, while no explicit light choice is in force ---- */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --zmc-bg: #090c11;
    --zmc-surface: #10151d;
    --zmc-panel: #161c26;
    --zmc-panel-2: #1e2531;
    --zmc-tint: #0d1219;
    --zmc-line: #242c39;
    --zmc-ink: #e8edf4;
    --zmc-muted: #8b96a5;
    --zmc-shadow: 0 30px 80px rgba(0, 0, 0, 0.5);
    --zmc-accent-text: #ff8a1f;
    --zmc-hud: rgba(150, 190, 255, 0.045);
  }
}

/* ---- DARK, chosen explicitly. Must match the block above. ---- */
:root[data-theme="dark"] {
  --zmc-bg: #090c11;
  --zmc-surface: #10151d;
  --zmc-panel: #161c26;
  --zmc-panel-2: #1e2531;
  --zmc-tint: #0d1219;
  --zmc-line: #242c39;
  --zmc-ink: #e8edf4;
  --zmc-muted: #8b96a5;
  --zmc-shadow: 0 30px 80px rgba(0, 0, 0, 0.5);
  --zmc-accent-text: #ff8a1f;
  --zmc-hud: rgba(150, 190, 255, 0.045);
}

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

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

.zmc {
  min-height: 100vh;
  background: var(--zmc-bg);
  color: var(--zmc-ink);
  font-family: "Inter", "Segoe UI", ui-sans-serif, system-ui, -apple-system, sans-serif;
  font-size: 16px;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
}

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

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

.zmc button,
.zmc input,
.zmc textarea,
.zmc select {
  font: inherit;
}

/* `:where()` because this is a RESET, and a reset must never outrank the rules
   that come after it. Written as `.zmc p` it has specificity (0,1,1), which beats
   a single class like `.zmc__case-problem` (0,1,0) — so every `margin` set on a
   paragraph class further down was silently dropped, and the only symptom was
   text that sat slightly too close together. `:where()` contributes nothing, so
   anything below wins by default. */
:where(.zmc) :where(h1, h2, h3, h4, p, ul, ol, dl, figure) {
  margin: 0;
}

.zmc h1,
.zmc h2,
.zmc h3 {
  line-height: 1.1;
  letter-spacing: -0.03em;
  font-weight: 700;
}

.zmc h1 {
  font-size: clamp(32px, 4.6vw, 54px);
}

.zmc h2 {
  font-size: clamp(25px, 2.9vw, 34px);
}

.zmc h3 {
  font-size: 18px;
  letter-spacing: -0.015em;
}

.zmc__container {
  width: min(1160px, calc(100% - 48px));
  margin-inline: auto;
}

/**
 * The reading column — 720px, and aligned to the SAME left rail as the 1160px
 * container rather than centred in the window.
 *
 * Centring it was the fault that made every prose page look misassembled: the
 * masthead began at the container's left edge, and then the article, the FAQ and
 * any plugin form jumped ~220px to the right of it. Two different left edges on
 * one page reads as a broken template, whatever the individual pieces look like.
 * `calc(50% - 580px)` is exactly half the difference between the two widths, so
 * the two edges are the same edge; below the width where the container is
 * gutter-bound, the `max()` falls back to the gutter.
 */
.zmc__measure {
  width: min(720px, calc(100% - 48px));
  margin-inline: max(24px, calc(50% - 580px)) auto;
}

.zmc__accent {
  color: var(--zmc-accent-text);
}

.zmc__lead {
  color: var(--zmc-muted);
  font-size: 16.5px;
  max-width: 58ch;
}

/**
 * The eyebrow, drawn as a gauge label.
 *
 * The accent tick in front of it is the smallest piece of the instrument
 * language, and it does real work: it gives every band a visible left edge to
 * start from, so eight consecutive sections read as eight marked stations
 * rather than as one undifferentiated column of headings.
 */
.zmc__eyebrow {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 14px;
  color: var(--zmc-accent-text);
  font-family: var(--zmc-mono);
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}

.zmc__eyebrow::before {
  content: "";
  width: 22px;
  height: 2px;
  flex: none;
  border-radius: 2px;
  background: currentColor;
}

.zmc__section-head--center .zmc__eyebrow {
  justify-content: center;
}

/**
 * The lane marking: a dashed accent line, the width of the band.
 *
 * Used as the top edge of every band that changes colour, and of the closing
 * call to action. It is the one ornament in the theme that is specific to what
 * the product IS — a strip of road paint — and it costs a gradient, no image.
 */
.zmc__lane {
  position: absolute;
  inset: 0 0 auto;
  height: 2px;
  background: repeating-linear-gradient(
    90deg,
    color-mix(in srgb, var(--zmc-accent) 55%, transparent) 0 26px,
    transparent 26px 62px
  );
  pointer-events: none;
}

/**
 * The instrument graticule: a 1px ruled grid, very faint.
 *
 * Applied to the hero, the number strip and the closing band — the three places
 * that are meant to read as panel rather than as page. Kept to a background
 * image on a pseudo-element so it never affects layout.
 */
.zmc__hud {
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(to right, var(--zmc-hud) 1px, transparent 1px),
    linear-gradient(to bottom, var(--zmc-hud) 1px, transparent 1px);
  background-size: 68px 68px;
  -webkit-mask-image: radial-gradient(120% 90% at 50% 0%, #000 30%, transparent 78%);
  mask-image: radial-gradient(120% 90% at 50% 0%, #000 30%, transparent 78%);
  pointer-events: none;
}

.zmc__empty {
  border: 1px dashed var(--zmc-line);
  border-radius: var(--zmc-radius);
  padding: 32px;
  color: var(--zmc-muted);
  text-align: center;
}

.zmc__note {
  margin-top: 20px;
  color: var(--zmc-muted);
  font-size: 14px;
}

.zmc__skip {
  position: fixed;
  z-index: 200;
  top: 12px;
  left: 12px;
  transform: translateY(-200%);
  border-radius: var(--zmc-radius-sm);
  background: var(--zmc-accent);
  color: var(--zmc-on-accent);
  padding: 10px 18px;
  font-weight: 600;
}

.zmc__skip:focus {
  transform: translateY(0);
}

.zmc :focus-visible {
  outline: 2px solid var(--zmc-accent);
  outline-offset: 3px;
}

/* -------------------------------------------------------------------------
 * Buttons and links
 * ---------------------------------------------------------------------- */

.zmc__button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  border: 1px solid transparent;
  border-radius: 999px;
  background: var(--zmc-accent);
  color: var(--zmc-on-accent);
  padding: 13px 26px;
  font-size: 15px;
  font-weight: 600;
  white-space: nowrap;
  transition: transform 0.15s ease, filter 0.15s ease;
}

.zmc__button:hover {
  transform: translateY(-1px);
  filter: brightness(1.08);
}

.zmc__button--small {
  padding: 9px 18px;
  font-size: 14px;
}

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

.zmc__button--ghost:hover {
  border-color: var(--zmc-accent);
  color: var(--zmc-accent-text);
  filter: none;
}

.zmc__text-link {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  color: var(--zmc-accent-text);
  font-weight: 600;
}

.zmc__text-link:hover span {
  transform: translateX(3px);
}

.zmc__text-link span {
  transition: transform 0.15s ease;
}

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

.zmc__icon {
  width: 24px;
  height: 24px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}

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

.zmc__header {
  position: sticky;
  top: 0;
  z-index: 90;
  border-bottom: 1px solid var(--zmc-line);
  background: color-mix(in srgb, var(--zmc-bg) 88%, transparent);
  -webkit-backdrop-filter: blur(14px);
  backdrop-filter: blur(14px);
}

.zmc__header-inner {
  display: flex;
  min-height: 68px;
  align-items: center;
  gap: 20px;
}

.zmc__brand {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-shrink: 0;
}

.zmc__brand img {
  width: auto;
  height: 34px;
}

.zmc__brand-mark {
  display: grid;
  place-items: center;
  width: 36px;
  height: 36px;
  border-radius: 11px;
  background: linear-gradient(150deg, var(--zmc-accent), color-mix(in srgb, var(--zmc-accent) 55%, #0b1220));
  box-shadow: 0 6px 20px color-mix(in srgb, var(--zmc-accent) 35%, transparent);
}

.zmc__brand-mark svg {
  width: 20px;
  height: 20px;
  fill: #fff;
}

.zmc__brand-text {
  display: flex;
  flex-direction: column;
  line-height: 1.25;
}

.zmc__brand-text strong {
  font-size: 16px;
  font-weight: 700;
  letter-spacing: -0.02em;
}

.zmc__brand-text small {
  color: var(--zmc-muted);
  font-size: 11.5px;
}

.zmc__nav {
  margin-inline-start: auto;
}

.zmc__nav ul {
  display: flex;
  align-items: center;
  gap: 4px;
  list-style: none;
  padding: 0;
}

/* `nowrap` at every width, not just the narrow ones. A menu label is a phrase;
   breaking "Hướng dẫn" across two lines to save eight pixels makes the nav
   unreadable long before it makes it fit. */
.zmc__nav a {
  display: block;
  border-radius: 999px;
  padding: 8px 14px;
  color: var(--zmc-muted);
  font-size: 14.5px;
  font-weight: 500;
  white-space: nowrap;
  transition: background 0.15s ease, color 0.15s ease;
}

.zmc__nav a:hover {
  background: var(--zmc-panel);
  color: var(--zmc-ink);
}

.zmc__header-actions {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-inline-start: auto;
}

.zmc__nav + .zmc__header-actions {
  margin-inline-start: 0;
}

/* The version pill: the app's build, visible on every page. A product site that
   does not say which version it is offering makes the visitor guess. */
.zmc__version-pill {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  border: 1px solid var(--zmc-line);
  border-radius: 999px;
  padding: 5px 12px;
  color: var(--zmc-muted);
  font-family: var(--zmc-mono);
  font-size: 12px;
}

.zmc__version-pill i {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--zmc-ok);
  box-shadow: 0 0 8px var(--zmc-ok);
}

.zmc__icon-btn {
  display: grid;
  place-items: center;
  width: 36px;
  height: 36px;
  border: 1px solid var(--zmc-line);
  border-radius: 50%;
  background: transparent;
  color: var(--zmc-muted);
  cursor: pointer;
  transition: color 0.15s ease, border-color 0.15s ease;
}

.zmc__icon-btn:hover {
  border-color: var(--zmc-accent);
  color: var(--zmc-ink);
}

.zmc__lang {
  position: relative;
}

.zmc__lang > summary {
  display: flex;
  align-items: center;
  gap: 6px;
  border: 1px solid var(--zmc-line);
  border-radius: 999px;
  padding: 6px 13px;
  color: var(--zmc-muted);
  font-size: 12.5px;
  font-weight: 600;
  cursor: pointer;
  list-style: none;
}

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

.zmc__lang > summary i {
  width: 0;
  height: 0;
  border-inline: 4px solid transparent;
  border-top: 5px solid currentColor;
}

/**
 * The dropdown panel.
 *
 * Anchored to its END edge, because on a wide screen the switcher is the last
 * thing in the header and a panel growing rightwards would leave the viewport.
 * On a narrow screen the header wraps and the switcher becomes the FIRST thing
 * in the actions row — at which point end-anchoring pushed the panel 97px off
 * the left of the screen at every width from 320 to 414. It was still clickable,
 * still focusable, and completely invisible. The narrow rule below flips the
 * anchor; `max-width` is the belt to that braces, so no future arrangement of
 * this row can put the panel somewhere a thumb cannot reach it.
 */
.zmc__lang ul {
  position: absolute;
  z-index: 30;
  top: calc(100% + 8px);
  inset-inline-end: 0;
  min-width: 168px;
  max-width: min(260px, calc(100vw - 32px));
  border: 1px solid var(--zmc-line);
  border-radius: var(--zmc-radius-sm);
  background: var(--zmc-panel);
  box-shadow: var(--zmc-shadow);
  padding: 6px;
  list-style: none;
}

.zmc__lang a {
  display: block;
  border-radius: 7px;
  padding: 8px 12px;
  font-size: 14px;
}

.zmc__lang a:hover,
.zmc__lang a[aria-current="page"] {
  background: var(--zmc-panel-2);
  color: var(--zmc-accent-text);
}

/* -------------------------------------------------------------------------
 * Sections
 * ---------------------------------------------------------------------- */

.zmc__section {
  position: relative;
  padding-block: var(--zmc-band);
}

/**
 * A coloured band, announced by a strip of road paint.
 *
 * The previous palette put `--zmc-tint`, `--zmc-surface` and `--zmc-bg` within
 * three hex steps of each other in dark mode, so the alternation the page
 * design depended on was invisible: eight bands read as one flat slab. The
 * tokens now step properly, and the lane marking gives the edge a hard line
 * even where the two tones are close — on a light background, or on a screen
 * that has crushed the blacks.
 */
.zmc__section--alt {
  background: var(--zmc-surface);
  border-block: 1px solid var(--zmc-line);
}

.zmc__section--tint {
  background: var(--zmc-tint);
  border-block: 1px solid var(--zmc-line);
}

.zmc__section--alt::before,
.zmc__section--tint::before {
  content: "";
  position: absolute;
  inset: -1px 0 auto;
  height: 2px;
  background: repeating-linear-gradient(
    90deg,
    color-mix(in srgb, var(--zmc-accent) 45%, transparent) 0 26px,
    transparent 26px 62px
  );
  pointer-events: none;
}

/* The page-head already carries its own bottom padding. Leaving the next
   section's full top padding on as well opened a void wide enough to read as a
   missing block. */
.zmc__page-head + .zmc__section,
.zmc__page-head + .zmc__notice,
.zmc__page-head + .zmc__hero {
  padding-top: clamp(22px, 2.4vw, 34px);
}

/**
 * Two plain sections in a row: collapse BOTH sides of the join, not just one.
 *
 * The old rule only trimmed the second section's top, so the first still
 * contributed its full 104px bottom and the pair sat ~150px apart — the widest
 * gap on the guide page fell between two halves of the same explanation. Each
 * side now gives up the same amount, which keeps the join centred and reads as
 * one gap rather than as two paddings that happened to meet.
 *
 * Scoped to plain-after-plain: a coloured band with a full bottom and a stubbed
 * top is visibly lopsided, and its edge is doing the separating anyway.
 */
.zmc__section:not(.zmc__section--alt, .zmc__section--tint)
  + .zmc__section:not(.zmc__section--alt, .zmc__section--tint) {
  padding-top: clamp(18px, 2vw, 28px);
}

.zmc__section:not(.zmc__section--alt, .zmc__section--tint):has(
    + .zmc__section:not(.zmc__section--alt, .zmc__section--tint)
  ) {
  padding-bottom: clamp(18px, 2vw, 28px);
}

/* A notice qualifies the content it sits against, so it is drawn close to it.
   Left alone, the notice's own band padding stacks on top of the next section's
   and opens a gap wide enough to read as two unrelated pages. */
.zmc__notice + .zmc__section,
.zmc__notice + .zmc__notice,
.zmc__section + .zmc__notice {
  padding-top: clamp(14px, 1.6vw, 24px);
}

/**
 * The section head, as a two-column station board.
 *
 * This is the single change that most affects how the page reads. The head used
 * to be `max-width: 720px` inside a 1200px column, so the top ~200px of every
 * band was 60% content and 40% empty — repeated eight times down the page, which
 * is what made a well-written site look unfinished. The heading and its
 * introduction now sit side by side and span the column, and the hairline under
 * them draws the full width, so each band opens on a line rather than on a void.
 *
 * `:has()` is what keeps it honest: a head with no introduction is a single
 * column, because a lone heading in the left half of a two-column grid is the
 * imbalance this rule exists to remove. Where `:has()` is unsupported the head
 * falls back to the two-column grid with an empty right side — exactly the old
 * behaviour, so nothing regresses.
 */
.zmc__section-head {
  display: grid;
  grid-template-columns: minmax(0, 1.08fr) minmax(0, 0.92fr);
  column-gap: clamp(28px, 4vw, 64px);
  /* `start`, not `end`. Bottom-aligning the two columns looked right for a
     one-line introduction and fell apart for a five-line one: the heading was
     pushed to the foot of the row and opened a 70px hole under its own eyebrow.
     Top-aligned, the heading always sits where the eyebrow points. */
  align-items: start;
  margin-bottom: var(--zmc-head-gap);
  padding-bottom: clamp(20px, 2.2vw, 28px);
  border-bottom: 1px solid var(--zmc-line);
}

.zmc__section-head .zmc__eyebrow {
  grid-column: 1 / -1;
}

.zmc__section-head h2 {
  grid-column: 1;
  margin: 0;
  max-width: 20ch;
}

.zmc__section-head .zmc__lead {
  grid-column: 2;
  margin: 0;
  /* Drops the introduction's first line onto the optical centre of the
     heading's first line, which is set three times its size. */
  padding-top: 7px;
}

.zmc__section-head:not(:has(.zmc__lead)) {
  grid-template-columns: minmax(0, 1fr);
}

.zmc__section-head:not(:has(h2)) .zmc__lead {
  grid-column: 1 / -1;
  max-width: 62ch;
}

.zmc__section-head--center {
  grid-template-columns: minmax(0, 1fr);
  justify-items: center;
  text-align: center;
}

.zmc__section-head--center h2 {
  grid-column: 1 / -1;
  max-width: 24ch;
}

.zmc__section-head--center .zmc__lead {
  grid-column: 1 / -1;
  margin-top: 14px;
  padding-top: 0;
}

@media (max-width: 940px) {
  .zmc__section-head {
    grid-template-columns: minmax(0, 1fr);
    align-items: start;
  }

  .zmc__section-head h2,
  .zmc__section-head .zmc__lead {
    grid-column: 1 / -1;
    max-width: 62ch;
  }

  .zmc__section-head .zmc__lead {
    margin-top: 14px;
    padding-top: 0;
  }
}

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

.zmc__hero {
  position: relative;
  overflow: hidden;
  border-bottom: 1px solid var(--zmc-line);
  background: var(--zmc-surface);
  padding-block: clamp(44px, 5.8vw, 84px);
}

/* The road glow: a wide, soft accent wash behind the cluster, the way a
   headlight lifts the tarmac. Pure gradient — no image to load. */
.zmc__hero::before {
  content: "";
  position: absolute;
  z-index: 0;
  inset: -34% -12% auto auto;
  width: 820px;
  height: 820px;
  border-radius: 50%;
  background: radial-gradient(
    circle,
    color-mix(in srgb, var(--zmc-accent) 20%, transparent),
    transparent 62%
  );
  pointer-events: none;
}

/* The graticule, drawn as a hero-scoped element rather than a `.zmc__hud`
   child: the hero is a block the runtime hands us with fixed markup, so its
   texture has to be a pseudo-element. */
.zmc__hero::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  background-image:
    linear-gradient(to right, var(--zmc-hud) 1px, transparent 1px),
    linear-gradient(to bottom, var(--zmc-hud) 1px, transparent 1px);
  background-size: 68px 68px;
  -webkit-mask-image: linear-gradient(to bottom, #000, transparent 72%);
  mask-image: linear-gradient(to bottom, #000, transparent 72%);
  pointer-events: none;
}

.zmc__hero-grid {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: minmax(0, 1.02fr) minmax(0, 0.98fr);
  align-items: center;
  gap: clamp(32px, 4.5vw, 60px);
}

.zmc__hero-copy h1 {
  margin-bottom: 20px;
  max-width: 15ch;
}

.zmc__hero-copy .zmc__lead {
  max-width: 48ch;
}

/**
 * The qualifying chips, drawn as a spec strip rather than as pills.
 *
 * Four rounded pills wrapping onto two ragged rows was the single untidiest
 * thing under the hero: the second row held one and a half items and left a
 * hole beside them. Set as a bordered strip with hairline separators they hold
 * one row at desktop width and stack cleanly below it, and they read as what
 * they are — the machine's requirements, not four more buttons.
 */
.zmc__hero-notes {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  margin-top: 30px;
  border: 1px solid var(--zmc-line);
  border-radius: var(--zmc-radius);
  background: color-mix(in srgb, var(--zmc-panel) 70%, transparent);
  list-style: none;
  padding: 0;
  overflow: hidden;
}

.zmc__hero-notes li {
  padding: 11px 16px;
  color: var(--zmc-muted);
  font-size: 12.5px;
  line-height: 1.45;
}

/* Two fixed columns rather than a wrapping flex row. Flex gave the four chips a
   row of three and a hanging fourth with no divider above it, which read as a
   rendering fault. A grid divides them evenly and the borders always land on a
   cell edge. An odd last chip takes the full width instead of leaving a hole. */
.zmc__hero-notes li:nth-child(even) {
  border-inline-start: 1px solid var(--zmc-line);
}

.zmc__hero-notes li:nth-child(n + 3) {
  border-top: 1px solid var(--zmc-line);
}

.zmc__hero-notes li:last-child:nth-child(odd) {
  grid-column: 1 / -1;
}

@media (max-width: 620px) {
  .zmc__hero-notes {
    grid-template-columns: minmax(0, 1fr);
  }

  .zmc__hero-notes li:nth-child(even) {
    border-inline-start: 0;
  }

  .zmc__hero-notes li + li {
    border-top: 1px solid var(--zmc-line);
  }
}

/* -------------------------------------------------------------------------
 * The instrument cluster
 * ---------------------------------------------------------------------- */

.zmc__cluster {
  position: relative;
  overflow: hidden;
  border: 1px solid var(--zmc-line);
  border-radius: 22px;
  background: #0e1116;
  box-shadow: var(--zmc-shadow);
  padding: 22px;
  color: #e9edf2;
}

/* No opacity on the wrapper any more.
   Fading the whole layer also made it a stacking context, which is why the old
   marker had to live outside the svg — and outside the svg it could not sit on
   the road. Each layer now carries its own fade, so the route, the roadside
   markers and the car stay at full strength on top of dimmed streets. */
.zmc__cluster-map {
  position: absolute;
  inset: 0;
}

/* Above the scrim — see the note in index.tsx. Not interactive, so it must never
   swallow a click aimed at the buttons underneath it. */
.zmc__cluster-nav {
  position: absolute;
  z-index: 1;
  inset: 0;
  pointer-events: none;
}

.zmc__cluster-nav svg {
  width: 100%;
  height: 100%;
}

.zmc__cluster-map svg {
  width: 100%;
  height: 100%;
}

/* A scrim between the map and the readings.
   Without it, a road line runs straight through the GPS status line and the
   trip figures — which is the one thing an instrument panel may never do. It is
   heaviest at the bottom, where the small text is, and lightest across the
   middle, where the route is meant to show. */
.zmc__cluster::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(
    to bottom,
    rgba(14, 17, 22, 0.62) 0%,
    rgba(14, 17, 22, 0.28) 42%,
    rgba(14, 17, 22, 0.82) 78%,
    rgba(14, 17, 22, 0.94) 100%
  );
  pointer-events: none;
}

.zmc__map-ground {
  opacity: 0.5;
}

.zmc__map-streets {
  opacity: 0.62;
}

.zmc__park {
  fill: #18251c;
}

.zmc__water {
  fill: #14202e;
}

.zmc__road {
  fill: none;
  stroke-linecap: round;
}

.zmc__road--minor {
  stroke: #232a34;
  stroke-width: 7;
}

.zmc__road--major {
  stroke: #2d3644;
  stroke-width: 12;
}

/* ----- the route ------------------------------------------------------------
   Three strokes over one another: a dark casing so the line survives crossing a
   major road, the solid route, then a dashed overlay that travels. The travelling
   dashes are what say "navigating now" rather than "a line was drawn here". */
.zmc__route-casing,
.zmc__route,
.zmc__route-flow {
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.zmc__route-casing {
  stroke: #0b1a2e;
  stroke-width: 15;
}

.zmc__route {
  stroke: var(--zmc-accent);
  stroke-width: 10;
}

.zmc__route-flow {
  stroke: rgba(255, 255, 255, 0.5);
  stroke-width: 3.4;
  stroke-dasharray: 9 17;
  animation: zmc-route-flow 1.4s linear infinite;
}

@keyframes zmc-route-flow {
  to {
    stroke-dashoffset: -26;
  }
}

/* ----- roadside markers ----------------------------------------------------- */
/* Filled in the category colour with a white glyph, not an outlined ring: the
   panel behind them is dark and busy, and an outline at this size disappeared
   into the street grid. */
.zmc__poi-dot {
  fill: currentColor;
  stroke: rgba(8, 11, 15, 0.85);
  stroke-width: 2;
}

.zmc__poi-glyph {
  fill: #fff;
}

/* A ring that swells and fades. Staggered per category so the four markers never
   pulse in unison, which reads as a blinking error rather than as live data. */
.zmc__poi-pulse {
  fill: none;
  stroke: currentColor;
  transform-origin: center;
  animation: zmc-poi-pulse 3.2s ease-out infinite;
}

.zmc__poi--fuel {
  color: #f2a33c;
}

.zmc__poi--charge {
  color: #38c172;
  animation-delay: 1.1s;
}

.zmc__poi--charge .zmc__poi-pulse {
  animation-delay: 1.1s;
}

.zmc__poi--food {
  color: #ef6a5a;
}

.zmc__poi--food .zmc__poi-pulse {
  animation-delay: 2.2s;
}

@keyframes zmc-poi-pulse {
  0% {
    stroke-width: 2.4;
    scale: 1;
    opacity: 0.55;
  }
  70%,
  100% {
    stroke-width: 0.6;
    scale: 2.1;
    opacity: 0;
  }
}

/* ----- the car --------------------------------------------------------------
   `offset-path` must carry the SAME `d` as the ROUTE constant in index.tsx.
   `offset-rotate: auto 90deg` because the car is drawn nose-up (-Y) while the
   path angle is measured from +X. */
.zmc__map-car {
  offset-path: path(
    "M330 246 C312 198 300 176 270 158 C238 138 216 138 190 114 C164 90 158 62 124 46 C100 35 70 34 40 42"
  );
  offset-rotate: auto 90deg;
  offset-distance: 0%;
  /* Negative delay so the scene opens with the car already on the road. Starting
     at 0% parks it just off the bottom edge, which reads as "no car" for the first
     seconds — and is exactly what a screenshot or a reduced-motion visitor sees. */
  animation: zmc-drive 17s linear infinite;
  animation-delay: -6.5s;
  filter: drop-shadow(0 2px 5px rgba(0, 0, 0, 0.7));
}

@keyframes zmc-drive {
  to {
    offset-distance: 100%;
  }
}

/* White body, NOT the accent colour: the route underneath is already accent, and
   an accent car on an accent line vanished. White also matches how the app itself
   draws an unconfigured vehicle, and it is the one colour that stays legible over
   both the orange route and the dark streets. */
.zmc__car-body {
  fill: #f4f7fb;
  stroke: #0b1016;
  stroke-width: 1.2;
  paint-order: stroke;
}

.zmc__car-glass {
  fill: #1b2430;
}

.zmc__car-lamp {
  fill: #fff3c4;
}

.zmc__car-tail {
  fill: #e03a2f;
}

/* ----- the turn banner ------------------------------------------------------
   Named `zmc__turn`, not `zmc__nav`.

   It used to be `zmc__nav` — the same class the HEADER navigation carries. Every
   declaration below therefore landed on the site menu as well, which is why the
   header's five links sat inside a dark rounded panel with a border and a blur:
   the menu was wearing the instrument cluster's turn banner. Two different things
   may not share a class; they are not the same thing merely because both are
   called navigation. */
.zmc__turn {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 0 0 14px;
  padding: 10px 12px;
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 14px;
  background: rgba(10, 13, 18, 0.82);
  -webkit-backdrop-filter: blur(3px);
  backdrop-filter: blur(3px);
}

.zmc__nav-turn svg {
  display: block;
  width: 26px;
  height: 26px;
  fill: none;
  stroke: var(--zmc-accent);
  stroke-width: 2.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.zmc__nav-head {
  fill: var(--zmc-accent);
  stroke: none;
}

.zmc__nav-text {
  display: flex;
  min-width: 0;
  flex: 1;
  flex-direction: column;
  font-size: 0.82rem;
  line-height: 1.25;
  color: #c7cfda;
}

.zmc__nav-text strong {
  font-size: 1.05rem;
  color: var(--zmc-accent);
}

.zmc__nav-eta {
  flex: none;
  font-size: 0.76rem;
  color: #8b95a3;
}

@media (max-width: 420px) {
  .zmc__nav-eta {
    display: none;
  }
}

.zmc__cluster-banner,
.zmc__cluster-readout,
.zmc__cluster-road,
.zmc__cluster-trip,
.zmc__cluster-status {
  position: relative;
  z-index: 1;
}

.zmc__cluster-banner {
  margin-bottom: 16px;
  border-radius: var(--zmc-radius-sm);
  background: #c22128;
  padding: 9px 14px;
  color: #fff;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-align: center;
  text-transform: uppercase;
}

.zmc__cluster-readout {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  border-radius: var(--zmc-radius);
  background: rgba(22, 26, 33, 0.82);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  padding: 20px 22px;
}

.zmc__speed {
  display: flex;
  align-items: baseline;
  gap: 8px;
}

.zmc__speed strong {
  font-size: clamp(56px, 9vw, 82px);
  font-weight: 700;
  line-height: 0.92;
  letter-spacing: -0.05em;
  font-variant-numeric: tabular-nums;
}

.zmc__speed span {
  color: #8a93a0;
  font-size: 15px;
  font-weight: 600;
}

/* The four speed levels the app uses. Only the number changes colour — the
   sign is a road sign and never does. */
.zmc__cluster--ok .zmc__speed strong {
  color: #e9edf2;
}
.zmc__cluster--margin .zmc__speed strong {
  color: var(--zmc-margin);
}
.zmc__cluster--warn .zmc__speed strong {
  color: var(--zmc-warn);
}
.zmc__cluster--severe .zmc__speed strong {
  color: var(--zmc-severe);
}

.zmc__sign {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  flex-shrink: 0;
}

.zmc__sign-disc {
  display: grid;
  place-items: center;
  width: 84px;
  height: 84px;
  border: 9px solid var(--zmc-sign-border);
  border-radius: 50%;
  background: var(--zmc-sign-bg);
}

.zmc__sign-disc span {
  color: var(--zmc-sign-ink);
  font-size: 30px;
  font-weight: 800;
  letter-spacing: -0.04em;
  font-variant-numeric: tabular-nums;
}

.zmc__sign small {
  color: #8a93a0;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.02em;
  text-align: center;
}

.zmc__cluster-road {
  margin-top: 14px;
  padding-inline: 4px;
  color: #e9edf2;
  font-size: 15px;
  font-weight: 600;
}

.zmc__cluster-trip {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 10px;
  margin-top: 14px;
}

.zmc__cluster-trip div {
  border-radius: var(--zmc-radius-sm);
  background: rgba(22, 26, 33, 0.7);
  padding: 11px 12px;
}

.zmc__cluster-trip strong {
  display: block;
  font-size: 17px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

.zmc__cluster-trip span {
  color: #8a93a0;
  font-size: 11.5px;
}

.zmc__cluster-status {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 14px;
  padding-inline: 4px;
  color: #8a93a0;
  font-size: 12.5px;
}

.zmc__cluster-status i {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--zmc-ok);
  box-shadow: 0 0 8px var(--zmc-ok);
}

/* -------------------------------------------------------------------------
 * Stats
 * ---------------------------------------------------------------------- */

/**
 * The number strip, drawn as a readout.
 *
 * Four figures in a row with nothing but whitespace between them read as four
 * unrelated statements. Hairline dividers and mono labels make it one
 * instrument with four cells — which is also what it is: the hard numbers about
 * the build, side by side for comparison.
 */
.zmc__stats {
  position: relative;
  overflow: hidden;
  border-block: 1px solid var(--zmc-line);
  background: var(--zmc-tint);
  padding-block: clamp(28px, 3vw, 40px);
}

.zmc__stats::before {
  content: "";
  position: absolute;
  inset: -1px 0 auto;
  height: 2px;
  background: repeating-linear-gradient(
    90deg,
    color-mix(in srgb, var(--zmc-accent) 45%, transparent) 0 26px,
    transparent 26px 62px
  );
}

.zmc__stats-grid {
  position: relative;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 200px), 1fr));
  gap: 1px;
  background: var(--zmc-line);
  border: 1px solid var(--zmc-line);
  border-radius: var(--zmc-radius);
  overflow: hidden;
}

.zmc__stats-grid > div {
  background: var(--zmc-surface);
  padding: 20px 22px;
}

.zmc__stats-grid strong {
  display: block;
  color: var(--zmc-accent-text);
  font-size: clamp(28px, 3.1vw, 38px);
  font-weight: 700;
  letter-spacing: -0.04em;
  line-height: 1.05;
  font-variant-numeric: tabular-nums;
}

.zmc__stats-grid span {
  display: block;
  margin-top: 10px;
  font-size: 13.5px;
  font-weight: 600;
}

.zmc__stats-grid small {
  display: block;
  margin-top: 4px;
  color: var(--zmc-muted);
  font-family: var(--zmc-mono);
  font-size: 11.5px;
  line-height: 1.5;
}

/* -------------------------------------------------------------------------
 * Features
 * ---------------------------------------------------------------------- */

/**
 * The feature wall.
 *
 * `auto-fit, minmax(272px, 1fr)` fitted FOUR columns into the 1200px column,
 * so the homepage's six features came out as a row of four and an orphan row of
 * two with half the band left empty beside them. A 320px floor gives three
 * columns at desktop width, which divides six exactly.
 *
 * The `:has()` rules below handle the counts three columns cannot divide: four
 * features become a 2x2, two become a pair. A browser without `:has()` gets the
 * plain three-column grid, which is the same thing it would have got anyway.
 */
.zmc__feature-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 320px), 1fr));
  gap: 16px;
}

.zmc__feature-grid:has(> :nth-child(4):last-child),
.zmc__feature-grid:has(> :nth-child(2):last-child) {
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 400px), 1fr));
}

.zmc__feature {
  position: relative;
  overflow: hidden;
  border: 1px solid var(--zmc-line);
  border-radius: var(--zmc-radius);
  background: var(--zmc-panel);
  padding: 24px;
  transition: border-color 0.18s ease, transform 0.18s ease;
}

/* A short accent tick at the top edge, lit on hover. The same gauge-mark
   language as the eyebrow, so a card belongs to the band it sits in. */
.zmc__feature::before {
  content: "";
  position: absolute;
  inset: 0 auto auto 0;
  width: 44px;
  height: 2px;
  background: color-mix(in srgb, var(--zmc-accent) 45%, transparent);
  transition: width 0.22s ease, background 0.22s ease;
}

.zmc__feature:hover {
  border-color: color-mix(in srgb, var(--zmc-accent) 55%, var(--zmc-line));
  transform: translateY(-2px);
}

.zmc__feature:hover::before {
  width: 100%;
  background: var(--zmc-accent);
}

.zmc__feature-icon {
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  margin-bottom: 16px;
  border-radius: 11px;
  background: color-mix(in srgb, var(--zmc-accent) 16%, transparent);
  color: var(--zmc-accent-text);
}

.zmc__feature-icon .zmc__icon {
  width: 21px;
  height: 21px;
}

.zmc__feature h3 {
  margin-bottom: 8px;
  /* The four-column grid used to break titles like "A speed reading even on bad
     GPS hardware" over three lines and leave the cards in a row at three
     different heights. At three columns they hold two. */
  text-wrap: balance;
}

.zmc__feature p {
  color: var(--zmc-muted);
  font-size: 14.5px;
}

/* -------------------------------------------------------------------------
 * Decision table
 * ---------------------------------------------------------------------- */

.zmc__table-wrap {
  overflow-x: auto;
  border: 1px solid var(--zmc-line);
  border-radius: var(--zmc-radius);
  background: var(--zmc-panel);
}

.zmc__table {
  width: 100%;
  border-collapse: collapse;
  text-align: start;
}

.zmc__table th,
.zmc__table td {
  border-bottom: 1px solid var(--zmc-line);
  padding: 16px 20px;
  text-align: start;
  vertical-align: top;
}

.zmc__table thead th {
  color: var(--zmc-muted);
  font-family: var(--zmc-mono);
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  white-space: nowrap;
}

.zmc__table tbody tr:last-child th,
.zmc__table tbody tr:last-child td {
  border-bottom: 0;
}

.zmc__table tbody th {
  font-size: 15px;
  font-weight: 600;
  white-space: nowrap;
}

.zmc__table td {
  color: var(--zmc-muted);
  font-size: 14.5px;
}

.zmc__chip {
  display: inline-block;
  border: 1px solid color-mix(in srgb, var(--zmc-accent) 40%, var(--zmc-line));
  border-radius: 999px;
  background: color-mix(in srgb, var(--zmc-accent) 12%, transparent);
  padding: 4px 12px;
  color: var(--zmc-accent-text);
  font-family: var(--zmc-mono);
  font-size: 12.5px;
  white-space: nowrap;
}

/* -------------------------------------------------------------------------
 * Case studies
 * ---------------------------------------------------------------------- */

.zmc__cases {
  display: grid;
  gap: 18px;
}

.zmc__case {
  display: grid;
  grid-template-columns: 72px minmax(0, 1fr);
  gap: 8px 24px;
  border: 1px solid var(--zmc-line);
  border-radius: var(--zmc-radius);
  background: var(--zmc-panel);
  padding: 28px;
}

.zmc__case-index {
  color: color-mix(in srgb, var(--zmc-accent) 70%, transparent);
  font-family: var(--zmc-mono);
  font-size: 34px;
  font-weight: 700;
  line-height: 1;
}

.zmc__case-body h3 {
  margin-bottom: 12px;
  font-size: 20px;
}

/* The failure, set apart from the fix: a reader skimming should be able to see
   what went wrong without reading the paragraph that follows. */
.zmc__case-problem {
  border-inline-start: 2px solid var(--zmc-severe);
  margin-bottom: 12px;
  padding-inline-start: 16px;
  color: var(--zmc-ink);
  font-size: 15px;
}

.zmc__case-body p {
  color: var(--zmc-muted);
  font-size: 15px;
}

.zmc__code-ref {
  display: inline-block;
  margin-top: 14px;
  border: 1px solid var(--zmc-line);
  border-radius: 7px;
  background: var(--zmc-panel-2);
  padding: 4px 10px;
  color: var(--zmc-muted);
  font-family: var(--zmc-mono);
  font-size: 12.5px;
  overflow-wrap: anywhere;
}

/* -------------------------------------------------------------------------
 * Downloads
 * ---------------------------------------------------------------------- */

.zmc__downloads {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 280px), 1fr));
  gap: 16px;
}

.zmc__download {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 14px;
  border: 1px solid var(--zmc-line);
  border-radius: var(--zmc-radius);
  background: var(--zmc-panel);
  padding: 26px;
}

.zmc__download--pick {
  border-color: var(--zmc-accent);
  box-shadow: 0 0 0 1px var(--zmc-accent) inset;
}

.zmc__download-tag {
  position: absolute;
  top: -11px;
  inset-inline-start: 24px;
  border-radius: 999px;
  background: var(--zmc-accent);
  padding: 3px 12px;
  color: var(--zmc-on-accent);
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.zmc__download-file {
  color: var(--zmc-muted);
  font-family: var(--zmc-mono);
  font-size: 12.5px;
  overflow-wrap: anywhere;
}

.zmc__download dl {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px;
  margin-block: auto;
  border-top: 1px solid var(--zmc-line);
  padding-top: 14px;
}

.zmc__download dt {
  color: var(--zmc-muted);
  font-size: 11.5px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.zmc__download dd {
  margin: 2px 0 0;
  font-size: 15px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.zmc__download-soon {
  border: 1px dashed var(--zmc-line);
  border-radius: 999px;
  padding: 12px;
  color: var(--zmc-muted);
  font-size: 14px;
  text-align: center;
}

/* -------------------------------------------------------------------------
 * Steps
 * ---------------------------------------------------------------------- */

.zmc__steps {
  display: grid;
  gap: 16px;
  counter-reset: zmc-step;
  list-style: none;
  padding: 0;
}

/**
 * `min-width: 0` is load-bearing, not tidiness.
 *
 * These are grid items, and a grid item's default `min-width: auto` refuses to
 * shrink below its content's min-content width. The `adb connect …` block inside
 * is `white-space: pre`, so its min-content width is the full command — which
 * made each step 405px wide and pushed the whole download page into a horizontal
 * scroll at every phone width. The `overflow-x: auto` on the block below could
 * never engage, because the item had already grown to fit it.
 */
.zmc__steps li {
  position: relative;
  counter-increment: zmc-step;
  min-width: 0;
  border: 1px solid var(--zmc-line);
  border-radius: var(--zmc-radius);
  background: var(--zmc-panel);
  padding: 24px 26px 24px 76px;
}

.zmc__steps li::before {
  content: counter(zmc-step, decimal-leading-zero);
  position: absolute;
  top: 24px;
  inset-inline-start: 26px;
  color: var(--zmc-accent-text);
  font-family: var(--zmc-mono);
  font-size: 18px;
  font-weight: 700;
}

.zmc__steps h3 {
  margin-bottom: 6px;
}

.zmc__steps p {
  color: var(--zmc-muted);
  font-size: 15px;
}

.zmc__pre {
  overflow-x: auto;
  max-width: 100%;
  margin-top: 14px;
  border: 1px solid var(--zmc-line);
  border-radius: var(--zmc-radius-sm);
  background: var(--zmc-bg);
  padding: 14px 16px;
}

.zmc__pre code {
  color: var(--zmc-ink);
  font-family: var(--zmc-mono);
  font-size: 13px;
  line-height: 1.7;
  white-space: pre;
}

/* -------------------------------------------------------------------------
 * Roadmap
 * ---------------------------------------------------------------------- */

/* Three columns, not the four that `minmax(250px, 1fr)` fitted: the roadmap
   ships six milestones, and four columns turned them into a row of four and an
   orphan pair. Six divides by three. */
.zmc__roadmap {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 320px), 1fr));
  gap: 16px;
  list-style: none;
  padding: 0;
}

.zmc__roadmap:has(> :nth-child(4):last-child),
.zmc__roadmap:has(> :nth-child(2):last-child) {
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 400px), 1fr));
}

.zmc__milestone {
  border: 1px solid var(--zmc-line);
  border-top: 3px solid var(--zmc-line);
  border-radius: var(--zmc-radius);
  background: var(--zmc-panel);
  padding: 22px 24px;
}

.zmc__milestone--done {
  border-top-color: var(--zmc-ok);
}
.zmc__milestone--now {
  border-top-color: var(--zmc-accent);
}
.zmc__milestone--next {
  border-top-color: var(--zmc-margin);
}

.zmc__milestone-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 14px;
}

.zmc__milestone-version {
  font-family: var(--zmc-mono);
  font-size: 15px;
  font-weight: 700;
}

.zmc__milestone-state {
  border-radius: 999px;
  background: var(--zmc-panel-2);
  padding: 3px 11px;
  color: var(--zmc-muted);
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.zmc__milestone--done .zmc__milestone-state {
  background: color-mix(in srgb, var(--zmc-ok) 18%, transparent);
  color: var(--zmc-ok);
}

.zmc__milestone--now .zmc__milestone-state {
  background: color-mix(in srgb, var(--zmc-accent) 18%, transparent);
  color: var(--zmc-accent-text);
}

.zmc__milestone h3 {
  margin-bottom: 8px;
}

.zmc__milestone p {
  color: var(--zmc-muted);
  font-size: 14.5px;
}

/* -------------------------------------------------------------------------
 * FAQ
 * ---------------------------------------------------------------------- */

.zmc__faq {
  display: grid;
  gap: 10px;
}

.zmc__faq details {
  border: 1px solid var(--zmc-line);
  border-radius: var(--zmc-radius-sm);
  background: var(--zmc-panel);
}

.zmc__faq summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 18px;
  padding: 18px 22px;
  font-size: 16px;
  font-weight: 600;
  cursor: pointer;
  list-style: none;
}

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

.zmc__faq summary i {
  position: relative;
  flex-shrink: 0;
  width: 13px;
  height: 13px;
}

.zmc__faq summary i::before,
.zmc__faq summary i::after {
  content: "";
  position: absolute;
  inset-inline: 0;
  top: 6px;
  height: 1.5px;
  background: var(--zmc-accent);
  transition: transform 0.18s ease;
}

.zmc__faq summary i::after {
  transform: rotate(90deg);
}

.zmc__faq details[open] summary i::after {
  transform: rotate(0deg);
}

.zmc__faq-answer {
  border-top: 1px solid var(--zmc-line);
  padding: 18px 22px;
  color: var(--zmc-muted);
  font-size: 15px;
}

/* -------------------------------------------------------------------------
 * Notice
 * ---------------------------------------------------------------------- */

/* A notice belongs to what it qualifies, so it is drawn tight against it. Its
   own band used to add 64px above and below on top of the neighbouring
   section's, which put it alone in the middle of a screenful of nothing. */
.zmc__notice {
  padding-block: clamp(20px, 2.4vw, 32px);
}

.zmc__notice-inner {
  display: grid;
  grid-template-columns: 40px minmax(0, 1fr);
  gap: 18px;
  border: 1px solid var(--zmc-line);
  border-inline-start: 3px solid var(--zmc-muted);
  border-radius: var(--zmc-radius);
  background: var(--zmc-panel);
  padding: 24px 26px;
}

.zmc__notice-mark {
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: var(--zmc-panel-2);
  color: var(--zmc-muted);
  font-size: 19px;
  font-weight: 800;
}

.zmc__notice h2 {
  margin-bottom: 10px;
  font-size: 21px;
}

.zmc__notice p {
  color: var(--zmc-muted);
  font-size: 15px;
}

.zmc__notice--info .zmc__notice-inner {
  border-inline-start-color: var(--zmc-accent);
}
.zmc__notice--info .zmc__notice-mark {
  background: color-mix(in srgb, var(--zmc-accent) 18%, transparent);
  color: var(--zmc-accent-text);
}

.zmc__notice--warn .zmc__notice-inner {
  border-inline-start-color: var(--zmc-warn);
}
.zmc__notice--warn .zmc__notice-mark {
  background: color-mix(in srgb, var(--zmc-warn) 18%, transparent);
  color: var(--zmc-warn);
}

.zmc__notice--critical .zmc__notice-inner {
  border-inline-start-color: var(--zmc-severe);
}
.zmc__notice--critical .zmc__notice-mark {
  background: color-mix(in srgb, var(--zmc-severe) 18%, transparent);
  color: var(--zmc-severe);
}

.zmc__notice-list {
  display: grid;
  gap: 12px;
  margin-top: 18px;
  list-style: none;
  padding: 0;
}

.zmc__notice-list li {
  border-top: 1px solid var(--zmc-line);
  padding-top: 12px;
}

.zmc__notice-list strong {
  display: block;
  font-size: 15px;
}

.zmc__notice-list span {
  display: block;
  margin-top: 3px;
  color: var(--zmc-muted);
  font-size: 14.5px;
}

/* -------------------------------------------------------------------------
 * Plugin forms
 *
 * `core/form` is rendered by the RUNTIME, not by this theme — it is an
 * interactive island and a server-rendered theme has no way to draw one. What
 * the runtime ships is deliberately plain: `zcms-form__*` classes plus inline
 * styles as a floor, so a form is never unstyled on a theme that ignored it.
 *
 * Inline styles cannot be beaten by specificity, which is why the declarations
 * that restate one carry `!important`. That is the intended override path here
 * (the medical theme does the same) and not a shortcut around a specificity bug:
 * the runtime's white input and near-black button are light-mode constants, and
 * on a dark page they would be a white box and an invisible button.
 *
 * How WIDE a form is, though, is not decided here. The runtime's 560px cap is
 * dropped because the panel is meant to fill whatever column it is given, and the
 * column comes from `.zmc__form-band` — the `zmc__section` + `zmc__measure`
 * wrapper `BlockFlow` puts around a `core/form` block, the same 760px column the
 * prose and the FAQ read at. Without that wrapper the dropped cap is what makes a
 * form run edge to edge across the window, so the two belong together.
 * ---------------------------------------------------------------------- */

.zmc .zcms-form {
  max-width: none !important;
  gap: 16px !important;
  border: 1px solid var(--zmc-line);
  border-radius: var(--zmc-radius);
  background: var(--zmc-panel);
  padding: clamp(24px, 3vw, 34px);
}

.zmc .zcms-form__title {
  color: var(--zmc-ink);
  font-size: 21px !important;
  letter-spacing: -0.02em;
}

.zmc .zcms-form__label {
  color: var(--zmc-muted);
  font-size: 12.5px !important;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

.zmc .zcms-form input,
.zmc .zcms-form select,
.zmc .zcms-form textarea {
  border-color: var(--zmc-line) !important;
  border-radius: var(--zmc-radius-sm) !important;
  background: var(--zmc-bg) !important;
  color: var(--zmc-ink) !important;
  padding: 12px 14px !important;
}

.zmc .zcms-form input:focus,
.zmc .zcms-form select:focus,
.zmc .zcms-form textarea:focus {
  border-color: var(--zmc-accent) !important;
  outline: 3px solid color-mix(in srgb, var(--zmc-accent) 20%, transparent);
  outline-offset: 0;
}

.zmc .zcms-form__submit {
  min-height: 46px;
  border-radius: 999px !important;
  background: var(--zmc-accent) !important;
  color: var(--zmc-on-accent) !important;
  padding-inline: 26px !important;
}

.zmc .zcms-form__error {
  color: var(--zmc-severe) !important;
}

.zmc .zcms-form--done {
  border: 1px solid color-mix(in srgb, var(--zmc-ok) 40%, var(--zmc-line));
  border-radius: var(--zmc-radius);
  background: color-mix(in srgb, var(--zmc-ok) 10%, transparent) !important;
  color: var(--zmc-ink) !important;
  padding: 22px 24px;
}

/* -------------------------------------------------------------------------
 * CTA
 * ---------------------------------------------------------------------- */

/**
 * The closing band.
 *
 * It used to be a bordered card floating inside a section that itself had 84px
 * of padding above and below — a small panel adrift in a large empty band, at
 * the exact point in the page where the reader is meant to act. It is now the
 * band: full bleed, its own lane marking and graticule, sitting hard against
 * the footer so the page ends on the call rather than on more air.
 */
.zmc__cta {
  position: relative;
  overflow: hidden;
  border-block: 1px solid color-mix(in srgb, var(--zmc-accent) 30%, var(--zmc-line));
  background:
    radial-gradient(
      100% 160% at 82% 0%,
      color-mix(in srgb, var(--zmc-accent) 20%, transparent),
      transparent 60%
    ),
    var(--zmc-surface);
  padding-block: clamp(40px, 4.6vw, 68px);
}

.zmc__cta::before {
  content: "";
  position: absolute;
  inset: -1px 0 auto;
  height: 2px;
  background: repeating-linear-gradient(
    90deg,
    var(--zmc-accent) 0 26px,
    transparent 26px 62px
  );
  opacity: 0.75;
}

.zmc__cta::after {
  content: "";
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(to right, var(--zmc-hud) 1px, transparent 1px),
    linear-gradient(to bottom, var(--zmc-hud) 1px, transparent 1px);
  background-size: 68px 68px;
  pointer-events: none;
}

.zmc__cta-inner {
  position: relative;
  z-index: 1;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 24px 40px;
}

.zmc__cta-inner > div {
  min-width: 0;
  flex: 1 1 420px;
}

.zmc__cta-inner h2 {
  max-width: 20ch;
}

.zmc__cta-inner .zmc__lead {
  margin-top: 12px;
  max-width: 52ch;
}

.zmc__cta-inner .zmc__actions {
  flex: none;
  margin-top: 0;
}

/* -------------------------------------------------------------------------
 * Page, post, archive
 * ---------------------------------------------------------------------- */

/**
 * The page and post masthead.
 *
 * Its padding used to be `clamp(48px, 7vw, 88px)`, and the section under it
 * added its own on top: an inner page opened with roughly 300px of empty band
 * between the title and the first sentence. It is now a compact band, and on a
 * wide screen the title and its standfirst sit side by side for the same reason
 * the section head does — a 54px heading in the left 60% of the column with
 * nothing beside it is the shape that made this site look empty.
 */
.zmc__page-head {
  position: relative;
  overflow: hidden;
  border-bottom: 1px solid var(--zmc-line);
  background: var(--zmc-surface);
  padding-block: clamp(38px, 4.2vw, 60px);
}

.zmc__page-head > .zmc__container {
  position: relative;
  z-index: 1;
}

.zmc__page-head--image .zmc__page-head-img {
  position: absolute;
  inset: 0;
  z-index: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0.24;
}

.zmc__page-head h1 {
  max-width: 20ch;
  text-wrap: balance;
}

.zmc__page-head .zmc__lead {
  margin-top: 16px;
}

@media (min-width: 941px) {
  /* Only where the head is a plain container — the post head reads at
     `zmc__measure` width, where a second column would be 300px wide. */
  .zmc__page-head > .zmc__container:not(.zmc__measure) {
    display: grid;
    grid-template-columns: minmax(0, 1.08fr) minmax(0, 0.92fr);
    column-gap: clamp(28px, 4vw, 64px);
    align-items: start;
  }

  .zmc__page-head > .zmc__container:not(.zmc__measure) > .zmc__eyebrow {
    grid-column: 1 / -1;
  }

  .zmc__page-head > .zmc__container:not(.zmc__measure) > h1 {
    grid-column: 1;
  }

  .zmc__page-head > .zmc__container:not(.zmc__measure) > .zmc__lead {
    grid-column: 2;
    margin-top: 0;
    padding-top: 12px;
  }
}

/* An article opens on its first sentence, not on a screenful of band. */
.zmc__post .zmc__page-head {
  padding-bottom: clamp(26px, 2.8vw, 38px);
}

.zmc__post-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 18px;
  margin-top: 20px;
  color: var(--zmc-muted);
  font-family: var(--zmc-mono);
  font-size: 12.5px;
}

/* Interpuncts between the meta items rather than whitespace alone: three grey
   phrases spaced apart read as three unrelated labels. */
.zmc__post-meta > * + *::before {
  content: "·";
  margin-inline-end: 18px;
  color: var(--zmc-line);
}

.zmc__prose {
  font-size: 16.5px;
}

.zmc__prose > div > * + * {
  margin-top: 20px;
}

.zmc__prose h2 {
  margin-top: 42px;
  font-size: 26px;
}

.zmc__prose h3 {
  margin-top: 32px;
  font-size: 19px;
}

.zmc__prose p,
.zmc__prose li {
  color: var(--zmc-muted);
}

.zmc__prose strong {
  color: var(--zmc-ink);
}

.zmc__prose ul,
.zmc__prose ol {
  padding-inline-start: 22px;
}

.zmc__prose li + li {
  margin-top: 8px;
}

.zmc__prose a {
  color: var(--zmc-accent-text);
  text-decoration: underline;
  text-underline-offset: 3px;
}

.zmc__prose code {
  border-radius: 5px;
  background: var(--zmc-panel-2);
  padding: 2px 6px;
  font-family: var(--zmc-mono);
  font-size: 0.88em;
}

.zmc__prose pre {
  overflow-x: auto;
  border: 1px solid var(--zmc-line);
  border-radius: var(--zmc-radius-sm);
  background: var(--zmc-surface);
  padding: 16px 18px;
}

.zmc__prose pre code {
  background: none;
  padding: 0;
}

.zmc__prose blockquote {
  border-inline-start: 3px solid var(--zmc-accent);
  margin: 0;
  padding-inline-start: 20px;
  color: var(--zmc-ink);
}

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

.zmc__prose th,
.zmc__prose td {
  border-bottom: 1px solid var(--zmc-line);
  padding: 12px 14px;
  text-align: start;
}

.zmc__figure {
  margin: 0;
}

.zmc__figure img {
  width: 100%;
  border-radius: var(--zmc-radius);
}

.zmc__figure figcaption {
  margin-top: 12px;
  color: var(--zmc-muted);
  font-size: 13.5px;
  text-align: center;
}

.zmc__post-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 320px), 1fr));
  gap: 16px;
}

.zmc__post-grid:has(> :nth-child(4):last-child),
.zmc__post-grid:has(> :nth-child(2):last-child) {
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 400px), 1fr));
}

.zmc__post-card {
  display: flex;
  flex-direction: column;
  gap: 18px;
  border: 1px solid var(--zmc-line);
  border-radius: var(--zmc-radius);
  background: var(--zmc-panel);
  padding: 26px;
  transition: border-color 0.18s ease;
}

.zmc__post-card:hover {
  border-color: color-mix(in srgb, var(--zmc-accent) 55%, var(--zmc-line));
}

.zmc__post-card-body {
  flex: 1;
}

.zmc__post-card-date {
  margin-bottom: 10px;
  color: var(--zmc-muted);
  font-family: var(--zmc-mono);
  font-size: 12px;
}

.zmc__post-card h3 {
  margin-bottom: 10px;
  font-size: 19px;
}

.zmc__post-card p {
  color: var(--zmc-muted);
  font-size: 14.5px;
}

.zmc__pager {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 8px;
  margin-top: 44px;
}

.zmc__pager a {
  display: grid;
  place-items: center;
  min-width: 42px;
  height: 42px;
  border: 1px solid var(--zmc-line);
  border-radius: var(--zmc-radius-sm);
  padding-inline: 12px;
  font-size: 14px;
  font-weight: 600;
}

.zmc__pager a[aria-current="page"] {
  border-color: var(--zmc-accent);
  background: var(--zmc-accent);
  color: var(--zmc-on-accent);
}

/* -------------------------------------------------------------------------
 * 404 / error
 * ---------------------------------------------------------------------- */

.zmc__state {
  display: grid;
  place-items: center;
  min-height: 64vh;
  padding-block: 80px;
  text-align: center;
}

.zmc__state .zmc__sign {
  margin-inline: auto;
  margin-bottom: 28px;
}

.zmc__state .zmc__sign-disc span {
  font-size: 26px;
}

.zmc__state h1 {
  font-size: clamp(28px, 4vw, 40px);
}

.zmc__state p {
  margin-top: 16px;
  color: var(--zmc-muted);
}

.zmc__state .zmc__actions {
  justify-content: center;
}

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

.zmc__footer {
  border-top: 1px solid var(--zmc-line);
  background: var(--zmc-surface);
  padding-block: 60px 32px;
}

.zmc__footer-grid {
  display: grid;
  grid-template-columns: minmax(0, 1.6fr) repeat(3, minmax(0, 1fr));
  gap: 40px;
}

.zmc__footer-about p {
  margin-top: 18px;
  max-width: 44ch;
  color: var(--zmc-muted);
  font-size: 14.5px;
}

.zmc__footer-build {
  font-family: var(--zmc-mono);
  font-size: 12.5px;
}

.zmc__footer-col h2 {
  margin-bottom: 16px;
  color: var(--zmc-muted);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.zmc__footer-col ul {
  display: grid;
  gap: 10px;
  list-style: none;
  padding: 0;
}

.zmc__footer-col a {
  color: var(--zmc-muted);
  font-size: 14.5px;
}

.zmc__footer-col a:hover {
  color: var(--zmc-accent-text);
}

.zmc__footer-contact {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 10px;
}

.zmc__footer-contact .zmc__button {
  margin-top: 8px;
}

.zmc__disclaimer {
  margin-top: 44px;
  border: 1px solid color-mix(in srgb, var(--zmc-warn) 32%, var(--zmc-line));
  border-radius: var(--zmc-radius-sm);
  background: color-mix(in srgb, var(--zmc-warn) 8%, transparent);
  padding: 14px 18px;
  color: var(--zmc-muted);
  font-size: 13.5px;
}

.zmc__footer-bottom {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 12px 24px;
  margin-top: 26px;
  border-top: 1px solid var(--zmc-line);
  padding-top: 22px;
  color: var(--zmc-muted);
  font-size: 13px;
}

.zmc__footer-bottom div {
  display: flex;
  flex-wrap: wrap;
  gap: 20px;
}

/* Copyright and platform credit read as one line on a wide screen and stack on a
   narrow one, rather than the credit being pushed onto a row of its own. */
.zmc__footer-copy {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px 18px;
}

/**
 * Quieter than the legal links beside it: a credit, not a destination.
 *
 * Separated by the flex `gap` above and nothing else. A bullet drawn as a
 * pseudo-element looked right on one line and then wrapped WITH the link at
 * 360px, leaving a dot leading the second line like a stray list marker. A gap
 * cannot wrap to the wrong place.
 */
.zmc__builtwith {
  color: var(--zmc-muted);
}

.zmc__builtwith:hover {
  color: var(--zmc-accent-text);
}

.zmc__footer-bottom a:hover {
  color: var(--zmc-accent-text);
}

/* -------------------------------------------------------------------------
 * Responsive
 *
 * One breakpoint per thing that actually breaks, rather than a global set of
 * device widths: the hero stacks before the nav needs to, and the decision
 * table has to change SHAPE rather than shrink.
 * ---------------------------------------------------------------------- */

@media (max-width: 1080px) {
  .zmc__hero-grid {
    grid-template-columns: minmax(0, 1fr);
  }

  .zmc__cluster {
    max-width: 520px;
  }

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

  /**
   * The header splits into two bands: brand + controls, then the nav.
   *
   * This used to happen at 860px, which left 861–1080 trying to fit brand,
   * version pill, five nav labels, a language switcher, a mode toggle and a
   * download button onto one row. At 1024 there was not enough width and every
   * label wrapped down the middle — "Tính / năng", "Hướng / dẫn". The single row
   * needs about 1100px to breathe, so that is where it now ends; below it, the
   * two-band layout that already reads well on a phone.
   */
  .zmc__header-inner {
    flex-wrap: wrap;
    gap: 12px 14px;
    padding-block: 12px;
  }

  /* Takes the leftover width so the controls sit hard against the end edge, and
     `min-width: 0` lets the brand text ellipsize instead of forcing a wrap. */
  .zmc__brand {
    flex: 1 1 auto;
    min-width: 0;
  }

  .zmc__header-actions {
    margin-inline-start: auto;
  }

  .zmc__nav {
    order: 3;
    width: 100%;
    margin-inline-start: 0;
  }

  /**
   * The nav WRAPS rather than scrolls. It used to be an `overflow-x: auto`
   * strip, on the reasoning that a hamburger would need JavaScript this theme
   * does not ship — true, and still not a reason to hide links. At 390px that
   * strip cut "Lộ trình" in half and put "Ghi chép" past the edge behind a
   * scrollbar nobody can see on a touch screen: two of five destinations gone.
   * Five short labels wrap to two tidy rows, all reachable without a gesture.
   */
  .zmc__nav ul {
    flex-wrap: wrap;
    gap: 2px 4px;
  }

  /* The dropdown's anchor flips with the header: the switcher is no longer the
     last thing on the row, it is the first. See `.zmc__lang ul`. */
  .zmc__lang ul {
    inset-inline-start: 0;
    inset-inline-end: auto;
  }

  .zmc__version-pill {
    display: none;
  }
}

@media (max-width: 860px) {
  .zmc__container,
  .zmc__measure {
    width: calc(100% - 32px);
  }

  .zmc__measure {
    margin-inline: 16px auto;
  }

  .zmc__case {
    grid-template-columns: minmax(0, 1fr);
    gap: 10px;
  }

  .zmc__cta-inner {
    flex-direction: column;
    align-items: flex-start;
  }
}

@media (max-width: 700px) {
  /* The table becomes records. Each cell carries its column name, which the
     header row was providing until it stopped being visible. */
  .zmc__table thead {
    display: none;
  }

  .zmc__table,
  .zmc__table tbody,
  .zmc__table tr,
  .zmc__table th,
  .zmc__table td {
    display: block;
    width: 100%;
  }

  .zmc__table tr {
    border-bottom: 1px solid var(--zmc-line);
    padding: 8px 0;
  }

  .zmc__table tbody tr:last-child {
    border-bottom: 0;
  }

  .zmc__table th,
  .zmc__table td {
    border-bottom: 0;
    padding: 6px 20px;
    white-space: normal;
  }

  .zmc__table td::before {
    content: attr(data-label);
    display: block;
    margin-bottom: 4px;
    color: var(--zmc-muted);
    font-family: var(--zmc-mono);
    font-size: 11px;
    letter-spacing: 0.1em;
    text-transform: uppercase;
  }

  .zmc__cluster-readout {
    flex-direction: column;
    align-items: flex-start;
    gap: 16px;
  }

  .zmc__footer-grid {
    grid-template-columns: minmax(0, 1fr);
    gap: 32px;
  }

  .zmc__steps li {
    padding: 22px 20px 22px 20px;
  }

  .zmc__steps li::before {
    position: static;
    display: block;
    margin-bottom: 8px;
  }
}

/* Phones held in one hand. */
@media (max-width: 520px) {
  /* The tagline goes first: it is the one line in the header that repeats what
     the page immediately below already says, and at 320px it wrapped to two rows
     of chrome the reader wants to scroll past. The brand NAME stays, truncated
     rather than wrapped, so the header keeps a predictable height. */
  .zmc__brand-text small {
    display: none;
  }

  .zmc__brand-text strong {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .zmc__header-actions {
    gap: 8px;
  }

  .zmc__button--small {
    padding: 9px 15px;
  }

  /* Full-bleed rather than a card at the very bottom of the range: 16px of
     gutter on each side of a 320px screen is 10% of the reading width. */
  .zmc__container,
  .zmc__measure {
    width: calc(100% - 24px);
  }

  .zmc__measure {
    margin-inline: 12px auto;
  }
}

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

  /* Killing the duration alone would snap the car to the END of the route and
     leave the pulse rings mid-swell. Park the scene somewhere it looks composed
     instead: car partway along the road, rings gone. */
  .zmc__map-car {
    animation: none !important;
    offset-distance: 46%;
  }

  .zmc__poi-pulse {
    animation: none !important;
    opacity: 0;
  }

  .zmc__route-flow {
    animation: none !important;
  }
}


/* ===== product showcase =====================================================
   Real screenshots in a head-unit bezel. The frame matters: a bare screenshot of
   a dark UI on a dark page dissolves into the background, and the reader cannot
   tell where the product stops and the page starts.

   The frames are a FIXED aspect ratio and the images cover them. That is the
   fix for what this section looked like before: the shipped shots are 1400x630
   and 2400x900, so `height: auto` gave every frame a different height, and the
   two captions in a row started 42px apart from one another — the row read as
   broken rather than as two items. An owner who uploads a portrait screenshot
   used to break the row the same way; now the frame decides, and the row holds
   whatever it is given. */
.zmc__shots {
  display: grid;
  gap: 18px;
  grid-template-columns: 1fr;
}

@media (min-width: 900px) {
  .zmc__shots {
    grid-template-columns: repeat(2, 1fr);
  }

  /* The first shot is the main screen — give it the full width so the speed
     figure and the limit sign stay readable at a glance. */
  .zmc__shot:first-child {
    grid-column: 1 / -1;
  }

  /* Three shots with the first full width leave a clean 1 + 2. An even count
     has no featured shot to give the width to: two equal rows read better than
     one wide item followed by a ragged pair. */
  .zmc__shots:has(> :nth-child(2):last-child) .zmc__shot:first-child,
  .zmc__shots:has(> :nth-child(4):last-child) .zmc__shot:first-child {
    grid-column: auto;
  }
}

.zmc__shot {
  margin: 0;
  display: grid;
  grid-template-rows: auto 1fr;
  gap: 12px;
}

.zmc__shot-frame {
  position: relative;
  overflow: hidden;
  border: 1px solid var(--zmc-line);
  border-radius: var(--zmc-radius-lg);
  background: #05070a;
  padding: 7px;
  box-shadow: var(--zmc-shadow);
}

.zmc__shot-frame img {
  display: block;
  width: 100%;
  height: 100%;
  /* 20:9, the shape of the head units these were taken on. `cover` rather than
     `contain`: a letterboxed screenshot floating in a black frame was the other
     half of what made this section look unfinished. */
  aspect-ratio: 20 / 9;
  object-fit: cover;
  object-position: center;
  border-radius: 13px;
}

/* The featured shot keeps 20:9 as well, deliberately.
   A wider frame would crop it — and the one screenshot in this section that must
   NOT be cropped is the driving screen, where the top bar carries the turn
   instruction and the bottom strip carries the trip figures. Losing either to a
   crop would show the reader a screen the app never draws. The featured shot is
   already prominent by being twice as wide. */

.zmc__shot figcaption {
  display: flex;
  flex-direction: column;
  gap: 4px;
  border-inline-start: 2px solid color-mix(in srgb, var(--zmc-accent) 50%, transparent);
  padding-inline-start: 14px;
}

.zmc__shot figcaption strong {
  font-size: 15.5px;
  color: var(--zmc-ink);
}

.zmc__shot figcaption span {
  font-size: 14px;
  line-height: 1.55;
  color: var(--zmc-muted);
}

@media print {
  .zmc__header,
  .zmc__footer,
  .zmc__cta,
  .zmc__skip {
    display: none;
  }
}
