/* ===========================================================
   Pylon-Check.com — base stylesheet (shared components: nav, forms,
   checkout, account, dashboard). Marketing-page components live in
   /assets/css/pc.css.
   =========================================================== */

:root {
  /* Pylon-Check — "Cloud console" theme: slate paper, navy ink, the green of
     the check mark on the device sticker, and a cyan reserved for everything
     that lives in the cloud. */
  --bg: #f4f7fa;
  --bg-2: #eaf0f5;
  --card: #ffffff;
  --card-2: #f7f9fc;
  --border: #dce4ec;
  --line: #b9c6d3;
  --text: #0c1a2b;
  --muted: #4a5b6e;
  --accent: #16a34a;
  --accent-2: #15803d;
  --accent-bright: #22c55e;
  --cloud: #0891b2;
  --cloud-2: #0e7490;
  --navy: #0b1726;
  --navy-2: #12233a;
  --green: #15803d;
  --green-2: #166534;
  --red: #b3261e;
  --radius: 12px;
  --radius-sm: 8px;
  --shadow: 0 1px 2px rgba(12, 26, 43, 0.06);
  --shadow-lg: 0 20px 48px rgba(12, 26, 43, 0.13);
  --ease: cubic-bezier(.22, 1, .36, 1);
  --font: "Inter", "Segoe UI", "Helvetica Neue", Helvetica, Arial, sans-serif;
  --font-display: "Inter", "Segoe UI", Helvetica, Arial, sans-serif;
  --mono: "JetBrains Mono", ui-monospace, "SF Mono", "Cascadia Mono", Consolas, monospace;
}

* { box-sizing: border-box; }
img { max-width: 100%; height: auto; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  scroll-behavior: smooth;
  /* The off-canvas mobile nav drawer is position:fixed + transform-translated
     off-screen when closed — Chrome still counts its post-transform bounds
     toward the document's scrollable width, which silently added ~320px of
     horizontal scroll/overflow to every page at mobile widths. This is the
     standard, robust guard against that class of off-canvas-panel bug.
     'clip' not 'hidden': overflow-x:hidden forces the browser to compute
     overflow-y as 'auto', turning <body> into a scroll container — which
     breaks position:sticky for every descendant (this is why the checkout
     order-summary sidebar wasn't staying pinned on desktop). 'clip' blocks
     the same horizontal overflow without that side effect. */
  overflow-x: clip;
}

body {
  background-color: var(--bg);
  min-height: 100vh;
}

a { color: var(--accent-2); text-decoration: none; transition: color .15s ease; }
a:hover { color: var(--accent-bright); }

h1, h2, h3, h4 { font-family: var(--font-display); color: var(--text); font-weight: 800; line-height: 1.15; margin: 0 0 .6em; letter-spacing: -.01em; }
h1 { font-size: clamp(2.1rem, 4vw + 1rem, 3.6rem); }
h2 { font-size: clamp(1.6rem, 2vw + 1rem, 2.2rem); margin-bottom: .4em; }
h3 { font-size: 1.2rem; font-weight: 700; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  * { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; transition-duration: 0.01ms !important; }
}

p { margin: 0 0 1em; }

code {
  font-family: var(--mono);
  background: var(--card-2);
  border: 1px solid var(--border);
  color: var(--accent-2);
  padding: 1px 6px;
  border-radius: 6px;
  font-size: .92em;
}

.container {
  max-width: 1180px;
  margin: 0 auto;
  padding: 0 24px;
}

/* ---------- Header / Nav ---------- */
body.nav-locked { overflow: hidden; }

.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  border-bottom: 1px solid transparent;
  transition: box-shadow .25s ease, border-color .25s ease;
}
/* Blur lives on a ::before, not on .site-header itself: a non-'none' backdrop-filter
   (like transform/filter/perspective) makes its element a fixed-positioning
   containing block for ITS descendants — and .nav-links (the mobile drawer) is
   one. With the filter on .site-header, the "fixed" drawer was fixed relative to
   .site-header's own box instead of the viewport, so scrolling down and opening
   it left the drawer sitting up near the top of the *document*, off-screen,
   until you scrolled back up (found 2026-08-19). A pseudo-element is a child,
   not an ancestor, of .nav-links, so it can't trigger this. */
.site-header::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: rgba(238, 241, 234, 0.86);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  transition: background .25s ease;
}
.site-header.scrolled::before {
  background: rgba(238, 241, 234, 0.96);
}
.site-header.scrolled {
  border-bottom-color: var(--border);
  box-shadow: 0 8px 24px rgba(19, 36, 51, 0.06);
}
/* Keep the header (logo, toggle) crisp above the blurred scrim while the mobile
   drawer is open — otherwise .nav-scrim's full-viewport blur washes it out too. */
body.nav-locked .site-header { z-index: 1006; }

.nav-scrim {
  position: fixed;
  inset: 0;
  background: rgba(19, 36, 51, 0.45);
  backdrop-filter: blur(2px);
  /* Above .cookie-banner (999) so the open drawer isn't hidden behind the consent
     banner on short phone viewports, where the two can otherwise overlap. */
  z-index: 1000;
  opacity: 0;
  pointer-events: none;
  transition: opacity .25s ease;
}
.nav-scrim.open { opacity: 1; pointer-events: auto; }

.nav-close { display: none; }

.nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  height: 68px;
}

.logo {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-weight: 700;
  color: var(--text);
  font-size: 1.1rem;
  letter-spacing: .2px;
  flex-shrink: 0;
  white-space: nowrap;
}
.logo:hover { color: var(--text); }
.logo-mark {
  display: inline-grid;
  place-items: center;
  width: 30px; height: 30px;
  background: var(--text);
  border: 1px solid var(--text);
  border-radius: 2px;
  color: var(--bg);
  font-weight: 900;
  transition: transform .2s var(--ease), background .2s ease;
}
.logo:hover .logo-mark { background: var(--accent); border-color: var(--accent); }
.logo-tld { color: var(--muted); font-weight: 500; font-family: var(--mono); font-size: .85em; }

.nav-links {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 20px;
  min-width: 0;
  flex: 1;
}
.nav-links-scroll {
  display: flex;
  align-items: center;
  gap: 16px;
  min-width: 0;
  /* overflow-x: auto (removed) silently forced overflow-y to clip too — per spec,
     setting either overflow axis to non-visible computes the other to auto as well
     — which clipped the absolutely-positioned .nav-dropdown-menu (Guides submenu)
     before it could ever show (found 2026-08-18). Was dead weight anyway: the
     1180px breakpoint below exists specifically so nothing ever needs to scroll
     here on desktop (see its comment) — mobile already gets its own
     `overflow: visible` in that same media query. */
  overflow: visible;
  scrollbar-width: none;
}
.nav-links-scroll::-webkit-scrollbar { display: none; }
.nav-links-scroll a {
  color: var(--text);
  font-weight: 500;
  font-size: .88rem;
  white-space: nowrap;
  flex-shrink: 0;
  position: relative;
}
.nav-links-scroll a:hover { color: var(--accent); }
.nav-links-scroll a.active { color: var(--accent); }
.nav-links-scroll a.active::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: -22px;
  height: 2px;
  background: var(--accent);
  border-radius: 2px;
}

