/* =========================================================================
   Cybernoob — www.cybernoob.io
   Feuille unique, écrite à la main. Aucune dépendance, aucune ressource tierce.
   Ordre : @font-face · tokens · reset · typo · layout · composants · sections
           · navigation partagée · page /contact · accessibilité & mouvement réduit
   ========================================================================= */

/* ------------------------------------------------------------------ 1. Polices
   Auto-hébergées (woff2, subsets latin + latin-ext). Aucune requête externe. */

@font-face {
  font-family: 'Montserrat';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('../fonts/montserrat-v31-latin_latin-ext-700.woff2') format('woff2');
}
@font-face {
  font-family: 'Montserrat';
  font-style: normal;
  font-weight: 800;
  font-display: swap;
  src: url('../fonts/montserrat-v31-latin_latin-ext-800.woff2') format('woff2');
}
@font-face {
  font-family: 'Ubuntu';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('../fonts/ubuntu-v21-latin_latin-ext-regular.woff2') format('woff2');
}
@font-face {
  font-family: 'Ubuntu';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('../fonts/ubuntu-v21-latin_latin-ext-700.woff2') format('woff2');
}
@font-face {
  font-family: 'Ubuntu';
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url('../fonts/ubuntu-v21-latin_latin-ext-italic.woff2') format('woff2');
}
@font-face {
  font-family: 'JetBrains Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('../fonts/jetbrains-mono-v24-latin_latin-ext-regular.woff2') format('woff2');
}
@font-face {
  font-family: 'JetBrains Mono';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('../fonts/jetbrains-mono-v24-latin_latin-ext-700.woff2') format('woff2');
}

/* ------------------------------------------------------- 2. Tokens de charte
   Déclarés UNE seule fois. Aucune couleur de charte en dur ailleurs. */

:root {
  --cn-bg: #0f0f0f;
  --cn-surface: #1a1a1a;
  --cn-deep: #0a0a0a;
  --cn-border: #2e2e2e;
  --cn-border-2: #3f3f46;
  --cn-input: #1e1e1e;
  --cn-red: #b51600;
  --cn-danger: #cc0000;
  --cn-green: #22c55e;
  --cn-text: #e4e4e7;
  --cn-muted: #a1a1aa;
  --cn-dim: #71717a;
  --cn-white: #ffffff;

  /* Le papier des extraits de presse, seul bloc CLAIR du site : les cartes de
     cas réels s'inversent sur la section sombre, l'inversion dit « ceci vient
     d'ailleurs ». Trois encres sur deux papiers (O7 les tient à 4.5:1). */
  --cn-paper: #f1ede3;
  --cn-paper-card: #faf8f2;
  --cn-paper-line: #cfc8b8;
  --cn-ink: #141414;
  --cn-ink-2: #3d3a35;
  --cn-ink-mute: #6e6a62;

  /* La bulle du perroquet est CLAIRE sur un site sombre : le contraste est ce qui
     fait comprendre en un coup d'œil que quelqu'un d'autre parle. Le contour suit
     le fond — un liseré rouge rattacherait la bulle à la charte et casserait
     l'effet « quelqu'un d'autre parle » (revue du 2026-08-31). */
  --cn-bubble: #ffffff;
  --cn-bubble-border: #ffffff;
  --cn-bubble-ink: #111111;

  /* Pas de couleur de lien globale. Sur ce site un lien n'est jamais un mot
     coloré au milieu d'une phrase : c'est un OBJET — carte, bouton, ligne de
     contact, entrée de nav — et chaque objet porte son propre signal
     d'interaction (bordure, relief, contraste au survol). Une teinte unique
     appliquée à tous les <a> produisait un orange absent de la charte, et elle
     fuitait partout où un composant ne la surchargeait pas.
     Le focus clavier reste porté par :focus-visible (fin de fichier). */
  --cn-link-hover: #ffffff;

  /* Les emoji sont du ton, pas de la décoration : la pile les nomme
     explicitement pour qu'ils ne tombent jamais en caractère manquant. */
  --cn-emoji: 'Apple Color Emoji', 'Segoe UI Emoji', 'Noto Color Emoji', 'Twemoji Mozilla';
  --cn-font-head: 'Montserrat', 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif, var(--cn-emoji);
  --cn-font-body: 'Ubuntu', 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif, var(--cn-emoji);
  --cn-font-mono: 'JetBrains Mono', ui-monospace, 'SFMono-Regular', Menlo, Consolas, monospace, var(--cn-emoji);

  --cn-max: 1080px;
  --cn-pad: 20px;
  --cn-radius: 12px;
  --cn-radius-lg: 18px;

  /* Formulaire (/inventaire-gratuit). Le liseré d'un champ tient 3:1 sur le
     fond (WCAG 1.4.11) : --cn-border-2 ne le tient pas, --cn-dim oui. Le gris
     des exemples et des étapes à venir tient 4.5:1 (O7) : --cn-dim ne le
     tient pas, --cn-faint oui. */
  --cn-faint: #85858e;
  --cn-field-border: var(--cn-dim);
  --cn-field-focus: var(--cn-text);
  --cn-field-h: 52px;
}

/* -------------------------------------------------------------- 3. Reset léger */

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

html {
  scroll-behavior: smooth;
  -webkit-text-size-adjust: 100%;
  scroll-padding-top: 80px;
}

body {
  margin: 0;
  background: var(--cn-bg);
  color: var(--cn-text);
  font-family: var(--cn-font-body);
  /* 18px et non 17 : à basse densité, du texte clair sur fond sombre paraît
     toujours plus fin qu'il ne l'est. Correctif « rendu non-Retina » (1/3). */
  font-size: 18px;
  line-height: 1.65;
  overflow-x: hidden;
}

img { max-width: 100%; height: auto; display: block; }

/* L'attribut `hidden` gagne toujours : sans cette règle, un composant qui pose
   son propre `display` (le bandeau de logos, en flex) s'affiche malgré lui. */
[hidden] { display: none !important; }

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

/* ------------------------------------------------------------------ 4. Typo */

/* Aucun espacement de lettres NÉGATIF sur les titres : à basse densité il n'y a
   pas assez de pixels pour séparer les glyphes, et les mots se collent.
   Correctif « rendu non-Retina » (2/3) — les espacements positifs restent. */
h1, h2, h3 {
  font-family: var(--cn-font-head);
  font-weight: 800;
  line-height: 1.15;
  margin: 0 0 0.6em;
}

h1 { font-size: clamp(2rem, 5.2vw, 3.4rem); }
h2 { font-size: clamp(1.5rem, 4.4vw, 2.35rem); }
h3 { font-size: clamp(1.12rem, 2.6vw, 1.35rem); font-weight: 700; }

/* Le titre d'une page intérieure : une phrase
   longue et non une accroche, donc un cran sous le titre de l'accueil. */
.h1--page { font-size: clamp(1.75rem, 4.2vw, 3rem); max-width: 22ch; }

p { margin: 0 0 1.1em; }
p:last-child { margin-bottom: 0; }

strong { font-weight: 700; color: var(--cn-white); }

/* Borne basse remontée (1.02 → 1.06) : correctif « rendu non-Retina » (3/3). */
.lead { font-size: clamp(1.06rem, 2.2vw, 1.15rem); color: var(--cn-text); }
.muted { color: var(--cn-muted); }
.mono { font-family: var(--cn-font-mono); }

.eyebrow {
  font-family: var(--cn-font-mono);
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--cn-red);
  margin: 0 0 0.9em;
}

/* --------------------------------------------------------------- 5. Layout */

.container {
  width: 100%;
  max-width: var(--cn-max);
  margin-inline: auto;
  padding-inline: var(--cn-pad);
}

.section { padding-block: clamp(56px, 9vw, 104px); }
.section--surface { background: var(--cn-surface); border-block: 1px solid var(--cn-border); }
.section__head { max-width: 44rem; margin-bottom: clamp(28px, 4vw, 44px); }
.section--tight { padding-top: 8px; }

/* Les grilles de section : un titre d'un côté, ce qu'il annonce de l'autre.
   Empilées sous 860px. */
.split { display: grid; gap: clamp(18px, 3vw, 24px); align-items: start; }
.split h2 { margin: 0; }
.split > div > h2:not(:last-child) { margin-bottom: 0.6em; }
@media (min-width: 860px) {
  .split { column-gap: 56px; }
  .split--1-1 { grid-template-columns: 1fr 1fr; }
  .split--7-5 { grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); }
  .split--5-7 { grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); }
  .split--4-8 { grid-template-columns: minmax(0, 4fr) minmax(0, 8fr); }
  .split--center { align-items: center; }
}

.prose { max-width: 42rem; }
.prose--wide { max-width: 48rem; }

/* --------------------------------------------------------- 6. Fond quadrillé
   Repris verbatim de custom.css. */

.bg-grid-pattern {
  background-image:
    repeating-linear-gradient(0deg, transparent, transparent 59px, rgba(255,255,255,0.03) 59px, rgba(255,255,255,0.03) 60px),
    repeating-linear-gradient(90deg, transparent, transparent 59px, rgba(255,255,255,0.03) 59px, rgba(255,255,255,0.03) 60px);
}

/* --------------------------------------------------------------- 7. Boutons */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5em;
  padding: 13px 24px;
  border-radius: var(--cn-radius);
  border: 2px solid transparent;
  font-family: var(--cn-font-head);
  font-weight: 700;
  font-size: 0.98rem;
  line-height: 1.2;
  text-decoration: none;
  cursor: pointer;
  transition: background-color .2s ease, border-color .2s ease, color .2s ease, transform .2s ease;
}
.btn:hover { transform: translateY(-2px); }

.btn--primary {
  background: var(--cn-red);
  border-color: var(--cn-red);
  color: var(--cn-white);
  box-shadow: 0 8px 24px -12px var(--cn-red);
}
.btn--primary:hover { background: var(--cn-danger); border-color: var(--cn-danger); color: var(--cn-white); }
.btn--primary[disabled],
.btn--primary[aria-busy="true"] { background: var(--cn-border-2); border-color: var(--cn-border-2); color: var(--cn-text); box-shadow: none; cursor: progress; transform: none; }

.btn--ghost {
  background: transparent;
  border-color: var(--cn-border-2);
  color: var(--cn-text);
}
.btn--ghost:hover { border-color: var(--cn-red); color: var(--cn-white); }

/* L'action discrète d'un formulaire (Retour, Ajouter, Retirer). Un bouton, pas
   un lien : il agit sur la page. Cible tactile de 48px. */
.btn--quiet {
  background: transparent;
  border-color: transparent;
  color: var(--cn-muted);
  min-height: 48px;
  padding: 11px 12px;
  font-family: var(--cn-font-body);
  font-weight: 400;
  font-size: 0.98rem;
  text-decoration: underline;
  text-underline-offset: 4px;
  text-decoration-color: var(--cn-border-2);
}
.btn--quiet:hover { color: var(--cn-white); text-decoration-color: var(--cn-red); transform: none; }

.btn-row {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: clamp(24px, 3.5vw, 34px);
}

/* --------------------------------------------------------------- 8. En-tête */

.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  background: rgba(15, 15, 15, 0.82);
  border-bottom: 1px solid var(--cn-border);
}
.nav-blur { backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px); }

.site-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  min-height: 64px;
}

.wordmark {
  font-family: var(--cn-font-mono);
  font-weight: 700;
  font-size: 1.06rem;
  color: var(--cn-white);
  text-decoration: none;
  white-space: nowrap;
}
.wordmark:hover { color: var(--cn-white); }
.wordmark__sigil { color: var(--cn-red); }

.site-header .btn { padding: 9px 18px; font-size: 0.9rem; }

/* ------------------------------------------------- 8b. Le menu partagé (nav)
   Règle load-bearing : SANS JavaScript, tout le menu reste atteignable. Le
   bouton hamburger n'existe que sous `.js` (comme .reveal). Le JS n'ajoute que
   du confort : fermeture à Échap, clic-dehors, aria-expanded synchronisé.
   Nav plate (v3) : plus de déroulant, trois entrées et le bouton de l'audit. */

