/* Generated by tools/fetch-fonts.mjs — do not edit by hand.
   Self-hosted on purpose: linking the Google CDN would leak visitor IPs
   outside the EU before any interaction (TZ §5.3). */

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

/* Bebas Neue 400 — latin */
@font-face {
  font-family: 'Bebas Neue';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/assets/fonts/bebas-neue-400-latin.441b026d.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;
}

/* Roboto Condensed 400 — cyrillic */
@font-face {
  font-family: 'Roboto Condensed';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/assets/fonts/roboto-condensed-400-cyrillic.b96fbbb3.woff2') format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}

/* Roboto Condensed 400 — greek */
@font-face {
  font-family: 'Roboto Condensed';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/assets/fonts/roboto-condensed-400-greek.9b3a8cab.woff2') format('woff2');
  unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
}

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

/* Roboto Condensed 400 — latin */
@font-face {
  font-family: 'Roboto Condensed';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/assets/fonts/roboto-condensed-400-latin.718ced55.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;
}

/* Roboto Condensed 700 — cyrillic */
@font-face {
  font-family: 'Roboto Condensed';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('/assets/fonts/roboto-condensed-700-cyrillic.b96fbbb3.woff2') format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}

/* Roboto Condensed 700 — greek */
@font-face {
  font-family: 'Roboto Condensed';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('/assets/fonts/roboto-condensed-700-greek.9b3a8cab.woff2') format('woff2');
  unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
}

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

/* Roboto Condensed 700 — latin */
@font-face {
  font-family: 'Roboto Condensed';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('/assets/fonts/roboto-condensed-700-latin.718ced55.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;
}

/* Share Tech Mono 400 — latin */
@font-face {
  font-family: 'Share Tech Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/assets/fonts/share-tech-mono-400-latin.73b87eb7.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;
}

/* Brand tokens — copied by value, not imported from the platform: the landing
   page is a standalone project (TZ Appendix B). */
:root {
  --bg-page:   #06080f;
  --bg-deep:   #0c1020;
  --bg-card:   #121826;
  --text:      #ffffff;
  --text-2:    #d9d9d9;
  --text-3:    #c8c8c8;
  /* Warm variants, used over the photographic hero. Neutral greys next to a
     sunset read as a different design pasted on top. */
  --text-warm:   #fff4e8;
  --text-warm-2: #e6d4c2;
  --accent:    #e84b0a;
  /* The wordmark and tagline use the loader's brighter orange, not the UI
     accent — matching the app's launch screen rather than its controls. */
  --logo-accent: #ff5500;
  --teal:      #00d496;
  --border:    rgba(232, 75, 10, 0.30);
  --border-on: rgba(232, 75, 10, 0.70);
  --border-n:  rgba(50, 85, 170, 0.28);

  /* No opacity below 0.7 for text or interactive borders — the site is read in
     sunlight, from a phone, wearing gloves. */

  /* One text face for every language, matching the platform — which imports
     Roboto Condensed for its whole UI (the variable there is still called
     --font-barlow-condensed, but Barlow is not the font behind it).
     --font-brand is Bebas, and it is used ONLY where the text is Latin by
     definition: the wordmark and the English tagline. Everything else, headings
     included, is one face, so Russian and Greek are not a different design. */
  --font-brand: 'Bebas Neue', 'Roboto Condensed', system-ui, sans-serif;
  --font-ui:    'Roboto Condensed', system-ui, sans-serif;
  --font-data:  'Share Tech Mono', 'Roboto Condensed', ui-monospace, monospace;

  --display-tracking: .02em;
  --pad: clamp(20px, 5vw, 48px);
  --gap: clamp(48px, 9vw, 96px);
  --radius: 12px;
  --maxw: 1280px;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--bg-page);
  color: var(--text);
  font-family: var(--font-ui);
  font-size: 18px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

/* A long unbreakable word must wrap, not push the page sideways. Pseudo-locale
   testing produced horizontal overflow without this, and German compounds or a
   stray URL in a translation would do the same for real. */
h1, h2, h3, h4, p, li, summary, a, .price {
  overflow-wrap: break-word;
}

/* break-word alone is not enough: it wraps the text but does not shrink the
   element's min-content width, and grid/flex children default to
   min-width:auto — so the track kept the long word's full width and stretched
   the page to 1524px at a 390px viewport. */
.grid-2 > *, .grid-3 > *, .footer-cols > *,
.place > *, .faq summary {
  min-width: 0;
}

h1, h2, h3, h4 {
  font-family: var(--font-ui);
  font-weight: 700;
  letter-spacing: var(--display-tracking);
  line-height: 1.05;
  margin: 0;
}
h1, h2, .logo { text-transform: uppercase; }

h1 { font-size: clamp(40px, 8vw, 72px); }
h2 { font-size: clamp(30px, 5vw, 48px); }
h3 { font-size: clamp(20px, 2.4vw, 24px); text-transform: none; }
h4 { font-size: 15px; text-transform: uppercase; letter-spacing: .08em; color: var(--text-3); }
p  { margin: 0; }
img { max-width: 100%; height: auto; }

a { color: inherit; }

.skip {
  position: absolute;
  inset-inline-start: -9999px;
}
.skip:focus {
  inset-inline-start: 8px;
  inset-block-start: 8px;
  z-index: 100;
  background: var(--accent);
  padding: 10px 16px;
  border-radius: 8px;
}

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

section { padding-block: var(--gap); }
section > h2 { margin-block-end: 40px; text-align: center; }

.grid-3, .grid-2, .footer-cols, .faq, .final, .pricing > .hint {
  max-width: var(--maxw);
  margin-inline: auto;
  padding-inline: var(--pad);
}

/* ------------------------------------------------------------------ header */

.site-header {
  position: sticky;
  inset-block-start: 0;
  z-index: 50;
  display: flex;
  align-items: center;
  gap: 20px;
  padding: 12px var(--pad);
  background: rgba(6, 8, 15, .97);
  border-block-end: 1px solid var(--border);
  backdrop-filter: blur(8px);
}

/* The mark is the helmet plus the wordmark — the helmet is the base, the text
   the second half. Both taken from the app's loading screen (MEGA white, RIDER
   in the loader's orange, Bebas with wide tracking) so the site and the app
   read as one brand rather than two designs of the same name. */
.logo {
  display: inline-flex;
  align-items: center;
  gap: 11px;
  font-family: var(--font-brand);
  font-weight: 400;
  font-size: 22px;
  text-decoration: none;
  letter-spacing: .22em;
  /* Padding, not a fixed height: the wordmark alone is a small target for a
     link people reach for one-handed. */
  padding-block: 10px;
  white-space: nowrap;
}
.logo-helmet {
  /* Intrinsic 118×148; height drives it so the wordmark stays the anchor. */
  height: 34px;
  width: auto;
  flex-shrink: 0;
  filter: drop-shadow(0 0 10px rgba(255, 85, 0, .35));
}
.logo-text  { display: inline-flex; }
.logo-mega  { color: var(--text); text-shadow: 0 0 30px rgba(255, 255, 255, .10); }
.logo-rider { color: var(--logo-accent); }

/* Larger in the footer, where it is the brand block rather than navigation. */
.footer-brand .logo { font-size: 26px; }
.footer-brand .logo-helmet { height: 42px; }

/* The tagline is a brand constant, never translated (see config.mjs). */
.tagline {
  font-family: var(--font-ui);
  font-weight: 700;
  font-size: 13px;
  letter-spacing: .34em;
  text-transform: uppercase;
  color: var(--logo-accent);
}
/* The motto as the hero heading. Smaller than a one-word headline would be —
   it is 27 characters, and at 72px it would wrap awkwardly on a laptop. */
.hero-motto {
  font-family: var(--font-brand);
  font-weight: 400;
  font-size: clamp(34px, 6vw, 68px);
  letter-spacing: .06em;
  max-width: 18ch;
  margin-inline: auto;
  /* Warm white, not #fff. Pure white over a sunset frame reads as a screenshot
     pasted on top; a few degrees of warmth and the type belongs to the photo. */
  color: var(--text-warm);
  /* The photo has bright sky in it — the shadow keeps the type readable wherever
     the crop lands, without darkening the image further. */
  text-shadow: 0 2px 24px rgba(8, 4, 2, .55);
}

/* One word carries the colour, echoing the wordmark's MEGA/RIDER split — and
   set in exactly the orange RIDER uses, so the heading and the logo agree. */
.accent-word { color: var(--logo-accent); }

.hero-motto + .sub { margin-block-start: 22px; }

.site-nav { display: flex; gap: 22px; margin-inline-start: auto; }
.site-nav a {
  color: var(--text-2);
  text-decoration: none;
  font-size: 16px;
}
.site-nav a:hover { color: var(--text); }

.lang { display: flex; }

/* A disclosure widget, sized for a list that is meant to reach twenty entries.
   <details> is used rather than a scripted dropdown so the switcher survives
   with JS off — which matters here more than elsewhere, because someone who
   cannot read the current language has no other way out of the page. */
.lang-select { position: relative; }

.lang-select summary {
  display: flex;
  align-items: center;
  gap: 7px;
  /* ≥44px tall including padding. */
  padding: 11px 12px;
  border: 1px solid var(--border-n);
  border-radius: 8px;
  cursor: pointer;
  list-style: none;
  font-size: 15px;
  color: var(--text-2);
  /* Language names are each written in their own script, so a webfont stack
     here would pull down the fonts of every writing system in the list. */
  font-family: system-ui, -apple-system, 'Segoe UI', sans-serif;
  white-space: nowrap;
}
.lang-select summary::-webkit-details-marker { display: none; }

/* Caret drawn in CSS rather than shipped as an icon or a glyph: one border
   triangle costs nothing and rotates on open. */
.lang-select summary::after {
  content: '';
  width: 0;
  height: 0;
  border: 4px solid transparent;
  border-block-start-color: currentColor;
  margin-block-start: 4px;
  transition: transform .15s;
}
.lang-select[open] summary::after { transform: rotate(180deg); margin-block: 0 4px; }

.lang-select summary:hover { color: var(--text); border-color: var(--border-on); }

.lang-menu {
  position: absolute;
  inset-block-start: calc(100% + 6px);
  inset-inline-end: 0;
  z-index: 60;
  display: grid;
  min-width: 100%;
  padding: 6px;
  background: var(--bg-card);
  border: 1px solid var(--border-n);
  border-radius: 10px;
  box-shadow: 0 12px 32px rgba(0, 0, 0, .55);
  /* The list is expected to grow well past what fits on screen: cap it and
     scroll rather than letting it run off the viewport. */
  max-height: min(60vh, 420px);
  overflow-y: auto;
  overscroll-behavior: contain;
}

.lang-menu a {
  display: block;
  padding: 10px 14px;
  border-radius: 6px;
  text-decoration: none;
  color: var(--text-2);
  font-size: 15px;
  font-family: system-ui, -apple-system, 'Segoe UI', sans-serif;
  white-space: nowrap;
}
.lang-menu a:hover { background: rgba(232, 75, 10, .16); color: var(--text); }
.lang-menu a.is-active { color: var(--logo-accent); }

/* Past roughly a dozen entries a single column becomes a long scroll; two
   columns keep it scannable without needing a search field yet. */
@media (min-width: 480px) {
  .lang-menu:has(a:nth-child(13)) { grid-template-columns: 1fr 1fr; }
}

/* In the footer the widget sits at the bottom of the page, so it opens upward. */
.lang-footer-select .lang-menu {
  inset-block-start: auto;
  inset-block-end: calc(100% + 6px);
  inset-inline-start: 0;
  inset-inline-end: auto;
}

.burger, .lang-in-menu, .menu-close { display: none; }

/* ------------------------------------------------------------------- world */

/* Two designs share this markup. Without the engine it is a document: the whole
   map at its natural aspect, then twelve places in reading order. Everything
   that overlaps, sticks or hides lives behind `.js-world`, which the engine adds
   only once it has found every part it needs. */

.world { position: relative; }

.world-viewport {
  position: relative;
  overflow: hidden;
  aspect-ratio: 16 / 10;
  background: var(--bg-page);
  border-block: 1px solid var(--border);
}

.world-camera { position: absolute; inset: 0; }
.world-camera picture { display: block; width: 100%; height: 100%; }

/* Sized in world units by the engine, so scale(k) means k screen pixels per
   world unit and the road, the map and the markers cannot drift apart. */
.js-world .world-camera {
  inset: 0 auto auto 0;
  transform-origin: 0 0;
  will-change: transform;
}
.js-world .world-map { object-fit: fill; }

.world-map {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  user-select: none;
  -webkit-user-drag: none;
}

/* The road, in two layers. The dim one is the whole route; the live one is drawn
   in behind the rider by the engine moving its dash offset. Non-scaling strokes
   keep both a constant width however far the camera zooms in. */
.world-route {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  fill: none;
  pointer-events: none;
}
.route-base {
  stroke: rgba(255, 255, 255, .22);
  stroke-linecap: round;
}
/* Width in world units, not screen pixels: the ridden road is meant to be as
   wide as the asphalt under it, so it has to grow with the zoom the way the road
   does. The hairline guide above does the opposite — it stays thin on screen. */
/* Frosted glass. The blur comes first and the halos after it, so the bloom is
   thrown by an already-soft shape rather than by a hard edge — that ordering is
   what the look rests on, not the numbers.
   Glow on the line alone. A drop-shadow filter here costs one composited pass;
   the same effect applied to every marker costs one per marker, and that is what
   turns a smooth ride into a slideshow on a mid-range phone. */
.route-live {
  stroke: rgba(255, 100, 30, .62);
  stroke-width: 12;
  stroke-linecap: round;
  filter:
    blur(1.1px)
    drop-shadow(0 0 6px rgba(255, 85, 0, .45))
    drop-shadow(0 0 20px rgba(255, 85, 0, .28))
    drop-shadow(0 0 48px rgba(232, 75, 10, .16));
}

/* Everything but the place you are at, pulled down. Sits under the markers, so
   the pins and their names stay at full strength inside the dark. */
.world-spot {
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: 0;
}
.js-world .world-spot {
  background: radial-gradient(circle var(--spot-r, 460px) at var(--spot-x, 50%) var(--spot-y, 50%),
    rgba(6, 8, 15, 0) 0%,
    rgba(6, 8, 15, 0) 58%,
    rgba(6, 8, 15, .26) 82%,
    rgba(6, 8, 15, .46) 100%);
  /* Absent on the opening frame, where the whole world is the subject. */
  opacity: calc(1 - var(--ov, 0));
}

.world-overlay {
  position: absolute;
  inset: 0;
  pointer-events: none;
}
.world-overlay > * { pointer-events: auto; }

/* ---- places on the map ---- */

/* A zero-size anchor: the engine puts its origin exactly on the landmark, and
   the pin and label are placed around that point rather than by centring a box
   whose size changes with the length of a translated name. */
.js-world .wp {
  position: absolute;
  inset-block-start: 0;
  inset-inline-start: 0;
  width: 0;
  height: 0;
  text-decoration: none;
  --near: 0;
}

.wp-pin {
  position: absolute;
  inset-block-start: -11px;
  inset-inline-start: -11px;
  width: 22px;
  height: 22px;
  border: 2px solid var(--logo-accent);
  /* Cut corners rather than a circle: the whole HUD speaks in brackets and
     bevels, and a plain dot reads as a generic map pin from any other product. */
  clip-path: polygon(28% 0, 100% 0, 100% 72%, 72% 100%, 0 100%, 0 28%);
  background: rgba(6, 8, 15, .72);
  transition: transform .18s, background-color .18s;
}
.wp-pin::after {
  content: '';
  position: absolute;
  inset: 4px;
  background: var(--logo-accent);
  opacity: calc(.25 + var(--near) * .75);
  clip-path: inherit;
}

.wp-name {
  position: absolute;
  inset-block-start: -9px;
  inset-inline-start: 20px;
  white-space: nowrap;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: .14em;
  text-transform: uppercase;
  /* Never below 0.7 — these sit over city lights and have to survive them. */
  color: rgba(255, 244, 232, calc(.72 + var(--near) * .28));
  text-shadow: 0 1px 10px #06080f, 0 0 22px #06080f;
  transition: color .18s;
}

/* Labels on the right-hand edge would run off the viewport; the engine flips
   them when the marker crosses into the last quarter. */
.wp.is-flipped .wp-name {
  inset-inline: auto 20px;
}

.wp:hover .wp-pin,
.wp:focus-visible .wp-pin { transform: scale(1.25); background: rgba(232, 75, 10, .35); }

.wp.is-active .wp-pin {
  background: var(--logo-accent);
  transform: scale(1.35);
  box-shadow: 0 0 0 5px rgba(255, 85, 0, .26), 0 0 34px 6px rgba(255, 85, 0, .85);
}
.wp.is-active .wp-name {
  color: #fff;
  font-size: 13px;
  letter-spacing: .18em;
  text-shadow: 0 1px 12px #06080f, 0 0 26px rgba(255, 85, 0, .5);
}

/* A ring going out from the active pin — the one piece of ambient motion on the
   page, and only ever on the single place being talked about. */
.js-world .wp.is-active::before {
  content: '';
  position: absolute;
  inset-block-start: -27px;
  inset-inline-start: -27px;
  width: 54px;
  height: 54px;
  border: 1px solid rgba(255, 85, 0, .8);
  border-radius: 50%;
  animation: wp-ping 2.4s cubic-bezier(.2, .6, .3, 1) infinite;
}
@keyframes wp-ping {
  0%   { transform: scale(.5); opacity: .85; }
  100% { transform: scale(1.35); opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .js-world .wp.is-active::before { animation: none; opacity: .45; }
}

/* Side places are found rather than announced: dimmer until you are near one. */
.wp.is-side .wp-pin { border-color: rgba(255, 85, 0, .72); width: 16px; height: 16px; inset-block-start: -8px; inset-inline-start: -8px; }
.wp.is-side .wp-name { font-size: 11px; opacity: calc(.55 + var(--near) * .45); }

/* ---- the rider ---- */

.world-rider {
  position: absolute;
  inset-block-start: 0;
  inset-inline-start: 0;
  width: 0;
  height: 0;
  pointer-events: none;
}
/* The opening frame marks nothing in particular — the world is the subject, and
   an arrow planted on the start would be answering a question nobody has asked
   yet. */
.js-world .world-rider { opacity: calc(1 - var(--ov, 0)); }

.world-rider svg {
  display: block;
  margin: -13px 0 0 -13px;
  width: 26px;
  height: 26px;
  fill: #fff;
  filter: drop-shadow(0 0 8px rgba(255, 85, 0, 1)) drop-shadow(0 0 18px rgba(255, 85, 0, .7));
}

/* ---- loading ---- */

.world-loader {
  position: absolute;
  inset: 0;
  display: grid;
  place-content: center;
  background: var(--bg-page);
  z-index: 3;
}
.world-loader-label {
  font-family: var(--font-data);
  font-size: 13px;
  letter-spacing: .28em;
  text-transform: uppercase;
  color: var(--logo-accent);
  animation: world-pulse 1.4s ease-in-out infinite;
}
@keyframes world-pulse { 50% { opacity: .35; } }

/* ---- HUD ---- */

.world-hud, .world-rail { display: none; }

.js-world .world-hud {
  position: absolute;
  inset-block-end: 0;
  inset-inline: 0;
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 20px;
  padding: var(--pad);
  pointer-events: none;
  z-index: 2;
}

.hud-stats { display: flex; gap: clamp(18px, 3vw, 40px); }
.hud-stat { display: grid; gap: 1px; }
.hud-stat b {
  font-family: var(--font-data);
  font-size: 22px;
  line-height: 1;
  color: var(--logo-accent);
}
.hud-stat span {
  font-size: 11px;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: rgba(255, 244, 232, .75);
}

.hud-hint {
  font-size: 12px;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: rgba(255, 244, 232, .72);
  text-align: end;
}

/* ---- map controls ---- */

.world-pad { display: none; }

@media (min-width: 768px) {
  .js-world .world-pad {
    position: absolute;
    inset-block-start: var(--pad);
    inset-inline-end: var(--pad);
    display: grid;
    grid-template-columns: repeat(3, 44px);
    grid-template-rows: repeat(3, 44px);
    gap: 2px;
    z-index: 3;
  }
}

.pad-btn {
  display: grid;
  place-items: center;
  padding: 0;
  border: 1px solid var(--border-on);
  background: rgba(6, 8, 15, .78);
  color: var(--text-warm);
  cursor: pointer;
  /* The same cut corner as the pins and the panels. */
  clip-path: polygon(22% 0, 100% 0, 100% 78%, 78% 100%, 0 100%, 0 22%);
  transition: background-color .12s, color .12s;
}
.pad-btn svg { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 1.8; }
.pad-btn:hover { background: rgba(232, 75, 10, .3); color: #fff; }
.pad-btn:active { background: var(--logo-accent); color: #fff; }

.pad-up    { grid-area: 1 / 2; }
.pad-left  { grid-area: 2 / 1; }
.pad-right { grid-area: 2 / 3; }
.pad-down  { grid-area: 3 / 2; }

/* ---- the route rail ---- */

/* Table of contents and progress readout in one. Only stations are listed: the
   side places are meant to be come across. */
.js-world .world-rail {
  position: absolute;
  inset-block-start: 58%;
  inset-inline-end: var(--pad);
  transform: translateY(-50%);
  display: grid;
  gap: 2px;
  z-index: 2;
  padding: 12px 0 12px 16px;
  /* Its own ground. The rail sits over the busiest quarter of the render, where
     map labels and city lights run straight through it otherwise. */
  background: linear-gradient(90deg, transparent 0%, rgba(6, 8, 15, .78) 34%, rgba(6, 8, 15, .88) 100%);
}
.world-rail a {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 30px;
  padding-inline: 10px;
  text-decoration: none;
  font-size: 12px;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: rgba(255, 244, 232, .72);
  border-inline-end: 2px solid rgba(255, 244, 232, .22);
  transition: color .15s, border-color .15s;
}
.world-rail a i {
  font-family: var(--font-data);
  font-style: normal;
  font-size: 11px;
  color: rgba(255, 244, 232, .55);
}
.world-rail a:hover { color: #fff; border-color: var(--border-on); }
.world-rail a.is-active {
  color: #fff;
  border-color: var(--logo-accent);
}
.world-rail a.is-active i { color: var(--logo-accent); }

/* ---- the places, as panels ---- */

.world-panels { display: grid; gap: var(--gap); padding: var(--gap) var(--pad); }

.place > * + * { margin-block-start: 14px; }
.place-tag {
  font-family: var(--font-data);
  font-size: 12px;
  letter-spacing: .28em;
  text-transform: uppercase;
  color: var(--logo-accent);
}
.place .lead { font-size: clamp(18px, 2.2vw, 21px); color: var(--text-warm-2); }
.place p { color: var(--text-2); }
.place .note {
  padding-inline-start: 14px;
  border-inline-start: 2px solid var(--border-on);
  color: var(--text-3);
  font-size: 16px;
}
.place-list { margin: 0; padding: 0; list-style: none; display: grid; gap: 12px; }
.place-list li { color: var(--text-2); font-size: 16px; }
.place-list b { color: var(--text); display: block; }

.sub { color: var(--text-warm-2); font-size: clamp(17px, 2.2vw, 21px); }
.cta { display: flex; flex-wrap: wrap; gap: 12px; }
.hero-creed {
  font-size: 15px;
  font-weight: 400;
  line-height: 1.7;
  color: rgba(255, 244, 232, .82);
  padding-block-start: 18px;
  border-block-start: 1px solid rgba(255, 255, 255, .16);
}

@media (min-width: 768px) {
  .js-world .world { height: calc(var(--stops) * 100vh); }

  .js-world .world-stage {
    position: sticky;
    inset-block-start: 0;
    height: 100vh;
    overflow: hidden;
  }
  .js-world .world-viewport {
    position: absolute;
    inset: 0;
    aspect-ratio: auto;
    border-block: 0;
    cursor: grab;
  }
  .js-world .world.is-dragging .world-viewport { cursor: grabbing; }

  /* One panel at a time, over the map. Kept in the DOM and merely faded so the
     text stays selectable, indexable and reachable by anchor. */
  .js-world .world-panels {
    position: absolute;
    inset-block: 0;
    inset-inline-start: 0;
    width: min(440px, 42vw);
    display: grid;
    align-content: center;
    padding: 96px var(--pad) 128px;
    gap: 0;
    z-index: 2;
    /* The container spans a third of the stage whether a panel is showing or
       not; without this it quietly swallows every drag that starts on the left
       of the map. The panels themselves take their events back. */
    pointer-events: none;
  }
  .js-world .place.is-active { pointer-events: auto; }
  /* The motto is a heading in a 440px column, not across a full-width hero, so
     it takes the panel's scale rather than the page's. */
  .js-world .place h1 { font-size: clamp(34px, 3.4vw, 46px); }
  .js-world .place h2 { font-size: clamp(26px, 2.8vw, 36px); }

  .js-world .place {
    grid-area: 1 / 1;
    opacity: 0;
    visibility: hidden;
    transform: translateY(14px);
    transition: opacity .34s, transform .34s, visibility .34s;
    /* The bevel is the same cut as the map pins — it is what makes a panel read
       as part of the same instrument rather than a card dropped on top. */
    clip-path: polygon(0 0, calc(100% - 18px) 0, 100% 18px, 100% 100%, 18px 100%, 0 calc(100% - 18px));
    background: linear-gradient(100deg, rgba(6, 8, 15, .96) 0%, rgba(6, 8, 15, .90) 70%, rgba(6, 8, 15, .62) 100%);
    padding: 26px 30px;
    border-inline-start: 2px solid var(--logo-accent);
  }
  .js-world .place.is-active {
    opacity: 1;
    visibility: visible;
    transform: none;
  }

  /* The left third of the render is dark rock, but the panel still needs to sit
     on something of its own on a bright frame. */
  .js-world .world-panels::before {
    content: '';
    position: absolute;
    inset: 0;
    background: linear-gradient(90deg, rgba(6, 8, 15, .94) 0%, rgba(6, 8, 15, .62) 58%, transparent 100%);
    z-index: -1;
    pointer-events: none;
    /* Gone on the opening frame, where it would only darken the corner the start
       sits in. --ov is written by the engine. */
    opacity: calc(1 - var(--ov, 0));
    /* Wider than the panel: the fade has to finish over the map, not stop dead
       at the text's edge, or the panel reads as a rectangle stuck on top. */
    inset-inline-end: -140px;
  }
}

/* On touch the world is a panel the page scrolls past, and dragging it is the
   native gesture for a map rather than something invented. `pan-y` keeps the
   page itself scrollable through the stage — a map that traps the scroll is the
   single most common way this idea goes wrong on a phone. */
@media (max-width: 767px) {
  /* Sized so the motto and the download button clear the fold underneath it.
     A map that fills the phone looks better in a screenshot and costs the one
     thing the page exists for. */
  /* Height, not aspect-ratio. A ratio plus a max-height shrinks the box on BOTH
     axes, so above ~400px wide the map stopped short of the right edge and left
     a bare strip beside it. */
  .js-world .world-viewport {
    aspect-ratio: auto;
    height: min(46vh, 100vw);
    touch-action: pan-y;
  }
  .js-world .world-rail { display: none; }
  .js-world .world-panels { padding-block: var(--gap); gap: var(--gap); }

  /* Twelve names at once is unreadable at this size. Only the one you are at
     keeps its label; the rest are pins until you reach them. */
  /* Written at the same specificity as the base rules it overrides — the side
     places set their own opacity with a two-class selector, so a one-class
     override here would lose and leave exactly those labels on screen. */
  .js-world .wp .wp-name,
  .js-world .wp.is-side .wp-name {
    font-size: 10px;
    letter-spacing: .1em;
    opacity: 0;
    transition: opacity .2s;
  }
  .js-world .wp.is-active .wp-name { opacity: 1; }
  .js-world .wp.is-side .wp-pin { width: 14px; height: 14px; inset-block-start: -7px; inset-inline-start: -7px; }

  .js-world .world-hud { padding: 12px var(--pad); }
  .js-world .hud-hint { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .js-world .place { transition: none; }
  .world-loader-label { animation: none; }
}

/* ------------------------------------------------------------------ button */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 48px;           /* ≥44px touch target */
  padding-inline: 28px;
  border-radius: 10px;
  text-decoration: none;
  font-weight: 600;
  font-size: 17px;
  transition: background-color .15s, border-color .15s, filter .15s;
}
/* White on the brand orange measures 3.86:1 — short of the 4.5:1 AA needs for
   normal text. The accent colour is fixed by the brand, so the text is pushed
   into WCAG's "large text" class (≥18.66px bold), where the threshold is 3:1
   and 3.86 clears it. Shrinking this text later would silently break contrast. */
.btn-primary {
  background: var(--accent);
  color: #fff;
  font-size: 19px;
  font-weight: 700;
}
.btn-primary:hover { filter: brightness(1.12); }
.btn-ghost {
  border: 1px solid var(--border-on);
  color: var(--text-warm);
  /* A tinted pane rather than clear glass: over the photo, a fully transparent
     button loses its label wherever the sky is bright behind it. */
  background: rgba(10, 6, 4, .42);
  backdrop-filter: blur(6px);
}
.btn-ghost:hover { background: rgba(232, 75, 10, .20); border-color: var(--logo-accent); }

/* Lifts the primary CTA off the map instead of letting it sit flat on the city
   lights it happens to match in hue. */
.place .btn-primary { box-shadow: 0 8px 28px rgba(232, 75, 10, .38); }
.btn-disabled { border: 1px solid var(--border-n); color: var(--text-3); cursor: default; }
.btn-sm { min-height: 40px; padding-inline: 18px; font-size: 15px; }
.btn-lg { min-height: 56px; padding-inline: 40px; font-size: 19px; }

.link { color: var(--accent); text-decoration: none; font-weight: 600; }
.link:hover { text-decoration: underline; }

/* ----------------------------------------------------------------- pricing */

.grid-3 { display: grid; gap: 20px; }
.grid-2 { display: grid; gap: 20px; }
@media (min-width: 760px)  { .grid-2 { grid-template-columns: 1fr 1fr; } }
@media (min-width: 900px)  { .grid-3 { grid-template-columns: repeat(3, 1fr); } }

.card {
  background: var(--bg-card);
  border: 1px solid var(--border-n);
  border-radius: var(--radius);
  padding: 24px;
}
.card p { color: var(--text-2); margin-block-start: 8px; }

.card .btn { margin-block-start: 18px; }
.hint { color: var(--text-3); font-size: 15px; margin-block-start: 12px; }
.hint.center { text-align: center; margin-block-start: 24px; }

.plan { text-align: center; }
.price {
  font-size: 28px;
  color: var(--logo-accent);
  margin-block: 10px;
}

.bullets { margin: 18px 0 22px; padding-inline-start: 20px; color: var(--text-2); }
.bullets li { margin-block: 6px; }
.store { display: flex; flex-wrap: wrap; gap: 12px; }

/* --------------------------------------------------------------------- faq */

.faq details {
  border-block-end: 1px solid var(--border-n);
  padding-block: 4px;
}
.faq summary {
  cursor: pointer;
  padding-block: 16px;
  font-size: 19px;
  font-weight: 600;
  list-style: none;
  display: flex;
  justify-content: space-between;
  gap: 16px;
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after {
  content: '+';
  color: var(--accent);
  font-size: 24px;
  line-height: 1;
}
.faq details[open] summary::after { content: '−'; }
.faq details p { color: var(--text-2); padding-block-end: 18px; max-width: 76ch; }

/* ------------------------------------------------------------------- final */

.final { text-align: center; }
.final h2 { margin-block-end: 28px; }
.final p { margin-block-start: 18px; }

/* ------------------------------------------------------------------ footer */

.site-footer {
  background: rgba(6, 8, 15, .97);
  border-block-start: 1px solid var(--border);
  padding: 48px var(--pad) 24px;
}
.footer-cols {
  display: grid;
  gap: 32px;
  padding-inline: 0;
}
@media (min-width: 760px) {
  .footer-cols { grid-template-columns: 2fr 1fr 1fr 1fr; }
}
.footer-cols nav { display: grid; gap: 10px; align-content: start; }
.footer-cols nav a { color: var(--text-2); text-decoration: none; font-size: 16px; }
.footer-cols nav a:hover { color: var(--text); }
.footer-brand .tagline { margin-block-start: 12px; }

.footer-bottom {
  max-width: var(--maxw);
  margin: 32px auto 0;
  padding-block-start: 20px;
  border-block-start: 1px solid var(--border-n);
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
  align-items: center;
  justify-content: space-between;
}
.rights { color: var(--text-3); font-size: 14px; }

/* ------------------------------------------------------------------ mobile */

@media (max-width: 899px) {
  .burger {
    display: grid;
    gap: 5px;
    margin-inline-start: auto;
    padding: 14px 10px;  /* 44px tall including the three 2px bars and gaps */
    cursor: pointer;
    text-decoration: none;
  }
  .burger span {
    display: block;
    width: 24px;
    height: 2px;
    background: var(--text);
  }

  .site-nav {
    position: fixed;
    inset: 56px 0 auto 0;
    flex-direction: column;
    gap: 0;
    margin: 0;
    background: var(--bg-page);
    border-block-end: 1px solid var(--border);
    transform: translateY(-120%);
    transition: transform .2s ease;
  }
  .site-nav a {
    padding: 16px var(--pad);
    border-block-end: 1px solid var(--border-n);
    font-size: 18px;
  }
  /* Opens with JS disabled and without depending on sibling order. */
  .site-nav:target { transform: translateY(0); }

  .menu-close {
    display: block;
    text-align: end;
    font-size: 28px;
    line-height: 1;
    padding: 16px var(--pad) !important;
    border-block-end: none !important;
  }

  /* The switcher does not fit beside a logo and a burger at 390px, so it moves
     into the menu rather than shrinking. */
  .lang-header, .header-cta { display: none; }
  .lang-in-menu {
    display: block;
    padding: 14px var(--pad);
  }
  /* Inside the burger panel there is nothing to overlay, and an absolutely
     positioned menu would spill past the panel's edge — so it expands in flow
     and pushes the panel taller instead. */
  .lang-in-menu .lang-menu {
    position: static;
    margin-block-start: 8px;
    max-height: 46vh;
  }
  .lang-in-menu summary { font-size: 17px; }

  .logo { font-size: 19px; }

  /* Full-width buttons: equal-width targets are easier to hit one-handed, and
     ragged button edges read as a layout bug on a narrow screen. */
  .cta { flex-direction: column; }
  .cta .btn, .store .btn { width: 100%; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
  }
  .hero-tracks path { stroke-dashoffset: 0; }
}

/* ------------------------------------------------------------------ notify */

/* Driven by :target so the dialog opens without JS — <dialog>.showModal() would
   leave a scripting-disabled visitor with a button that does nothing. */
.notify {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: none;
  align-items: center;
  justify-content: center;
  padding: var(--pad);
}
.notify:target { display: flex; }

/* A full-bleed link, so clicking outside closes the dialog the way people
   expect. Anchored to "#" rather than a page link: no navigation, just an
   empty target. */
.notify-scrim {
  position: absolute;
  inset: 0;
  background: rgba(4, 3, 2, .82);
  backdrop-filter: blur(4px);
}

.notify-box {
  position: relative;
  width: min(460px, 100%);
  max-height: 90vh;
  overflow-y: auto;
  padding: clamp(24px, 5vw, 36px);
  background: var(--bg-card);
  border: 1px solid var(--border-on);
  border-radius: 14px;
  box-shadow: 0 24px 64px rgba(0, 0, 0, .6);
}

.notify-close {
  position: absolute;
  inset-block-start: 8px;
  inset-inline-end: 8px;
  /* ≥44px target, even though the glyph is small. */
  padding: 10px 16px;
  font-size: 24px;
  line-height: 1;
  color: var(--text-3);
  text-decoration: none;
}
.notify-close:hover { color: var(--text); }

.notify h2 { font-size: clamp(24px, 4vw, 32px); }
.notify-body { margin-block: 14px 22px; color: var(--text-2); }

.notify-form { display: grid; gap: 16px; }

.notify-field { display: grid; gap: 7px; }
.notify-field span { font-size: 15px; color: var(--text-3); }
.notify-field input {
  min-height: 48px;
  padding-inline: 14px;
  background: var(--bg-page);
  border: 1px solid var(--border-input, rgba(232, 75, 10, .40));
  border-radius: 8px;
  color: var(--text);
  font-family: var(--font-ui);
  font-size: 17px;
}
.notify-field input:focus { border-color: var(--logo-accent); outline: none; }
.notify-field input:user-invalid { border-color: var(--red, #ff3333); }

.notify-consent {
  display: flex;
  gap: 10px;
  align-items: start;
  font-size: 15px;
  color: var(--text-2);
  cursor: pointer;
}
/* Never pre-ticked: a pre-ticked consent box is not consent under GDPR. */
.notify-consent input {
  flex-shrink: 0;
  width: 20px;
  height: 20px;
  margin-block-start: 2px;
  accent-color: var(--accent);
}
.notify-consent a { color: var(--logo-accent); }

/* Bait for bots, invisible to everyone else. Not display:none — some bots skip
   those; off-canvas with no tab stop is harder to detect. */
.notify-hp {
  position: absolute;
  inset-inline-start: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.notify-status { font-size: 15px; min-height: 1.4em; }
.notify-status.is-ok { color: var(--teal); }
.notify-status.is-err { color: #ff6a4d; }
.notify-status a { color: var(--logo-accent); }

.notify-form.is-sent .notify-field,
.notify-form.is-sent .notify-consent,
.notify-form.is-sent button { display: none; }

/* ------------------------------------------------------------------- legal */

.legal { padding-block: clamp(40px, 7vw, 72px); }
.legal-doc {
  /* Reading measure, not the full grid: legal text is read line by line. */
  max-width: 720px;
  margin-inline: auto;
  padding-inline: var(--pad);
}
.legal-doc h1 { font-size: clamp(30px, 5vw, 44px); }
.legal-doc h2 {
  font-size: clamp(21px, 2.6vw, 26px);
  text-transform: none;
  margin-block: 40px 12px;
}
.legal-doc h3 { font-size: 19px; margin-block: 28px 8px; }
.legal-doc p, .legal-doc li { color: var(--text-2); margin-block: 12px; }
.legal-doc ul, .legal-doc ol { padding-inline-start: 22px; }
.legal-doc a { color: var(--logo-accent); }
.legal-doc strong { color: var(--text); }

.legal-updated {
  color: var(--text-3);
  font-size: 15px;
  margin-block-start: 10px !important;
}

/* Wide content scrolls inside its own box rather than pushing the page. */
.table-wrap { overflow-x: auto; margin-block: 18px; }
.legal-doc table {
  width: 100%;
  border-collapse: collapse;
  font-size: 16px;
}
.legal-doc th, .legal-doc td {
  text-align: start;
  padding: 10px 14px;
  border-block-end: 1px solid var(--border-n);
  vertical-align: top;
}
.legal-doc th { color: var(--text); white-space: nowrap; }
.legal-doc td { color: var(--text-2); }

/* Intro line under a section heading. Centred with the heading, and narrow
   enough to stay a readable measure rather than a full-width band. */
.section-lead {
  max-width: 60ch;
  margin: -24px auto 40px;
  padding-inline: var(--pad);
  text-align: center;
  color: var(--text-2);
  font-size: clamp(17px, 2vw, 19px);
}

/* ------------------------------------------------- tap targets on phones -- */

/* These are standalone calls to action, not links inside a sentence, so the
   44px rule applies to them. Measured on a phone: "Открыть" was 21px tall and
   the footer links 26px. Padding rather than a fixed height, so a wrapped label
   still grows the box instead of overflowing it. */
.row-text .link,
.final .link {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
}

.footer-cols nav a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
}
/* The tighter gap compensates for the taller links, so the column does not
   suddenly read as double-spaced. */
.footer-cols nav { gap: 2px; }

.skip:focus { min-height: 44px; display: inline-flex; align-items: center; }

/* The header is sticky, so an anchor jump parks the section heading underneath
   it. Reserving the header's height plus a little air puts the heading back in
   view — visible on #faq, where "Вопросы" landed behind the bar. */
/* scroll-margin-top, not the logical variant: the logical property is not
   honoured everywhere yet, and here it silently resolved to 0. The value is the
   measured header height (79px) plus air. */
section[id] { scroll-margin-top: 96px; }

/* Smooth only when the visitor has not asked otherwise. */
@media (prefers-reduced-motion: no-preference) {
  html { scroll-behavior: smooth; }
}

/* -------------------------------------------------------------- tablets -- */

/* Between phone and laptop the page was behaving like a stretched phone: single
   column cards with a lot of empty margin, while the footer had already jumped
   to four cramped columns. Two columns in both places suits the width. */
@media (min-width: 600px) and (max-width: 899px) {
  .grid-3 { grid-template-columns: 1fr 1fr; }
  /* Six feature cards split 2x3 evenly; three pillars leave one on its own
     row, so that one spans the full width rather than sitting half-empty. */
  .pillars .grid-3 > :last-child { grid-column: 1 / -1; }
}

@media (min-width: 760px) and (max-width: 899px) {
  .footer-cols { grid-template-columns: 1fr 1fr; }
}

/* ============================================================== rhythm ==== */
/* The page read as one continuous stream: nothing told the eye where a topic
   started or ended. Four devices fix that, in order of how much work they do:
   an eyebrow that names the topic, alternating backgrounds, a divider borrowed
   from the app's loading screen, and heavier headings. */

/* --- 1. Eyebrow: names the topic before the heading states it ------------- */

.eyebrow {
  display: flex;
  align-items: center;
  gap: 12px;
  max-width: var(--maxw);
  margin: 0 auto 14px;
  padding-inline: var(--pad);
  font-size: 14px;
  font-weight: 700;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--logo-accent);
}
.eyebrow-num {
  font-family: var(--font-data);
  font-size: 13px;
  letter-spacing: 0;
  color: var(--text-3);
}
/* A short rule between number and label — enough to read as a marker rather
   than as two stray words. */
.eyebrow-line {
  width: 34px;
  height: 1px;
  background: linear-gradient(90deg, var(--logo-accent), transparent);
  flex-shrink: 0;
}

/* Sections whose heading is centred keep the eyebrow centred with it. */
.pillars .eyebrow,
.features .eyebrow,
.business .eyebrow,
.pricing .eyebrow,
.faq .eyebrow { justify-content: center; }

/* --- 2. Alternating grounds ---------------------------------------------- */
/* Two tones, strictly alternating, so a scroll past a boundary is visible even
   without reading. */
.pillars, .download, .platform, .pricing { background: var(--bg-deep); }
.features, .safety, .business, .faq { background: var(--bg-page); }
.final { background: var(--bg-deep); }

/* --- 3. Divider ---------------------------------------------------------- */
/* The horizon line from the app's loading screen: bright in the middle, fading
   to nothing at the edges. Cheaper than a border and unmistakably ours. */
main > section + section::before {
  content: '';
  display: block;
  position: absolute;
  inset-inline: 0;
  inset-block-start: 0;
  height: 1px;
  background: linear-gradient(90deg,
    transparent 0%,
    rgba(255, 85, 0, .05) 8%,
    rgba(255, 85, 0, .42) 35%,
    rgba(255, 85, 0, .75) 50%,
    rgba(255, 85, 0, .42) 65%,
    rgba(255, 85, 0, .05) 92%,
    transparent 100%);
  box-shadow: 0 0 10px rgba(255, 85, 0, .16);
}
main > section { position: relative; }

/* --- 4. Headings --------------------------------------------------------- */

section > h2 {
  margin-block-end: 16px;
  font-size: clamp(32px, 5.4vw, 52px);
}
/* The lead now sits under a heading that has its own bottom margin, so the old
   negative offset is gone. */
.section-lead { margin-block: 0 44px; }

/* Sections whose heading sits inside a two-column layout align left with it. */
.download .eyebrow, .safety .eyebrow { justify-content: flex-start; }

/* --- 5. Cards: visible edges, not floating rectangles --------------------- */

.pillar, .feature, .card {
  border-color: var(--border-n);
  transition: border-color .18s, transform .18s;
}
.pillar:hover, .feature:hover, .card:hover {
  border-color: var(--border-on);
  transform: translateY(-2px);
}
/* On the deep ground the cards need to be lighter than their surroundings, and
   on the page ground darker — otherwise one of the two disappears. */
.pillars .pillar { background: var(--bg-card); }
.features .feature { background: var(--bg-card); }

@media (prefers-reduced-motion: reduce) {
  .pillar:hover, .feature:hover, .card:hover { transform: none; }
}

/* The placeholders are empty elements sized by aspect-ratio, so they have no
   intrinsic width. Combined with the min-width:0 added for overflow safety and
   the centred grid in the download block, one of them collapsed to 2x4px. An
   explicit width gives them something to be. */
.shot { width: 100%; }
.shot-phone { width: min(300px, 100%); }

@media (max-width: 899px) {
  /* A 533px-tall placeholder pushed the heading and the install button below
     the fold — the visitor met a striped box instead of the offer. Text first,
     mockup after it and smaller. */
  .download-inner, .safety-inner { display: flex; flex-direction: column; }
  .download-inner > div:not(.shot), .safety-inner > div:not(.shot) { order: 1; }
  .download-inner .shot-phone, .safety-inner .shot-phone { order: 2; width: min(220px, 70%); }
}

/* ------------------------------------------------------- hero creed ------ */

.hero-creed {
  max-width: 54ch;
  margin: clamp(36px, 5vw, 56px) auto 0;
  padding-block-start: clamp(22px, 3vw, 30px);
  border-block-start: 1px solid rgba(255, 255, 255, .16);
  font-size: clamp(15px, 1.6vw, 17px);
  font-weight: 400;
  line-height: 1.75;
  /* Lighter than the subtitle above: this is the quietest text in the hero,
     and it should read as an aside rather than as another sales line. */
  color: rgba(255, 244, 232, .82);
  text-shadow: 0 1px 14px rgba(8, 4, 2, .6);
  letter-spacing: .01em;
}

@media (max-width: 899px) {
  /* On a phone the buttons must stay reachable, so the creed gets less room
     above it and sits closer to the fold's edge. */
  .hero-creed { margin-block-start: 28px; padding-block-start: 18px; font-size: 15px; }
}

/* Eight feature cards, so four columns divide evenly where there is room. At
   three they left a single orphan on the last row, which reads as a card
   someone forgot to finish. */
@media (min-width: 1100px) {
  .features .grid-3 { grid-template-columns: repeat(4, 1fr); }
}
