/*
 * VEDU marketing site — vedu's palette in cuberto.com's design language.
 *
 * What is borrowed from Cuberto is *form*, never colour: oversized display type, generous section
 * rhythm, big-radius media, pill CTAs that fill on hover. Not their line-height ~1 or -.035em
 * tracking, which Latvian diacritics collide in — see the display-type block below. Not their
 * blend-mode cursor, and not their marquee: a strip of scrolling nav labels said nothing.
 *
 * What stays vedu is everything you can see: Poppins, the palette below (measured off
 * getvedu.app), and every word of copy.
 *
 * Motion is progressive enhancement. Every `[data-reveal]` is visible by default and only hidden
 * once site.js confirms it can animate — so with JS off, or under prefers-reduced-motion, the page
 * is simply a static page. Never invert that.
 */

/*
 * Poppins, self-hosted. It used to come from fonts.googleapis.com, which sent every visitor's IP to
 * Google before first paint — on a page whose forms are about children — and cost two cross-origin
 * round trips on the critical path. These are subset to latin + latin-ext (Ā Č Ē Ģ Ī Ķ Ļ Ņ Š Ū Ž
 * live in latin-ext; drop that range and the whole Latvian site falls back to a system face) and
 * come to ~10KB each, against the five weights × two subsets Google was serving — of which 300 and
 * 700 were never used by a single rule in this file.
 *
 * Regenerate with fontTools if the face changes; the sources are `ios/Resources/Fonts/*.ttf`.
 */
@font-face {
  font-family: Poppins; font-style: normal; font-weight: 400; font-display: swap;
  src: url("/fonts/Poppins-Regular.woff2") format("woff2");
}
@font-face {
  font-family: Poppins; font-style: normal; font-weight: 500; font-display: swap;
  src: url("/fonts/Poppins-Medium.woff2") format("woff2");
}
@font-face {
  font-family: Poppins; font-style: normal; font-weight: 600; font-display: swap;
  src: url("/fonts/Poppins-SemiBold.woff2") format("woff2");
}
/* 700 is unused by the marketing site; the Ops/admin pages set it (and synthesise 800 from it). */
@font-face {
  font-family: Poppins; font-style: normal; font-weight: 700; font-display: swap;
  src: url("/fonts/Poppins-Bold.woff2") format("woff2");
}

/*
 * The palette. Do not introduce a colour that isn't in this block.
 *
 * Three of these are identity hues that do NOT carry text, and each has a functional twin that
 * does. Brand purple on white is 4.27:1 — fine as a fill, a fail as small text. The identity
 * green is 1.89:1 as a mark, nowhere near the 3:1 a meaningful glyph needs. The identity blue
 * is 2.90:1 on canvas, and it is what every body link was painted with. Reach for the `-t`
 * ("text") twin whenever the colour lands on type or on a glyph that must be seen.
 */