.nav-toggle { display: none; }

.site-nav { display: flex; align-items: center; gap: 16px; }

.site-nav__list {
  display: flex;
  align-items: center;
  gap: 4px;
  list-style: none;
  margin: 0;
  padding: 0;
}

.site-nav a {
  display: block;
  padding: 8px 12px;
  border-radius: var(--cn-radius);
  font-family: var(--cn-font-head);
  font-weight: 700;
  font-size: 0.92rem;
  color: var(--cn-text);
  text-decoration: none;
  cursor: pointer;
}
.site-nav a:hover { color: var(--cn-white); background: var(--cn-bg); }

/* Le bouton du header : identique sur toutes les pages (fragment CN:NAV). */
.site-nav .site-nav__cta {
  display: inline-flex;
  padding: 9px 18px;
  font-size: 0.9rem;
  color: var(--cn-white);
  box-shadow: none;
}
.site-nav .site-nav__cta:hover { background: var(--cn-danger); color: var(--cn-white); }

/* La page courante, portée par <body data-page> : hors du fragment partagé,
   donc le menu reste byte-identique d'une page à l'autre. */
[data-page="home"] .site-nav a[href="/"],
[data-page="pentest-externe"] .site-nav a[href="/services/pentest-externe/"],
[data-page="contact"] .site-nav a[href="/contact/"] {
  color: var(--cn-white);
  box-shadow: inset 0 -2px 0 var(--cn-red);
  border-radius: 0;
}

@media (max-width: 860px) {
  .site-header__inner { flex-wrap: wrap; }

  .js .nav-toggle {
    display: inline-flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 4px;
    width: 44px;
    height: 44px;
    background: transparent;
    border: 1px solid var(--cn-border-2);
    border-radius: var(--cn-radius);
    cursor: pointer;
  }
  .js .nav-toggle:hover { border-color: var(--cn-red); }
  .nav-toggle__bar { display: block; width: 18px; height: 2px; background: var(--cn-text); }

  .site-nav { flex-basis: 100%; flex-direction: column; align-items: stretch; }
  .js .site-nav { display: none; }
  .js .site-nav.is-open { display: grid; }

  .site-nav__list {
    flex-direction: column;
    align-items: stretch;
    gap: 2px;
  }
  .site-nav .site-nav__cta { width: 100%; justify-content: center; margin-bottom: 12px; }
}

/* ----------------------------------------------------------------- 9. Hero
   v3 : ni quadrillage ni halo (la maquette n'en a pas). Texte à gauche, une
   image à droite dès 900px ; empilés en dessous, le texte d'abord. */

.hero { padding-block: clamp(36px, 6vw, 72px) clamp(32px, 5vw, 56px); }

.hero__inner { display: grid; gap: clamp(18px, 3vw, 22px); }
@media (min-width: 900px) {
  .hero__inner {
    grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
    column-gap: 56px;
    align-items: center;
  }
}
.hero--solo .hero__inner { grid-template-columns: 1fr; }

.hero__text { display: grid; gap: clamp(16px, 2.4vw, 22px); }
.hero h1 { margin: 0; max-width: 18ch; }
.hero h1.h1--page { max-width: 22ch; }
.hero h1 .hero__line-2 { display: block; color: var(--cn-muted); font-size: 0.62em; margin-top: 0.5em; font-weight: 700; }
.hero .lead { max-width: 38rem; margin: 0; font-size: clamp(1.06rem, 2.2vw, 1.19rem); }
.hero .kicker { margin: 0; }

/* Le geste et sa ligne de réassurance, toujours ensemble. Réutilisé hors hero
   (bloc audit de l'accueil, /services). */
.hero__cta { display: grid; gap: 10px; justify-items: start; }
.hero__micro { margin: 0; font-size: 0.9rem; font-style: italic; color: var(--cn-muted); max-width: 38rem; }
@media (max-width: 859px) {
  .hero__cta { justify-items: stretch; }
  .hero__cta .btn { width: 100%; }
  .hero__micro { text-align: center; }
}

.hero__figure {
  margin: 0;
  border: 1px solid var(--cn-border);
  border-radius: var(--cn-radius-lg);
  overflow: hidden;
  background: var(--cn-surface);
  width: 100%;
}
.hero__figure img { width: 100%; height: 100%; object-fit: cover; }

/* Le portrait de l'accueil : on le voit en entier en desktop (4/5), cadré sur
   le visage en mobile (carré, ancré en haut). */
.hero__figure--portrait { aspect-ratio: 1 / 1; max-width: none; }
.hero__figure--portrait img { object-position: top; }
@media (min-width: 900px) {
  .hero__figure--portrait { aspect-ratio: 4 / 5; max-height: 520px; max-width: 420px; justify-self: end; }
}

/* Une capture de travail garde son ratio natif : la recadrer en portrait
   détruirait ce qu'elle prouve. Jamais de `cover`. */
.hero__figure--capture { aspect-ratio: 1176 / 676; max-width: 420px; }
.hero__figure--capture img { object-fit: contain; }
@media (min-width: 900px) { .hero__figure--capture { justify-self: end; } }

/* Le nom de l'offre, au-dessus du titre. Il porte une INFORMATION : savoir sur
   quelle page on est sans avoir lu l'accueil — donc il se lit comme un libellé
   et non comme une phrase de plus : mono, court, rouge.
   La classe existait dans le markup et n'avait AUCUNE règle : elle se rendait
   en paragraphe ordinaire, à la taille du corps de texte et avec sa marge, ce
   qui la faisait lire comme une phrase orpheline.
   Pas de capitales espacées : ce traitement est déjà pris par `.eyebrow`, qui
   signale un STATUT (« En construction » sur la surveillance). Réutiliser le
   même signal pour deux informations différentes le vide de son sens, et une
   capitale espacée au-dessus de chaque titre est un ornement, pas une
   information. */
.kicker {
  font-family: var(--cn-font-mono);
  font-size: 0.84rem;
  font-weight: 700;
  color: var(--cn-red);
  margin: 0 0 0.75em;
}

/* ------------------------------------------- 10. Perroquet + bulle (signature)
   .speech-bubble / -inner / -left, parrot-float et bubble-pop repris verbatim
   de custom.css, hex remplacés par les tokens. */

.speech-bubble {
  position: relative;
  background: var(--cn-bubble);
  border: 2px solid var(--cn-bubble-border);
  border-radius: 16px;
  padding: 12px 20px;
  font-family: var(--cn-font-head);
  font-weight: 700;
  color: var(--cn-bubble-ink);
  font-size: 0.98rem;
  line-height: 1.45;
}
.speech-bubble::after {
  content: '';
  position: absolute;
  bottom: -12px;
  left: 30px;
  width: 0;
  height: 0;
  border-left: 12px solid transparent;
  border-right: 12px solid transparent;
  border-top: 12px solid var(--cn-bubble-border);
}
.speech-bubble-inner::after {
  content: '';
  position: absolute;
  bottom: -9px;
  left: 32px;
  width: 0;
  height: 0;
  border-left: 10px solid transparent;
  border-right: 10px solid transparent;
  border-top: 10px solid var(--cn-bubble);
}

/* Bulle à queue latérale (perroquet à gauche, réplique à droite) */
.speech-bubble-left::after {
  bottom: auto;
  left: -12px;
  top: 50%;
  transform: translateY(-50%);
  border-left: none;
  border-right: 12px solid var(--cn-bubble-border);
  border-top: 12px solid transparent;
  border-bottom: 12px solid transparent;
}
.speech-bubble-left .speech-bubble-inner::after {
  bottom: auto;
  left: -9px;
  top: 50%;
  transform: translateY(-50%);
  border-left: none;
  border-right: 10px solid var(--cn-bubble);
  border-top: 10px solid transparent;
  border-bottom: 10px solid transparent;
}

@keyframes parrot-float {
  0%, 100% { transform: translateY(0px) rotate(0deg); }
  25% { transform: translateY(-8px) rotate(1deg); }
  75% { transform: translateY(4px) rotate(-1deg); }
}
.parrot-float { animation: parrot-float 4s ease-in-out infinite; }

@keyframes bubble-pop {
  0% { transform: scale(0.5); opacity: 0; }
  70% { transform: scale(1.05); }
  100% { transform: scale(1); opacity: 1; }
}
.bubble-pop { animation: bubble-pop 0.5s cubic-bezier(0.34, 1.56, 0.64, 1) forwards; }

/* La réplique : mascotte + bulle, physiquement solidaires. */
.parrot-say {
  display: flex;
  align-items: center;
  gap: 14px;
  margin-top: clamp(28px, 4vw, 40px);
  max-width: 38rem;
}
.parrot-say__mascot {
  width: 68px;
  flex: 0 0 68px;
  filter: drop-shadow(0 6px 14px rgba(0,0,0,0.5));
}
.parrot-say .speech-bubble { flex: 1 1 auto; }

/* La bulle est un fond BLANC posé sur un site sombre : la règle globale
   `strong { color: var(--cn-white) }` y rend l'emphase invisible. Dans une
   bulle, l'emphase porte donc l'accent de la charte. (Décision opérateur,
   2026-09-01 — vaut pour TOUT strong de bulle, pas seulement le hero.) */
.speech-bubble strong { color: var(--cn-red); }

/* Variante hero : perroquet plus grand, réplique au-dessus. */
.parrot-say--hero {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 18px;
  max-width: 30rem;
}
.parrot-say--hero .parrot-say__mascot { width: 116px; flex-basis: auto; margin-left: 8px; }


/* La 404 : le perroquet parle, perroquet à gauche, bulle à droite, retour
   centré dessous. En étroit, le perroquet passe au-dessus et la queue de la
   bulle pointe vers le haut. */
.not-found { padding-block: clamp(56px, 10vw, 120px); }
.not-found__scene {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: clamp(20px, 3vw, 32px);
  max-width: 44rem;
  margin-inline: auto;
}
.not-found__parrot {
  width: clamp(120px, 18vw, 170px);
  height: auto;
  flex: 0 0 auto;
  filter: drop-shadow(0 8px 18px rgba(0,0,0,0.55));
}
.not-found__bubble {
  flex: 0 1 auto;
  min-width: 0;
  padding: 20px 26px;
  font-size: clamp(1.02rem, 2vw, 1.2rem);
}
.not-found__line { margin: 0; }
.not-found__cry {
  margin: 0.4em 0 0;
  color: var(--cn-red);
  font-weight: 800;
}
.not-found__actions {
  display: flex;
  justify-content: center;
  margin-top: clamp(36px, 5vw, 52px);
}
.not-found__btn {
  background: var(--cn-surface);
  border-color: var(--cn-border-2);
  color: var(--cn-text);
  border-radius: 999px;
  padding-inline: 30px;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  font-size: 0.86rem;
}
.not-found__btn:hover { border-color: var(--cn-red); color: var(--cn-white); }

@media (max-width: 639px) {
  .not-found__scene { flex-direction: column; gap: 22px; }
  .not-found__bubble { text-align: center; }
  .not-found__bubble.speech-bubble-left::after {
    left: 50%;
    top: -12px;
    transform: translateX(-50%);
    border-right: 12px solid transparent;
    border-left: 12px solid transparent;
    border-top: none;
    border-bottom: 12px solid var(--cn-bubble-border);
  }
  .not-found__bubble.speech-bubble-left .speech-bubble-inner::after {
    left: 50%;
    top: -9px;
    transform: translateX(-50%);
    border-right: 10px solid transparent;
    border-left: 10px solid transparent;
    border-top: none;
    border-bottom: 10px solid var(--cn-bubble);
  }
}

/* ------------------------------------------------------- 12. Cartes & listes */

.card {
  background: var(--cn-surface);
  border: 1px solid var(--cn-border);
  border-radius: var(--cn-radius-lg);
  padding: clamp(20px, 3vw, 28px);
  transition: border-color .2s ease;
}
.card:hover { border-color: var(--cn-border-2); }
/* Sur une section surface, la carte reprend le fond de page pour se détacher. */
.section--surface .card { background: var(--cn-bg); }
.card h3 { margin-bottom: 0.5em; }
.card p { color: var(--cn-muted); font-size: 0.98rem; }