/* Highlighted "Tour" link in header */
.nav-links-scroll a.nav-tour {
  background: transparent;
  color: var(--accent-2);
  padding: 6px 12px;
  border: 1px solid var(--accent);
  border-radius: 2px;
  font-weight: 700;
  font-size: .88rem;
  letter-spacing: .02em;
  transition: background .15s ease, color .15s ease;
}
.nav-links-scroll a.nav-tour::before {
  content: "▶";
  display: inline-block;
  margin-right: 6px;
  font-size: .68em;
  transform: translateY(-1px);
}
.nav-links-scroll a.nav-tour:hover {
  background: var(--accent);
  color: #fff;
}
.nav-links-scroll a.nav-tour.active { background: var(--accent); color: #fff; }
.nav-links-scroll a.nav-tour.active::after { display: none; }

/* "Guides" nav dropdown (groups Quickstart/Installation/Home Assistant) — same
   open/close pattern as .lang-switch below, but styled to blend into the plain
   text nav links around it rather than looking like a bordered pill. */
.nav-dropdown { position: relative; flex-shrink: 0; }
.nav-dropdown-btn {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-family: inherit;
  font-weight: 500;
  font-size: .88rem;
  color: var(--text);
  background: transparent;
  border: none;
  padding: 0;
  cursor: pointer;
  white-space: nowrap;
}
.nav-dropdown-btn:hover, .nav-dropdown-btn.active { color: var(--accent); }
.nav-dropdown-btn:focus-visible { outline: 2px solid var(--accent-2); outline-offset: 2px; }
.nav-dropdown-caret { color: var(--muted); transition: transform .15s ease; flex-shrink: 0; }
.nav-dropdown.open .nav-dropdown-caret { transform: rotate(180deg); }
.nav-dropdown-menu {
  position: absolute;
  top: calc(100% + 14px);
  left: 0;
  min-width: 190px;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 4px;
  box-shadow: var(--shadow-lg);
  padding: 4px;
  margin: 0;
  list-style: none;
  z-index: 70;
}
.nav-dropdown-menu[hidden] { display: none; }
.nav-dropdown-menu li { margin: 0; }
.nav-dropdown-menu a {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 10px;
  border-radius: 2px;
  color: var(--text);
  font-size: .86rem;
  font-weight: 500;
  white-space: nowrap;
}
.nav-dropdown-icon { flex-shrink: 0; display: block; }
.nav-dropdown-menu a:hover, .nav-dropdown-menu a:focus-visible { background: var(--bg); color: var(--accent); outline: none; }
.nav-dropdown-menu a.active { color: var(--accent); }
.nav-dropdown-group-label {
  padding: 6px 10px 4px;
  font-size: .68rem;
  font-weight: 700;
  letter-spacing: .05em;
  text-transform: uppercase;
  color: var(--muted);
}
.nav-dropdown-divider { height: 1px; margin: 4px 6px; background: var(--border); }
/* .nav-links-scroll a.active::after (the horizontal nav's underline indicator)
   also matches these links, since they're descendants of .nav-links-scroll —
   its bottom:-22px offset, tuned for a single row of top-level links, instead
   overlaps neighboring items in this tight vertical list, drawing a stray
   orange bar across them (found 2026-08-18). The color change above is enough
   feedback for "current page" here; suppress the bar entirely, same as the
   existing .nav-tour.active override just above in the desktop rules. */
.nav-dropdown-menu a.active::after { content: none; }

/* Lang switch + order button: always fully visible, never part of the scrollable nav-links-scroll */
.nav-actions {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-shrink: 0;
}
.nav-actions .btn-primary,
.nav-actions .btn-primary:hover { color: var(--bg); }
.nav-actions .btn-primary:hover { background: var(--accent); border-color: var(--accent); }

.nav-toggle {
  display: none;
  background: transparent;
  border: 1px solid var(--line);
  color: var(--text);
  font-size: 1.3rem;
  padding: 6px 12px;
  border-radius: 8px;
  cursor: pointer;
}

/* Language switcher */
.lang-switch { position: relative; }
.lang-switch-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: var(--mono);
  font-size: .76rem;
  font-weight: 700;
  letter-spacing: .04em;
  color: var(--text);
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: 2px;
  padding: 6px 8px;
  cursor: pointer;
}
.lang-switch-btn:hover { border-color: var(--text); }
.lang-switch-btn:focus-visible { outline: 2px solid var(--accent-2); outline-offset: 1px; }
.lang-switch-caret { color: var(--muted); transition: transform .15s ease; flex-shrink: 0; }
.lang-switch.open .lang-switch-caret { transform: rotate(180deg); }
.lang-switch-menu {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  min-width: 130px;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 4px;
  box-shadow: var(--shadow-lg);
  padding: 4px;
  margin: 0;
  list-style: none;
  z-index: 70;
}
.lang-switch-menu[hidden] { display: none; }
.lang-switch-menu li { margin: 0; }
.lang-switch-menu a {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 7px 8px;
  border-radius: 2px;
  color: var(--text);
  font-family: var(--mono);
  font-size: .82rem;
  font-weight: 600;
  white-space: nowrap;
}
.lang-switch-menu a:hover, .lang-switch-menu a:focus-visible { background: var(--bg); color: var(--accent); outline: none; }
.lang-switch-menu a.active { color: var(--accent); }
.flag-icon { border-radius: 1px; flex-shrink: 0; box-shadow: 0 0 0 1px rgba(19, 36, 51, .08); }

/* ---------- Made-in-France bar ---------- */
.made-in-bar {
  background: var(--text);
  color: var(--bg);
}
.made-in-bar-inner {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 7px 24px;
  font-family: var(--mono);
  font-size: .72rem;
  letter-spacing: .06em;
  text-transform: uppercase;
}
.flag-fr { border-radius: 1px; flex-shrink: 0; box-shadow: 0 0 0 1px rgba(238, 241, 234, .25); }

/* ---------- Launch promo bar ---------- */
.promo-bar {
  background: var(--accent);
  color: #fff;
}
.promo-bar-inner {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 9px 24px;
  font-size: .84rem;
  font-weight: 700;
  text-align: center;
  flex-wrap: wrap;
}
.promo-bar-inner s { opacity: .75; font-weight: 500; }
.promo-bar-inner a { color: #fff; text-decoration: underline; text-underline-offset: 2px; }
.price-strike {
  color: var(--muted);
  font-size: .6em;
  font-weight: 500;
  text-decoration: line-through;
  margin-right: 6px;
}
.price-promo-note {
  color: var(--accent);
  font-size: .85rem;
  font-weight: 700;
  margin: -8px 0 12px;
}

/* ---------- Order-volume shipping-delay notice bar ---------- */
/* Red, because this bar now carries a delay rather than a promise: it has to be
   read BEFORE the order, not discovered in the confirmation email. A tinted
   ground rather than a solid red block — a full-width scarlet band above the
   logo reads as a site error and costs more trust than the delay itself. */
.ship-notice-bar {
  background: rgba(179, 38, 30, .08);
  color: var(--red);
  border-bottom: 1px solid rgba(179, 38, 30, .3);
}
/* Bandeau haute tension (2026-09-08). Construit sur le meme squelette que le
   bandeau d'expedition juste au-dessus -- meme rythme vertical, meme
   comportement responsive -- mais en vert : les deux peuvent s'afficher le meme
   jour, l'un annonce un retard et l'autre une nouveaute, et rien ne serait plus
   confus que deux barres de la meme couleur qui disent le contraire. */
/* Etiquette "haute tension" dans la grille de compatibilite de l'accueil.
   Les deux dernieres tuiles ne sont lisibles que par la generation de carte
   actuelle : le dire sur la tuile evite qu'un proprietaire de Force H2 avec un
   ancien boitier se croie couvert. */
.compat-hv {
  display: block;
  margin-top: 3px;
  font-size: .62rem;
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--green-2);
}

