/* ──────────────────────────────────────────────────────────────────
   css/base.css
   ──────────────────────────────────────────────────────────────────
   The four rules every page used to declare inline, identically:

     1. * { margin:0; padding:0; box-sizing:border-box }
        — universal reset
     2. html { scroll-behavior:smooth; scrollbar-gutter:stable }
        — smooth anchor scrolls + reserve scrollbar gutter so the
          page doesn't shift when content overflows
     3. .stripe { … }
        — 3px animated gradient bar pinned to the top of every page,
          used as the brand "moving rainbow" accent
     4. @keyframes stripe { … }
        — the keyframes the .stripe animation references
     5. body { background; color; font-family; overflow-x }
        — universal body baseline. References var(--bg) and var(--txt)
          so pages still need a :root declaring them.

   Loaded BEFORE each page's inline <style> so per-page rules can
   still override these if needed. account.html for example sets its
   own body { …; min-height:100vh; display:flex; flex-direction:column }
   which wins over base.css for those properties — the cascade flows
   correctly. Loaded BEFORE css/mobile-fixes.css so mobile overrides
   still win on small viewports (e.g. mobile freezes the stripe
   animation).

   ────────────────────────────────────────────────────────────────── */
/* ── Self-hosted fonts ─────────────────────────────────────────────
   Pulled down from Google Fonts (Bebas Neue 400 + IBM Plex Mono
   400/600/700) via scripts/download-fonts.mjs and shipped from
   /fonts/. unicode-range scopes each face to the latin glyphs the
   site actually uses; cyrillic/vietnamese/latin-ext text falls back
   to the system monospace, same as before (those .woff2 files were
   never downloaded by Google Fonts either since no matching glyph
   appeared on any page).
   ────────────────────────────────────────────────────────────────── */