.card-grid {
  display: grid;
  gap: 16px;
  grid-template-columns: 1fr;
}
@media (min-width: 760px) {
  .card-grid--3 { grid-template-columns: repeat(3, 1fr); }
  .card-grid--2 { grid-template-columns: repeat(2, 1fr); }
}
.card h3 { font-size: clamp(1.15rem, 2.2vw, 1.3rem); }
.card__num {
  display: block;
  margin-bottom: 12px;
  font-family: var(--cn-font-mono);
  font-size: 0.78rem;
  font-weight: 700;
  color: var(--cn-white);
}
/* Le rouge accent tombe à 2,6–2,8:1 sur fond sombre : il reste aux sigils
   décoratifs (le 01 02 03 de l'accueil), jamais à une étiquette qu'on lit. */
[data-page="home"] .card__num, [data-page="pentest-externe"] .card__num { color: var(--cn-red); }

/* Pages v4 (accueil, pentest externe) : l'échelle de la maquette (h1 50/33,
   h2 38/27, h3 22/20). Scopée : la page AD garde ses clamps jusqu'à sa v4. */
[data-page="home"] h1, [data-page="pentest-externe"] h1 { font-size: clamp(2.06rem, 4.6vw, 3.125rem); }
[data-page="home"] h2, [data-page="pentest-externe"] h2 { font-size: clamp(1.69rem, 3.6vw, 2.375rem); }
[data-page="home"] .card h3, [data-page="pentest-externe"] .card h3 { font-size: clamp(1.25rem, 2vw, 1.375rem); }
[data-page="home"] .hero .lead, [data-page="pentest-externe"] .hero .lead { font-size: clamp(1.03rem, 1.6vw, 1.15rem); }
[data-page="home"] .section, [data-page="pentest-externe"] .section { padding-block: clamp(56px, 7vw, 88px); }
#preuve h2, #cas h2 { max-width: 44rem; }
#pourquoi-moi h2 { max-width: 30ch; }
/* Deux sections surface qui se suivent (l'offre puis le problème 1) : un seul filet. */
.section--surface + .section--surface { border-top: 0; }

/* Le sous-titre sous un h2 : la seconde phrase d'une catchline. */
[data-page="home"] .section__head, [data-page="pentest-externe"] .section__head { display: grid; gap: 14px; }
[data-page="home"] .section__head > *, [data-page="pentest-externe"] .section__head > * { margin: 0; }
/* Un titre court et son sous-titre (problème 1, problème 4, solution) : la tête s'élargit. */
.section__head--wide { max-width: 52rem; }
.split > .section__head { margin-bottom: 0; }
.nw { white-space: nowrap; }
.section__sub {
  margin: 0;
  font-family: var(--cn-font-head);
  font-weight: 700;
  font-size: clamp(1.09rem, 2vw, 1.31rem);
  line-height: 1.4;
  color: var(--cn-muted);
}

/* ------------------------------------------------ 12a. Composants v3 (2026-10) */

/* Bandeau « Ils m'ont fait confiance » (v4) : un logo = un fichier déposé dans
   `assets/img/logos/`, même hauteur, gris clair. Le gris est dans le fichier ;
   `grayscale` rattrape un fichier déposé en couleur. Pas de lien.
   Une seule ligne qui défile en continu (retour Samy, 2026-10-20). Le HTML ne
   porte chaque logo qu'une fois ; main.js répète les logos jusqu'à remplir la
   largeur puis double la liste (copie `aria-hidden`, `data-clone`), et la piste
   glisse de -50 % en boucle : le raccord tombe pile sur le début de la copie.
   Le `padding-inline-end` égal au gap garde l'écart constant au raccord.
   Sans JS ou en mouvement réduit : ligne statique, défilable au doigt et à la
   barre (fine), fondu à droite pour dire que la ligne continue. */