/* ── Bandeau "suivi en direct" sous le hero (2026-09-08) ──────────────────────
   Trois compteurs mesures + un total declare, dans la matiere du site : meme
   carte, meme bordure, meme .live-dot que le badge du hero. Volontairement
   sobre -- ces nombres bougent de quelques unites par jour, et un affichage
   qui clignote comme un tableau de trading les ferait passer pour du decor. */
.livebar-wrap { padding: 0 0 8px; }
.livebar {
  display: inline-flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 14px;
  max-width: 100%;
  padding: 18px 22px;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 10px;
  box-shadow: var(--shadow);
}
.livebar-head { display: flex; align-items: center; gap: 8px; }
.livebar-label {
  font-size: .72rem;
  font-weight: 800;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--green-2);
}
.livebar-stats { display: flex; flex-wrap: wrap; gap: 12px 30px; }
.livebar-stat { display: flex; align-items: center; gap: 11px; }
.livebar-ico {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 36px; height: 36px;
  flex-shrink: 0;
  border-radius: 9px;
  background: var(--bg-2);
  color: var(--accent);
}
.livebar-ico svg { width: 18px; height: 18px; }
.livebar-num {
  margin: 0;
  font-size: 1.28rem;
  font-weight: 800;
  line-height: 1;
  color: var(--text);
  /* chiffres a chasse fixe : le nombre ne fait pas sautiller la ligne quand il
     change sous les yeux du lecteur */
  font-variant-numeric: tabular-nums;
}
.livebar-cap { margin: 5px 0 0; font-size: .76rem; color: var(--muted); line-height: 1.3; }
.livebar-foot {
  display: flex;
  align-items: flex-start;
  gap: 6px;
  margin: 0;
  max-width: 62ch;
  font-size: .72rem;
  color: var(--muted);
  line-height: 1.5;
}
.livebar-foot svg { width: 13px; height: 13px; flex-shrink: 0; margin-top: 3px; }
/* Changement de valeur : une pulsation d'une demi-seconde, pas un compteur qui
   defile. Le lecteur voit QUE le chiffre a bouge, sans spectacle. */
@keyframes lb-bump { 0% { color: var(--green-2); } 100% { color: var(--text); } }
.lb-bump { animation: lb-bump .6s ease-out; }
@media (prefers-reduced-motion: reduce) { .lb-bump { animation: none; } }
@media (max-width: 640px) {
  .livebar { padding: 15px 16px; gap: 12px; }
  .livebar-stats { gap: 10px 20px; }
  .livebar-num { font-size: 1.12rem; }
}

.hv-notice-bar {
  background: rgba(47, 122, 82, .10);
  color: var(--green-2);
  border-bottom: 1px solid rgba(47, 122, 82, .32);
}
.hv-notice-bar-inner {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 9px 24px;
  font-size: .72rem;
  font-weight: 600;
  line-height: 1.5;
  text-align: center;
  flex-wrap: wrap;
  max-width: 1600px;
}
.hv-notice-bar-inner strong { font-weight: 800; color: var(--green-2); }
.hv-notice-bar-inner a {
  color: var(--green-2);
  font-weight: 800;
  text-decoration: underline;
  text-underline-offset: 2px;
  white-space: nowrap;
}
@media (max-width: 640px) {
  .hv-notice-bar-inner { font-size: .74rem; padding: 8px 14px; }
}
.lite-notice-bar {
  background: rgba(47, 122, 82, .10);
  color: var(--green-2);
  border-bottom: 1px solid rgba(47, 122, 82, .32);
}
.lite-notice-bar-inner {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 9px 24px;
  font-size: .72rem;
  font-weight: 600;
  line-height: 1.5;
  text-align: center;
  flex-wrap: wrap;
  max-width: 1600px;
}
.lite-notice-bar-inner strong { font-weight: 800; color: var(--green-2); }
.lite-notice-bar-inner a {
  color: var(--green-2);
  font-weight: 800;
  text-decoration: underline;
  text-underline-offset: 2px;
  white-space: nowrap;
}
@media (max-width: 640px) {
  .lite-notice-bar-inner { font-size: .74rem; padding: 8px 14px; }
}
.teaser-notice-bar {
  background: rgba(143, 163, 173, .14);
  color: var(--muted);
  border-bottom: 1px solid rgba(143, 163, 173, .38);
}
.teaser-notice-bar-inner {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 9px 24px;
  font-size: .72rem;
  font-weight: 600;
  line-height: 1.5;
  text-align: center;
  flex-wrap: wrap;
  max-width: 1600px;
}
.teaser-notice-bar-inner strong { font-weight: 800; color: var(--green-2); }
.teaser-notice-bar-inner a { color: var(--green-2); font-weight: 800; text-decoration: underline; text-underline-offset: 2px; }
@media (max-width: 640px) {
  .teaser-notice-bar-inner { font-size: .74rem; padding: 8px 14px; }
}
.ship-notice-bar-inner {
  padding: 9px 24px;
  font-size: .82rem;
  line-height: 1.5;
  text-align: center;
}
.ship-notice-bar-inner strong { font-weight: 800; color: var(--red); }
/* The dispatch plan sits on its own line, a shade quieter than the notice above
   it: it is reference material the reader scans for their own date, not the
   headline. Monospace keeps the arrows and the dates in tidy columns. */
.ship-notice-bar-inner .ship-plan {
  display: block;
  margin-top: 4px;
  font-family: var(--mono);
  font-size: .74rem;
  letter-spacing: -.01em;
  color: rgba(179, 38, 30, .82);
}
.ship-notice-bar-inner .ship-plan strong { font-weight: 800; }
@media (max-width: 560px) {
  .ship-notice-bar-inner .ship-plan { font-size: .7rem; line-height: 1.6; }
}
.price-badge-launch {
  display: inline-block;
  background: var(--accent);
  color: #fff;
  font-size: .62rem;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: .04em;
  padding: 2px 8px;
  border-radius: 3px;
  margin-left: 8px;
  vertical-align: middle;
}

/* ---------- Buttons ---------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 12px 22px;
  border-radius: var(--radius);
  font-weight: 700;
  font-family: var(--mono);
  font-size: .92rem;
  letter-spacing: .01em;
  border: 1.5px solid transparent;
  cursor: pointer;
  transition: transform .15s var(--ease), background .15s ease, border-color .15s ease, color .15s ease;
  text-decoration: none;
}
/* Scoped to hover-capable pointers only — on touch, this rule would otherwise
   stay "stuck" (lifted/highlighted) after a tap until the user taps elsewhere. */
@media (hover: hover) {
  .btn:hover { transform: translateY(-1px); }
}
.btn:active { transform: translateY(0); }
.btn:focus-visible { outline: 2px solid var(--accent-2); outline-offset: 2px; }
.btn-sm { padding: 8px 14px; font-size: .82rem; }
.btn-lg { padding: 15px 28px; font-size: 1rem; }