@font-face {
  font-family: 'Bebas Neue';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(/fonts/bebas-neue-400.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(/fonts/ibm-plex-mono-400.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url(/fonts/ibm-plex-mono-600.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url(/fonts/ibm-plex-mono-700.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;
}

*{margin:0;padding:0;box-sizing:border-box}
html{scroll-behavior:smooth;scrollbar-gutter:stable}
body{background:var(--bg);color:var(--txt);font-family:'IBM Plex Mono',monospace;overflow-x:hidden}
.stripe{position:fixed;top:0;left:0;right:0;height:3px;z-index:999;background:linear-gradient(90deg,#c0007a,var(--c),#c8c000,#c0002a,var(--c),#c0007a);background-size:400% 100%;animation:stripe 6s linear infinite;opacity:.7}
@keyframes stripe{0%{background-position:0% 0}100%{background-position:400% 0}}

/* ── Keyboard focus indicator ──────────────────────────────────────
   :focus-visible only fires for keyboard navigation, not mouse
   clicks, so mouse users don't see an outline ring on every click.
   ──────────────────────────────────────────────────────────────── */
:focus-visible {
  outline: 2px solid var(--c, #00e5b0);
  outline-offset: 2px;
  border-radius: 2px;
}

/* Don't paint the focus ring on <main> when we hand focus to it via
   the skip-link — the user wanted to read the content, not see a
   ring around the whole section. */
main:focus,
main:focus-visible { outline: none; }

/* ── Skip-link ─────────────────────────────────────────────────────
   Injected by js/a11y.js as the first focusable element on every
   public page. Hidden off-screen by default; the moment a keyboard
   user tabs onto it, it slides into view at the top-left corner so
   they can hit Enter to jump past the nav.
   ──────────────────────────────────────────────────────────────── */
.skip-link {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 10000;
  padding: 10px 16px;
  background: var(--c, #00e5b0);
  color: var(--bg, #0a0a0c);
  font: 700 12px/1 'IBM Plex Mono', monospace;
  letter-spacing: .1em;
  text-transform: uppercase;
  text-decoration: none;
  border-radius: 0 0 4px 0;
  transform: translateY(-150%);
  transition: transform .2s ease;
}
.skip-link:focus,
.skip-link:focus-visible {
  transform: translateY(0);
  outline: 2px solid var(--bg, #0a0a0c);
  outline-offset: -4px;
}

/* ── Top nav (sticky) ──────────────────────────────────────────────
   Was duplicated inline on all 21 pages with subtle drift between
   `padding:22px 0` and `padding:22px 32px`. The two variants made the
   nav contents jump 32px horizontally on every cross-page click —
   centralised here so the bar renders identically on every page.

   Pages with a pre-existing inline override still win (cascade order:
   base.css → inline <style>), so this is additive and safe to roll
   out one HTML at a time. Strip the inline block from a page to opt
   it into the shared rules.
   ──────────────────────────────────────────────────────────────── */
nav {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 22px 0;
  width: 100%;
  max-width: 1160px;
  margin: 0 auto;
  position: sticky;
  top: 3px;
  z-index: 100;
}
nav::before {
  content: '';
  position: absolute;
  top: 0;
  bottom: 0;
  left: calc(50% - 50vw);
  right: calc(50% - 50vw);
  background: rgba(10, 10, 12, .88);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border-bottom: 1px solid var(--border);
  z-index: -1;
  pointer-events: none;
}
nav .brand {
  font: 400 30px/1 'Bebas Neue', sans-serif;
  letter-spacing: .18em;
  color: #e0e0e0;
  text-decoration: none;
  display: flex;
  align-items: center;
  gap: 10px;
}
nav .brand img { height: 38px; width: auto; }
nav .links { display: flex; gap: 24px; }
nav .links a {
  font-size: 11px;
  color: #454550;
  text-decoration: none;
  letter-spacing: .1em;
  text-transform: uppercase;
  transition: color .3s;
}
nav .links a:hover,
nav .links a.active { color: var(--c); }
nav .nav-actions { display: flex; align-items: center; gap: 10px; }
nav .nav-cta,
nav .nav-account {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font: 600 10px/1 'IBM Plex Mono', monospace;
  letter-spacing: .14em;
  text-transform: uppercase;
  text-decoration: none;
  padding: 6px 12px;
  border: 1px solid;
  transition: .25s;
  white-space: nowrap;
  min-width: 92px;
}
nav .nav-cta { color: var(--bg); background: var(--c); border-color: var(--c); }
nav .nav-cta:hover {
  background: transparent;
  color: var(--c);
  box-shadow: 0 0 20px rgba(0, 229, 176, .25);
}
nav .nav-account { color: #888; background: transparent; border-color: #2a2a30; }
nav .nav-account:hover {
  color: var(--c);
  border-color: var(--c);
  background: rgba(0, 229, 176, .04);
}

/* ── Main content wrapper ──────────────────────────────────────────
   `.shell` was redeclared inline on every page with 8 different
   max-widths (460/780/880/920/1100/1140/1160/1240 + drift on padding).
   Default is wide (1160px, aligned with the nav). Pages that need a
   narrower reading column add a variant class.

   Variants:
     .shell.narrow → 780px  (textual pages: about, account, security,
                             privacy, terms)
     .shell.mid    → 880px  (mid-density: faq, changelog, support,
                             proof)
   Pages with a true outlier width (auth 460px, compare 1240px, etc.)
   keep their inline override.
   ──────────────────────────────────────────────────────────────── */
.shell {
  position: relative;
  z-index: 2;
  max-width: 1160px;
  margin: 0 auto;
  padding: 0 32px;
}
.shell.narrow { max-width: 780px; }
.shell.mid    { max-width: 880px; }
.shell.api    { max-width: 920px; }
.shell.wide   { max-width: 1240px; }

/* ── Page title (h1) ───────────────────────────────────────────────
   Was inlined per page with 7 different size scales (clamp(40,7vw,68)
   on demo all the way up to clamp(68,11vw,130) on the home hero, plus
   fixed 48/56px on legal/auth/account). Navigating between pages made
   the page title pop bigger then smaller — user-visible inconsistency.
   One size everywhere. The home hero keeps its oversized title via the
   `.hero h1` scoped selector in index.html which beats this rule on
   specificity.
   ──────────────────────────────────────────────────────────────── */
h1 {
  font: 400 clamp(52px, 9vw, 100px) / .9 'Bebas Neue', sans-serif;
  letter-spacing: .04em;
  color: #eaeaea;
  margin-bottom: 20px;
}
h1 .accent {
  color: var(--c);
  text-shadow: 0 0 60px rgba(0, 229, 176, .15);
}

/* ── Page hero — same shape on every non-home page ─────────────────
   User asked: "même hauteur, largeur, emplacement pour chaque page".
   The features/engine/sources pattern (min-height 50vh + vertically
   centred flex column) is the most "baroque" — title floats in the
   upper half, content opens below. Made it the default so every
   `<section class="page-hero">` lands the title at the same screen
   position, with the same h1 size + left-aligned eyebrow above.

   Left-aligned by default; no centering. Only home uses `.hero`
   (different class) so it's not affected and keeps its 130px hero.
   ──────────────────────────────────────────────────────────────── */
.page-hero {
  padding: 100px 0 80px;
  min-height: 50vh;
  display: flex;
  flex-direction: column;
  justify-content: center;
}

/* ── Reduced-motion preference ─────────────────────────────────────
   Users who set "Reduce motion" in their OS get a static page: no
   stripe gradient loop, no particle drift, no scroll-triggered fades,
   no typewriter sweeps. The site stays readable; only the decoration
   stops moving. Keeps scroll-behavior smooth for anchor navigation
   though — that's accessibility benefit, not motion sickness risk.
   ──────────────────────────────────────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
  html { scroll-behavior: auto; }
  .stripe { animation: none !important; }
}