.logo-band { --logo-gap: 64px; padding-block: 16px 56px; }
.logo-band .logo-band__label { margin: 0 0 18px; }
.logo-band__viewport {
  overflow-x: auto;
  scrollbar-width: thin;
  -webkit-mask-image: linear-gradient(to right, #000 90%, transparent);
  mask-image: linear-gradient(to right, #000 90%, transparent);
}
@media (prefers-reduced-motion: no-preference) {
  .logo-band__viewport.is-marquee { scrollbar-width: none; }
  .logo-band__viewport.is-marquee::-webkit-scrollbar { display: none; }
}
.logo-band__track { display: flex; width: max-content; }
.logo-band__list { list-style: none; margin: 0; padding: 0 var(--logo-gap) 0 0; display: flex; flex-wrap: nowrap; gap: var(--logo-gap); align-items: center; }
.logo-band__item { display: flex; align-items: center; flex: none; }
.logo-band__logo { display: block; height: 36px; width: auto; max-width: 160px; object-fit: contain; filter: grayscale(1); }
.logo-band__viewport.is-marquee {
  overflow: hidden;
  -webkit-mask-image: linear-gradient(to right, transparent, #000 10%, #000 90%, transparent);
  mask-image: linear-gradient(to right, transparent, #000 10%, #000 90%, transparent);
}
.is-marquee .logo-band__track { animation: logo-marquee var(--marquee-duration, 40s) linear infinite; }
.is-marquee:hover .logo-band__track { animation-play-state: paused; }
@keyframes logo-marquee { to { transform: translate3d(-50%, 0, 0); } }
@media (max-width: 639px) { .logo-band { --logo-gap: 44px; } .logo-band__logo { height: 30px; max-width: 132px; } }
@media (prefers-reduced-motion: reduce) {
  /* Le `*` global (0.01ms) ferait clignoter une boucle infinie : on coupe net. */
  .logo-band__viewport.is-marquee {
    overflow-x: auto;
    -webkit-mask-image: linear-gradient(to right, #000 90%, transparent);
    mask-image: linear-gradient(to right, #000 90%, transparent);
  }
  .is-marquee .logo-band__track { animation: none; }
  .logo-band [data-clone] { display: none; }
}

/* Chips : une situation par ligne, dans laquelle le lecteur se reconnaît. */
.chips { display: flex; flex-wrap: wrap; gap: 12px; list-style: none; margin: 0; padding: 0; }
.chip {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 12px 18px;
  border: 1px solid var(--cn-border);
  border-radius: var(--cn-radius);
  background: var(--cn-bg);
  font-size: 0.92rem;
  line-height: 1.35;
}
.section--surface .chip { background: var(--cn-bg); }
.section:not(.section--surface) .chip { background: var(--cn-surface); }
.chip__key { color: var(--cn-white); font-family: var(--cn-font-mono); font-size: 0.72rem; font-weight: 700; flex: none; }
.chip--self { border-style: dashed; }
.chips + p { margin-top: 18px; font-size: 0.95rem; }
@media (max-width: 859px) {
  .chips { flex-direction: column; }
  .chip { width: 100%; }
}

/* Une phrase-preuve, bordée du filet rouge : lis ça en priorité. */
.claim-line {
  margin: 36px 0 0;
  padding-left: clamp(16px, 2vw, 20px);
  border-left: 3px solid var(--cn-red);
  font-family: var(--cn-font-head);
  font-weight: 700;
  font-size: clamp(1.12rem, 2.4vw, 1.3rem);
  line-height: 1.35;
  color: var(--cn-white);
}

/* Liste au sigil `>` du wordmark. */
.sigil-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 10px; }
.sigil-list li { display: flex; gap: 10px; }
.sigil-list li::before {
  content: '>';
  flex: none;
  color: var(--cn-red);
  font-family: var(--cn-font-mono);
  font-weight: 700;
}
.sigil-list--facts li { font-size: clamp(1.02rem, 2.1vw, 1.12rem); }

/* Objections : la question du lecteur, la réponse en dessous. */
.objections { display: grid; gap: 14px; }
@media (min-width: 860px) { .objections--2 { grid-template-columns: 1fr 1fr; } }
.objection-card {
  background: var(--cn-bg);
  border: 1px solid var(--cn-border);
  border-radius: var(--cn-radius-lg);
  padding: 22px 24px;
}
.section:not(.section--surface) .objection-card { background: var(--cn-surface); }
.objection-card__q {
  margin: 0 0 6px;
  font-family: var(--cn-font-head);
  font-weight: 700;
  font-size: 1rem;
  color: var(--cn-white);
}
.objection-card p:last-child { margin: 0; color: var(--cn-muted); font-size: 0.94rem; }

/* Étapes : quatre cartes en desktop, des lignes numérotées en mobile. */
.steps { list-style: none; margin: 0; padding: 0; display: grid; gap: 14px; }
.steps__item { display: grid; gap: 8px; }
.steps__num { font-family: var(--cn-font-mono); font-weight: 700; color: var(--cn-red); }
.steps__title {
  margin: 0;
  font-family: var(--cn-font-head);
  font-weight: 700;
  font-size: 1.05rem;
  color: var(--cn-white);
}
.steps__item p { margin: 0; color: var(--cn-muted); font-size: 0.94rem; }
@media (min-width: 860px) {
  .steps { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 18px; }
  .steps__item {
    align-content: start;
    background: var(--cn-bg);
    border: 1px solid var(--cn-border);
    border-radius: var(--cn-radius-lg);
    padding: clamp(18px, 2.4vw, 24px);
  }
}
@media (max-width: 859px) {
  .steps__item { grid-template-columns: auto 1fr; column-gap: 14px; }
  .steps__num { grid-row: 1 / span 2; }
}

/* Cartes d'offre (/services) : la carte entière est le lien.
   (page retirée le 2026-10-26, règles conservées jusqu'au balayage CSS) */
.offer-grid { display: grid; gap: 22px; }
@media (min-width: 860px) { .offer-grid { grid-template-columns: 1fr 1fr; } }
.offer-card {
  display: flex;
  flex-direction: column;
  gap: 20px;
  padding: clamp(22px, 3vw, 32px);
  background: var(--cn-surface);
  border: 1px solid var(--cn-border-2);
  border-radius: var(--cn-radius-lg);
  color: inherit;
  transition: border-color .2s ease, transform .2s ease;
}
.offer-card:hover { border-color: var(--cn-red); transform: translateY(-2px); }
.offer-card__head { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; }
.offer-card__num { font-family: var(--cn-font-mono); font-size: 0.78rem; font-weight: 700; color: var(--cn-white); }
.offer-card__arrow { font-family: var(--cn-font-mono); font-size: 0.78rem; color: var(--cn-muted); }
.offer-card h2 { margin: 0; font-size: clamp(1.4rem, 3vw, 1.85rem); }
.offer-card__group { display: grid; gap: 6px; }
.offer-card__group p { margin: 0; }
.eyebrow--muted { color: var(--cn-muted); font-size: 0.72rem; letter-spacing: 0.12em; margin: 0; }
.offer-card__more {
  margin-top: auto;
  align-self: flex-start;
  padding: 6px 0;
  font-family: var(--cn-font-head);
  font-weight: 700;
  font-size: 0.95rem;
  color: var(--cn-white);
  border-bottom: 1px solid var(--cn-red);
}

/* Un lien dans une phrase : muet, il se signale au survol. */
.link-inline { color: var(--cn-text); border-bottom: 1px solid var(--cn-border-2); }
.link-inline:hover { color: var(--cn-white); border-bottom-color: var(--cn-red); }

/* Le dernier bloc d'une page offre : centré, un geste, une sortie discrète. */
.cta-final { display: grid; justify-items: center; text-align: center; gap: 20px; }
.cta-final .kicker { margin: 0; }
.cta-final h2 { max-width: 24ch; margin: 0; }
.cta-final p { max-width: 36rem; margin: 0; }
.cta-final__alt { font-size: 0.95rem; color: var(--cn-muted); border-bottom: 1px solid var(--cn-border-2); }
.cta-final__alt:hover { color: var(--cn-white); border-bottom-color: var(--cn-red); }
@media (max-width: 859px) {
  .cta-final { justify-items: stretch; }
  .cta-final .btn { width: 100%; }
}

/* Bloc « qui je suis » : portrait + texte */
.bio { display: grid; gap: clamp(24px, 4vw, 40px); align-items: start; }
@media (min-width: 860px) { .bio { grid-template-columns: minmax(0, 320px) minmax(0, 1fr); } }

.bio__portrait {
  border: 1px solid var(--cn-border);
  border-radius: var(--cn-radius-lg);
  overflow: hidden;
  background: var(--cn-surface);
}
.bio__portrait img { width: 100%; }
.bio__portrait--flush { margin: 0; }
/* Variante resserrée du bloc bio : la photo d'enfance est une illustration
   SECONDAIRE à côté du texte, pas la photo principale de la section. */
@media (min-width: 860px) { .bio--tight { grid-template-columns: minmax(0, 230px) minmax(0, 1fr); } }

/* PAIRE DE PREUVE — deux images côte à côte qui portent un seul argument :
   « j'ai construit ces infrastructures avant d'apprendre à les casser ».
   Elles sont à ÉGALITÉ stricte — même largeur, même cadre, même légende — parce
   que l'argument est la symétrie des deux métiers. Déséquilibrer les tailles
   ferait de l'une l'illustration de l'autre.
   Elles empilent sous 860px : côte à côte sur un téléphone, chacune devient
   trop petite pour qu'on y lise quoi que ce soit, et une preuve illisible
   n'est plus une preuve. */
.proof-pair {
  display: grid;
  gap: clamp(14px, 2.5vw, 22px);
  margin: clamp(26px, 4vw, 38px) 0;
}
@media (min-width: 860px) { .proof-pair { grid-template-columns: 1fr 1fr; } }

.proof-pair__item { margin: 0; }
.proof-pair__item img {
  width: 100%;
  border: 1px solid var(--cn-border);
  border-radius: var(--cn-radius-lg);
  background: var(--cn-surface);
}
/* La légende NOMME ce qu'on regarde : sans elle, un lecteur non technique voit
   « du matériel » et « du code ». C'est elle qui transforme une photo en
   preuve. Mono et discrète — elle informe, elle ne commente pas. */
.proof-pair__item figcaption {
  font-family: var(--cn-font-mono);
  font-size: 0.78rem;
  color: var(--cn-muted);
  margin-top: 9px;
}

/* PREUVE SEULE — même traitement que la paire, sur toute la largeur du bloc.
   Elle a remplacé un terminal reconstitué : une capture réelle n'a pas besoin
   d'être belle, elle a besoin d'être vraie. */
.proof-figure { margin: clamp(26px, 4vw, 38px) 0; }
.proof-figure img {
  width: 100%;
  border: 1px solid var(--cn-border);
  border-radius: var(--cn-radius-lg);
  background: var(--cn-surface);
}
.proof-figure figcaption {
  font-family: var(--cn-font-mono);
  font-size: 0.78rem;
  color: var(--cn-muted);
  margin-top: 9px;
}

/* APARTE DE FIN DE SECTION — une anecdote qui suit un argument, et qui doit se
   lire comme telle : on descend son rang, on ne l'encadre pas.
   Le filet est HORIZONTAL et neutre, jamais le filet rouge de `.callout` :
   celui-là veut dire « lis ça en priorité », soit l'exact inverse. Une hiérarchie
   se descend par l'échelle, la couleur et l'air — jamais avec un ornement
   emprunté à un composant qui dit le contraire.
   La photo rétrécit avec le texte : sinon elle contredit à l'œil ce que le texte
   annonce, et c'est l'image qui gagne. */
.aside-coda {
  margin-top: clamp(34px, 5vw, 56px);
  padding-top: clamp(22px, 3vw, 30px);
  border-top: 1px solid var(--cn-border);
}
@media (min-width: 860px) { .aside-coda.bio--tight { grid-template-columns: minmax(0, 180px) minmax(0, 1fr); } }
.aside-coda .prose p {
  font-size: 0.94rem;
  color: var(--cn-muted);
}

/* ------------------- 12d. Composants des pages v4 : accueil et pentest externe */

/* Bloc 3 : ceux qui réclament la preuve. Six cartes, un visuel et un nom. */
.asks { list-style: none; margin: 40px 0 0; padding: 0; display: grid; gap: 14px; grid-template-columns: repeat(6, minmax(0, 1fr)); grid-auto-rows: 1fr; }
@media (max-width: 1099px) { .asks { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 639px) { .asks { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.ask {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-start;
  gap: 14px;
  padding: 22px 14px;
  background: var(--cn-bg);
  border: 1px solid var(--cn-border);
  border-radius: var(--cn-radius);
}
.ask__logo { height: 52px; width: 100%; object-fit: contain; }
.icon.ask__icon { width: 34px; height: 52px; color: var(--cn-text); }
.ask__label { font-size: 0.88rem; line-height: 1.4; color: var(--cn-muted); text-align: center; }
/* NIS2 et DORA (retour Samy, 2026-10-20) : le cercle d'étoiles de l'UE en
   filigrane, centré dans la case, et le nom par-dessus dans le style exact
   d'ISO 27001 (`ask__mark`). Or de l'emblème, très atténué. */
.ask--eu { position: relative; justify-content: center; overflow: hidden; }
.ask__stars {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 104px;
  height: 104px;
  transform: translate(-50%, -50%);
  color: #fc0;
  opacity: 0.28;
  pointer-events: none;
}
.ask--eu .ask__mark { position: relative; }
/* ISO 27001 n'a pas de logo affiché (décision Samy, 2026-10-20) : le nom, en
   typographie forte, occupe la place du visuel. */
.ask__mark {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: 1 1 auto;
  min-height: 52px;
  font-family: var(--cn-font-head);
  font-weight: 800;
  font-size: clamp(1rem, 1.7vw, 1.25rem);
  line-height: 1.1;
  color: var(--cn-white);
  text-align: center;
  white-space: nowrap;
}

/* Bloc 4 : le carrousel de cas réels. Une piste à défilement natif (swipe et
   clavier sans JS) ; le JS n'ajoute que les flèches, les points, le compteur
   et l'auto-défilement. Sans JS, la piste se fait défiler à la main. */
.cases { overflow: hidden; }
.cases__sub { margin: -4px 0 0; font-family: var(--cn-font-head); font-weight: 700; font-size: clamp(1rem, 1.8vw, 1.15rem); line-height: 1.4; color: var(--cn-muted); max-width: 44rem; }
.cases__viewport { --cases-pad: 9px; margin: 36px calc(-1 * var(--cases-pad)) 0; }
.cases__track {
  list-style: none;
  margin: 0;
  padding: 0 var(--cases-pad);
  display: flex;
  gap: 18px;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-padding-inline: var(--cases-pad);
  scroll-behavior: smooth;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}
.cases__track::-webkit-scrollbar { display: none; }
/* min-width: 0 : sans lui, l'item flex prend la largeur min-content de son
   contenu (un long mot, une URL) et sort de sa flex-basis. Toutes les cartes
   ont ainsi la même largeur, quel que soit le titre. */
.case { flex: 0 0 calc((100% - 2 * 18px) / 3); min-width: 0; scroll-snap-align: start; display: flex; }
@media (max-width: 899px) { .case { flex-basis: calc((100% - 18px) / 2); } }
@media (max-width: 639px) { .case { flex-basis: 100%; } }
/* La carte, commune aux deux carrousels : un extrait de presse, CLAIR (papier
   et encre) sur la section qui reste sombre ; l'inversion dit « ceci vient
   d'ailleurs ». Sur la page pentest, la porte d'entrée de l'attaquant en
   bandeau de tête (icône rouge, libellé mono, papier soutenu) ; l'accueil n'a
   pas de bandeau. Corps : type d'incident, organisation, headline, impact
   étiqueté ; pied ancré en bas sous un filet, média · date à gauche, source à
   droite. Les cartes ont la hauteur de la plus longue : la piste flex les
   étire (align-items: stretch). */
.case__card {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  min-width: 0;
  overflow: hidden;
  background: var(--cn-paper-card);
  border: 1px solid var(--cn-paper-line);
  border-radius: var(--cn-radius-lg);
  color: var(--cn-ink);
  overflow-wrap: anywhere;
  transition: border-color .2s ease;
}
.case__card:hover { border-color: var(--cn-ink-mute); }
.case__porte {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 0;
  padding: 11px 24px;
  background: var(--cn-paper);
  border-bottom: 1px solid var(--cn-paper-line);
  font-family: var(--cn-font-mono);
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  line-height: 1.3;
  color: var(--cn-ink);
}
.icon.case__porte-icon { width: 15px; height: 15px; color: var(--cn-red); flex: 0 0 auto; }
.case__body { flex: 1 1 auto; display: flex; flex-direction: column; gap: 12px; padding: 18px 24px 20px; }
.case__type { margin: 0; font-family: var(--cn-font-mono); font-size: 11px; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase; color: var(--cn-ink-mute); }
.case__org { margin: -6px 0 0; font-family: var(--cn-font-head); font-size: 17px; font-weight: 700; line-height: 1.3; color: var(--cn-ink); }
.case__headline { margin: 0; font-size: 16px; line-height: 1.45; color: var(--cn-ink); }
.case__impact { margin: 2px 0 0; font-size: 14px; line-height: 1.45; color: var(--cn-ink-2); }
.case__label { display: block; margin-bottom: 4px; font-family: var(--cn-font-mono); font-size: 10.5px; font-weight: 700; letter-spacing: 0.12em; text-transform: uppercase; color: var(--cn-ink-mute); }
.case__source {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: baseline;
  gap: 6px 14px;
  margin: auto 0 0;
  padding-top: 12px;
  border-top: 1px solid var(--cn-paper-line);
}
.case__meta { font-family: var(--cn-font-mono); font-size: 12px; color: var(--cn-ink-mute); }
.case__source a { font-family: var(--cn-font-mono); font-size: 0.81rem; font-weight: 700; color: var(--cn-ink); border-bottom: 1px solid var(--cn-ink-mute); }
.case__source a:hover { color: var(--cn-red); border-bottom-color: var(--cn-red); }
/* Les clones de bouclage (posés par le JS) sont des copies visuelles, hors de
   l'arbre accessible ; aucun style propre. */
.case--clone { scroll-snap-align: start; }

.cases__controls { display: none; }
.js .cases__controls { display: flex; align-items: center; justify-content: space-between; gap: 20px; margin-top: 28px; }
.cases__nav { display: flex; align-items: center; gap: 10px; }
.cases__arrow {
  width: 44px;
  height: 44px;
  padding: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--cn-surface);
  border: 1px solid var(--cn-border);
  border-radius: var(--cn-radius);
  color: var(--cn-text);
  cursor: pointer;
}
.cases__arrow:hover { border-color: var(--cn-border-2); color: var(--cn-white); }
.cases__chevron { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; }
.cases__counter { margin-left: 6px; font-family: var(--cn-font-mono); font-size: 0.81rem; color: var(--cn-muted); }
.cases__dots { display: flex; flex-wrap: wrap; justify-content: flex-end; align-items: center; gap: 5px; }
.cases__dot { width: 8px; height: 8px; padding: 0; border: 0; border-radius: 4px; background: var(--cn-border-2); cursor: pointer; transition: width .3s ease, background-color .3s ease; }
.cases__dot[aria-current="true"] { width: 22px; background: var(--cn-red); }
@media (max-width: 759px) { .cases__dots { display: none; } }

/* Les illustrations qui imitent un outil (résultat du hero, fiche de domaine,
   inventaire, scanner) : décoratives (aria-hidden), en anglais, domaine
   d'exemple metacortex.com. Leurs gris et leurs couleurs de risque ne sont pas
   de la charte : tokens locaux, jamais dans :root. `--win-dim` n'est employé
   que dans ces illustrations ; tout texte lu reste en --cn-muted. */
.win, .dom {
  --win-chrome: #111111;
  --win-line: #1f1f1f;
  --win-dim: #71717a;
  --risk-high: #d97706;
  --risk-high-ink: #f59e0b;
  --risk-medium: #ca8a04;
  --risk-ink: #111111;
}
.win { position: relative; overflow: hidden; margin: 0; background: var(--cn-deep); border: 1px solid var(--cn-border); border-radius: 8px; font-family: var(--cn-font-mono); }
.win__bar { display: flex; align-items: center; gap: 6px; height: 32px; padding: 0 14px; background: var(--win-chrome); border-bottom: 1px solid var(--cn-border); }
.win__bar span { width: 10px; height: 10px; border-radius: 50%; background: var(--cn-border-2); }
.win__bar span:first-child { background: var(--cn-red); }
.win__body { padding: 10px 16px 0; }
.win__head { display: flex; justify-content: space-between; align-items: center; gap: 12px; margin: 0; padding-bottom: 8px; border-bottom: 1px solid var(--cn-border); font-size: 12px; line-height: 1.5; color: var(--cn-muted); }
.win__head b { color: var(--cn-text); font-size: 13px; }
/* La pastille « exemple » : une légende pour le lecteur, en français. */
.pill { display: inline-block; padding: 3px 8px; border: 1px solid var(--cn-border-2); border-radius: 6px; font-family: var(--cn-font-mono); font-size: 11px; font-weight: 700; letter-spacing: 0.12em; text-transform: uppercase; line-height: 1.5; color: var(--cn-muted); }

/* Risque et état, partagés par le résultat du hero, l'inventaire et la fiche. */
.risk { display: inline-flex; align-items: center; justify-content: center; min-width: 22px; height: 18px; padding: 0 5px; border-radius: 4px; font-size: 11px; font-weight: 700; color: var(--risk-ink); background: var(--risk-high); }
.risk--3 { background: var(--cn-red); color: var(--cn-white); }
.risk--2 { background: var(--risk-high); }
.risk--1 { background: var(--risk-medium); }
.risk--0 { background: transparent; color: var(--cn-border-2); }
.state { display: inline-flex; align-items: center; gap: 5px; padding: 2px 8px; border: 1px solid transparent; border-radius: 5px; font-size: 11px; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase; }
.state--pwn { background: var(--cn-red); color: var(--cn-white); }
.state--vul { border-color: var(--risk-high); color: var(--risk-high-ink); }
.state--ok { border-color: var(--cn-border-2); color: var(--win-dim); }
.skull { width: 12px; height: 12px; fill: currentColor; }

/* Hero de la page pentest : texte et résultat dessiné à parts égales. Le
   résultat est décalé vers le bord droit et s'y fond : un arrière-plan, pas
   un widget. */
.hero--result { overflow: hidden; }
.hero--result h1 { max-width: none; }
.hero__sub { margin: 0; font-family: var(--cn-font-head); font-weight: 700; font-size: clamp(1.25rem, 2.4vw, 1.9rem); line-height: 1.3; color: var(--cn-muted); text-wrap: balance; }
@media (min-width: 900px) {
  .hero--result .hero__inner { grid-template-columns: minmax(0, 6fr) minmax(0, 6fr); column-gap: 48px; align-items: center; }
  .res { width: 122%; transform: translateX(5%); -webkit-mask-image: linear-gradient(to right, #000 62%, transparent 100%); mask-image: linear-gradient(to right, #000 62%, transparent 100%); }
}
.res .win__body { padding: 10px 16px 14px; }
.res__pill { margin-right: auto; margin-left: 14px; }
.res__dom { color: var(--win-dim); }
.res__table { width: 100%; table-layout: fixed; border-collapse: collapse; margin-top: 2px; font-size: 13px; line-height: 1.4; }
.res__table col.c-risk { width: 60px; }
.res__table col.c-host { width: 22%; }
.res__table col.c-state { width: 128px; }
.res__table col.c-svc { width: auto; }
.res__table th { padding: 10px 8px 8px 0; text-align: left; font-weight: 400; font-size: 11px; letter-spacing: 0.08em; text-transform: uppercase; color: var(--win-dim); border-bottom: 1px solid var(--cn-border); }
.res__row td { padding: 7px 8px 7px 0; border-bottom: 1px solid var(--win-line); color: var(--cn-muted); vertical-align: middle; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.res__table th:last-child, .res__row td:last-child { padding-right: 0; }
.res__host { color: var(--cn-text); }
.res__row--vul .res__host, .res__row--ok .res__host { font-weight: 400; }
.res__row--pwn .res__host { color: var(--cn-white); font-weight: 700; }
@media (max-width: 639px) {
  .res .win__body { padding: 10px 12px 12px; }
  .res__pill { margin: 0; }
  .res__table { table-layout: auto; font-size: 11.5px; }
  .res__svc, .res__dom { display: none; }
  .res__table th, .res__table td { padding-right: 12px; }
  .res__table th:last-of-type, .res__table td:last-of-type { padding-right: 0; }
  .res .win__head { flex-wrap: nowrap; }
}

/* L'offre (bloc 1b et CTA final de la page pentest, même composant posé deux
   fois) : une carte, le texte à gauche, la fiche de domaine dessinée à droite. */
.section--cta, [data-page="pentest-externe"] .section--cta { padding-block: clamp(40px, 5vw, 56px); }
.offer-block { display: grid; gap: 28px; padding: clamp(24px, 3.5vw, 44px); background: var(--cn-bg); border: 1px solid var(--cn-border); border-radius: var(--cn-radius-lg); }
.offer-block__text { display: grid; gap: 18px; align-content: center; min-width: 0; }
.offer-block__text > * { margin: 0; }
.offer-block__text h2 { font-size: clamp(1.45rem, 2.5vw, 1.95rem); max-width: 24ch; }
.offer-block .lead { max-width: 40rem; }
.offer-block .hero__cta { margin-top: 6px; }
.offer-block .hero__micro { text-align: left; max-width: 34rem; }
@media (min-width: 900px) {
  .offer-block { grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); column-gap: clamp(32px, 4vw, 56px); align-items: center; }
}
/* La fiche de domaine : ce que l'inventaire gratuit produit. Des compteurs,
   pas une liste de plus ; pas de barre de fenêtre : une fiche, pas un écran. */
.dom { display: grid; gap: 14px; min-width: 0; margin: 0; padding: 16px 18px 18px; background: var(--cn-deep); border: 1px solid var(--cn-border); border-radius: 8px; font-family: var(--cn-font-mono); line-height: 1.4; }
.dom__head { display: flex; justify-content: space-between; align-items: flex-start; gap: 12px; padding-bottom: 12px; border-bottom: 1px solid var(--cn-border); }
.dom__head > div { display: grid; gap: 3px; min-width: 0; }
.dom__name { font-size: 15px; font-weight: 700; color: var(--cn-text); }
.dom__meta { font-size: 11px; color: var(--win-dim); }
.dom__k { font-size: 10.5px; font-weight: 700; letter-spacing: 0.12em; text-transform: uppercase; color: var(--win-dim); }
.dom__tiles { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
.dom__tiles li { display: grid; gap: 5px; min-width: 0; padding: 12px 14px 11px; background: var(--cn-surface); border: 1px solid var(--cn-border); border-radius: 6px; }
.dom__tiles b { font-family: var(--cn-font-head); font-weight: 800; font-size: 30px; line-height: 1; color: var(--cn-text); }
.dom__s { font-size: 11px; line-height: 1.35; color: var(--win-dim); }
.dom__s em { font-style: normal; color: var(--risk-high-ink); }
.dom__sec { display: grid; gap: 8px; }
.dom__chips { display: flex; flex-wrap: wrap; gap: 6px; }
.dom__chips .state { text-transform: none; letter-spacing: 0; font-size: 11px; }
@media (max-width: 899px) { .dom { max-width: 460px; } }

/* Problème 1 : la vue « Services » après découverte, groupée par IP. Les
   lignes en évidence sont celles de la question ; hauteur fixe, fondu. */
.inv { height: 440px; }
.inv::after { content: ''; position: absolute; left: 0; right: 0; bottom: 0; height: 90px; background: linear-gradient(180deg, rgba(10, 10, 10, 0), var(--cn-deep)); }
.svc__filters { display: flex; flex-wrap: wrap; gap: 6px; margin: 10px 0 6px; }
.svc__chip { padding: 2px 9px; border: 1px solid var(--cn-border); border-radius: 999px; font-size: 11px; color: var(--win-dim); }
.svc__chip--on { border-color: var(--cn-red); color: var(--cn-text); background: rgba(181, 22, 0, 0.14); }
.svc { width: 100%; border-collapse: collapse; table-layout: fixed; font-size: 12px; line-height: 1.35; color: var(--win-dim); }
.svc th { padding: 6px 10px 6px 0; text-align: left; font-weight: 400; font-size: 11px; letter-spacing: 0.06em; text-transform: uppercase; color: var(--win-dim); border-bottom: 1px solid var(--cn-border); white-space: nowrap; }
.svc__row td { padding: 6px 10px 6px 0; border-bottom: 1px solid var(--win-line); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; vertical-align: middle; }
.svc .svc__risk { width: 34px; padding-right: 4px; overflow: visible; text-overflow: clip; }
.svc__ip { width: 108px; color: var(--cn-muted); }
.svc__port { width: 44px; }
.svc__host { width: 33%; }
.svc__loc { width: 52px; }
.svc__row--hot td { color: var(--cn-text); }
.svc__row--hot .svc__name { color: var(--cn-white); font-weight: 700; }
.svc__row--hot .svc__host { color: var(--cn-muted); }
.svc .risk { font-size: 10.5px; padding: 0 5px; }
@media (max-width: 639px) {
  .inv { height: 420px; }
  .svc__loc, .svc__ip, .svc__dom, .svc__filters { display: none; }
  .svc__host { width: 32%; }
}

/* Bloc « faux positifs » : une sortie de scanner. Nette, sans outil nommé.
   Les couleurs de sévérité ne sont pas de la charte : tokens locaux. */
.scan {
  --scan-critical: #b51600;
  --scan-high: #d97706;
  --scan-medium: #ca8a04;
  --scan-low: #2563eb;
  --scan-info: #52525b;
  --scan-line: #1f1f1f;
  --scan-chrome: #111111;
  height: 470px;
}
@media (max-width: 899px) { .scan { height: 380px; } }
.scan .win__body { padding: 10px 26px 0 16px; }
.scan__dom { display: none; }
.scan__rows { list-style: none; margin: 0; padding: 0; }
.scan__row { display: flex; align-items: center; gap: 12px; padding: 7px 0; border-bottom: 1px solid var(--scan-line); font-size: 13px; line-height: 1.4; }
.scan__sev { flex: none; min-width: 62px; padding: 2px 7px; border-radius: 5px; font-size: 11px; font-weight: 700; text-align: center; color: #111111; }
.scan__sev--critical { background: var(--scan-critical); color: var(--cn-white); }
.scan__sev--high { background: var(--scan-high); }
.scan__sev--medium { background: var(--scan-medium); }
.scan__sev--low { background: var(--scan-low); color: var(--cn-white); }
.scan__sev--info { background: var(--scan-info); color: var(--cn-text); }
.scan__score { flex: none; min-width: 30px; color: var(--cn-muted); }
.scan__title { flex: 1 1 auto; min-width: 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; color: var(--cn-text); }
.scan__host { flex: none; color: var(--cn-muted); }
@media (max-width: 479px) {
  .scan .win__body { padding: 10px 18px 0 12px; }
  .scan__row { gap: 9px; font-size: 11px; }
  .scan__sev { min-width: 52px; padding: 2px 5px; font-size: 10px; }
  .scan__score { min-width: 24px; }
  .scan__host, .scan .win__head span:last-child { display: none; }
}
.scan__scrollbar { position: absolute; top: 32px; right: 0; bottom: 0; width: 10px; background: var(--scan-chrome); border-left: 1px solid var(--scan-line); }
.scan__scrollbar span { position: absolute; top: 6px; left: 2px; right: 2px; height: 22px; border-radius: 3px; background: var(--cn-border-2); }
.scan::after { content: ''; position: absolute; left: 0; right: 10px; bottom: 0; height: 90px; background: linear-gradient(180deg, rgba(10, 10, 10, 0), var(--cn-deep)); }

/* Problème 4 : la frise sur une année (SVG généré par tools/build-timeline.py),
   douze mois nommés en desktop, initiales en mobile. */
.tl { display: block; width: 100%; height: auto; }
.tl--m { display: none; }
@media (max-width: 639px) { .tl--d { display: none; } .tl--m { display: block; } }

/* « Ce que vous recevez », bloc commun aux deux pages : trois livrables
   numérotés à gauche, le rapport dessiné à droite. */
.deliverables { list-style: none; margin: 10px 0 0; padding: 0; display: grid; gap: 26px; }
.deliverables li { display: grid; gap: 8px; }
.deliverables__num { font-family: var(--cn-font-mono); font-size: 13px; font-weight: 700; color: var(--cn-red); }
.deliverables h3 { font-size: 19px; margin: 0; }
.deliverables p { font-size: 16.5px; line-height: 1.55; color: var(--cn-muted); margin: 0; }

/* Le rapport, dessiné comme un DOCUMENT (papier clair, seconde feuille
   derrière). */
.report {
  --report-paper: #f4f4f5;
  --report-ink: #18181b;
  --report-ink-2: #27272a;
  --report-rule: #d4d4d8;
  --report-dim: #52525b;
  --report-behind: #e4e4e7;
  position: relative;
  margin: 0;
  padding: 0 10px 10px 0;
}
.report__behind { position: absolute; inset: 10px 0 0 10px; background: var(--report-behind); border: 1px solid var(--report-rule); border-radius: 6px; }
.report__paper { position: relative; overflow: hidden; background: var(--report-paper); color: var(--report-ink); border: 1px solid var(--report-rule); border-radius: 6px; }
.report__bar { display: flex; justify-content: space-between; align-items: center; gap: 12px; padding: 12px 30px; background: var(--report-ink); }
.report__bar .wordmark { font-size: 0.81rem; }
.report__kind { font-family: var(--cn-font-mono); font-size: 11px; letter-spacing: 0.08em; text-transform: uppercase; color: var(--cn-muted); text-align: right; }
.report__body { display: grid; gap: 18px; padding: 28px 30px 30px; }
.report__head { display: flex; justify-content: space-between; align-items: center; gap: 12px; margin: 0; padding-bottom: 12px; border-bottom: 2px solid var(--report-ink); }
.report__title { font-family: var(--cn-font-mono); font-weight: 700; font-size: 18px; line-height: 1.3; }
.report__pill { padding: 3px 8px; border: 1px solid var(--report-rule); border-radius: 6px; font-family: var(--cn-font-mono); font-size: 11px; font-weight: 700; letter-spacing: 0.12em; text-transform: uppercase; color: var(--report-dim); }
.report__intro { margin: 0; font-size: 15px; line-height: 1.5; }
.report__finding { display: grid; gap: 10px; padding-top: 6px; }
.report__finding + .report__finding { padding-top: 14px; border-top: 1px solid var(--report-rule); }
.report__finding-head { display: flex; align-items: center; gap: 10px; margin: 0; }
.report__num { font-family: var(--cn-font-mono); font-size: 12px; font-weight: 700; color: var(--report-dim); }
.report__crit { display: inline-block; padding: 2px 9px; border-radius: 6px; font-family: var(--cn-font-mono); font-size: 11.5px; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase; line-height: 1.5; }
.report__crit--critique { background: var(--cn-red); color: var(--cn-white); }
.report__crit--elevee { background: #d97706; color: #111111; }
.report__finding-title { margin: 0; font-family: var(--cn-font-head); font-weight: 700; font-size: 17px; line-height: 1.3; color: var(--report-ink); }
.report__facts { display: grid; grid-template-columns: 96px minmax(0, 1fr); gap: 6px 14px; margin: 0; font-size: 14px; line-height: 1.45; color: var(--report-ink-2); }
.report__facts dt { padding-top: 2px; font-family: var(--cn-font-mono); font-size: 10.5px; font-weight: 700; letter-spacing: 0.14em; text-transform: uppercase; color: var(--report-dim); }
.report__facts dd { margin: 0; }
.report__foot { display: flex; justify-content: space-between; align-items: center; gap: 12px; margin: 0; padding: 10px 30px; border-top: 1px solid var(--report-rule); font-family: var(--cn-font-mono); font-size: 10.5px; letter-spacing: 0.08em; text-transform: uppercase; line-height: 1.5; color: var(--report-dim); }
.report__foot > span:last-child { display: inline-flex; align-items: center; gap: 8px; }
.report__pdf { padding: 1px 6px; border: 1px solid var(--report-rule); border-radius: 4px; font-weight: 700; }
@media (max-width: 639px) {
  .report__facts { grid-template-columns: 1fr; gap: 2px 0; }
  .report__facts dd + dt { margin-top: 8px; }
  .report__bar, .report__body, .report__foot { padding-inline: 18px; }
}
/* Page pentest, « Comment ça se passe » : quatre jalons en cartes reliées par
   un rail, et une boucle en pointillés de l'étape 4 vers l'étape 1. En
   mobile, les cartes en colonne et la boucle devient icône + légende. */
.flow { position: relative; display: grid; margin-top: 32px; }
.steps--flow .steps__item {
  position: relative;
  align-content: start;
  gap: 10px;
  background: var(--cn-surface);
  border: 1px solid var(--cn-border);
  border-radius: var(--cn-radius-lg);
  padding: 24px;
}
.steps--flow .steps__num { display: inline-flex; align-items: center; justify-content: center; width: 34px; height: 34px; border: 1px solid var(--cn-border-2); border-radius: 50%; background: var(--cn-bg); font-size: 13px; }
.steps--flow .steps__title { font-size: 19px; }
.steps--flow p { font-size: 16px; line-height: 1.55; }
.loop { display: block; width: 100%; height: auto; }
.loop__icon { color: var(--cn-red); }
.loop--m { display: none; }
@media (min-width: 860px) {
  .steps--flow::before { content: ''; position: absolute; left: 12.5%; right: 12.5%; top: 41px; height: 1px; background: var(--cn-border-2); }
}
@media (max-width: 859px) {
  .steps--flow .steps__item { grid-template-columns: 34px 1fr; column-gap: 16px; }
  .loop--d { display: none; }
  .loop--m { display: flex; align-items: center; gap: 12px; margin-top: 14px; font-family: var(--cn-font-mono); font-size: 13px; color: var(--cn-muted); }
  .loop--m .icon { width: 18px; height: 18px; }
}

/* « Ce que ça vous demande » : un encadré, le libellé puis trois pastilles
   cochées. L'effort côté client est minimal. */
.needs { display: flex; flex-wrap: wrap; align-items: center; gap: 12px 18px; margin-top: 28px; padding: 18px 22px; background: var(--cn-bg); border: 1px solid var(--cn-border); border-radius: var(--cn-radius); }
.needs__label { margin: 0; font-family: var(--cn-font-head); font-weight: 700; font-size: 16px; color: var(--cn-white); }
.needs__list { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 10px 12px; }
.needs__list li { display: inline-flex; align-items: center; gap: 9px; padding: 8px 14px 8px 11px; border: 1px solid var(--cn-border-2); border-radius: 999px; font-size: 15px; line-height: 1.3; color: var(--cn-text); }
.icon.needs__check { width: 13px; height: 13px; color: var(--cn-red); }
@media (max-width: 639px) { .needs, .needs__list { flex-direction: column; align-items: flex-start; } }

/* « Pourquoi moi », bloc commun aux deux pages : trois faits numérotés à
   gauche, une seule photo 4:3 à droite, légende discrète. */
#pourquoi-moi .split { margin-top: 24px; }
.facts-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 26px; }
.fact { display: grid; gap: 10px; }
.fact__num { font-family: var(--cn-font-mono); font-size: 13px; font-weight: 700; color: var(--cn-red); }
.fact p { margin: 0; font-size: 16.5px; line-height: 1.55; }
.photo { display: grid; align-content: start; gap: 10px; margin: 0; }
.photo img { width: 100%; aspect-ratio: 4 / 3; object-fit: cover; border: 1px solid var(--cn-border); border-radius: var(--cn-radius); }
.photo--conference img { object-position: 32% 50%; }
.photo figcaption { font-size: 12.5px; line-height: 1.5; color: var(--cn-muted); }

/* Bloc 9 : titre, texte et bouton à gauche, l'objection à droite ; en mobile
   l'objection passe avant le bouton. Quatre enfants, deux ordres, un bouton. */
.final { display: grid; gap: 22px; grid-template-areas: "title" "text" "objection" "cta"; }
@media (min-width: 860px) {
  .final {
    grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
    grid-template-rows: auto auto 1fr;
    column-gap: 56px;
    grid-template-areas: "title objection" "text objection" "cta objection";
    align-items: start;
  }
}
.final__title { grid-area: title; margin: 0; }
.final__text { grid-area: text; margin: 0; }
.final__objection { grid-area: objection; }
.final__cta { grid-area: cta; margin-top: 6px; }

/* ------------------------------------------ 12b. Icônes (sprite SVG local) */
/* Monochromes : elles héritent de la couleur du contexte via `currentColor`,
   donc elles restent dans la charte partout. Aucune bibliothèque d'icônes,
   aucune ressource externe — un sprite local, et rien d'autre. */

.icon {
  width: 1.25em;
  height: 1.25em;
  fill: currentColor;
  display: inline-block;
  vertical-align: -0.15em;
  flex: none;
}

/* Libellé lu par les lecteurs d'écran quand l'icône seule porte le lien. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* --------------------------------------------- 12c. Encadré de mise en garde
   Sert la distinction « je ne détecte pas des attaques » : sans elle, tout le
   monde comprend « encore de la détection ». */

.callout {
  margin: clamp(24px, 3.5vw, 34px) 0;
  background: var(--cn-surface);
  border: 1px solid var(--cn-border-2);
  border-left: 3px solid var(--cn-red);
  border-radius: var(--cn-radius);
  padding: clamp(18px, 2.6vw, 26px);
  max-width: 46rem;
}
.callout h3 { margin-bottom: 0.4em; }
.callout p { margin-bottom: 0.8em; }
.callout p:last-child { margin-bottom: 0; }

/* -------------------------------------------------------------- 13. Pied de page
   v3 : le bloc de contact des pages hors /contact.
   Trois colonnes : me contacter, ressources, me suivre. */

.site-footer {
  background: var(--cn-bg);
  border-top: 1px solid var(--cn-border);
  padding-block: clamp(40px, 5vw, 56px) clamp(32px, 4vw, 40px);
}
.site-footer__inner { display: grid; gap: 26px; }
.site-footer__cols { display: flex; flex-wrap: wrap; gap: 24px 48px; align-items: flex-start; }
.site-footer__col { display: grid; gap: 10px; }
.site-footer__label {
  font-family: var(--cn-font-mono);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--cn-muted);
}

/* Tuiles : cible tactile de 44px, icône seule ou icône + nom. */
.tile-row { display: flex; flex-wrap: wrap; gap: 10px; }
.tile {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-width: 44px;
  height: 44px;
  padding: 0 12px;
  border: 1px solid var(--cn-border);
  border-radius: var(--cn-radius);
  background: var(--cn-surface);
  color: var(--cn-text);
  font-size: 0.9rem;
  transition: border-color .2s ease, color .2s ease, transform .2s ease;
}
.tile:hover { border-color: var(--cn-red); color: var(--cn-white); transform: translateY(-2px); }
.tile .icon { width: 20px; height: 20px; }
.tile--label { padding: 0 14px; }

/* Mention légale : la ligne est atténuée, le lien remonte au texte courant. */
.site-footer__legal { margin: 6px 0 0; font-size: 0.92rem; color: var(--cn-muted); }
.site-footer__legal a { color: var(--cn-text); }
.site-footer__legal a:hover { color: var(--cn-white); }

/* Pied allégé (/contact) : la page EST le contact, le pied ne le répète pas.
   Même ligne légale que le pied complet (fragment CN:LEGAL, O8). */
.site-footer--lite { padding-block: 22px; }
.site-footer--lite .site-footer__inner { display: flex; align-items: center; justify-content: space-between; gap: 16px; flex-wrap: wrap; }
.site-footer--lite .site-footer__legal { margin: 0; }
@media (max-width: 899px) {
  .site-footer--lite { padding-block: 16px; }
  .site-footer--lite .site-footer__inner { justify-content: center; text-align: center; }
  .site-footer--lite .wordmark { display: none; }
}

/* ---------------------------------------------------------- 14. Page /contact
   Maquette validée par Samy le 2026-10-26 (v3). Un seul écran : le body est une
   grille en-tête / contenu / pied sur la hauteur de la fenêtre, le contenu centré.
   Desktop (≥ 900px) : la fiche dans un cadre, photo 5 / carte 7 ; les lignes de
   canal, les tuiles et la photo passent sur le fond de page pour rester en
   relief. Mobile : pas de cadre, photo ronde en tête. */
body[data-page="contact"] { min-height: 100vh; min-height: 100dvh; display: grid; grid-template-rows: auto 1fr auto; }
.contact-page { display: grid; align-content: center; padding-block: clamp(24px, 4vh, 48px); }
.contact-sheet { display: grid; gap: clamp(28px, 5vw, 64px); align-items: center; }
.contact-sheet__photo { margin: 0; justify-self: center; width: min(100%, 380px); }
.contact-sheet__photo img { width: 100%; aspect-ratio: 1; object-fit: cover; border-radius: var(--cn-radius-lg); border: 1px solid var(--cn-border); }
.contact-card { display: grid; gap: 22px; min-width: 0; }
.contact-card__head { display: grid; gap: 10px; }
.contact-card__head .eyebrow { margin: 0; }
.contact-card h1 { font-size: clamp(2.06rem, 4.2vw, 2.875rem); margin: 0; }
.contact-card__role { font-family: var(--cn-font-mono); font-size: 0.75rem; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase; color: var(--cn-muted); margin: 0; }
/* Les trois canaux : une ligne cliquable entière, icône + libellé + identifiant visible. */
.channels { display: grid; gap: 10px; list-style: none; margin: 0; padding: 0; max-width: 34rem; }
.channel { display: flex; align-items: center; gap: 14px; min-height: 60px; padding: 12px 16px; border: 1px solid var(--cn-border); border-radius: var(--cn-radius); background: var(--cn-surface); color: var(--cn-text); transition: border-color .2s ease, background-color .2s ease; }
.channel:hover { border-color: var(--cn-border-2); background: var(--cn-input); }
.channel__icon { flex: none; width: 40px; height: 40px; display: inline-flex; align-items: center; justify-content: center; border-radius: 10px; background: var(--cn-bg); color: var(--cn-red); }
.channel__icon .icon { width: 20px; height: 20px; }
.channel__text { display: grid; gap: 1px; min-width: 0; line-height: 1.3; }
.channel__label { font-family: var(--cn-font-head); font-weight: 700; font-size: 0.86rem; color: var(--cn-white); }
.channel__value { font-family: var(--cn-font-mono); font-size: 0.78rem; color: var(--cn-muted); overflow-wrap: anywhere; }
.channel__arrow { margin-left: auto; font-family: var(--cn-font-mono); font-size: 0.83rem; color: var(--cn-muted); }
/* Ressources et réseaux : les tuiles du pied de page (.tile), les mêmes libellés. */
.contact-card__groups { display: flex; flex-wrap: wrap; gap: 36px; }
.contact-group { display: grid; gap: 10px; }
.contact-group__label { font-family: var(--cn-font-mono); font-size: 0.72rem; font-weight: 700; letter-spacing: 0.14em; text-transform: uppercase; color: var(--cn-muted); }
@media (min-width: 900px) {
  .contact-sheet { grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); max-width: 1000px; margin-inline: auto; padding: clamp(28px, 3.5vw, 44px); background: var(--cn-surface); border: 1px solid var(--cn-border); border-radius: var(--cn-radius-lg); }
  .contact-sheet .channel, .contact-sheet .tile, .contact-sheet__photo img { background: var(--cn-bg); }
  .contact-sheet .channel:hover { background: var(--cn-input); }
  .contact-sheet .channel__icon { background: var(--cn-surface); }
}
@media (max-width: 899px) {
  .contact-page { padding-block: 22px 20px; align-content: start; }
  .contact-sheet { gap: 18px; }
  .contact-sheet__photo { width: 128px; }
  .contact-sheet__photo img { border-radius: 50%; }
  .contact-card { gap: 16px; justify-items: start; }
  .contact-card__head { gap: 6px; }
  .contact-card h1 { font-size: 1.9rem; }
  .channels { gap: 8px; width: 100%; }
  .channel { min-height: 54px; padding: 10px 14px; }
  .channel__icon { width: 36px; height: 36px; }
  .channel__arrow { display: none; }
  .contact-card__groups { gap: 20px 36px; }
}

/* --------------------------- 15. Pages de document (/privacy, /404) */

.doc { padding-block: clamp(48px, 7vw, 88px); }
.doc h2 { font-size: clamp(1.15rem, 3vw, 1.4rem); margin-top: 2em; }
.doc ul { color: var(--cn-muted); padding-left: 1.2em; }
.doc li { margin-bottom: 0.5em; }

/* Version et date d'entrée en vigueur : des conditions générales sans version
   sont difficiles à opposer, faute de pouvoir prouver laquelle a été acceptée.
   (page CG retirée le 2026-10-26, règle conservée jusqu'au balayage CSS) */
.doc__meta {
  display: grid;
  gap: 6px;
  background: var(--cn-surface);
  border: 1px solid var(--cn-border-2);
  border-left: 3px solid var(--cn-red);
  border-radius: var(--cn-radius);
  padding: 16px 20px;
  margin-bottom: 2em;
  font-family: var(--cn-font-mono);
  font-size: 0.88rem;
  color: var(--cn-muted);
}
.doc__meta strong { font-family: var(--cn-font-body); }
.doc__meta a { color: var(--cn-muted); }
.doc__meta a:hover { color: var(--cn-white); }

/* --------------------------------------------------- 16. Révélation au défilement
   Masqué UNIQUEMENT si <html class="js"> — posé par un script en ligne dans le
   head. Sans JavaScript, rien n'est masqué et la page reste entièrement lisible. */

.js .reveal {
  opacity: 0;
  transform: translateY(30px);
  transition: opacity 0.7s ease, transform 0.7s ease;
}
.js .reveal.revealed { opacity: 1; transform: translateY(0); }

/* ----------------------------------------- 17. Accessibilité & mouvement réduit */

:focus-visible { outline: 2px solid var(--cn-red); outline-offset: 3px; border-radius: 4px; }
::selection { background: var(--cn-red); color: var(--cn-white); }

.skip-link {
  position: absolute;
  left: -9999px;
  top: 8px;
  z-index: 100;
  background: var(--cn-red);
  color: var(--cn-white);
  padding: 10px 16px;
  border-radius: var(--cn-radius);
  font-family: var(--cn-font-head);
  font-weight: 700;
  text-decoration: none;
}
.skip-link:focus { left: 12px; color: var(--cn-white); }

::-webkit-scrollbar { width: 8px; }
::-webkit-scrollbar-track { background: var(--cn-bg); }
::-webkit-scrollbar-thumb { background: var(--cn-border); border-radius: 4px; }
::-webkit-scrollbar-thumb:hover { background: var(--cn-border-2); }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .parrot-float,
  .bubble-pop { animation: none; }
  .js .reveal { opacity: 1; transform: none; transition: none; }
  .cases__track { scroll-behavior: auto; }
  .cases__dot { transition: none; }
  .btn:hover,
  .offer-card:hover,
  .tile:hover { transform: none; }
  *, *::before, *::after { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; }
}


/* ---------------------------------------- 18. Formulaire (/inventaire-gratuit)
   Le parcours « inventaire gratuit » en quatre écrans : colonne, jauge, écrans,
   champs, choix, champ répétable, avis. L'écran 4 a sa section (19).
   Repris de la maquette alignée par Samy le 2026-10-26. */

/* Une colonne de lecture centrée : un formulaire se remplit de haut en bas,
   le regard ne doit rien chercher à droite. 40rem = ~70 caractères. */
.journey { padding-block: clamp(32px, 5vw, 56px) clamp(48px, 7vw, 80px); }
.journey__col { max-width: 40rem; margin-inline: auto; display: grid; gap: clamp(24px, 3.5vw, 32px); }

/* L'en-tête du parcours : le nom de la page en œil-de-perdrix, et la jauge. */
.journey__head { display: grid; gap: 14px; }
.journey__head .eyebrow { margin: 0; display: flex; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.journey__head .eyebrow .step-count { color: var(--cn-muted); letter-spacing: 0.12em; }

/* La jauge : quatre segments, les noms des écrans sous chacun dès 600px.
   Fait = rouge, en cours = rouge + nom en blanc, à venir = gris. */
.stepper { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; }
.stepper__step { display: grid; gap: 8px; }
.stepper__bar { display: block; height: 4px; border-radius: 2px; background: var(--cn-border-2); }
.stepper__name { font-family: var(--cn-font-mono); font-size: 0.78rem; line-height: 1.3; color: var(--cn-faint); }
.stepper__step[data-state="done"] .stepper__bar,
.stepper__step[data-state="current"] .stepper__bar { background: var(--cn-red); }
.stepper__step[data-state="done"] .stepper__name { color: var(--cn-muted); }
.stepper__step[data-state="current"] .stepper__name { color: var(--cn-white); font-weight: 700; }
@media (max-width: 599px) { .stepper__name { display: none; } .stepper__bar { height: 5px; } }
@media (min-width: 600px) { .journey__head .step-count { display: none; } }

/* Un écran : un titre, son texte, ses champs, sa rangée d'actions. */
.screen { display: grid; gap: clamp(20px, 3vw, 28px); }
.screen[hidden] { display: none; }
.screen__head { display: grid; gap: 14px; }
.screen__head h1 { margin: 0; font-size: clamp(1.7rem, 4vw, 2.4rem); max-width: 22ch; }
/* Le titre reçoit le focus à chaque changement d'écran (lecteurs d'écran) :
   pas d'anneau visible sur un titre, ce n'est pas une commande. */
.screen__head h1:focus { outline: none; }
.screen__text { margin: 0; font-size: clamp(1.02rem, 2vw, 1.08rem); color: var(--cn-text); max-width: 40rem; }
.screen__text--after { color: var(--cn-muted); }
/* Un nom de domaine dans la prose : le monospace du site, un fond qui fait
   écho au champ (« c'est ça que vous tapez »). */
.screen__text code { font-family: var(--cn-font-mono); font-size: 0.88em; color: var(--cn-white); background: var(--cn-input); border: 1px solid var(--cn-border); border-radius: 6px; padding: 1px 6px; white-space: nowrap; }
.screen__fields { display: grid; gap: 22px; }
.screen__actions { display: flex; align-items: center; gap: 8px 16px; flex-wrap: wrap; margin-top: 4px; }
@media (max-width: 599px) {
  .screen__actions { flex-direction: column; align-items: stretch; }
  .screen__actions .btn { width: 100%; }
}

/* Le champ : étiquette au-dessus (toujours visible), champ, aide, erreur.
   L'étiquette est plus proche de son champ que du champ suivant. */
.field { display: grid; gap: 8px; }
fieldset.field { display: block; border: 0; padding: 0; margin: 0; min-width: 0; }
fieldset.field > legend { padding: 0; margin: 0 0 8px; float: left; width: 100%; }
fieldset.field > .choices { clear: both; }
fieldset.field > .field__error { margin-top: 8px; }
.field__control { display: grid; grid-template-columns: 1fr auto; gap: 8px; align-items: center; }
.field__label { font-family: var(--cn-font-head); font-weight: 700; font-size: 0.98rem; color: var(--cn-white); line-height: 1.3; }
.field__req { color: var(--cn-red); margin-left: 2px; }
.field__opt { color: var(--cn-muted); font-family: var(--cn-font-body); font-weight: 400; font-size: 0.9rem; margin-left: 6px; }
.field__input {
  width: 100%; min-height: var(--cn-field-h); padding: 12px 16px;
  background: var(--cn-input); color: var(--cn-text); border: 1px solid var(--cn-field-border);
  border-radius: var(--cn-radius); font: inherit; font-size: 1rem; line-height: 1.4;
  transition: border-color .15s ease, box-shadow .15s ease;
}
.field__input::placeholder { color: var(--cn-faint); font-style: italic; }
.field__input:hover { border-color: var(--cn-muted); }
.field__input:focus { outline: none; border-color: var(--cn-field-focus); box-shadow: 0 0 0 1px var(--cn-field-focus); }
.field__input[aria-invalid="true"] { border-color: var(--cn-danger); box-shadow: 0 0 0 1px var(--cn-danger); }
.field__help { margin: 0; font-size: 0.9rem; font-style: italic; color: var(--cn-muted); }
.field__help a { color: var(--cn-text); text-decoration: underline; text-underline-offset: 3px; text-decoration-color: var(--cn-border-2); }
.field__help a:hover { color: var(--cn-white); text-decoration-color: var(--cn-red); }
.field__error { margin: 0; display: flex; gap: 8px; align-items: flex-start; font-size: 0.92rem; color: var(--cn-text); }
.field__error[hidden] { display: none; }
.field__error .icon { flex: none; width: 18px; height: 18px; margin-top: 3px; fill: var(--cn-danger); }
.field__row { display: grid; gap: 22px; }
@media (min-width: 600px) { .field__row { grid-template-columns: 1fr 1fr; } }

/* Téléphone international : le pays (select natif) et le numéro dans un
   seul groupe ; l'indicatif est affiché, pas tapé. */
.phone { display: grid; grid-template-columns: minmax(10rem, 12rem) 1fr; gap: 8px; }
.phone__country { padding-right: 36px; appearance: none; -webkit-appearance: none; background-image: url(/assets/img/select-arrow.svg); background-repeat: no-repeat; background-position: right 12px center; text-overflow: ellipsis; cursor: pointer; }
.phone__num { position: relative; }
.phone__dial { position: absolute; left: 16px; top: 50%; transform: translateY(-50%); font-family: var(--cn-font-mono); color: var(--cn-muted); pointer-events: none; }
.phone__num .field__input { padding-left: 64px; font-family: var(--cn-font-mono); letter-spacing: 0.02em; }
@media (max-width: 479px) { .phone { grid-template-columns: 1fr; } }

/* Choix unique : chaque option est une ligne entière, cliquable, lisible
   d'un coup. Les options sont des phrases : un menu déroulant les couperait. */
.choices { display: grid; gap: 8px; }
.choice {
  display: flex; align-items: center; gap: 14px; min-height: 52px; padding: 12px 16px;
  border: 1px solid var(--cn-border); border-radius: var(--cn-radius); background: var(--cn-surface);
  color: var(--cn-text); cursor: pointer; font-size: 1rem; line-height: 1.4;
  transition: border-color .15s ease, background-color .15s ease;
}
.choice:hover { border-color: var(--cn-muted); background: var(--cn-input); }
.choice input { flex: none; width: 20px; height: 20px; margin: 0; accent-color: var(--cn-red); cursor: pointer; }
.choice:has(input:checked) { border-color: var(--cn-red); background: rgba(181, 22, 0, 0.09); color: var(--cn-white); }
.choice:has(input:focus-visible) { outline: 2px solid var(--cn-field-focus); outline-offset: 2px; }
.choice input:focus-visible { outline: none; }
.choices[aria-invalid="true"] .choice { border-color: var(--cn-danger); }

/* Le champ répétable des noms de domaine : une ligne = un champ + Retirer. */
.domains { display: grid; gap: 10px; }
.domain-row .field { min-width: 0; }
.domain-row .btn--quiet { min-height: var(--cn-field-h); }
.domain-row--single .btn--quiet { display: none; }
.domain-row--single .field__control { grid-template-columns: 1fr; }
.domains__add { justify-self: start; margin-left: -12px; }

/* Avis sous la rangée d'actions : la panne du backend, inline, près du bouton. */
.notice {
  display: flex; gap: 12px; align-items: flex-start; padding: 16px 18px;
  border: 1px solid var(--cn-danger); border-left-width: 3px; border-radius: var(--cn-radius);
  background: var(--cn-surface); color: var(--cn-text); font-size: 0.98rem;
}
.notice[hidden] { display: none; }
.notice .icon { flex: none; width: 20px; height: 20px; margin-top: 4px; fill: var(--cn-danger); }
.notice p { margin: 0; }
.notice a { color: var(--cn-white); text-decoration: underline; text-underline-offset: 3px; }

.booking__foot { margin: 0; font-size: 0.92rem; color: var(--cn-muted); max-width: 40rem; }

/* Le titre d'écran reçoit le focus par script (tabindex=-1). */
.screen__head h1[tabindex] { outline: none; }

/* Piège à robots : hors écran, jamais vu ni atteint au clavier. */
.hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

/* Sans JavaScript, le backend renvoie vers #error (refus) ou vers #booking
   (succès) : l'avis de panne et l'écran 4 s'affichent par la cible d'ancre,
   l'écran 4 avec sa seule phrase de recours (.nojs, section 19).
   !important : la règle globale [hidden] l'est aussi. Sous JS, le script
   gère l'attribut hidden seul (la cible ne bouge pas avec l'historique). */
html:not(.js) #error:target { display: flex !important; }
html:not(.js) #booking:target { display: grid !important; }


/* ---------------------------------------- 19. Le créneau (écran 4, maison)
   Un sélecteur à la charte, sans rien d'incrusté : les jours qui ont des
   créneaux, les heures du jour choisi, le fuseau, un récapitulatif, un seul
   bouton. La colonne reste à 40rem comme les écrans 1 à 3. */

.booking, .booking__picker { display: grid; gap: clamp(20px, 3vw, 28px); }
.booking__group { display: grid; gap: 10px; }
.booking__legend { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 10px; }
.booking__legend .field__label { margin: 0; }
.booking__legend-when { font-size: 0.95rem; color: var(--cn-muted); }

/* Jours et heures : des choix uniques, donc des radios natives habillées,
   la même famille que .choice (surface, liseré, rouge quand coché). Le jour
   porte deux lignes (jour de semaine, date), l'heure une seule, en mono. */
/* Le legend du site est flotté (fieldset.field > legend) : la grille repasse dessous. */
.picks { display: grid; gap: 8px; clear: both; }
.picks--days { grid-template-columns: repeat(auto-fill, minmax(6rem, 1fr)); }
.picks--slots { grid-template-columns: repeat(auto-fill, minmax(5.5rem, 1fr)); }
.pick {
  position: relative; display: grid; align-content: center; justify-items: center; gap: 2px;
  min-height: 52px; padding: 8px 10px; text-align: center;
  border: 1px solid var(--cn-border); border-radius: var(--cn-radius); background: var(--cn-surface);
  color: var(--cn-text); cursor: pointer; line-height: 1.25;
  transition: border-color .15s ease, background-color .15s ease;
}
.pick input { position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; opacity: 0; cursor: pointer; }
.pick:hover { border-color: var(--cn-muted); background: var(--cn-input); }
/* Coché : liseré rouge doublé (forme), voile rouge, texte blanc en gras
   (poids) : trois indices, pas seulement la couleur. */
.pick:has(input:checked) { border-color: var(--cn-red); box-shadow: inset 0 0 0 1px var(--cn-red); background: rgba(181, 22, 0, 0.09); color: var(--cn-white); }
.pick:has(input:focus-visible) { outline: 2px solid var(--cn-field-focus); outline-offset: 2px; }
.pick--day .pick__dow { font-size: 0.82rem; color: var(--cn-muted); }
.pick--day .pick__date { font-family: var(--cn-font-head); font-weight: 700; font-size: 0.95rem; }
.pick:has(input:checked) .pick__dow { color: var(--cn-text); }
.pick--slot { font-family: var(--cn-font-mono); font-size: 1rem; letter-spacing: 0.02em; font-variant-numeric: tabular-nums; }
.pick--slot:has(input:checked) { font-weight: 700; }

/* Le fuseau : détecté dans le navigateur, modifiable, select natif. */
.tz { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 14px; }
.tz__label { font-size: 0.92rem; color: var(--cn-muted); }
.tz__select {
  width: auto; max-width: 100%; min-height: 44px; padding: 8px 40px 8px 14px; font-size: 0.95rem;
  appearance: none; -webkit-appearance: none; cursor: pointer; text-overflow: ellipsis;
  background-image: url(/assets/img/select-arrow.svg);
  background-repeat: no-repeat; background-position: right 12px center;
}

/* Le récapitulatif du choix, au-dessus du bouton : ce que le clic va réserver. */
.booking__pick { margin: 0; font-size: 1.02rem; color: var(--cn-text); }
.booking__pick strong { color: var(--cn-white); }
.booking__pick[hidden] { display: none; }

/* Chargement : des silhouettes à la place des jours et des heures. */
.skel { min-height: 52px; border: 1px solid var(--cn-border); border-radius: var(--cn-radius); background: var(--cn-surface); animation: skel 1.6s ease-in-out infinite; }
@keyframes skel { 50% { opacity: 0.5; } }
/* La règle globale du mouvement réduit raccourcit les animations à 0,01 ms :
   une boucle infinie clignoterait. Les silhouettes restent donc immobiles. */
@media (prefers-reduced-motion: reduce) { .skel { animation: none; } }
.booking__status { margin: 0; font-size: 0.95rem; color: var(--cn-muted); }

/* Avis calme (aucun créneau) : même objet que l'avis de panne, sans le rouge. */
.notice--calm { border-color: var(--cn-border-2); border-left-color: var(--cn-muted); }

/* Réservé : le résultat, encadré comme un objet fini, puis la suite en points. */
.booked {
  display: grid; gap: 14px; padding: clamp(20px, 3vw, 28px);
  border: 1px solid var(--cn-border-2); border-radius: var(--cn-radius-lg); background: var(--cn-surface);
}
.booked__head { display: flex; align-items: center; gap: 12px; }
.booked__icon { flex: none; width: 40px; height: 40px; border-radius: 50%; background: rgba(34, 197, 94, 0.14); display: grid; place-items: center; }
.booked__icon .icon { width: 18px; height: 18px; fill: var(--cn-green); }
.booked h2 { margin: 0; font-size: clamp(1.2rem, 2.6vw, 1.5rem); }
.booked h2:focus { outline: none; }
.booked__when { margin: 0; font-family: var(--cn-font-head); font-weight: 700; font-size: clamp(1.06rem, 2.2vw, 1.22rem); color: var(--cn-white); }
.booked__list { margin: 0; padding: 0; list-style: none; display: grid; gap: 10px; }
.booked__list li { position: relative; padding-left: 20px; }
.booked__list li::before { content: ""; position: absolute; left: 2px; top: 0.62em; width: 7px; height: 7px; border-radius: 50%; background: var(--cn-red); }
/* La note discrète sous les points : l'italique gris de .field__help (4,5:1 tenu sur la surface). */
.booked__note { margin: 4px 0 0; font-size: 0.9rem; font-style: italic; color: var(--cn-muted); }
.booked a { color: var(--cn-white); text-decoration: underline; text-underline-offset: 3px; }

/* Sans JavaScript (ou sans référence) : une phrase de recours, rien d'autre.
   Sous JS, le script la montre par .nojs--shown quand il n'a pas de référence. */
.nojs { margin: 0; max-width: 40rem; }
.nojs a { color: var(--cn-white); text-decoration: underline; text-underline-offset: 3px; }
.js .nojs:not(.nojs--shown) { display: none; }
html:not(.js) .booking { display: none; }