.btn-primary {
  background: var(--text);
  border-color: var(--text);
  color: var(--bg);
}
.btn-primary:hover { background: var(--accent); border-color: var(--accent); color: #fff; }

.btn-green {
  background: var(--green-2);
  border-color: var(--green-2);
  color: #fff;
}
.btn-green:hover { background: var(--green); border-color: var(--green); color: #fff; }

.btn-ghost {
  background: transparent;
  color: var(--text);
  border-color: var(--line);
}
.btn-ghost:hover { border-color: var(--text); color: var(--text); background: rgba(19, 36, 51, .04); }

.btn-danger {
  background: var(--red);
  color: #fff;
}

/* ---------- Hero ---------- */
.hero {
  padding: 80px 0 60px;
}
.hero-grid {
  display: grid;
  /* minmax(0, ...) not bare fr: a grid track's automatic minimum size is its
     content's min-content, so an unshrinkable child (e.g. the nowrap
     .hero-live-badge pill) silently grows this track — and the whole
     .container with it — past the viewport. Every fr track below needs the
     same guard; see the mobile override further down for the worst offender. */
  grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr);
  gap: 60px;
  align-items: center;
}
.badge {
  display: inline-block;
  background: rgba(22, 163, 74, 0.08);
  color: var(--accent);
  padding: 6px 14px;
  border-radius: 3px;
  font-size: .85rem;
  font-weight: 600;
  border: 1px solid rgba(22, 163, 74, 0.25);
  margin-bottom: 22px;
}
.accent { color: var(--accent); }
.badge-maker {
  background: rgba(47, 122, 82, 0.08);
  color: var(--green-2);
  border-color: rgba(47, 122, 82, 0.28);
}
.lead {
  font-size: 1.15rem;
  color: var(--muted);
  max-width: 600px;
}
.cta-row {
  display: flex;
  gap: 14px;
  margin: 28px 0 32px;
  flex-wrap: wrap;
}
.hero-bullets {
  list-style: none;
  padding: 0; margin: 0;
  color: var(--text);
}
.hero-bullets li {
  padding: 6px 0 6px 26px;
  font-size: .98rem;
  position: relative;
}
.hero-bullets li::before {
  content: "✓";
  position: absolute;
  left: 0;
  color: var(--green);
  font-weight: 700;
  font-family: var(--mono);
}
/* Small "also available" product card under the hero photo — this is what
   actually shows the Lite's own image on the homepage, not just a text link
   (a plain link here read as "V2-only page with a footnote", not two
   products — found 2026-09-12). */
.hero-lite-card {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-top: 18px;
  padding: 10px 14px;
  width: 100%;
  max-width: 340px;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 14px;
  box-shadow: var(--shadow-lg);
}
.hero-lite-card:hover { border-color: var(--accent); }
.hero-lite-card img {
  width: 56px; height: 56px;
  border-radius: 10px;
  object-fit: cover;
  flex-shrink: 0;
  background: #fff;
  border: 1px solid var(--border);
}
.hero-lite-card-text { display: flex; flex-direction: column; flex: 1; min-width: 0; }
.hero-lite-card-text strong { color: var(--text); font-size: .92rem; }
.hero-lite-card-text small { color: var(--muted); font-size: .78rem; }
.hero-lite-card-price {
  color: var(--accent);
  font-weight: 800;
  font-size: 1.1rem;
  flex-shrink: 0;
}

/* Hero device mock */
.hero-visual {
  display: grid;
  place-items: center;
  position: relative;
}
.hero-photo {
  width: 100%;
  max-width: 440px;
  display: flex;
  flex-direction: column;
  align-items: center;
  animation: float-mock 6s ease-in-out infinite;
}
.hero-photo img {
  width: 100%;
  height: auto;
  display: block;
  border-radius: 8px;
  box-shadow: var(--shadow-lg);
  border: 1px solid var(--border);
}
@keyframes float-mock {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-8px); }
}
.hero-live-badge {
  margin-top: 18px;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  background: var(--card);
  border: 1px solid var(--border);
  padding: 8px 16px;
  border-radius: 999px;
  font-size: .78rem;
  font-weight: 700;
  color: var(--text);
  box-shadow: var(--shadow);
  white-space: nowrap;
}
.live-dot {
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--green);
  box-shadow: 0 0 0 0 rgba(47, 122, 82, .6);
  animation: live-pulse 2s infinite;
  flex-shrink: 0;
}
@keyframes live-pulse {
  0%   { box-shadow: 0 0 0 0 rgba(47, 122, 82, .55); }
  70%  { box-shadow: 0 0 0 7px rgba(47, 122, 82, 0); }
  100% { box-shadow: 0 0 0 0 rgba(47, 122, 82, 0); }
}

/* ---------- Sections ---------- */
section {
  padding: 70px 0;
}
.section-sub {
  color: var(--muted);
  font-size: 1.05rem;
  max-width: 700px;
  margin-bottom: 36px;
}

/* ---------- Maker story ---------- */
.maker {
  background:
    radial-gradient(800px 300px at 15% 0%, rgba(47, 122, 82, 0.06), transparent 65%),
    rgba(47, 122, 82, 0.025);
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
}
@media (hover: hover) {
  .maker .card:hover { border-color: var(--green); box-shadow: 0 10px 30px rgba(47, 122, 82, 0.12); }
}
.maker .card-icon { background: rgba(47, 122, 82, 0.1); }

/* ---------- Stats ---------- */
.stats {
  padding: 30px 0;
  background: rgba(241, 245, 249, 0.8);
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
}
.stats-grid {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 24px;
  text-align: center;
}
.stats-grid div {
  display: flex;
  flex-direction: column;
}
.stats-grid strong {
  font-size: 1.8rem;
  color: var(--accent);
  font-weight: 700;
}
.stats-grid span {
  color: var(--muted);
  font-size: .9rem;
  margin-top: 4px;
}

/* ---------- Grids / Cards ---------- */
.grid-2 {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 22px;
}
.grid-3 {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 22px;
}

.card {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 26px;
  transition: transform .25s var(--ease), border-color .25s ease, box-shadow .25s ease;
}
@media (hover: hover) {
  .card:hover {
    transform: translateY(-4px);
    border-color: var(--accent);
    box-shadow: var(--shadow);
  }
}
.card-icon {
  width: 42px; height: 42px;
  display: grid; place-items: center;
  background: transparent;
  border: 1.5px solid var(--accent);
  border-radius: 2px;
  font-family: var(--mono);
  font-weight: 700;
  font-size: .68rem;
  letter-spacing: .01em;
  color: var(--accent-2);
  margin-bottom: 16px;
  transition: transform .25s var(--ease), background .25s ease, color .25s ease;
}
@media (hover: hover) {
  .card:hover .card-icon { transform: scale(1.06); background: var(--accent); color: #fff; }
}
/* Same fix as .step h3: title length varies per language and per card, so
   some wrap to 2 lines and others don't — reserving 2 lines keeps every
   card's paragraph starting at the same y across the row. */
.card h3 { min-height: 2.4em; }
.card p { color: var(--muted); margin: 0; }

/* Home Assistant is this product's single most compelling integration — its card
   gets the real brand logo (not a text abbreviation like the other cards) plus a
   highlighted border/badge so it reads as the standout feature, not one of six
   equal tiles. */
.card.card-ha {
  border-color: var(--accent);
  box-shadow: 0 10px 30px rgba(22, 163, 74, .1);
  position: relative;
}
.card.card-ha .card-icon {
  border-color: #18BCF2;
  background: rgba(24, 188, 242, .08);
}
.card.card-ha .card-icon img { width: 22px; height: 22px; display: block; }
@media (hover: hover) {
  .card.card-ha:hover .card-icon { background: rgba(24, 188, 242, .16); transform: scale(1.06); }
}
.card-ha-badge {
  position: absolute;
  top: -11px; left: 22px;
  background: var(--accent);
  color: #fff;
  font-size: .68rem;
  font-weight: 700;
  padding: 3px 10px;
  border-radius: 999px;
  letter-spacing: .5px;
  text-transform: uppercase;
  white-space: nowrap;
}

/* ---------- Compat ---------- */
.compat-grid {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: 14px;
  margin-bottom: 18px;
}
.compat-item {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 18px 10px;
  text-align: center;
  font-weight: 600;
  color: var(--text);
}
.compat-note {
  color: var(--muted);
  text-align: center;
}

/* ---------- Steps ---------- */
.steps {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 22px;
  margin-bottom: 30px;
  position: relative;
}
.step {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 28px;
  position: relative;
}
.step-num {
  width: 38px; height: 38px;
  background: linear-gradient(135deg, var(--accent-bright), var(--accent-2));
  color: #ffffff;
  border-radius: 50%;
  display: grid; place-items: center;
  font-weight: 800;
  font-size: 1.1rem;
  margin-bottom: 14px;
  position: relative;
  z-index: 1;
}
/* Continuous dashed "trace" running through every step-num center, like a
   schematic circuit line — each card draws its own segment reaching into
   both neighboring gaps so they meet edge-to-edge; the node's own z-index
   sits above it, so the line visually runs into the circle, not past it. */
.step::before {
  content: "";
  position: absolute;
  top: 47px; left: -11px; right: -11px;
  border-top: 2px dashed var(--border);
}
.step:first-child::before { left: 47px; }
.step:last-child::before { right: 47px; }
/* Titles vary in length per language ("Rejoignez le WiFi de configuration"
   vs "Branchez-le") and can wrap to 1 or 2 lines independently of each
   other. Reserving 2 lines' worth of height keeps every paragraph starting
   at the same y — without it the row looks visibly staggered/unbalanced. */
.step h3 { min-height: 2.4em; }
.step p { color: var(--muted); margin: 0; }
.center { text-align: center; margin-top: 28px; }

/* ---------- API preview ---------- */
.api-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 50px;
  align-items: center;
}
.check-list {
  list-style: none;
  padding: 0;
  margin: 0 0 24px;
}
.check-list li {
  padding: 6px 0 6px 28px;
  position: relative;
  color: var(--text);
}
.check-list li::before {
  content: "✓";
  position: absolute;
  left: 0;
  top: 6px;
  color: var(--green);
  font-weight: 700;
}
.code-block {
  background: var(--text);
  border: 1px solid var(--text);
  border-radius: var(--radius);
  padding: 22px;
  overflow-x: auto;
  font-family: var(--mono);
  font-size: .88rem;
  line-height: 1.55;
  color: var(--line);
  box-shadow: var(--shadow);
}
.code-block code { background: transparent; border: none; padding: 0; color: inherit; }