:root {
  --brand:   #994fe7;   /* primary: CTA fills, accents, hover sweeps. Fills only. */
  --brand-d: #7f3fca;   /* darker brand: :hover on a brand fill, and brand-coloured small text */
  --blue:    #788dec;   /* identity blue — decorative only, never text */
  --blue-t:  #4d61d6;   /* body links: 4.95:1 on canvas, 5.25:1 on surface */
  --green:   #8ac926;   /* identity green — decorative only, never a mark */
  --green-t: #4f7d0e;   /* success marks: 4.63:1 as a glyph, 4.92:1 behind a white tick */
  --yellow:  #ffd600;   /* accent (artwork only — unused in this stylesheet) */

  --ink:     #424242;   /* body copy and headings */
  --dark:    #0a0a0a;   /* the palette's darkest: buttons, footer, the dark CTA band */
  --muted:   #6f6f6f;
  --ink-70:  rgba(66, 66, 66, .82);

  --canvas:  #f8f8f8;   /* page background */
  --surface: #ffffff;   /* cards and alternating sections sit above the canvas */
  --line:    rgba(66, 66, 66, .14);      /* dividers and resting card borders */
  --line-i:  rgba(66, 66, 66, .34);      /* an input's resting underline — a divider is too faint to sit on */
  --danger:  #cf2e2e;

  --radius:  28px;
  --radius-s: 14px;

  /*
   * Decorative gradients. These carry no text and no meaning — they are the identity hues doing
   * what they may: colouring a surface. Any type placed over one must still be measured against
   * the darkest stop.
   */
  --wash-brand: linear-gradient(180deg, #fbf7ff 0%, var(--canvas) 62%);
  /* Section washes. The old site carried colour the whole way down; this one had bleached its tints
     to ~10% and read as flat grey (the exact note the user gave back). Warmed and roughly doubled so
     a washed section is unmistakably tinted — still light enough that dark ink over it keeps its
     contrast. `--wash-warm` is the amber the old site's mid-page bands had; it alternates with cool. */
  --wash-cool:  linear-gradient(200deg, rgba(120, 141, 236, .17) 0%, rgba(153, 79, 231, .12) 55%, rgba(248, 248, 248, 0) 100%);
  --wash-warm:  linear-gradient(200deg, rgba(255, 205, 60, .20) 0%, rgba(255, 148, 92, .12) 52%, rgba(248, 248, 248, 0) 100%);
  /*
   * The violet card's fill. BOTH stops must hold white body text (small text → 4.5:1), so this runs
   * dark-violet → darker-violet, not `--blue → --brand`: an earlier version started at the identity
   * blue and white body copy over it measured 3.4:1 — a WCAG failure the gradient hid in plain sight.
   * `#8A43D8` (the light stop) is 5.42:1 under white; `#6E37B0`, 7.40:1.
   */
  --grad-brand: linear-gradient(135deg, #8a43d8 0%, #6e37b0 100%);
  /*
   * The closing band's fill — the old site's signature indigo→violet sweep, brought back as the
   * page's one full-bleed gradient so it ends on colour, not on a second near-black before the
   * footer. Every stop is dark enough to carry small white text at reduced opacity: the lightest,
   * `#6E37B0`, is 7.40:1 under white (5.18:1 at .78 alpha), the indigo `#4634C4` is 8.24:1.
   */
  --grad-cta: linear-gradient(120deg, #4634c4 0%, #6e37b0 55%, #7a2fa0 100%);

  --container: 1440px;
  --gutter: clamp(20px, 4.4vw, 72px);
  /*
   * Rhythm. Originally `clamp(80px, 11vw, 168px)` / `clamp(56px, 6vw, 104px)` — 316px between every
   * two sections and a 13,115px page, 39% longer than the WordPress original with fewer images. That
   * first felt empty; tightened once to 116/72, then again to the below after the page still read as
   * too long and airy. Cuberto's whitespace works because its sections are single objects; ours are
   * card grids that already breathe internally, so they need less air around them, not more.
   */
  --section: clamp(44px, 5vw, 84px);
  --block: clamp(32px, 3.4vw, 54px);   /* a secondary block below a section's lead block */
  --gap-head: clamp(16px, 1.4vw, 22px);   /* heading → its own body copy */

  --radius-pill: 999px;
  --shadow: 0 18px 40px rgba(66, 66, 66, .14);   /* the one elevation recipe */

  --ease: cubic-bezier(.22, 1, .36, 1);   /* the long, heavy out-expo everything uses */
  --ease-io: cubic-bezier(.76, 0, .24, 1);

  /*
   * The site is light-only. Without this a dark-mode OS paints the native form controls and,
   * worse, Chrome's autofill dark — a name/email autofilled into a transparent field becomes
   * light-on-white and invisible on all three forms.
   */
  color-scheme: light;
}

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

/* Every tap on a 999px pill otherwise flashes the UA's square grey rectangle. `:active` and
   `:focus-visible` already give the feedback this was standing in for. */
* { -webkit-tap-highlight-color: transparent; }

/*
 * The browser's own `[hidden] { display: none }` is a UA rule, so ANY author `display` beats it —
 * `.btn { display: inline-flex }` silently un-hid the wizard's Back and "Create account" buttons on
 * step one. Anything toggled with the `hidden` property needs this to actually disappear.
 */
[hidden] { display: none !important; }

/* Scrolling is native (no wheel hijack — see `initAnchorFocus` for why). `smooth` glides anchor
   jumps and the skip link; the wheel and trackpad stay on the OS's own scrolling. */
html { scroll-behavior: smooth; scroll-padding-top: 100px; }

body {
  margin: 0;
  background: var(--canvas);
  color: var(--ink);
  font: 400 17px/1.6 Poppins, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;   /* without its pair, Poppins renders heavier in Firefox/macOS */
  overflow-x: hidden;
  /* Latvian compounds ("pasažieru komercpārvadājumi") outrun a 280px column; break rather than
     overflow, because `overflow-x: hidden` above would silently clip what spills. */
  overflow-wrap: break-word;
}

::selection { background: var(--brand); color: #fff; }

img, video { max-width: 100%; height: auto; display: block; }
/* Links inherit their surroundings by default; long-form and contact links take the brand blue. */
a { color: inherit; }
.contact-emails a { color: var(--blue-t); }
p { margin: 0; }

/* ── display type ────────────────────────────────────────────────────────────────────────────── */

h1, h2, h3, h4, h5 { margin: 0; color: var(--ink); font-weight: 600; }

/*
 * Cuberto's signature is enormous type at line-height ~1 — but that assumes plain Latin. Latvian
 * stacks a diacritic on top and a descender below, and in Poppins the tallest of them is the caron
 * (Č Š Ž) at 0.928em above the baseline — taller than the macron (Ā Ē Ī Ū), which is the trap: a
 * value tuned on "Ā" alone still collides on "Š". With descenders (g ļ ķ ņ ģ) reaching 0.289em
 * below, one line's ink spans 1.217em, so that is the hard floor for the distance between baselines.
 *
 * 1.24 clears it by ~2px at the hero's 84px. Never take these below 1.22 — re-measure with
 * canvas `actualBoundingBoxAscent` on "ĀĒĪŪČŠŽ" and "gļķņģpj" if you change the font.
 *
 * The tracking has the same problem sideways. Cuberto sets -.035em; at that value the macrons in
 * "izglītības" and "pašvaldībām" run into the ascenders beside them and the word grows a solid bar
 * across its top. -.015em is the tightest that still reads as separate marks at 84px.
 */
/*
 * The clamp floors carry the hierarchy on a phone, where they are ALL that is in effect: h1 and h2
 * differ only in size (same weight, line-height, tracking), so 38/32 left the hero headline barely
 * outranking a section heading at 320px. 44/29 is a clear rung. h4's old ceiling (23px at 1533px)
 * was unreachable inside the 1440px container, pinning it to its 19px floor — exactly h5's size —
 * so the how-it-works step titles and the card titles rendered identically everywhere.
 */
h1 { font-size: clamp(44px, 6.6vw, 92px); line-height: 1.24; letter-spacing: -.015em; }
h2 { font-size: clamp(29px, 5.2vw, 74px); line-height: 1.24; letter-spacing: -.015em; }
h3 { font-size: clamp(24px, 2.6vw, 38px); line-height: 1.26; letter-spacing: -.012em; }
h4 { font-size: clamp(21px, 1.9vw, 27px); line-height: 1.3;  letter-spacing: -.01em; font-weight: 600; }
h5 { font-size: 19px; line-height: 1.35; letter-spacing: -.01em; font-weight: 600; }

/* Oversized type is where a one-word orphan hurts most, and Latvian's long words orphan often.
   `balance` only changes where lines break — the tuned tracking and line-height above are untouched. */
h1, h2, h3 { text-wrap: balance; }

.container { width: 100%; max-width: var(--container); margin: 0 auto; padding: 0 var(--gutter); }
.section { padding: var(--section) 0; }
.section--tight { padding: clamp(56px, 6vw, 96px) 0; }
/* Half a section's padding — used where a block leads directly into the next one (the audience
   picker sits right under the hero, so it must not open with a full section's air). */
.section--snug { padding: clamp(40px, 4.4vw, 72px) 0 var(--section); }
.section--alt { background: var(--surface); }
/* A faint cool wash — the identity blue and violet at <12% over canvas. It gives the "why" and
   "how" sections a tint the old site had and this one had bleached out to flat grey. Carries no
   text of its own; the cards on top keep their own backgrounds. */
.section--wash { background: var(--wash-cool), var(--canvas); }
/* The warm twin of `--wash`, for the mid-page bands the old site ran in amber (the drivers/earn
   block especially). Same contract: carries no text of its own, cards on top keep their surfaces. */
.section--warm { background: var(--wash-warm), var(--canvas); }
/* The closing CTA is the page's one full-bleed gradient — the old site's indigo→violet signature.
   It used to be near-black (#141317), which left the page ending dark→white→dark→black-footer, two
   blacks rhyming with a white gap. Colour here reads as the arrival the old site had, and separates
   cleanly from the black footer below. Kept as `.section--dark` because everything on it is still
   white type; the token is measured for small white text against its lightest stop (see `--grad-cta`). */
.section--dark { background: var(--grad-cta); color: #fff; }
.section--dark h2, .section--dark h3 { color: #fff; }

/* The small label above a headline: a purple dot and tracked-out caps. */
.eyebrow {
  display: inline-flex; align-items: center; gap: 10px;
  font-size: 13px; font-weight: 500; letter-spacing: .14em; text-transform: uppercase;
  color: var(--muted); margin-bottom: 24px;
}
.eyebrow::before { content: ""; width: 8px; height: 8px; border-radius: 50%; background: var(--brand); flex: none; }
.section--dark .eyebrow { color: rgba(255, 255, 255, .6); }

/* A pill variant of the eyebrow — a soft brand-tinted chip in the same language as the audience
   cards' icon wells. Its text is `--brand-d`, 5.3:1 on the wash the chip sits in; the label was
   `--muted` grey, which is what made the hero read as colourless. Used on the hero only. */
.eyebrow--pill {
  padding: 8px 16px 8px 14px; border-radius: var(--radius-pill);
  background: rgba(153, 79, 231, .10); color: var(--brand-d); margin-bottom: 28px;
}
.eyebrow--pill::before { background: var(--brand-d); }

.lede { color: var(--muted); font-size: clamp(17px, 1.35vw, 21px); line-height: 1.65; }
.lede, .section__head p, .prose p { text-wrap: pretty; }

/* A block sitting below a section's lead block — the badge strip, the driver grid, the stats.
   Five one-off margins used to do this job, three of them inline on the markup. */
.section-block { margin-top: var(--block); }

.section__head { max-width: 900px; margin-bottom: clamp(32px, 3.4vw, 56px); }
/* A standfirst under a 74px h2 must not be body size. The hero gets `.lede`; this is its twin. */
.section__head p {
  margin-top: var(--gap-head); color: var(--muted); line-height: 1.65; max-width: 60ch;
  font-size: clamp(18px, 1.4vw, 21px);
}
.section__head--center { margin-left: auto; margin-right: auto; text-align: center; }
.section__head--center p { margin-left: auto; margin-right: auto; }

/* ── buttons ─────────────────────────────────────────────────────────────────────────────────── */

/* Pill with a fill that sweeps up from the bottom on hover. `span` sits above the sweep. */
.btn {
  position: relative; display: inline-flex; align-items: center; justify-content: center; gap: 10px;
  border: 0; cursor: pointer; isolation: isolate; overflow: hidden;
  padding: 18px 40px; border-radius: var(--radius-pill);
  /* `overflow: hidden` clips the sweep to the pill — which means it also clips a wrapped label.
     At line-height 1 a Latvian caron or descender is what gets cut; 1.25 clears the 1.217em ink span. */
  font: 500 16px/1.25 Poppins, sans-serif; letter-spacing: -.01em; text-decoration: none;
  background: var(--dark); color: #fff;
  transition: color .35s var(--ease);
}
.btn::after {
  content: ""; position: absolute; inset: 0; z-index: -1; border-radius: inherit;
  background: var(--brand); transform: translateY(101%);
  transition: transform .5s var(--ease);
}
.btn:hover::after, .btn:focus-visible::after { transform: translateY(0); }
/* The sweep alone is not a focus indicator — it is indistinguishable from a mouse hover. */
.btn:focus-visible { outline: 2px solid var(--brand); outline-offset: 3px; }
.btn:active { transform: scale(.98); }
/* `cursor: progress` on a genuinely disabled control claims it is working. Only a busy one is. */
.btn[disabled] { opacity: .5; cursor: not-allowed; }
.btn[aria-busy="true"] { cursor: progress; }
.btn--block { display: flex; width: 100%; }

.btn--light { background: #fff; color: var(--dark); }
.btn--light::after { background: var(--brand); }
.btn--light:hover { color: #fff; }

.btn--outline { background: transparent; color: var(--ink); box-shadow: inset 0 0 0 1.5px var(--ink); }
.btn--outline:hover { color: #fff; }

/* An arrow that nudges on hover. */
.btn svg { width: 16px; height: 16px; transition: transform .4s var(--ease); }
.btn:hover svg { transform: translateX(4px); }

/* Text link with an underline that draws in. `scaleX`, not `right`: animating `right` relayouts
   and repaints every frame on every link; a transform is composited. */
.link {
  position: relative; text-decoration: none; padding-bottom: 2px;
}
.link::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 1px;
  background: currentColor; transform: scaleX(0); transform-origin: left;
  transition: transform .4s var(--ease);
}
.link:hover::after, .link:focus-visible::after { transform: scaleX(1); }

/*
 * There is no custom cursor. The native one is never hidden — `cursor: none` anywhere on this site
 * is a bug. The blend-mode follower we used to ship inverted the brand purple to a muddy #66b018
 * over a hovered pill, and its enlarged state stuck open whenever a native <select> popup ate the
 * pointerleave. It cost more than it bought.
 */

/* ── header ──────────────────────────────────────────────────────────────────────────────────── */

/*
 * The header must never become a containing block for `position: fixed` descendants, or the
 * full-screen mobile nav inside it gets trapped in this 88px bar. `transform`, `filter`,
 * `backdrop-filter` and `will-change` all do that — so the frosted background lives on a
 * pseudo-element instead, and the hide-on-scroll transform is pinned off while the menu is open.
 */
.site-header {
  position: fixed; top: 0; left: 0; right: 0; z-index: 90;
  transition: transform .5s var(--ease);
}
.site-header::before {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background: rgba(248, 248, 248, .86);
  backdrop-filter: saturate(160%) blur(14px);
  opacity: 0; transition: opacity .4s ease;
}
.site-header.is-stuck::before { opacity: 1; }
/* The frost is within 2% of the canvas it sits on, so once white cards pass under the stuck bar it
   has no edge at all. A hairline gives it one. */
.site-header.is-stuck { box-shadow: 0 1px 0 var(--line); }
.site-header.is-up { transform: translateY(-100%); }   /* hides on scroll down, returns on scroll up */
.site-header__inner { display: flex; align-items: center; gap: 28px; min-height: 88px; }
/*
 * A horizontal wordmark's presence is its height against the bar, not its width. At 108px this
 * 1024×446 mark stood 47px in an 88px bar — 53%, and less once its internal padding is discounted —
 * so it read as a caption beside the nav rather than the header's anchor. 132px puts it at 57.5px
 * (~65%), the range a wordmark needs to anchor, and still leaves 15px of air top and bottom. The
 * source is 1024px wide, so this costs no sharpness.
 */
.site-header__logo img { width: 132px; }

.nav { display: flex; align-items: center; gap: 36px; margin-left: auto; }
.nav a { text-decoration: none; font-size: 16px; font-weight: 500; letter-spacing: -.01em; }
/* One disclosure instead of loose code pills. <details> keeps switching working without JS. */
.lang-menu { position: relative; }
.lang-menu__btn {
  display: inline-flex; align-items: center; gap: 8px; cursor: pointer; list-style: none;
  font-size: 15px; font-weight: 600; letter-spacing: .08em; padding: 13px 18px;
  border-radius: var(--radius-pill); color: var(--ink);
  /* A 28%-alpha ring among four plain text links reads as a control, not a fifth link. */
  box-shadow: inset 0 0 0 1.5px rgba(66, 66, 66, .28);
  transition: background .3s var(--ease), color .3s var(--ease);
}
.lang-menu__btn::-webkit-details-marker { display: none; }
.lang-menu__btn::after { content: none; }
.lang-menu__btn svg { width: 10px; height: 6px; transition: transform .3s var(--ease); }
.lang-menu__btn:hover { background: var(--dark); color: #fff; }
.lang-menu__btn:focus-visible { outline: 2px solid var(--brand); outline-offset: 3px; }
.lang-menu[open] .lang-menu__btn svg { transform: rotate(180deg); }
.lang-menu__list {
  position: absolute; right: 0; top: calc(100% + 10px); z-index: 20;
  margin: 0; padding: 8px; list-style: none; min-width: 176px;
  background: var(--surface); border: 1px solid var(--line); border-radius: 18px;
  box-shadow: 0 18px 44px rgba(10, 10, 10, .10);
}
.lang-menu .lang-menu__item {
  display: block; padding: 10px 14px; border-radius: 12px;
  font-size: 15px; font-weight: 500; letter-spacing: 0; color: var(--ink);
  transition: background .25s var(--ease);
}
.lang-menu a.lang-menu__item:hover { background: var(--canvas); }
.lang-menu a.lang-menu__item::after { content: none; }
.lang-menu .lang-menu__item.is-current {
  color: var(--brand-d); font-weight: 600; background: rgba(153, 79, 231, .08);
}
.lang-menu a.lang-menu__item:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }

.nav-toggle { display: none; margin-left: auto; background: none; border: 0; cursor: pointer; padding: 13px 12px; line-height: 0; }
.nav-toggle span { display: block; width: 26px; height: 2px; background: var(--ink); transition: transform .4s var(--ease), opacity .3s; }
/* The collapse transforms are pitch-locked: 2px bar + 7px gap ⇒ 9px centre-to-centre. */
.nav-toggle span + span { margin-top: 7px; }
.nav-toggle[aria-expanded="true"] span:nth-child(1) { transform: translateY(9px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.nav-toggle[aria-expanded="true"] span:nth-child(3) { transform: translateY(-9px) rotate(-45deg); }

/* 1120, not 940: the five English labels ("Educational Institutions" is the long one) only fit on one
   line above ~1080px, so between 940 and 1080 the inline nav wrapped to two lines and looked broken.
   Below 1120 we show the full-screen menu instead — comfortably clear of that wrap point. */
@media (max-width: 1120px) {
  .nav-toggle { display: block; }

  /* A transform/opacity overlay, not a clip-path circle: a percentage clip radius re-resolves (and
     restarts its transition) whenever the box resizes, which it does the moment we lock body scroll. */
  .nav {
    position: fixed; inset: 0; margin: 0; padding: 120px var(--gutter) 40px;
    flex-direction: column; align-items: flex-start; justify-content: center; gap: 4px;
    background: var(--canvas);
    transform: translateY(-100%); opacity: 0; visibility: hidden;   /* hidden ⇒ not tabbable */
    transition: transform .6s var(--ease-io), opacity .35s ease, visibility 0s linear .6s;
  }
  .nav.is-open {
    transform: none; opacity: 1; visibility: visible;
    transition: transform .6s var(--ease-io), opacity .3s ease, visibility 0s;
    /* Body scroll is locked while this is open, so a menu taller than the viewport — landscape, or
       iOS Larger Text — would clip its first and last links off-screen with no way to reach them. */
    overflow-y: auto; justify-content: flex-start;
  }
  /* -.03em is double the -.015em Latvian floor, and these are the exact collision cases: the macrons
     in "Izglītības iestādēm" fuse into one bar, at 30px+ where it is most visible. 26px at the floor
     keeps that same label on one line in a 280px column. */
  .nav a { font-size: clamp(26px, 7.5vw, 48px); font-weight: 600; letter-spacing: -.015em; padding: 10px 0; }
  /* Inside the full-screen menu the panel joins the flow — a floating card over the
     overlay would detach from its button on scroll. */
  .lang-menu { margin-top: 28px; }
  .nav .lang-menu__btn { font-size: 15px; padding: 14px 22px; }
  .lang-menu__list {
    position: static; min-width: 0; padding: 10px 0 0; border: 0; border-radius: 0;
    background: transparent; box-shadow: none;
  }
  .nav .lang-menu__item { font-size: 17px; font-weight: 500; letter-spacing: 0; padding: 10px 14px; }
}

/* While the menu is open the header must not be mid-transform: a transformed ancestor becomes the
   containing block for the fixed overlay and would clip it back into the header bar. */
.site-header.is-menu-open { transform: none; transition: none; }

/* ── hero ────────────────────────────────────────────────────────────────────────────────────── */

/* The hero shares the page's colour now instead of opening on stark white. A soft violet wash at
   the top fades to canvas by ~68%, so the hero, the audience cards below it and the washed "why"
   section all sit in one tinted family rather than white-then-sudden-colour. The wash carries no
   text — the headline sits on the light end (≥16:1) and the accent clause is measured separately. */
.hero {
  /* The header is fixed and 88px tall, so this top padding is header + the gap below it. At the old
     `clamp(72px,7vw,116px)` the headline sat ~2–13px under the bar at desktop widths — cramped. This
     clears the 88px and leaves ~16px (tablet) to ~60px (wide) of air. The ≤480px override below keeps
     phones tighter, where the CTA has to stay above the fold. */
  padding: clamp(104px, 9vw, 148px) 0 clamp(44px, 4.8vw, 76px);
  background: linear-gradient(176deg, #f1e9fd 0%, #f5effc 30%, var(--canvas) 80%);
}
/* Text and photo share the first screen. The text column is a touch wider so the headline keeps its
   weight; below the tablet breakpoint the two stack (photo under the copy). */
.hero__grid {
  display: grid; grid-template-columns: 1.02fr 0.98fr;
  gap: clamp(32px, 4vw, 68px); align-items: center;
}
/* Smaller than the global h1 (max 92px): at ~half width that would wrap to five lines of Latvian.
   Line-height stays at the global 1.24 — never drop it, or a caron/descender clips in the mask reveal. */
.hero h1 { font-size: clamp(38px, 4.6vw, 66px); max-width: 15ch; }
/* A violet gradient panel peeks out below-right of the photo — the hero's splash of brand colour,
   and a bit of depth so the image doesn't float on the wash. */
.hero__media { position: relative; z-index: 0; margin-top: 0; border-radius: var(--radius); }
.hero__media::before {
  content: ""; position: absolute; inset: 22px -22px -22px 22px; z-index: -1;
  background: var(--grad-brand); border-radius: var(--radius);
}
/* The eyebrow, overlaid on the photo. Solid white (not the `.eyebrow--pill` translucent violet, which
   would let the image show through and drop the tracked caps' contrast) with a soft shadow so the pill
   lifts off any part of the picture. Text stays `--brand-d`, which is 4.5:1+ on white. */
.hero__badge {
  position: absolute; top: clamp(14px, 1.6vw, 20px); left: clamp(14px, 1.6vw, 20px);
  margin: 0; z-index: 2;
  background: rgba(255, 255, 255, .94);
  -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
  box-shadow: 0 8px 24px rgba(20, 12, 40, .18);
}
/* The payoff clause, in the same violet gradient the parent card wears — the page's one coloured
   headline, and the thread that ties the hero to the picker. Clipped to the glyphs; the lightest
   stop is 5.4:1 on the wash, and this is 74px large text (3:1 bar), so it clears it many times over.
   `-webkit-*` first: Safari still needs the prefixed clip. */
.grad-text {
  background: var(--grad-brand);
  -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent; color: transparent;
}
.hero p { margin: 28px 0 40px; max-width: 34ch; }
/* The image itself carries the radius and the clip (not `.hero__media`, whose gradient panel spills
   outside on purpose). 4:3 fills the column beside the tall copy — the old 16:8 crop was a thin band. */
.hero__media img {
  display: block; width: 100%; object-fit: cover; aspect-ratio: 4 / 3; object-position: 50% 40%;
  border-radius: var(--radius); position: relative;
}
.hero__band { margin-top: clamp(40px, 4vw, 68px); border-radius: var(--radius-s); overflow: hidden; }

@media (max-width: 900px) {
  /* Stack: copy, then photo below it. The mobile gutter is only 20px, so the panel's right offset
     is pulled in to 10px — at -22px it spilled 2px past the viewport and added a horizontal scroll. */
  .hero__grid { grid-template-columns: 1fr; gap: clamp(36px, 8vw, 56px); }
  .hero__media { max-width: 560px; }
  .hero__media::before { inset: 14px -10px -14px 10px; }
}

/* 140px of top padding on a 568px-tall phone pushed the primary CTA below the fold — and the
   Latvian label is the longer of the two. */
@media (max-width: 480px) {
  .hero { padding-top: 104px; }
  .hero p { margin: 18px 0 28px; }
}

/* ── grids & cards ───────────────────────────────────────────────────────────────────────────── */

.grid { display: grid; gap: clamp(20px, 2.2vw, 32px); }
.grid--2 { grid-template-columns: repeat(2, 1fr); }
.grid--3 { grid-template-columns: repeat(3, 1fr); }
.grid--4 { grid-template-columns: repeat(4, 1fr); }
/* Grid tracks size to their content minimum; without this a wide child overflows the page. */
.grid > *, .split > * { min-width: 0; }
@media (max-width: 1000px) { .grid--3, .grid--4 { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 660px) { .grid--2, .grid--3, .grid--4 { grid-template-columns: 1fr; } }

/* Cards always sit one step lighter than their section, so they read as surfaces on both. */
.card {
  position: relative; background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius-s); padding: clamp(28px, 2.6vw, 40px);
  transition: transform .6s var(--ease), border-color .4s ease, background .4s ease, box-shadow .6s var(--ease);
}
.section--alt .card { background: var(--canvas); border-color: transparent; }
/* On the tinted wash the cards go white too, so they read as raised on the colour, not lost in it. */
.section--wash .card,
.section--warm .card { background: var(--canvas); border-color: transparent; }
.card:hover { transform: translateY(-6px); border-color: var(--brand); box-shadow: var(--shadow); }
.card p { margin-top: 14px; color: var(--muted); line-height: 1.65; font-size: 16px; }

/* ── audience picker (parent · driver · school) ────────────────────────────────────────────────
   Three whole-colour cards under the hero. Each is a full brand fill — the page's one burst of
   colour up front, answering "there aren't enough colours". They are links, so the whole card is
   the target.

   Contrast is the constraint that shapes them. White type only survives on the violet (4.54:1);
   on `--blue` white is 3.08:1 and on `--yellow` 1.41:1 — both fail — so those two carry near-black
   `--dark` ink instead (6.43:1 and 14:1). That is *why* the tones differ per card rather than a
   whim. */
.audience {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: clamp(16px, 1.8vw, 26px);
}
@media (max-width: 860px) { .audience { grid-template-columns: 1fr; } }

.audience__card {
  display: flex; flex-direction: column; align-items: flex-start;
  min-height: clamp(230px, 24vw, 300px); padding: clamp(26px, 2.4vw, 38px);
  border-radius: var(--radius); text-decoration: none; color: inherit;
  transition: transform .5s var(--ease), box-shadow .5s var(--ease);
}
.audience__card:hover { transform: translateY(-6px); box-shadow: var(--shadow); }
.audience__card:focus-visible { outline: 3px solid var(--dark); outline-offset: 3px; }

/* `color: inherit` is load-bearing: the global `h1,h2,h3 { color: var(--ink) }` otherwise wins over
   the card's inherited white and paints the violet card's title dark grey — ~2.2:1, unreadable. Each
   title must take its own card's ink (white on violet, near-black on yellow/blue). */
.audience__card h3 { color: inherit; font-size: clamp(23px, 2vw, 30px); line-height: 1.24; margin-bottom: 10px; }
.audience__card p { line-height: 1.6; font-size: clamp(15px, 1.1vw, 17px); max-width: 26ch; margin-bottom: 22px; }

/* The icon disc: a translucent well of the card's own ink, so it reads on any of the three fills. */
.audience__icon {
  display: grid; place-items: center; width: 56px; height: 56px; margin-bottom: clamp(22px, 2vw, 34px);
  border-radius: 16px; background: rgba(255, 255, 255, .18);
}
.audience__icon svg { width: 28px; height: 28px; }

/* The CTA line: label + arrow, nudged right on hover — the affordance the old flat cards lacked.
   `margin-top: auto` pins it to the card's bottom edge so all three CTAs align regardless of how many
   lines the copy above wraps to; the icon now takes a fixed bottom margin so the titles top-align too
   (bottom-anchoring the whole text block via the icon's old `margin-bottom: auto` left the headings at
   three different heights). */
.audience__cta {
  display: inline-flex; align-items: center; gap: 8px; margin-top: auto;
  font-weight: 600; font-size: 15px; letter-spacing: -.01em;
}
.audience__cta svg { width: 16px; height: 16px; transition: transform .4s var(--ease); }
.audience__card:hover .audience__cta svg { transform: translateX(5px); }

/* Parent → the brand violet, the only fill that takes white type. */
.audience__card--violet { background: var(--grad-brand); color: #fff; }
.audience__card--violet .audience__icon { background: rgba(255, 255, 255, .2); }
/* Driver → the yellow; ink is near-black because white on yellow is 1.41:1. */
.audience__card--yellow { background: var(--yellow); color: var(--dark); }
.audience__card--yellow .audience__icon { background: rgba(10, 10, 10, .09); }
/* School → the identity blue; near-black ink again (white on blue is 3.08:1). */
.audience__card--blue { background: var(--blue); color: var(--dark); }
.audience__card--blue .audience__icon { background: rgba(10, 10, 10, .1); }

/* Oversized step numeral, the way Cuberto indexes its services list — set in the brand gradient
   (like the hero's accent clause) so the "how it works" band carries the page's colour instead of
   one flat violet. Large text, so both gradient stops clear 3:1 by a wide margin. */
.step__num {
  font-size: clamp(40px, 4vw, 58px); font-weight: 600; letter-spacing: -.04em; line-height: 1;
  margin-bottom: 28px;
  background: var(--grad-brand);
  -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent; color: transparent;
}

.tick { display: flex; gap: 12px; margin-top: 14px; color: var(--muted); line-height: 1.6; font-size: 16px; }
.tick::before { content: "→"; color: var(--brand); flex: none; }

/* ── split sections ──────────────────────────────────────────────────────────────────────────── */

.split { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(40px, 6vw, 100px); align-items: center; }
.split--reverse .split__media { order: -1; }
.split p { margin: var(--gap-head) 0 40px; color: var(--muted); line-height: 1.75; max-width: 42ch; }
.split__media { border-radius: var(--radius); overflow: hidden; }
.split__media img { width: 100%; transition: transform 1.2s var(--ease); }
.split__media:hover img { transform: scale(1.04); }
@media (max-width: 940px) {
  .split { grid-template-columns: 1fr; }
  .split--reverse .split__media { order: 0; }
}

.phone-shot { border-radius: 0; overflow: visible; }
/* `min(380px, 100%)`, not `380px`: a hard cap would set the grid track's minimum and overflow. */
.phone-shot img { max-width: min(380px, 100%); margin: 0 auto; filter: drop-shadow(0 30px 60px color-mix(in srgb, var(--ink) 28%, transparent)); }
.phone-shot:hover img { transform: none; }

/* The mobile-app section as a full brand-gradient card — the page's big colour block in the middle,
   where a long white stretch used to sit. White type is measured against the gradient's lightest
   stop (`--grad-cta`: #6E37B0 → 7.4:1 heading, 5.5:1 body at .86 alpha). `.app-panel p` follows
   `.split p` in source order, so its white wins over the muted grey at equal specificity. */
.app-panel {
  background: var(--grad-cta); border-radius: var(--radius); overflow: hidden;
  padding: clamp(36px, 4.6vw, 76px); color: #fff;
}
.app-panel h2 { color: #fff; }
.app-panel p { color: rgba(255, 255, 255, .86); }
/* The drop-shadow reads muddy over violet; a dark cool cast sits right on the gradient. The real
   screenshot is a full-height phone (taller than the old cropped mockup), so cap it a touch tighter
   here to keep the card balanced against the text column. */
.app-panel .phone-shot img { filter: drop-shadow(0 26px 46px rgba(18, 10, 38, .4)); max-width: min(330px, 100%); }

/* A 1050×1400 portrait in a 620px-tall box loses a third of its height on tablet. Bias the crop
   upward so the subject's head survives it. */
.photo-cover img { width: 100%; height: auto; max-height: 620px; object-fit: cover; object-position: 50% 22%; }

/* Capped and centred: the 16:9 artwork carries a lot of internal whitespace, so full-container width
   turned a trust badge into a ~675px-tall near-empty white band. A 620px cap keeps it proportionate. */
/* The safety badge: a compact centred card on the wash — a two-tone caption over five gold stars.
   Replaces a 1920×1080 raster that was mostly whitespace and read as a big empty band. The stars
   take the yellow token as ARTWORK (a rating star is the one sanctioned fill), never as text. */
.badge {
  max-width: 560px; margin: var(--block) auto 0; padding: clamp(28px, 3vw, 40px) clamp(28px, 3vw, 48px);
  display: flex; flex-direction: column; align-items: center; gap: 18px; text-align: center;
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius-s);
}
.badge__caption {
  margin: 0; max-width: 22ch; color: var(--ink);
  font-size: clamp(19px, 1.7vw, 27px); line-height: 1.32; font-weight: 600; letter-spacing: -.01em;
}
.badge__lead { color: var(--muted); }
.badge__stars { display: inline-flex; gap: clamp(5px, .7vw, 9px); color: var(--yellow); }
.badge__stars svg { width: clamp(26px, 2.6vw, 32px); height: auto; display: block; }

/* Contacts aside. The message form is tall and the info block was two lines, so the right half read
   as empty. Centre a defined card against the form; the addresses are icon rows that fill on hover,
   the same affordance the site's pills use. */
/* Top-aligned so the two headings ("Submit Form" / "Ready to Get Started?") line up; the card's own
   weight carries the shorter column, so the space below it reads as layout, not emptiness. */
.split--contact { align-items: start; }
.contact-aside {
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius);
  padding: clamp(30px, 3.2vw, 46px);
}
.contact-aside h3 { margin-bottom: 18px; }
.contact-aside__company { color: var(--muted); line-height: 1.8; margin-bottom: 26px; max-width: 34ch; }
.contact-aside__methods { display: flex; flex-direction: column; gap: 12px; }
.contact-method {
  display: flex; align-items: center; gap: 14px; text-decoration: none;
  padding: 15px 18px; border-radius: var(--radius-s); background: var(--canvas);
  color: var(--ink); font-size: clamp(16px, 1.4vw, 19px); font-weight: 600; letter-spacing: -.01em;
  transition: background .3s var(--ease), color .3s var(--ease);
}
.contact-method svg { width: 22px; height: 22px; color: var(--brand-d); flex: none; transition: color .3s var(--ease); }
.contact-method:hover { background: var(--brand-d); color: #fff; }
.contact-method:hover svg { color: #fff; }
.contact-method:focus-visible { outline: 2px solid var(--brand); outline-offset: 3px; }

/* ── testimonials ────────────────────────────────────────────────────────────────────────────── */

.quote {
  display: flex; flex-direction: column; justify-content: space-between;
  border-radius: var(--radius-s); padding: clamp(28px, 2.6vw, 40px);
  background: var(--surface); transition: background .5s var(--ease), color .5s var(--ease);
}
.section--alt .quote { background: var(--canvas); }
.section--wash .quote { background: var(--canvas); }
.quote:hover { background: var(--dark); color: #fff; }
.quote p { font-size: clamp(17px, 1.3vw, 20px); line-height: 1.55; letter-spacing: -.015em; margin-bottom: 40px; }
.quote footer { display: flex; align-items: baseline; gap: 12px; padding-top: 22px; border-top: 1px solid var(--line); }
.quote:hover footer { border-color: rgba(255, 255, 255, .2); }
.quote strong { font-size: 15px; font-weight: 600; }
.quote span { color: var(--muted); font-size: 14px; }
.quote:hover span { color: rgba(255, 255, 255, .6); }

/* ── photo band ──────────────────────────────────────────────────────────────────────────────── */

.band {
  position: relative; border-radius: var(--radius); overflow: hidden; color: #fff;
  padding: clamp(56px, 8vw, 130px) clamp(28px, 4vw, 72px);
}
.band__bg { position: absolute; inset: -12% 0; width: 100%; height: 124%; object-fit: cover; will-change: transform; }
.band::after { content: ""; position: absolute; inset: 0; background: color-mix(in srgb, var(--dark) 70%, transparent); }
.band > .grid { position: relative; z-index: 1; }
.band h3 { color: #fff; }
.band p { color: rgba(255, 255, 255, .78); margin-top: var(--gap-head); line-height: 1.75; max-width: 40ch; }

/* ── stats ───────────────────────────────────────────────────────────────────────────────────── */

.stats { display: grid; grid-template-columns: repeat(3, 1fr); gap: clamp(20px, 2.2vw, 32px); }
.stats div { padding-top: 28px; border-top: 1px solid var(--line); }
/* At .18 alpha (1.64:1) the only structure inside the dark band was invisible and it read as a slab. */
.section--dark .stats div { border-color: rgba(255, 255, 255, .28); }
/* At 5.6vw these numerals overtook the h2 above them (5.2vw) from ~615px up — the figures shouted
   louder than the headline that introduced them. */
.stats strong {
  display: block; font-size: clamp(40px, 4.6vw, 66px); font-weight: 600; line-height: 1;
  letter-spacing: -.04em; margin-bottom: 12px; font-variant-numeric: tabular-nums;
}
.stats span { color: var(--muted); font-size: 16px; }
.section--dark .stats span { color: rgba(255, 255, 255, .8); }
@media (max-width: 660px) { .stats { grid-template-columns: 1fr; } }

/* ── closing CTA ─────────────────────────────────────────────────────────────────────────────── */

.cta { text-align: center; }
.cta h2 { max-width: 16ch; margin: 0 auto; }
.cta p { margin: 28px auto 0; max-width: 46ch; color: rgba(255, 255, 255, .82); line-height: 1.7; }

/* Floating circular CTA, bottom-right — Cuberto's `.cb-intouch`. */
.floating-cta {
  position: fixed; right: clamp(16px, 2.5vw, 40px); bottom: clamp(16px, 2.5vw, 36px); z-index: 80;
  width: 118px; height: 118px; border-radius: 50%;
  display: grid; place-items: center; text-align: center; text-decoration: none;
  background: var(--brand); color: #fff; font-size: 13px; font-weight: 500; line-height: 1.3;
  padding: 12px; box-shadow: 0 16px 40px color-mix(in srgb, var(--brand) 38%, transparent);
  opacity: 0; transform: scale(.4); pointer-events: none;
  transition: opacity .5s var(--ease), transform .6s var(--ease), background .3s ease;
}
.floating-cta.is-visible { opacity: 1; transform: scale(1); pointer-events: auto; }
/* Not `--dark`: the disc is fixed over the dark CTA band and the footer, both #0a0a0a, so on hover
   it dissolved into the background and left only its purple shadow behind. */
.floating-cta:hover { background: var(--brand-d); }
/* On a phone an 88px disc at bottom-right lands squarely on the full-width form submit and on the
   wizard's Next button. The header nav already carries the same link. */
@media (max-width: 660px) { .floating-cta { display: none; } }

/* ── forms ───────────────────────────────────────────────────────────────────────────────────── */

.form-card {
  background: var(--canvas); border: 1px solid var(--line); border-radius: var(--radius);
  padding: clamp(28px, 2.6vw, 40px); text-align: left;   /* the same interior scale as .card / .quote */
}
.section--alt .form-card, .section--dark .form-card { background: var(--canvas); border-color: transparent; color: var(--ink); }
.section--dark .form-card h3 { color: var(--ink); }
.form-card > .form-card__body > p { color: var(--muted); line-height: 1.7; margin-top: 14px; }
.form-card form { margin-top: 34px; }

/* The two lead forms ask a different number of fields (the parent form 2, the driver form 3), so
   their cards ended at different heights with mismatched bottoms. Stretch each to the taller of the
   pair so they read as one matched set. Scoped with `:has` to the lead-form grid only. */
.grid--2:has(> * > .form-card) > * { display: flex; }
.grid--2:has(> * > .form-card) .form-card { flex: 1; }

label { display: block; font-size: 13px; font-weight: 500; letter-spacing: .04em; text-transform: uppercase; color: var(--muted); margin: 26px 0 10px; }
label:first-of-type { margin-top: 0; }

/* An underline-style field's whole affordance is that underline, so it cannot be drawn with the
   14%-alpha token meant for dividers — an empty field was a near-invisible hairline. */
/* `password` belongs here or it falls back to the UA's ~13px form font — and iOS Safari zooms the
   page in on any focused input under 16px, stranding the applicant zoomed into the final step. */
input[type=text], input[type=email], input[type=tel], input[type=number], input[type=password],
textarea, select {
  width: 100%; padding: 16px 0; color: var(--ink);
  font: 400 17px/1.5 Poppins, sans-serif;
  background: transparent; border: 0; border-bottom: 1.5px solid var(--line-i); border-radius: 0;
  caret-color: var(--brand);
  transition: border-color .4s var(--ease), box-shadow .4s var(--ease);
}
/* Firefox applies its own ~.54 opacity to placeholders; `opacity: 1` is what stops it re-breaking
   the contrast this rule just fixed. */
::placeholder { color: var(--muted); opacity: 1; }

/* Scoped to the text controls: the blanket reset also stripped the ring from checkboxes and radios,
   whose focus can't be shown by recolouring a border-bottom they do not have. */
input[type=text]:focus, input[type=email]:focus, input[type=tel]:focus,
input[type=number]:focus, input[type=password]:focus, textarea:focus, select:focus {
  outline: none; border-bottom-color: var(--brand);
  box-shadow: 0 1.5px 0 0 var(--brand);   /* doubles the underline to ~3px without shifting layout */
}
input[type=checkbox]:focus-visible, input[type=radio]:focus-visible {
  outline: 2px solid var(--brand); outline-offset: 2px;
}
/* An error the user can read but not locate is half an error message. */
input[aria-invalid="true"], select[aria-invalid="true"], textarea[aria-invalid="true"] {
  border-bottom-color: var(--danger);
}
textarea { min-height: 120px; resize: vertical; }
select { appearance: none; cursor: pointer;
  background-image: linear-gradient(45deg, transparent 50%, var(--ink) 50%), linear-gradient(135deg, var(--ink) 50%, transparent 50%);
  background-position: calc(100% - 14px) 25px, calc(100% - 8px) 25px;
  background-size: 6px 6px; background-repeat: no-repeat; padding-right: 34px; }

/*
 * Dial-code selector + national number on one underlined row. The select is sized to its content and
 * allowed to shrink, the input takes the rest — `min-width: 0` because a flex item's default
 * `min-width: auto` refuses to go below its intrinsic width and would push the row into a horizontal
 * scroll on a 320px screen. The option text carries the country name, so the closed select ellipsises
 * it away when there is no room; the flag and dial code, the parts that matter, always survive.
 */
.phone-row {
  display: flex; align-items: baseline; gap: 14px;
  /* One control, so one underline. Two separate border-bottoms with a gap between them read as two
     broken fields rather than a dial code attached to a number. */
  border-bottom: 1.5px solid var(--line-i);
  transition: border-color .4s var(--ease), box-shadow .4s var(--ease);
}
.phone-row select, .phone-row input { border-bottom: 0; }
.phone-row select:focus, .phone-row input:focus { box-shadow: none; }
.phone-row:focus-within { border-bottom-color: var(--brand); box-shadow: 0 1.5px 0 0 var(--brand); }
.phone-row:has(input[aria-invalid="true"]) { border-bottom-color: var(--danger); }
.phone-row select { flex: 0 1 auto; width: auto; max-width: 52%; text-overflow: ellipsis; }
.phone-row input { flex: 1 1 auto; min-width: 0; }
.phone-row + .note { margin-top: 10px; font-size: 13px; }
/* The hint states the rule; when the rule is broken the same sentence turns red rather than being
   repeated verbatim underneath itself in a second element. */
.note.is-error { color: var(--danger); }

.consent { display: flex; gap: 14px; align-items: flex-start; margin-top: 32px;
  font-size: 13px; line-height: 1.6; color: var(--muted); font-weight: 400; text-transform: none; letter-spacing: 0; }
.consent input { margin-top: 3px; flex: none; width: 18px; height: 18px; accent-color: var(--brand); }
.consent a { color: var(--blue-t); }

.err { display: none; color: var(--danger); font-size: 13px; line-height: 1.5; margin-top: 8px; }
.form-error { display: none; color: var(--danger); font-size: 14px; margin-top: 16px; text-align: center; }
.form-card .btn { margin-top: 36px; }

/* Honeypot: off-screen and untabbable. A human never sees it; a bot fills it and is dropped. */
.hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

/* ── driver onboarding wizard ────────────────────────────────────────────────────────────────── */

.container--narrow { max-width: 860px; }

/* `flex` + `fit-content`, not `inline-flex`: an inline box lets the eyebrow that follows sit on the
   same line, and "Atpakaļ uz sākumlapu • AUTOVADĪTĀJIEM" runs together. */
.back-link {
  display: flex; width: fit-content; align-items: center; gap: 10px; margin-bottom: 28px;
  color: var(--muted); font-size: 15px; font-weight: 500; text-decoration: none;
  transition: color .25s var(--ease);
}
.back-link svg { width: 16px; height: 16px; transition: transform .3s var(--ease); }
.back-link:hover { color: var(--ink); }
.back-link:hover svg { transform: translateX(-4px); }

.btn--ghost { background: transparent; color: var(--muted); box-shadow: inset 0 0 0 1.5px var(--line); }
.btn--ghost::after { background: var(--ink); }
.btn--ghost:hover { color: #fff; }

/* The three-phase spine: profile → safety test → review. */
.spine { display: flex; gap: clamp(16px, 3vw, 44px); list-style: none; margin: 0 0 clamp(32px, 4vw, 56px); padding: 0; }
.spine__item { display: flex; align-items: center; gap: 12px; color: var(--muted); font-size: 15px; font-weight: 500; }
.spine__dot {
  display: grid; place-items: center; flex: none; width: 34px; height: 34px; border-radius: 50%;
  background: transparent; color: var(--muted); font-size: 14px;
  box-shadow: inset 0 0 0 1.5px var(--line-i); transition: background .4s var(--ease), color .4s var(--ease);
}
.spine__item.is-active { color: var(--ink); }
.spine__item.is-active .spine__dot { background: var(--brand); color: #fff; box-shadow: none; }
/* Without this a finished phase reverts to muted — indistinguishable from one never visited, so the
   spine showed position rather than progress. */
.spine__item.is-done { color: var(--ink); }
.spine__item.is-done .spine__dot { background: var(--green-t); color: #fff; box-shadow: none; }
.spine__item.is-done .spine__num { display: none; }
.spine__tick { display: none; }
.spine__item.is-done .spine__tick { display: block; width: 15px; height: 15px; }
@media (max-width: 640px) { .spine__label { display: none; } }

/* Only the active step is in the document; `hidden` steps keep their values for the single POST. */
.apply-step { display: none; border: 0; margin: 0; padding: 0; min-width: 0; }
.apply-step.is-active { display: block; }
.apply-step > p { color: var(--muted); line-height: 1.7; margin-top: 14px; }
.apply-step > h3 + p { margin-bottom: 34px; }

/* A heading for a group of radios/checkboxes — `label` is taken, and would bind to one input. */
.field-label {
  display: block; font-size: 13px; font-weight: 500; letter-spacing: .04em; text-transform: uppercase;
  color: var(--muted); margin: 34px 0 14px;
}

.choices { display: grid; gap: 10px; }
.choice {
  display: flex; align-items: flex-start; gap: 14px; margin: 0; padding: 16px 18px;
  border: 1.5px solid var(--line); border-radius: var(--radius-s); cursor: pointer;
  color: var(--ink); font-size: 16px; font-weight: 400; line-height: 1.5;
  text-transform: none; letter-spacing: 0;
  transition: border-color .3s var(--ease), background .3s var(--ease);
}
.choice:hover { border-color: var(--brand); }
.choice input { flex: none; margin-top: 2px; width: 18px; height: 18px; accent-color: var(--brand); }
.choice:has(input:checked) { border-color: var(--brand); background: color-mix(in srgb, var(--brand) 5%, transparent); }

/* The "Other" reveals are the first label of their wrapper, so `label:first-of-type { margin-top: 0 }`
   zeroed the gap and glued them to the control that revealed them. */
[data-referral-other] > label { margin-top: 26px; }

/* Vehicle search: the suggestion list floats under the field (a plain text input above it), styled
   like a card. `mousedown` on a row selects it before the input's blur can hide the list. */
.vehicle-search { position: relative; }
.vehicle-suggest {
  position: absolute; left: 0; right: 0; top: calc(100% + 6px); z-index: 30;
  margin: 0; padding: 6px; list-style: none;
  background: var(--surface); border: 1px solid var(--line); border-radius: 16px;
  box-shadow: 0 22px 48px -24px rgba(66, 66, 66, .45);
  max-height: 320px; overflow-y: auto;
}
.vehicle-suggest li {
  display: flex; align-items: center; gap: 12px;
  padding: 13px 14px; border-radius: 10px; cursor: pointer;
  font: 400 16px/1.4 Poppins, sans-serif;
}
.vehicle-suggest li + li { border-top: 1px solid var(--line); border-radius: 0; }
.vehicle-suggest li:hover { background: color-mix(in srgb, var(--brand) 9%, transparent); border-radius: 10px; }
.vehicle-suggest li:hover + li { border-top-color: transparent; }
.vehicle-suggest__car { color: var(--ink); flex: 0 0 auto; opacity: .65; }
.vehicle-suggest__label { color: var(--muted); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.vehicle-suggest__label strong { color: var(--ink); font-weight: 600; }

.swatches { display: flex; flex-wrap: wrap; gap: 10px; }
.swatch { margin: 0; padding: 8px 14px 8px 8px; min-height: 44px; display: inline-flex; align-items: center; gap: 10px;
  border: 1.5px solid var(--line); border-radius: var(--radius-pill); cursor: pointer;
  font-size: 14px; font-weight: 400; text-transform: none; letter-spacing: 0; color: var(--ink);
  transition: border-color .3s var(--ease); }
.swatch:hover { border-color: var(--brand); }
.swatch input { position: absolute; opacity: 0; pointer-events: none; }
/* The white chip needs a stronger ring than a divider or it vanishes on the canvas-coloured card. */
.swatch__chip { width: 22px; height: 22px; border-radius: 50%; flex: none; box-shadow: inset 0 0 0 1px var(--line-i); }
/* The "Other — specify" chip: a colour wheel, i.e. any paint we didn't list. */
.swatch__chip--other { background: conic-gradient(#d1352c, #f2c94c, #2e8b3d, #2f6fdb, #994fe7, #d1352c); }
.swatch:has(input:checked) { border-color: var(--brand); box-shadow: 0 0 0 1.5px var(--brand); }

.photo-drop {
  display: flex; align-items: center; gap: 20px; margin: 0; padding: 20px;
  border: 1.5px dashed var(--line-i); border-radius: var(--radius-s); cursor: pointer;
  text-transform: none; letter-spacing: 0; transition: border-color .3s var(--ease);
}
.photo-drop:hover { border-color: var(--brand); }
.photo-drop input[type=file] { position: absolute; opacity: 0; width: 1px; height: 1px; }

/* Both controls hide their real input off-screen, so the focus ring has to be drawn on the visible
   proxy — otherwise tabbing the vehicle step shows nothing at all. */
.swatch:has(input:focus-visible), .photo-drop:has(input:focus-visible) {
  border-color: var(--brand); box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand) 35%, transparent);
}
.photo-drop__preview { width: 76px; height: 76px; border-radius: 50%; object-fit: cover; flex: none; }
.photo-drop__text strong { display: block; color: var(--ink); font-size: 16px; font-weight: 600; }
.photo-drop__text small { display: block; margin-top: 4px; color: var(--muted); font-size: 14px; }

.link-list { list-style: none; margin: 0 0 8px; padding: 0; display: grid; gap: 14px; }
.link-list a { display: inline-flex; align-items: center; gap: 8px; color: var(--blue-t); font-size: 16px; }
.link-list svg { width: 16px; height: 16px; flex: none; }

.rules { list-style: none; margin: 22px 0 0; padding: 0; display: grid; gap: 8px; }
.rules li { display: flex; gap: 10px; color: var(--muted); font-size: 14px; }
/* An unmet rule drawn at 14% alpha is a rule the user cannot read — and the unmet ones are the
   only ones that matter. */
.rules li::before { content: "○"; color: var(--muted); }
.rules li.is-met { color: var(--ink); }
.rules li.is-met::before { content: "✓"; color: var(--green-t); }

.note { color: var(--muted); font-size: 14px; line-height: 1.6; margin-top: 18px; }
.err--block { display: block; margin-top: 14px; }
.question + .question { margin-top: 40px; }
.question__prompt { color: var(--ink); font-size: 18px; line-height: 1.5; margin-bottom: 16px; }

/*
 * ── the recorded safety test ──
 * Phase 2 of the wizard: each scenario question is answered by RECORDING voice or video in the
 * browser (driver-apply.js). Additive to the `.question` card — the mode toggle reuses `.choice`,
 * the controls are `.btn` / `.btn--ghost`; only the recorder's own furniture is new.
 */
.rec { margin-top: 20px; }
/* The API's intro paragraph keeps its own line breaks — hence pre-line, not a Blade string. */
.rec-intro { white-space: pre-line; color: var(--muted); line-height: 1.7; margin-bottom: 34px; }
/* A binary voice/video toggle, not a stacked list — two slim `.choice` pills on one row. */
.rec__modes { display: flex; flex-wrap: wrap; gap: 10px; }
.rec__modes .choice { padding: 10px 18px; align-items: center; }
.rec__row { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; margin-top: 20px; }
/* `.form-card .btn` stacks a 36px top margin meant for a lone submit — same reset `.apply-nav` does. */
.rec__row .btn { margin-top: 0; }
.rec__timer {
  display: inline-flex; align-items: center; gap: 8px;
  color: var(--ink); font-size: 15px; font-variant-numeric: tabular-nums;
}
.rec__timer::before { content: ""; width: 10px; height: 10px; border-radius: 50%; background: var(--danger); }
.rec__preview { margin-top: 20px; }
/* The same element is the live viewfinder while recording and the playback player after. */
.rec__preview video { display: block; width: 100%; max-height: 340px; border-radius: var(--radius-s); background: #000; }
.rec__preview audio { display: block; width: 100%; }
.rec__done { display: flex; align-items: center; gap: 8px; margin-top: 20px; color: var(--green-t); font-size: 15px; font-weight: 600; }

.apply-nav { display: flex; align-items: center; gap: 14px; margin-top: 40px; }
.apply-nav__count { margin-left: auto; color: var(--muted); font-size: 14px; }
/* `.form-card .btn` adds a 36px top margin meant for a single stacked submit button. */
.apply-nav .btn { margin-top: 0; }
.apply-nav .btn[disabled] { cursor: not-allowed; }

/*
 * "Back · step 3 of 7 · Next" cannot sit on one line on a phone; stack the counter above it. The
 * breakpoint is 600px, not 380px: at 380 it missed every iPhone from the 12 up (390–430px), where
 * the Latvian counter ("3. solis no 7") plus "Izveidot kontu" still overflowed the ~294px card —
 * and `.btn { overflow: hidden }` clips the label rather than ellipsising it.
 */
@media (max-width: 600px) {
  .apply-nav { flex-wrap: wrap; }
  .apply-nav__count { order: -1; width: 100%; margin: 0; text-align: center; }
  .apply-nav .btn { flex: 1 1 0; min-width: 0; justify-content: center; padding-left: 14px; padding-right: 14px; }
}

.apply__result { text-align: center; }
.apply__result h4 { margin-bottom: 12px; }
.apply__code {
  display: inline-flex; align-items: center; gap: 12px; margin: 28px 0 36px; padding: 14px 22px;
  border-radius: var(--radius-pill); background: color-mix(in srgb, var(--brand) 8%, transparent);
  color: var(--ink); font-size: 14px;
}
.apply__code strong { color: var(--brand-d); font-size: 20px; letter-spacing: .02em; }

.form-done { display: none; }
/* Not `.form-done .tickmark`: the wizard's result card carries a `.tickmark` too and is NOT a
   `.form-done`, so the payoff screen rendered a bare 17px glyph where the green disc should be. */
.tickmark {
  width: 72px; height: 72px; margin-bottom: 28px; border-radius: 50%;
  background: var(--green-t); color: #fff; font-size: 34px; display: grid; place-items: center;
}
.apply__result .tickmark { margin-inline: auto; }
.form-done p { color: var(--muted); margin-top: 12px; line-height: 1.7; }

/* ── prose / legal ───────────────────────────────────────────────────────────────────────────── */

.page-head { padding: clamp(140px, 15vw, 200px) 0 clamp(40px, 4vw, 64px); }
.page-head p { margin-top: 24px; max-width: 62ch; color: var(--muted); line-height: 1.7; }

/* 780px at 16px ran ~90 characters a line — a punishing measure for a document nobody wants to read
   in the first place. 68ch lands at ~640px, in line with the rest of the system. */
.prose { max-width: 68ch; font-size: 16px; }
.prose h2 { font-size: clamp(24px, 2.4vw, 32px); margin: 56px 0 20px; }
.prose h2:first-child { margin-top: 0; }
.prose h3 { font-size: 21px; margin: 40px 0 14px; letter-spacing: -.01em; }
.prose h4 { margin: 32px 0 12px; }
.prose p { margin: 0 0 18px; line-height: 1.8; color: var(--ink-70); }
.prose ul, .prose ol { margin: 0 0 22px; padding-left: 22px; line-height: 1.8; color: var(--ink-70); }
.prose li { margin-bottom: 10px; }
/* Colour alone can't carry a link (WCAG 1.4.1), and the identity blue failed the 4.5:1 floor besides. */
.prose a {
  color: var(--blue-t); text-decoration: underline;
  text-underline-offset: .18em; text-decoration-thickness: .06em;
}
.contact-emails a, .prose a, .link-list a { overflow-wrap: anywhere; }
.prose table { width: 100%; border-collapse: collapse; margin-bottom: 22px; display: block; overflow-x: auto; }
.prose td, .prose th { border: 1px solid var(--line); padding: 12px 14px; text-align: left; }

/* ── footer ──────────────────────────────────────────────────────────────────────────────────── */

.site-footer { background: var(--dark); color: #fff; padding: clamp(72px, 8vw, 128px) 0 40px; }
/* The one brand mark on the dark ground — the footer is otherwise pure greyscale. */
.site-footer { border-top: 3px solid var(--brand); }
.site-footer__grid { display: grid; grid-template-columns: 1.6fr 1fr 1fr; gap: 48px; }
.site-footer img { width: 132px; margin-bottom: 28px; filter: brightness(0) invert(1); }
.site-footer p { color: rgba(255, 255, 255, .55); line-height: 1.7; max-width: 34em; font-size: 16px; }
/* Three tiers, in the right order: links .8 (12.6:1) > headings .62 (7.7:1) > fine print .58 (6.9:1).
   At .45 the headings were dimmer than the links they label AND sat exactly on the 4.5:1 floor. */
.site-footer h5 { color: rgba(255, 255, 255, .62); font-size: 13px; font-weight: 500;
  letter-spacing: .14em; text-transform: uppercase; margin-bottom: 24px; }
.site-footer ul { list-style: none; margin: 0; padding: 0; }
.site-footer li { margin-bottom: 14px; }
.site-footer li a { display: inline-block; padding-block: 6px; color: rgba(255, 255, 255, .8); text-decoration: none; font-size: 16px; }
/* #994fe7 on #0a0a0a is 4.35:1 — a fail for text. The lightened brand clears it at 7.6:1. */
.site-footer li a:hover { color: #b98cef; }
.site-footer__legal {
  margin-top: clamp(56px, 6vw, 96px); padding-top: 28px; border-top: 1px solid rgba(255, 255, 255, .14);
  color: rgba(255, 255, 255, .58); font-size: 14px;
  /* `space-between` flung the registered-entity line — the page's one hard trust signal — to the far
     right, stranded from the copyright it belongs with. */
  display: flex; flex-wrap: wrap; gap: 6px 28px; justify-content: flex-start;
}
@media (max-width: 820px) { .site-footer__grid { grid-template-columns: 1fr; gap: 40px; } }

.skip-link { position: absolute; left: -9999px; top: 0; background: var(--brand); color: #fff; padding: 14px 22px; z-index: 600; }
.skip-link:focus { left: 0; }

/* ── reveal machinery ────────────────────────────────────────────────────────────────────────── */

/*
 * Only armed once site.js sets `html.can-animate` — so a no-JS or reduced-motion visitor never sees
 * an element stuck at opacity 0. This is the whole reason the selectors are prefixed.
 */
html.can-animate [data-reveal] { opacity: 0; transform: translateY(34px); }
html.can-animate [data-reveal].is-in {
  opacity: 1; transform: none;
  transition: opacity .9s var(--ease), transform 1s var(--ease);
  transition-delay: var(--reveal-delay, 0ms);
}

/* Headline lines rise out of a mask. The padding guards the clip edge: .12em below for descenders,
   .06em above because a caron reaches 0.928em and the 1.24 line-box has little room to spare. */
html.can-animate [data-reveal="mask"] { opacity: 1; transform: none; overflow: hidden; padding: .06em 0 .12em; }
html.can-animate [data-reveal="mask"] > span { display: block; transform: translateY(105%); }
html.can-animate [data-reveal="mask"].is-in > span {
  transform: none; transition: transform 1.1s var(--ease); transition-delay: var(--reveal-delay, 0ms);
}

/* Media wipes open, and the image inside settles back from a slight zoom. */
html.can-animate [data-reveal="media"] { opacity: 1; transform: none; clip-path: inset(0 0 100% 0); }
html.can-animate [data-reveal="media"] img { transform: scale(1.16); }
html.can-animate [data-reveal="media"].is-in { clip-path: inset(0 0 0 0); transition: clip-path 1.1s var(--ease); }
html.can-animate [data-reveal="media"].is-in img { transform: none; transition: transform 1.5s var(--ease); }

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