/* ---------- Gallery preview ---------- */
.gallery-grid {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 20px;
}
.gallery-item {
  margin: 0;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
  transition: transform .25s var(--ease), border-color .25s ease, box-shadow .25s ease;
}
@media (hover: hover) {
  .gallery-item:hover { transform: translateY(-4px); border-color: var(--accent); box-shadow: var(--shadow); }
}
.gallery-item img { display: block; width: 100%; height: auto; border-bottom: 1px solid var(--border); }
.gallery-item figcaption { padding: 14px 16px; }
.gallery-item figcaption strong { display: block; color: var(--text); font-size: .92rem; }
.gallery-item figcaption span { display: block; color: var(--muted); font-size: .8rem; margin-top: 3px; line-height: 1.4; }

/* ---------- Pricing ---------- */
.pricing {
  text-align: center;
}
.pricing-card {
  max-width: 460px;
  margin: 40px auto 0;
  background: var(--card);
  border: 1.5px solid var(--accent);
  border-radius: var(--radius);
  padding: 40px;
  position: relative;
  box-shadow: var(--shadow-lg);
}
/* Two products side by side: same card component, laid out in a 2-col grid
   instead of the single centered card the markup used before 2026-09-12. */
.pricing-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 30px;
  max-width: 980px;
  margin: 40px auto 0;
  align-items: start;
}
.pricing-grid .pricing-card { max-width: none; margin: 0; }
.pricing-card-lite { border-color: var(--border); }
.pricing-badge-lite { background: var(--text); }
@media (max-width: 760px) {
  .pricing-grid { grid-template-columns: 1fr; max-width: 460px; }
}
.pricing-badge {
  position: absolute;
  top: -14px; left: 50%;
  transform: translateX(-50%);
  background: var(--accent);
  color: #ffffff;
  font-weight: 700;
  padding: 4px 14px;
  border-radius: 3px;
  font-size: .8rem;
  letter-spacing: 1px;
  text-transform: uppercase;
  white-space: nowrap;
}
.price {
  font-size: 4rem;
  font-weight: 800;
  color: var(--text);
  margin: 18px 0;
  line-height: 1;
}
.price .currency { font-size: 2rem; vertical-align: top; color: var(--accent); margin-right: 4px; }
.price .vat { font-size: .85rem; color: var(--muted); display: block; margin-top: 8px; font-weight: 500; }
.pricing-card-img {
  display: block;
  width: 100%;
  max-width: 220px;
  height: auto;
  margin: 0 auto 18px;
  border-radius: 10px;
  border: 1px solid var(--border);
}
.price-features {
  list-style: none;
  padding: 0;
  margin: 24px 0;
  text-align: left;
}
.price-features li { color: var(--text); }
.ship-note { color: var(--muted); font-size: .85rem; margin-top: 16px; }

/* ---------- FAQ preview ---------- */
.qa {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 24px;
}
.qa h3 { margin-bottom: 8px; color: var(--text); }
.qa p { color: var(--muted); margin: 0; }

/* ---------- Footer ---------- */
.site-footer {
  background: var(--card-2);
  border-top: 1px solid var(--border);
  padding: 60px 0 24px;
  margin-top: 60px;
}
.footer-grid {
  display: grid;
  grid-template-columns: 1.5fr 1fr 1fr 1fr;
  gap: 30px;
  margin-bottom: 40px;
}
.footer-grid h4 {
  color: var(--text);
  font-size: .95rem;
  margin-bottom: 14px;
  text-transform: uppercase;
  letter-spacing: 1px;
}
.footer-grid a {
  display: block;
  color: var(--muted);
  padding: 4px 0;
  font-size: .95rem;
}
.footer-grid a:hover { color: var(--accent); }
.muted { color: var(--muted); }
.footer-bottom {
  border-top: 1px solid var(--border);
  padding-top: 20px;
  display: flex;
  justify-content: space-between;
  gap: 20px;
  flex-wrap: wrap;
  font-size: .85rem;
  color: var(--muted);
}
.footer-bottom-left { display: inline-flex; align-items: center; gap: 10px; }
.social-icon-link { display: inline-flex; color: var(--muted); }
.social-icon-link:hover { color: var(--accent); }
.facebook-fans-link { margin-left: -4px; }
.facebook-fans-count {
  background: var(--card); border: 1px solid var(--border); border-radius: 20px;
  padding: 2px 10px; font-size: .75rem; color: var(--muted);
}
.facebook-fans-count:hover { color: var(--accent); border-color: var(--accent); }
.payment-badges { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.payment-label { color: var(--muted); font-size: .78rem; }
.payment-chip {
  background: var(--card); border: 1px solid var(--border); border-radius: 2px;
  padding: 2px 8px; font-size: .7rem; font-family: var(--mono); color: var(--muted);
}
.payment-chip-accent { color: var(--accent-2); border-color: var(--accent); }

/* ===========================================================
   Inner pages
   =========================================================== */
.page-hero {
  padding: 70px 0 40px;
  text-align: center;
  border-bottom: 1px solid var(--border);
  background: linear-gradient(180deg, rgba(22, 163, 74, .05), transparent);
}
.page-hero h1 { margin-bottom: 14px; }
.page-hero p { color: var(--muted); font-size: 1.1rem; max-width: 720px; margin: 0 auto; }

.content {
  padding: 60px 0;
}
.content-narrow {
  max-width: 820px;
  margin: 0 auto;
}
.content h2 { margin-top: 50px; }
.content h2:first-child { margin-top: 0; }
.content h3 { margin-top: 30px; }
.content ul, .content ol { color: var(--text); padding-left: 22px; }
.content li { padding: 4px 0; }

.callout {
  background: rgba(22, 163, 74, 0.06);
  border-left: 4px solid var(--accent);
  border-radius: 8px;
  padding: 18px 20px;
  margin: 24px 0;
  color: var(--text);
}
.callout.warn {
  background: rgba(220, 38, 38, 0.06);
  border-left-color: var(--red);
}
.callout.ok {
  background: rgba(47, 122, 82, 0.06);
  border-left-color: var(--green);
}
.callout strong { color: var(--text); }

/* ---------- Guides / articles ---------- */
.guide-meta {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 18px;
  font-family: var(--mono);
  font-size: .78rem;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: .04em;
}
.guide-meta .guide-tag {
  background: rgba(22, 163, 74, .1);
  color: var(--accent-2);
  border: 1px solid var(--accent);
  border-radius: 3px;
  padding: 3px 9px;
  font-weight: 700;
}
/* Master-battery wiring photo (CONSOLE + LINK PORT 1) — usable outside .content too */
.wiring-figure { margin: 26px auto; }
.wiring-figure img { width: 100%; height: auto; display: block; border-radius: 8px; border: 1px solid var(--border); }
.wiring-figure figcaption { margin-top: 10px; font-size: .85rem; color: var(--muted); text-align: center; line-height: 1.45; }

.content figure { margin: 30px 0; }
.content figure img { width: 100%; height: auto; display: block; border-radius: 8px; border: 1px solid var(--border); }
.content figcaption { margin-top: 10px; font-size: .85rem; color: var(--muted); text-align: center; }
/* Guide FAQ — the same [question, answer] pairs that feed the FAQPage JSON-LD,
   shown to the reader. A <dl> because that is literally what this is. */
.guide-faq { margin: 50px 0 0; }
.guide-faq h2 { margin-top: 0 !important; }
.guide-faq dl { margin: 0; }
.guide-faq dt {
  margin: 26px 0 0;
  padding-top: 22px;
  border-top: 1px solid var(--border);
  color: var(--text);
  font-weight: 700;
  font-size: 1.03rem;
  line-height: 1.45;
}
.guide-faq dt:first-of-type { border-top: 0; padding-top: 0; margin-top: 18px; }
.guide-faq dd {
  margin: 9px 0 0;
  color: var(--muted);
  line-height: 1.7;
}
@media (max-width: 640px) {
  .guide-faq dt { font-size: .99rem; }
}

.guide-cta {
  background: linear-gradient(135deg, rgba(22, 163, 74, .09), rgba(22, 163, 74, .03));
  border: 1px solid var(--accent);
  border-radius: var(--radius);
  padding: 26px 28px;
  margin: 40px 0;
  text-align: center;
}
.guide-cta p { margin: 0 0 16px; color: var(--text); font-size: 1.02rem; }
.guide-cta .price-note { display: block; margin-top: 10px; font-size: .8rem; color: var(--muted); font-family: var(--mono); }
.related-guides { margin: 50px 0 10px; }
.related-guides h2 { margin-top: 0 !important; }
.related-guides-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 18px;
}
.related-guide-card {
  display: block;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 20px;
  transition: transform .2s var(--ease), border-color .2s ease;
}
@media (hover: hover) {
  .related-guide-card:hover { transform: translateY(-3px); border-color: var(--accent); }
}
.related-guide-card .rg-tag { font-family: var(--mono); font-size: .7rem; color: var(--accent-2); text-transform: uppercase; letter-spacing: .04em; font-weight: 700; }
.related-guide-card h3 { margin: 8px 0 6px; font-size: 1.02rem; color: var(--text); }
.related-guide-card p { margin: 0; color: var(--muted); font-size: .88rem; }
.guides-index-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 24px;
  margin-top: 40px;
}
.guide-index-card {
  display: flex;
  flex-direction: column;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
  transition: transform .25s var(--ease), border-color .25s ease, box-shadow .25s ease;
}
@media (hover: hover) {
  .guide-index-card:hover { transform: translateY(-4px); border-color: var(--accent); box-shadow: var(--shadow); }
}
.guide-index-card img { width: 100%; height: 190px; object-fit: cover; display: block; border-bottom: 1px solid var(--border); }
.guide-index-card-body { padding: 22px; display: flex; flex-direction: column; flex: 1; }
.guide-index-card .rg-tag { font-family: var(--mono); font-size: .72rem; color: var(--accent-2); text-transform: uppercase; letter-spacing: .04em; font-weight: 700; }
.guide-index-card h2 { margin: 8px 0 10px !important; font-size: 1.2rem; }
.guide-index-card p { color: var(--muted); margin: 0 0 16px; flex: 1; }
@media (max-width: 860px) {
  .related-guides-grid { grid-template-columns: minmax(0, 1fr); }
  .guides-index-grid { grid-template-columns: minmax(0, 1fr); }
}

.steps-vert {
  list-style: none;
  padding: 0;
  margin: 30px 0;
  counter-reset: step;
}
.steps-vert li {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 22px 22px 22px 70px;
  margin-bottom: 16px;
  position: relative;
  counter-increment: step;
}
.steps-vert li::before {
  content: counter(step);
  position: absolute;
  left: 22px; top: 22px;
  width: 36px; height: 36px;
  background: var(--accent);
  color: #ffffff;
  border-radius: 50%;
  display: grid; place-items: center;
  font-weight: 800;
}
.steps-vert h3 { margin: 0 0 6px; }
.steps-vert p { margin: 0; color: var(--muted); }

.feature-row {
  display: grid;
  grid-template-columns: 80px 1fr;
  gap: 24px;
  align-items: start;
  padding: 26px 0;
  border-bottom: 1px solid var(--border);
}
.feature-row:last-child { border-bottom: none; }
.feature-row .fr-icon {
  width: 56px; height: 56px;
  background: transparent;
  border: 1.5px solid var(--accent);
  border-radius: 2px;
  display: grid; place-items: center;
  font-family: var(--mono);
  font-weight: 700;
  font-size: .72rem;
  color: var(--accent-2);
}
.feature-row .fr-icon.fr-icon-ha { border-color: #18BCF2; background: rgba(24, 188, 242, .08); }
.feature-row .fr-icon.fr-icon-ha img { width: 28px; height: 28px; display: block; }
.feature-row h3 { margin-bottom: 6px; }
.feature-row p, .feature-row .fr-desc { color: var(--muted); margin: 0; }
.feature-row .fr-desc ul { margin: 10px 0 0; }

.fw-list {
  list-style: none;
  padding: 0;
}
.fw-list li {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 22px;
  margin-bottom: 14px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  flex-wrap: wrap;
}
.fw-list .fw-version { font-weight: 700; color: var(--text); font-size: 1.1rem; }
.fw-list .fw-meta { color: var(--muted); font-size: .9rem; display: block; margin-top: 4px; }
.fw-list .fw-notes { color: var(--text); flex: 1; min-width: 300px; }

details.faq {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 18px 22px;
  margin-bottom: 12px;
}
details.faq summary {
  cursor: pointer;
  font-weight: 600;
  color: var(--text);
  list-style: none;
  padding: 4px 0;
  position: relative;
  padding-right: 30px;
}
details.faq summary::-webkit-details-marker { display: none; }
details.faq summary::after {
  content: "+";
  position: absolute;
  right: 0; top: 0;
  font-size: 1.4rem;
  color: var(--accent);
  transition: transform .2s ease;
}
details.faq[open] summary::after { content: "−"; }
details.faq p { color: var(--muted); margin: 12px 0 0; }
details.faq code { white-space: nowrap; }

.copy-block {
  position: relative;
}
.copy-btn {
  position: absolute;
  top: 12px; right: 12px;
  background: var(--text);
  color: var(--border);
  border: 1px solid var(--muted);
  padding: 6px 12px;
  border-radius: 6px;
  font-size: .8rem;
  cursor: pointer;
  font-family: var(--font);
}
.copy-btn:hover { border-color: var(--accent-bright); color: var(--accent-bright); }

/* ---------- Scroll reveal ---------- */
.reveal {
  opacity: 0;
  transform: translateY(28px);
  transition: opacity .7s var(--ease), transform .7s var(--ease);
}
.reveal.in-view { opacity: 1; transform: none; }

/* ---------- Responsive ----------
   Breakpoint raised to 1180px (not the usual ~900px): French/German nav labels
   run noticeably longer than English ("Démarrage rapide", "Fonctionnalités"),
   so anything narrower than the full desktop container gets the slide-out menu
   instead of a cramped, wrapping horizontal nav. */
@media (max-width: 1180px) {
  .nav-links {
    display: flex;
    position: fixed;
    top: 0; right: 0;
    width: min(320px, 84vw);
    height: 100vh;
    background: var(--card);
    border-left: 1px solid var(--border);
    flex-direction: column;
    align-items: flex-start;
    padding: 24px 24px 32px;
    gap: 6px;
    /* Above .cookie-banner (999): otherwise the banner can cover the drawer's
       last items (FAQ, language switcher, Commander button) on short phones. */
    z-index: 1005;
    box-shadow: -20px 0 40px rgba(19, 36, 51, .12);
    /* transform, not `right`, to slide off-canvas — an offscreen `right` value
       still counts toward the document's scrollWidth and was causing horizontal
       overflow/scroll on every page at mobile widths, even with the drawer closed. */
    transform: translateX(100%);
    transition: transform .3s var(--ease);
    overflow-y: auto;
  }
  .nav-links.open { transform: translateX(0); }
  .nav-links-scroll { flex-direction: column; align-items: flex-start; overflow: visible; width: 100%; gap: 6px; }
  /* Small staggered entrance once the drawer is open, so the menu content feels
     like it's arriving rather than just snapping into place. */
  .nav-links-scroll a, .nav-links-scroll .nav-dropdown, .nav-actions {
    opacity: 0;
    transform: translateX(12px);
  }
  .nav-links.open .nav-links-scroll a,
  .nav-links.open .nav-links-scroll .nav-dropdown,
  .nav-links.open .nav-actions {
    animation: nav-link-in .35s var(--ease) forwards;
  }
  .nav-links-scroll a:nth-child(1), .nav-links-scroll .nav-dropdown:nth-child(1) { animation-delay: .05s; }
  .nav-links-scroll a:nth-child(2), .nav-links-scroll .nav-dropdown:nth-child(2) { animation-delay: .09s; }
  .nav-links-scroll a:nth-child(3), .nav-links-scroll .nav-dropdown:nth-child(3) { animation-delay: .13s; }
  .nav-links-scroll a:nth-child(4), .nav-links-scroll .nav-dropdown:nth-child(4) { animation-delay: .17s; }
  .nav-links-scroll a:nth-child(5), .nav-links-scroll .nav-dropdown:nth-child(5) { animation-delay: .21s; }
  .nav-links-scroll a:nth-child(6), .nav-links-scroll .nav-dropdown:nth-child(6) { animation-delay: .25s; }
  .nav-links-scroll a:nth-child(7), .nav-links-scroll .nav-dropdown:nth-child(7) { animation-delay: .29s; }
  .nav-links.open .nav-actions { animation-delay: .32s; }
  @keyframes nav-link-in {
    to { opacity: 1; transform: none; }
  }
  .nav-links-scroll a { width: 100%; padding: 12px 4px 12px 14px; border-bottom: 1px solid var(--bg-2); }
  /* .nav-tour already draws its own full accent-colored pill border (all 4 sides,
     from the base .nav-tour rule above) at the same specificity as this override —
     explicitly cancelling border-bottom here used to win the cascade by source
     order and clip off just the bottom edge of that pill on mobile. Only reset
     width/spacing, leave the border alone. */
  .nav-links-scroll a.nav-tour { width: auto; margin: 6px 0; padding-left: 12px; }
  /* Desktop's active-link underline uses bottom:-22px to sit below the whole
     horizontal bar — in this vertical drawer that offset lands it on the row
     underneath instead. Swap it for a left accent bar confined to its own row. */
  .nav-links-scroll a.active::after {
    left: 0; right: auto; top: 0; bottom: 0;
    width: 3px; height: auto;
    border-radius: 0 2px 2px 0;
  }
  .nav-links-scroll a.nav-tour.active { padding-left: 12px; }
  .nav-actions { flex-direction: column; align-items: stretch; width: 100%; gap: 10px; margin-top: 10px; }
  .lang-switch { width: 100%; }
  .lang-switch-btn { width: 100%; justify-content: space-between; }
  .lang-switch-menu { position: static; width: 100%; margin-top: 6px; box-shadow: none; }
  .nav-actions .btn { width: 100%; }
  .nav-toggle { display: inline-block; }
  .nav-close {
    display: block;
    align-self: flex-end;
    background: transparent;
    border: 1px solid var(--border);
    color: var(--text);
    font-size: 1.1rem;
    width: 44px; height: 44px;
    border-radius: 8px;
    cursor: pointer;
    margin-bottom: 10px;
    transition: border-color .15s ease, color .15s ease;
  }
  .nav-close:hover { border-color: var(--accent); color: var(--accent); }

  /* "Ressources" dropdown, mobile drawer: the desktop version is an absolutely
     positioned floating panel — inside the slide-out drawer that overlay isn't
     part of the drawer's own document flow, so its lower rows could sit past
     the drawer's visible bounds and read as "the submenu doesn't fully show"
     (user report 2026-08-19: a menu nested inside a menu). Turned into an
     inline accordion instead: it simply pushes the rest of the drawer down and
     scrolls with it, so it's always fully reachable. */
  .nav-dropdown { width: 100%; }
  .nav-dropdown-btn {
    width: 100%;
    justify-content: space-between;
    padding: 12px 4px 12px 14px;
    border-bottom: 1px solid var(--bg-2);
  }
  .nav-dropdown.open .nav-dropdown-btn { border-bottom-color: transparent; }
  .nav-dropdown-menu {
    position: static;
    width: 100%;
    min-width: 0;
    margin: 0 0 4px;
    padding: 4px 0 4px 14px;
    background: transparent;
    border: none;
    border-left: 2px solid var(--border);
    border-radius: 0;
    box-shadow: none;
    z-index: auto;
  }
  .nav-dropdown-menu a { padding: 10px 10px 10px 12px; font-size: .86rem; }
  .nav-dropdown-group-label { padding: 10px 10px 4px 12px; }
  .nav-dropdown-divider { margin: 4px 12px 4px 26px; }

  .hero { padding: 50px 0 40px; }
  .hero-grid { grid-template-columns: minmax(0, 1fr); gap: 40px; }
  .hero-visual { order: -1; }
  /* Translated badge copy runs long (e.g. Dutch/German) — nowrap made this the
     min-content source that pushed .hero-grid past the viewport (2026-08-19,
     "photo and text stuck to the right edge"). Let it wrap instead. */
  .hero-live-badge { white-space: normal; text-align: center; max-width: 100%; border-radius: 14px; }

  .stats-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .grid-3 { grid-template-columns: minmax(0, 1fr); }
  .grid-2 { grid-template-columns: minmax(0, 1fr); }
  .compat-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .steps { grid-template-columns: minmax(0, 1fr); }
  /* Stacked layout: swap the horizontal trace for a short vertical dash
     bridging each card's bottom edge to the next card's top, confined to
     the gap so it never runs across the step's own title/text. */
  .step::before {
    top: 100%; left: 47px; right: auto;
    width: 0; height: 22px;
    border-top: none;
    border-left: 2px dashed var(--border);
  }
  .step:last-child::before { display: none; }
  .api-grid { grid-template-columns: minmax(0, 1fr); gap: 30px; }
  .gallery-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .footer-grid { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
  .feature-row { grid-template-columns: minmax(0, 1fr); gap: 14px; }
  .feature-row .fr-icon { width: 56px; height: 56px; }
}

@media (max-width: 520px) {
  h1 { font-size: 2rem; }
  .price { font-size: 3rem; }
  .compat-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .footer-grid { grid-template-columns: minmax(0, 1fr); }
  .pricing-card { padding: 30px 22px; }
  /* Below ~520px the row's three flex children (version+meta, notes, download
     button) no longer fit side by side but also don't quite wrap onto full-width
     rows on their own — flexbox instead squeezes all three into cramped, narrow
     columns sharing one row. Force a clean single-column stack instead. */
  .fw-list li { padding: 18px; flex-direction: column; align-items: stretch; }
  .fw-list .fw-notes { min-width: 0; }
  .fw-list .btn { width: 100%; text-align: center; }
}

/* Cookie consent banner */
.cookie-banner {
  display: flex;
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 999;
  background: var(--text);
  color: #fff;
  padding: 16px 24px;
  border-top: 2px solid var(--accent);
  box-shadow: var(--shadow-lg);
  visibility: hidden;
  opacity: 0;
  transform: translateY(12px);
  transition: opacity .25s ease, transform .25s ease, visibility 0s linear .25s;
}
.cookie-banner.is-visible {
  visibility: visible;
  opacity: 1;
  transform: translateY(0);
  transition: opacity .25s ease, transform .25s ease;
}
.cookie-banner-content {
  width: 100%;
  max-width: 1100px;
  margin: 0 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
}
.cookie-banner-content p {
  margin: 0;
  font-size: .85rem;
  line-height: 1.5;
  color: var(--border);
  flex: 1 1 420px;
}
.cookie-banner-content a { color: #fff; text-decoration: underline; text-underline-offset: 2px; }
.cookie-banner-actions {
  display: flex;
  gap: 10px;
  flex-shrink: 0;
}
.cookie-banner .btn-ghost {
  border-color: rgba(255,255,255,.3);
  color: #fff;
}
.cookie-banner .btn-ghost:hover { border-color: #fff; color: #fff; }
.cookie-banner .btn-primary {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}
.cookie-banner .btn-primary:hover { background: var(--accent-bright); border-color: var(--accent-bright); }

@media (max-width: 520px) {
  .cookie-banner { padding: 14px 16px; }
  .cookie-banner-content {
    flex-direction: column;
    align-items: stretch;
    gap: 12px;
  }
  .cookie-banner-content p { font-size: .78rem; line-height: 1.45; flex-basis: auto; }
  .cookie-banner-actions { justify-content: stretch; gap: 8px; }
  .cookie-banner-actions .btn { flex: 1; }
}

/* ---------- Image lightbox (click any product/screenshot photo to zoom) ---------- */
img.zoomable {
  cursor: zoom-in;
  transition: opacity .15s ease;
}
img.zoomable:hover { opacity: .92; }
.lightbox-overlay {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 2000;
  background: rgba(11, 15, 25, .88);
  backdrop-filter: blur(3px);
  padding: 40px 20px;
  align-items: center;
  justify-content: center;
  cursor: zoom-out;
}
.lightbox-overlay.open { display: flex; }
.lightbox-overlay img {
  max-width: min(1100px, 100%);
  max-height: calc(100vh - 80px);
  width: auto;
  height: auto;
  border-radius: 8px;
  box-shadow: 0 30px 80px rgba(0,0,0,.5);
  cursor: default;
}
.lightbox-close {
  position: fixed;
  top: 18px; right: 20px;
  width: 42px; height: 42px;
  border-radius: 50%;
  background: rgba(255,255,255,.1);
  border: 1px solid rgba(255,255,255,.25);
  color: #fff;
  font-size: 1.3rem;
  line-height: 1;
  cursor: pointer;
  display: grid;
  place-items: center;
  transition: background .15s ease;
}
.lightbox-close:hover { background: rgba(255,255,255,.2); }
@media (max-width: 520px) {
  .lightbox-overlay { padding: 20px 12px; }
  .lightbox-close { top: 10px; right: 10px; width: 38px; height: 38px; }
}

/* ---------- "From anywhere" band (homepage, under the hero) ----------
   Deliberately the one dark block on an otherwise paper-coloured page: it is the
   claim a visitor arrives comparing against a competitor, so it gets the page's
   single strongest contrast rather than becoming another card in the stack. */
.anywhere {
  background: var(--text);
  color: #f4f7fa;
  padding: 46px 0;
  margin: 0 0 10px;
}
.anywhere-inner { max-width: 860px; text-align: center; }
.anywhere h2 {
  color: #fff;
  font-size: clamp(1.35rem, 1.6vw + 1rem, 1.9rem);
  margin: 0 0 14px;
  text-wrap: balance;
}
.anywhere p {
  color: #c3d0d8;
  font-size: 1rem;
  line-height: 1.7;
  margin: 0 auto 22px;
  max-width: 68ch;
}
.anywhere-chips {
  list-style: none;
  padding: 0;
  margin: 0 0 20px;
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  justify-content: center;
}
.anywhere-chips li {
  font-family: var(--mono);
  font-size: .78rem;
  letter-spacing: .02em;
  color: #f4f7fa;
  border: 1px solid rgba(238, 241, 234, .28);
  border-radius: 20px;
  padding: 7px 14px;
}
.anywhere-chips li::before { content: "\2713"; color: var(--accent-bright); margin-right: 7px; font-weight: 700; }
.anywhere-cmp {
  display: inline-block;
  color: var(--accent-bright);
  font-weight: 700;
  font-size: .92rem;
  border-bottom: 1px solid rgba(34, 197, 94, .45);
  padding-bottom: 2px;
}
.anywhere-cmp:hover { color: #fff; border-color: #fff; }
@media (max-width: 640px) {
  .anywhere { padding: 34px 0; }
  .anywhere-chips li { font-size: .72rem; padding: 6px 11px; }
}

/* ── Customer reviews (homepage, above the pricing block) ──────────────────
   Masonry-ish columns rather than a grid: the reviews are deliberately of very
   uneven length ("Impeccable." next to a six-line one), and a grid would stretch
   every card in a row to match the tallest, leaving big empty boxes. */
.reviews-grid {
  columns: 3;
  column-gap: 20px;
}
.review-card {
  break-inside: avoid;
  margin: 0 0 20px;
  padding: 20px 22px;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
}
.review-stars {
  color: var(--accent);
  font-size: .95rem;
  letter-spacing: 2px;
  margin-bottom: 10px;
}
.review-card blockquote {
  margin: 0 0 14px;
  font-size: .96rem;
  line-height: 1.6;
  color: var(--text);
}
.review-card figcaption {
  display: flex;
  align-items: baseline;
  gap: 10px;
  flex-wrap: wrap;
  font-size: .88rem;
}
.review-card figcaption strong { color: var(--text); }

@media (max-width: 1180px) {
  .reviews-grid { columns: 2; }
}
@media (max-width: 640px) {
  .reviews-grid { columns: 1; }
}
