@font-face{font-family:'Geist Variable';font-style:normal;font-display:swap;font-weight:100 900;src:url('fonts/geist-latin-wght-normal.woff2') format('woff2')}

/* Jenie — Color tokens
   System: neutral (white→near-black) + a single strong accent.
   Accent "Bleu Jenie" is a deep electric blue inspired by International Klein Blue —
   a distinctly French, premium reference. Confident, trustworthy, ownable.
   Defined in oklch for perceptual consistency across the scale. */

:root {
  /* ----- Base neutrals (very slight cool tint) ----- */
  --gray-0:   #ffffff;
  --gray-50:  oklch(0.985 0.001 264);
  --gray-100: oklch(0.970 0.002 264);
  --gray-150: oklch(0.952 0.003 264);
  --gray-200: oklch(0.928 0.004 264);
  --gray-300: oklch(0.888 0.005 264);
  --gray-400: oklch(0.760 0.007 264);
  --gray-500: oklch(0.612 0.009 264);
  --gray-600: oklch(0.500 0.010 264);
  --gray-700: oklch(0.398 0.009 264);
  --gray-800: oklch(0.278 0.008 264);
  --gray-900: oklch(0.205 0.007 264);
  --gray-950: oklch(0.145 0.006 264);
  --black:    oklch(0.135 0.006 264);
  --white:    #ffffff;

  /* ----- Accent · Bleu Jenie ----- */
  --accent-50:  oklch(0.972 0.013 264);
  --accent-100: oklch(0.936 0.034 264);
  --accent-200: oklch(0.874 0.069 264);
  --accent-300: oklch(0.788 0.118 264);
  --accent-400: oklch(0.676 0.176 264);
  --accent-500: oklch(0.560 0.214 264);  /* primary */
  --accent-600: oklch(0.498 0.214 264);  /* hover */
  --accent-700: oklch(0.438 0.190 264);  /* press */
  --accent-800: oklch(0.372 0.155 264);
  --accent-900: oklch(0.312 0.120 264);

  /* ----- Semantic status (muted, premium) ----- */
  --green-100: oklch(0.94 0.05 158);
  --green-500: oklch(0.640 0.150 158);
  --green-600: oklch(0.560 0.140 158);
  --amber-100: oklch(0.95 0.05 78);
  --amber-500: oklch(0.760 0.150 70);
  --amber-600: oklch(0.680 0.150 62);
  --red-100:   oklch(0.94 0.04 22);
  --red-500:   oklch(0.620 0.210 22);
  --red-600:   oklch(0.548 0.205 22);

  /* ================= Semantic aliases ================= */
  /* Surfaces */
  --surface-page:    var(--gray-50);
  --surface-card:    var(--gray-0);
  --surface-sunken:  var(--gray-100);
  --surface-inset:   var(--gray-150);
  --surface-inverse: var(--black);
  --surface-accent:  var(--accent-500);
  --surface-accent-subtle: var(--accent-50);
  /* Surface accent au survol (E17, BRIEF-43) : un cran plus soutenu que
     --surface-accent → bouton primaire qui « répond » au survol, contraste AA
     conservé (plus foncé = plus de contraste avec --text-on-accent blanc).
     Redéfini par chaque thème/DA (theme.ts) pour rester un cran sous SA surface. */
  --surface-accent-hover: var(--accent-600);
  /* Remplissage du bouton primaire — PILOTABLE par le Style Guide (preset
     « Gradient », BRIEF-51). Défaut = surface accent (aplat) → rendu inchangé ;
     le preset bascule sur --gradient-accent (conceptCssVars, scope client). */
  --btn-fill: var(--surface-accent);

  /* Text */
  --text-strong:  var(--gray-950);
  --text-body:    var(--gray-800);
  --text-muted:   var(--gray-600);
  --text-subtle:  var(--gray-500);
  --text-accent:  var(--accent-600);
  --text-on-accent: var(--white);
  --text-inverse: var(--gray-100);
  /* Texte MUTÉ sur surface inverse (footers sombres) — BRIEF-31. Dérivé du texte
     inverse vers la surface inverse → reste LISIBLE (AA) quelle que soit la
     clarté de la surface inverse du thème (un --text-subtle, pensé pour fond
     CLAIR, échouait sur un footer sombre peu contrasté). ⚠️ Redéclaré dans chaque
     scope de thème (piège var() imbriquée, cf. theme.ts) → capte le
     --text-inverse / --surface-inverse LOCAL. */
  --text-inverse-muted: color-mix(in oklch, var(--text-inverse) 72%, var(--surface-inverse));

  /* Médias (sections v2 à traitement propre, règle 7 du gabarit) */
  /* Voile posé sur les images de FOND — ISO variable Figma « Opacity/Neutral
     Darkest 40 » : le neutre le plus sombre à 40 %. Littéral = DÉFAUT du socle
     (bloc scopé aplati) ; sur le canvas, conceptCssVars RE-ÉMET ce token depuis
     les neutres DU CONCEPT (teinté marque) — idem --surface-media. */
  --overlay-scrim: color-mix(in oklch, oklch(0.145 0.006 264) 40%, transparent);
  /* Aplat « photo grise » : le placeholder plein cadre d'une image de fond
     absente (gris moyen, jamais sombre-sur-sombre). */
  --surface-media: var(--gray-400);

  /* Borders */
  --border-subtle:  oklch(0.928 0.004 264);
  --border-default: oklch(0.888 0.005 264);
  --border-strong:  oklch(0.760 0.007 264);
  --border-accent:  var(--accent-500);
  --ring-accent:    color-mix(in oklch, var(--accent-500) 35%, transparent);

  /* Dégradés sémantiques (BRIEF-30) — DÉFAUT PLAT (= surface unie). Chaque
     « système de DA » (couche thème, cf. theme.ts) les redéfinit en vrais
     dégradés oklch dérivés de la palette. Le défaut pointant vers une surface
     sémantique, le neutre et la DA d'exemple restent rigoureusement inchangés
     (rien ne casse) ; seuls les systèmes de DA introduisent un vrai dégradé. */
  --gradient-accent:  var(--surface-accent);
  --surface-gradient: var(--surface-inverse);

  /* Status aliases */
  --success: var(--green-600);
  --warning: var(--amber-600);
  --danger:  var(--red-600);
}

/* Jenie — Typography tokens
   One family, weight + size + tracking do the work. "Typographie forte":
   large display sizes, heavy weights, tight tracking. Geist for everything,
   Geist Mono for code / technical labels.

   Polices SELF-HOST (woff2 OFL via Fontsource, cf. fonts.css + main.tsx) →
   familles « *Variable » (un seul fichier couvre tous les poids). */

:root {
  /* Families (self-host Variable — souverain, zéro CDN) */
  --font-sans: 'Geist Variable', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --font-mono: 'Geist Mono Variable', ui-monospace, 'SF Mono', 'Menlo', monospace;

  /* Weights */
  --weight-light:    300;
  --weight-regular:  400;
  --weight-medium:   500;
  --weight-semibold: 600;
  --weight-bold:     700;
  --weight-black:    800;

  /* Multiplicateur d'échelle de type (Style Guide « Size » — Small/Regular/Large).
     Défaut 1 = aucun changement. Le moteur (`conceptCssVars`) le surcharge INLINE
     sur le scope `.jn-canvas` → seul l'aperçu/site client est mis à l'échelle, le
     chrome plateforme (:root = 1) reste intact. Chaque `--text-*` en dépend. */
  --type-scale: 1;

  /* Type scale (1.250 major-third-ish, tuned) — mis à l'échelle par --type-scale */
  --text-2xs: calc(0.6875rem * var(--type-scale));  /* 11px */
  --text-xs:  calc(0.75rem   * var(--type-scale));  /* 12px */
  --text-sm:  calc(0.8125rem * var(--type-scale));  /* 13px */
  --text-base:calc(0.9375rem * var(--type-scale));  /* 15px — UI default */
  --text-md:  calc(1rem      * var(--type-scale));  /* 16px */
  --text-lg:  calc(1.1875rem * var(--type-scale));  /* 19px */
  --text-xl:  calc(1.5rem    * var(--type-scale));  /* 24px */
  --text-2xl: calc(1.9375rem * var(--type-scale));  /* 31px */
  --text-3xl: calc(2.5rem    * var(--type-scale));  /* 40px */
  --text-4xl: calc(3.25rem   * var(--type-scale));  /* 52px */
  --text-5xl: calc(4.25rem   * var(--type-scale));  /* 68px */
  --text-6xl: calc(5.5rem    * var(--type-scale));  /* 88px */

  /* ── Échelle « bibliothèque v2 » (chantier sections — spec Figma Benjamin) ──
     Nom = rôle éditorial ; compagnon `-m` = valeur MOBILE de la maquette
     (bascule au seuil CQ.medium dans le CSS des sections v2). Suit
     `--type-scale` (levier DA) comme l'échelle historique, qui reste servie
     aux sections d'origine jusqu'à la fin de leur remplacement. */
  --heading-1:   calc(3.5rem   * var(--type-scale));  /* 56px */
  --heading-1-m: calc(2.5rem   * var(--type-scale));  /* 40px */
  --heading-2:   calc(3rem     * var(--type-scale));  /* 48px */
  --heading-2-m: calc(2.25rem  * var(--type-scale));  /* 36px */
  --heading-3:   calc(2.5rem   * var(--type-scale));  /* 40px */
  --heading-3-m: calc(2rem     * var(--type-scale));  /* 32px */
  --heading-4:   calc(2rem     * var(--type-scale));  /* 32px */
  --heading-4-m: calc(1.5rem   * var(--type-scale));  /* 24px */
  --heading-5:   calc(1.5rem   * var(--type-scale));  /* 24px */
  --heading-5-m: calc(1.25rem  * var(--type-scale));  /* 20px */
  --heading-6:   calc(1.25rem  * var(--type-scale));  /* 20px */
  --heading-6-m: calc(1.125rem * var(--type-scale));  /* 18px */
  --text-large:    calc(1.25rem  * var(--type-scale)); /* 20px */
  --text-large-m:  calc(1.125rem * var(--type-scale)); /* 18px */
  --text-medium:   calc(1.125rem * var(--type-scale)); /* 18px */
  --text-medium-m: calc(1rem     * var(--type-scale)); /* 16px */
  --text-regular:  calc(1rem     * var(--type-scale)); /* 16px */
  --text-small:    calc(0.875rem * var(--type-scale)); /* 14px */
  --text-tiny:     calc(0.75rem  * var(--type-scale)); /* 12px */

  /* Line heights */
  --leading-tight:   1.05;
  --leading-snug:    1.2;
  --leading-normal:  1.5;
  --leading-relaxed: 1.65;

  /* Letter spacing */
  --tracking-tighter: -0.04em;
  --tracking-tight:   -0.02em;
  --tracking-snug:    -0.01em;
  --tracking-normal:  0em;
  --tracking-wide:    0.02em;
  --tracking-caps:    0.06em;  /* uppercase eyebrows / labels */

  /* Semantic roles */
  --display-font:      var(--font-sans);
  --display-weight:    var(--weight-bold);
  --display-tracking:  var(--tracking-tighter);
  --display-leading:   var(--leading-tight);
  /* Transformation des titres (Style Guide « Style » → Uppercase). Défaut none =
     aucun changement ; surchargé par le moteur sur le scope client uniquement. */
  --display-transform: none;

  --heading-weight:    var(--weight-semibold);
  --heading-tracking:  var(--tracking-tight);

  --body-leading:      var(--leading-relaxed);
  --eyebrow-tracking:  var(--tracking-caps);
}

/* Jenie — Spacing tokens
   Base unit 4px. Generous whitespace is core to the brand — prefer larger steps. */

:root {
  /* Gamme d'espacement — nomenclature VALEUR (BRIEF-139) : le nom du token EST
     sa valeur en pixels, ISO avec les variables Figma « Spacer/space-N » de la
     bibliothèque V2 (correspondance 1:1, aucune conversion). Les VALEURS sont
     celles de la gamme historique, seuls les noms ont changé. */
  --space-0:   0;
  --space-4:   0.25rem;
  --space-8:   0.5rem;
  --space-12:  0.75rem;
  --space-16:  1rem;
  --space-20:  1.25rem;
  --space-24:  1.5rem;
  --space-32:  2rem;
  --space-40:  2.5rem;
  --space-48:  3rem;
  --space-64:  4rem;
  --space-80:  5rem;
  --space-96:  6rem;
  --space-128: 8rem;
  --space-160: 10rem;

  /* Layout — modèle « cap unique + gutter responsive » (BRIEF-26)
     ─────────────────────────────────────────────────────────────────────────
     Le CONTENU d'une section est plafonné par un cap unique `--container-max`,
     et c'est le `--gutter` (espacement des bords) qui crée la marge latérale :
     responsive de ~24px (mobile) à ~80px (desktop) → ~1280px de contenu sur un
     artboard 1440 (80px/côté). Premium, pas edge-to-edge, pas trop vide.

     Les caps `--container-sm/md/lg/xl` restent les caps de TEXTE étroits
     (longueur de ligne lisible) appliqués aux sous-titres/paragraphes/variantes
     centrées — on n'élargit QUE les sections/grilles, pas le texte courant.

     ⚠️ PIÈGE `cqi` (NON négociable) : `--gutter` est en `cqi`, qui se résout sur
     le CONTENEUR ANCÊTRE le plus proche (`container: jn-section / inline-size`,
     posé sur la RACINE de chaque section), PAS sur l'élément qui le consomme.
     → `padding-inline: var(--gutter)` doit donc être porté par un DESCENDANT de
     la racine (le wrapper interne `__inner`), JAMAIS par la racine elle-même
     (sinon `cqi` mesurerait un ancêtre, ou retomberait sur la fenêtre = perte
     de fidélité multi-device, cf. leçon W1-14 / payoff BRIEF-25). Jamais de
     `vw` ni de media query pour la largeur/le gutter : container queries only. */
  --container-sm:  640px;
  --container-md:  860px;
  --container-lg:  1080px;
  --container-xl:  1280px;
  --container-max: 1440px;                  /* plafond de CONTENU (cap unique) */
  --gutter:        clamp(1.5rem, 6cqi, 5rem); /* ~24px → ~80px, suit l'ARTBOARD (cqi), pas la fenêtre */

  /* ── Paddings de section « bibliothèque v2 » (chantier sections — spec Figma
     Benjamin). Contrat : le nom dit la valeur DESKTOP de référence, le
     compagnon `-m` porte la valeur MOBILE de la maquette (bascule CQ.medium
     dans le CSS des sections v2). Cohabite avec `--gutter`/`--section-y`
     (sections d'origine) jusqu'à la fin du remplacement par famille. */
  --padding-global:          4rem;    /* 64 — marge latérale des sections v2 */
  --padding-global-m:        1.25rem; /* 20 */
  --padding-section-large:   7rem;    /* 112 — vertical, sections majeures */
  --padding-section-large-m: 4rem;    /* 64 */
  --padding-section-medium:  5rem;    /* 80 */
  --padding-section-medium-m:3rem;    /* 48 */
  --padding-section-small:   3rem;    /* 48 */
  --padding-section-small-m: 2rem;    /* 32 */
  /* Largeur de colonne de CONTENU centrée (ISO Figma « Max Width/max-width-* ») :
     cap de lecture des heros/intros, plus étroit que --container-xl. */
  --max-width-large:         48rem;   /* 768 */
  --max-width-medium:        35rem;   /* 560 (ISO Figma « Max Width/max-width-medium », hero-04) */
  /* Hauteurs du CHROME v2 (navbar-01, BRIEF-148) : barre desktop / mobile,
     valeurs de la maquette (72 / 64). */
  --navbar-height:           4.5rem;  /* 72 */
  --navbar-height-m:         4rem;    /* 64 */

  /* Logo client (BRIEF-32) — slot NORMALISÉ : hauteur fixe, largeur libre (jamais
     étiré). Tokens dédiés → placement cohérent quel que soit le ratio/format. */
  --logo-height:    2rem;    /* 32px — hauteur normalisée navbar/footer */
  --logo-max-width: 12rem;   /* 192px — garde-fou pour les logos très larges */

  /* ⚠️ Token DÉFINI MAIS NON UTILISÉ : le rythme vertical des sections est posé
     EN DIRECT dans les composants (`padding-block: var(--space-80/24/16)`).
     `--section-y` ne pilote rien aujourd'hui — ne pas croire qu'il le fait.
     (Standardiser le rythme vertical sur ce token = candidat à un futur lot.) */
  --section-y:     var(--space-128);
}

/* Jenie — Radius tokens
   Soft, modern corners. Cards ~12–16px, controls ~8–10px, pills full. */

:root {
  --radius-xs:   4px;
  --radius-sm:   6px;
  --radius-md:   8px;
  --radius-lg:   10px;
  --radius-xl:   12px;
  --radius-2xl:  16px;
  --radius-3xl:  24px;
  --radius-full: 999px;

  /* Semantic */
  --radius-control: var(--radius-md);
  --radius-card:    var(--radius-xl);
  --radius-panel:   var(--radius-2xl);
  --radius-pill:    var(--radius-full);

  /* Rayon du bouton — PILOTABLE par le Style Guide (presets boutons, BRIEF-51).
     Défaut = rayon de contrôle → rendu actuel inchangé ; surchargé par le moteur
     (`conceptCssVars`) sur le scope client uniquement. */
  --btn-radius: var(--radius-control);
}

/* Jenie — Elevation tokens
   Restrained, premium shadows. Soft, low-spread, cool-tinted. Never harsh.
   Layering relies on borders + tiny shadows rather than heavy drop shadows. */

:root {
  /* Cool shadow color base */
  --shadow-color: 264 25% 12%;

  --shadow-xs:  0 1px 2px hsl(var(--shadow-color) / 0.05);
  --shadow-sm:  0 1px 2px hsl(var(--shadow-color) / 0.06),
                0 1px 1px hsl(var(--shadow-color) / 0.04);
  --shadow-md:  0 2px 4px hsl(var(--shadow-color) / 0.05),
                0 4px 12px hsl(var(--shadow-color) / 0.06);
  --shadow-lg:  0 4px 8px hsl(var(--shadow-color) / 0.05),
                0 12px 28px hsl(var(--shadow-color) / 0.09);
  --shadow-xl:  0 8px 16px hsl(var(--shadow-color) / 0.06),
                0 24px 56px hsl(var(--shadow-color) / 0.12);

  /* Focus ring */
  --ring-width: 3px;
  --shadow-focus: 0 0 0 var(--ring-width) var(--ring-accent);

  /* Hairline border used as 1px elevation */
  --border-hairline: 1px solid var(--border-subtle);

  /* Accent glow (sparing — primary CTA, AI-active states) */
  --glow-accent: 0 1px 2px hsl(var(--shadow-color) / 0.10),
                 0 8px 24px color-mix(in oklch, var(--accent-500) 28%, transparent);

  /* Ombre du bouton primaire — PILOTABLE par le Style Guide (presets boutons,
     BRIEF-51). Défaut = glow accent → rendu actuel inchangé ; le preset « Brick »
     la remplace par une ombre dure (conceptCssVars, scope client). */
  --btn-shadow: var(--glow-accent);
}

/* Jenie — Motion tokens
   Calm, confident, quick. Mostly opacity + small translate/scale. No bounce on UI.
   Easing favors a gentle ease-out; springy only for delightful AI-generation moments. */

:root {
  --ease-out:     cubic-bezier(0.22, 1, 0.36, 1);    /* @kind other */
  --ease-in-out:  cubic-bezier(0.65, 0, 0.35, 1);    /* @kind other */
  --ease-standard:cubic-bezier(0.4, 0, 0.2, 1);      /* @kind other */
  /* delight only — springy entrance for AI-generation moments */
  --ease-spring:  cubic-bezier(0.34, 1.56, 0.64, 1); /* @kind other */

  --dur-fast:   120ms;  /* @kind other */
  --dur-base:   180ms;  /* @kind other */
  --dur-slow:   280ms;  /* @kind other */
  --dur-slower: 480ms;  /* @kind other */

  --transition-control: color var(--dur-fast) var(--ease-out),
                        background-color var(--dur-fast) var(--ease-out),
                        border-color var(--dur-fast) var(--ease-out),
                        box-shadow var(--dur-fast) var(--ease-out),
                        transform var(--dur-fast) var(--ease-out);
}

/* Jenie — Base resets + element defaults.
   Light, opinionated baseline so any page picks up the brand voice immediately. */

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

html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }

body {
  margin: 0;
  font-family: var(--font-sans);
  font-size: var(--text-base);
  line-height: var(--body-leading);
  color: var(--text-body);
  background: var(--surface-page);
  font-feature-settings: 'cv01', 'ss01';
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

h1, h2, h3, h4 {
  margin: 0;
  color: var(--text-strong);
  font-weight: var(--heading-weight);
  letter-spacing: var(--heading-tracking);
  line-height: var(--leading-snug);
}
h1 { font-size: var(--text-3xl); letter-spacing: var(--tracking-tighter); line-height: var(--leading-tight); }
h2 { font-size: var(--text-2xl); }
h3 { font-size: var(--text-xl); }
h4 { font-size: var(--text-lg); }

p { margin: 0; }
a { color: var(--text-accent); text-decoration: none; }
a:hover { text-decoration: underline; text-underline-offset: 2px; }

code, kbd, samp, pre {
  font-family: var(--font-mono);
  font-size: 0.92em;
}

::selection {
  background: color-mix(in oklch, var(--accent-500) 22%, transparent);
  color: var(--text-strong);
}

/* Utility primitives */
/* Eyebrow/tagline ALIGNÉE sur la V2 Figma (« Heading/Tagline », décision
   Benjamin 16/7 — BRIEF-143) : 16 semibold, interligne 150 %, casse d'origine,
   couleur = rôle Texte fort. */
.jn-eyebrow {
  font-size: var(--text-regular);
  font-weight: var(--weight-semibold);
  line-height: var(--leading-normal);
  letter-spacing: var(--tracking-normal);
  color: var(--text-strong);
}
.jn-mono-label {
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--text-subtle);
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: 0.001ms !important; transition-duration: 0.001ms !important; }
}

.jn-canvas {
  font-family: var(--font-sans);
  font-size: var(--text-base);
  line-height: var(--body-leading);
  color: var(--text-body);
  background: var(--surface-page);
  text-align: left;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}
.jn-canvas *,
.jn-canvas *::before,
.jn-canvas *::after { box-sizing: border-box; }
.jn-canvas h1,
.jn-canvas h2,
.jn-canvas h3,
.jn-canvas h4,
.jn-canvas p,
.jn-canvas figure,
.jn-canvas ul,
.jn-canvas ol { margin: var(--space-0); }
.jn-canvas ul,
.jn-canvas ol { padding: var(--space-0); list-style: none; }
.jn-canvas a { color: inherit; text-decoration: none; }
.jn-canvas img { display: block; max-width: 100%; height: auto; }
.jn-canvas button { font: inherit; cursor: pointer; }
/* Wrapper de RYTHME par section (B-SG-4b, SG-8) : le build/showcase enveloppe
   chaque section dans .jn-section portant les tokens de son schéma INLINE
   (conceptCssVars(concept, mode, scheme)). Bande PLEINE LARGEUR : un fond de
   repli au cas où une section ne peindrait pas son propre --surface-page
   (les sections actuelles le font déjà). Sans Concept, aucun .jn-section n'est
   émis -> comportement legacy inchangé.
   ⚠️ La bande est AUSSI un conteneur de requête nommé (BRIEF-140) : les règles
   @container posées sur la RACINE d'un composant (padding-block/min-height
   mobiles des sections v2) s'évaluent contre l'ANCÊTRE — la racine étant
   elle-même le conteneur de ses descendants, sans ceci elles ne matchaient
   JAMAIS. Même nom que les racines : les descendants continuent de mesurer la
   racine (plus proche), la racine mesure la bande (même largeur).
   B167 lot C ; « l'enveloppe peint, la section laisse voir » : quand une bande
   porte un traitement de surface non-aplat, le moteur émet le fond (dégradé/
   glow) dans --band-bg au wrapper et --surface-page: transparent → la racine de
   section laisse voir l'enveloppe. Sans --band-bg (legacy), repli inchangé sur
   --surface-page. Même règle côté canvas web et build (feuille partagée). */
.jn-canvas .jn-section { display: block; background: var(--band-bg, var(--surface-page)); container: jn-section / inline-size; }

.jn-canvas .jn-section {
  /* Wrapper de schéma (BRIEF-53/60) = bande PLEINE LARGEUR : il porte le FOND et le
     texte du schéma (tokens inline), rien d'autre. Le PADDING (rythme vertical +
     gutter) appartient au COMPOSANT (.jn-c-X et son __inner) : le poser AUSSI ici
     doublait le padding (navbar/hero/footer décalés — régression visuelle pré-B60).
     Le display:block + fond de repli vivent dans le RESET (scope.ts).
     B167 lot C : même mécanique d'enveloppe que le RESET ; --band-bg (traitement
     de surface émis par le moteur) prime, repli legacy sur --surface-page. */
  background: var(--band-bg, var(--surface-page));
  color: var(--text-body);
}
.jn-canvas .jn-section--sunken { background: var(--surface-sunken); }
.jn-canvas .jn-section--inverse { background: var(--surface-inverse); color: var(--text-inverse); }
.jn-canvas .jn-section--accent { background: var(--surface-accent); color: var(--text-on-accent); }

/* Wrapper interne de section : plafonne le contenu (cap unique --container-max)
   et porte le gutter responsive (cqi). Posé sur un DESCENDANT de la racine-
   conteneur → le cqi du gutter mesure bien la largeur d'artboard (cf. spacing.css). */
.jn-canvas .jn-container { max-width: var(--container-max); margin-inline: auto; padding-inline: var(--gutter); }
.jn-canvas .jn-container--narrow { max-width: var(--container-md); } /* cap TEXTE étroit (lisibilité) */

/* --- Bibliothèque V2 (chantier sections) — règles HISSÉES (BRIEF-149) -------
   Wrapper interne des modules V2 : plafonne le contenu au conteneur 1280
   (--container-xl) SANS avaler les gutters — box-sizing oblige, le calc()
   ajoute les deux paddings au cap, sinon le contenu ferait 1152 au lieu des
   1280 maquette (bug corrigé au B142). Centre, et porte le gutter global
   (--padding-global, valeur -m en mobile). La RACINE du module garde le fond
   pleine largeur + le padding VERTICAL (piège cqi, cf. spacing.css).
   Chaque module V2 pose « jn-inner » sur son wrapper, à côté de sa classe
   « jn-c-<clé>__inner » qui ne garde que ses spécificités (position, width…). */
.jn-canvas .jn-inner { max-width: calc(var(--container-xl) + var(--padding-global) * 2); margin-inline: auto; padding-inline: var(--padding-global); }

/* Titre de SECTION V2 = style Figma « Heading/H2 » (protocole de passation §2).
   Partagé par les modules dont le titre ouvre une section de page (balise h2,
   règle 3.6 « balise ≠ style »). Les heros (h1) gardent le style display. */
.jn-canvas .jn-sectitle {
  font-size: var(--heading-2);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-tight);
  line-height: var(--leading-snug);
  color: var(--text-strong);
}

/* Robustesse typographique (calibrage 27/7 — retour Benjamin : un mot long
   déborde de sa carte). Tout titre casse PROPREMENT : filet overflow-wrap
   (n'agit que si le mot ne tient vraiment pas), et les titres de niveau ITEM
   (h3 : cartes, colonnes étroites) césurent à la française avec trait d'union
   (hyphens ; le document porte lang="fr"). Jamais de débordement, jamais de
   coupe brute sans tiret. */
.jn-canvas h1, .jn-canvas h2, .jn-canvas h3, .jn-canvas h4 { overflow-wrap: break-word; }
.jn-canvas h3 { hyphens: auto; }

/* Valeurs MOBILES des règles V2 hissées (variante Mobile de la maquette). */
@container jn-section (max-width: 48rem) {
  .jn-canvas .jn-inner { padding-inline: var(--padding-global-m); }
  .jn-canvas .jn-sectitle { font-size: var(--heading-2-m); }
}

/* Eyebrow/tagline ALIGNÉE sur la V2 Figma (style « Heading/Tagline », décision
   Benjamin 16/7 — BRIEF-143) : 16 semibold, interligne 150 %, casse d'origine,
   couleur = rôle Texte. (Avant : petites capitales accentuées.) */
.jn-canvas .jn-eyebrow {
  display: block;
  font-size: var(--text-regular);
  font-weight: var(--weight-semibold);
  line-height: var(--leading-normal);
  letter-spacing: var(--tracking-normal);
  color: var(--text-strong);
}

/* Police des TITRES = --display-font (BRIEF-30). Défaut = var(--font-sans) (cf.
   typography.css) → aucun changement aujourd'hui ; un système de DA peut basculer
   les titres sur une autre stack DISPONIBLE (ex. serif premium) sans toucher au
   HTML. Couvre toutes les sections (titres = vraies balises h1–h4).
   --display-stretch (BRIEF-199) : chasse des titres (axe wdth des fichiers
   variables, ex. Archivo Expanded à 125 %) ; défaut 100 % = valeur initiale
   CSS → aucun changement pour les paires qui ne la déclarent pas. */
.jn-canvas h1, .jn-canvas h2, .jn-canvas h3, .jn-canvas h4 { font-family: var(--display-font); font-stretch: var(--display-stretch, 100%); text-transform: var(--display-transform); }

.jn-canvas .jn-title {
  font-size: var(--text-2xl);
  font-weight: var(--display-weight);
  letter-spacing: var(--display-tracking);
  line-height: var(--display-leading);
  color: var(--text-strong);
}
.jn-canvas .jn-title--xl { font-size: var(--text-4xl); }
.jn-canvas .jn-lead {
  font-size: var(--text-lg);
  line-height: var(--leading-relaxed);
  color: var(--text-muted);
}

/* Rayon / remplissage / ombre du bouton = TOKENS PILOTABLES par le Style Guide
   (presets UI Styling : Default · Bubble · Brick · Gradient — BRIEF-51). Les
   fallbacks reproduisent EXACTEMENT le comportement actuel → zéro régression tant
   qu'un Concept ne les surcharge pas (posés par conceptCssVars, DS « B »). */
.jn-canvas .jn-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-12);
  padding: var(--space-12) var(--space-24);
  border-radius: var(--btn-radius);
  font-size: var(--text-regular);
  font-weight: var(--weight-regular);
  letter-spacing: var(--tracking-normal);
  border: var(--border-hairline);
  transition: var(--transition-control);
}
/* Spec Bouton V2 (BRIEF-138, composant Figma Benjamin — protocole de passation) :
   texte 16 normal · padding 12/24 (small 12/16, icône seule 12) · bordure 1px
   sur TOUTES les variantes, couleur du FOND sur la primaire (règle « bordure =
   fond », les hovers ne font jamais sauter la mise en page). */
.jn-canvas .jn-btn--primary {
  background: var(--btn-fill);
  /* B167 lot C (point 12) : le texte de BOUTON est dédoublé du texte de carte
     accent ; --btn-text (résolu contre --surface-accent) n'est émis que quand un
     traitement de surface re-pointe --text-on-accent vers le dégradé réel ;
     repli = comportement historique, rendu legacy identique. */
  color: var(--btn-text, var(--text-on-accent));
  border-color: var(--btn-fill);
  box-shadow: var(--btn-shadow);
}
.jn-canvas .jn-btn--secondary {
  background: transparent;
  color: var(--text-strong);
  border-color: var(--border-default);
}
.jn-canvas .jn-btn--ghost {
  background: transparent;
  color: var(--text-strong);
  border-color: transparent;
}
/* Style=Link (spec V2, revue Benjamin 16/7) : lien d'action nu — zéro padding,
   zéro bordure, gap picto-texte = space-8 (SA valeur, modifiée le 16/7),
   chevron 24 « derrière » (Icon/chevron-right), texte = rôle Text du schéma. */
.jn-canvas .jn-btn--link {
  padding: 0;
  border: 0;
  background: transparent;
  gap: var(--space-8);
  color: var(--text-strong);
}
.jn-canvas .jn-btn--link .jn-btn__icon { width: var(--space-24); height: var(--space-24); flex: none; }
.jn-canvas .jn-btn--small { padding: var(--space-12) var(--space-16); }
.jn-canvas .jn-btn--icon-only { padding: var(--space-12); }
.jn-canvas .jn-btn--small.jn-btn--icon-only { padding: var(--space-8); }
/* Valeurs MOBILES de la maquette (modes des spacers V2) — bascule commune.
   (Le Link est identique aux deux tailles : padding 0 réaffirmé.) */
@container jn-section (max-width: 48rem) {
  .jn-canvas .jn-btn { padding: var(--space-8) var(--space-20); gap: var(--space-8); }
  .jn-canvas .jn-btn--small { padding: var(--space-8) var(--space-12); }
  .jn-canvas .jn-btn--icon-only, .jn-canvas .jn-btn--small.jn-btn--icon-only { padding: var(--space-8); }
  .jn-canvas .jn-btn--link { padding: 0; }
}
/* États interactifs (E17, BRIEF-43). La transition est déjà déclarée ci-dessus.
   Tokens DS uniquement (test no-hardcode) ; contraste AA conservé dans tous les
   systèmes DA. Hover = la surface « répond » (accent plus soutenu / réaction de
   surface / léger lift) ; focus-visible = anneau accent net (a11y clavier).
   S'applique éditeur ET site publié (CSS de composant partagé). */
.jn-canvas .jn-btn--primary:hover {
  background: var(--surface-accent-hover);
  border-color: var(--surface-accent-hover);
  box-shadow: var(--glow-accent), var(--shadow-md);
}
.jn-canvas .jn-btn--secondary:hover {
  background: var(--surface-sunken);
  border-color: var(--border-strong);
}
.jn-canvas .jn-btn--ghost:hover {
  background: var(--surface-accent-subtle);
}
/* Link : pas de surface qui répond (il n'en a pas) — le texte prend l'accent.
   Défaut moteur en attendant la passe d'états Figma de Benjamin. */
.jn-canvas .jn-btn--link:hover {
  background: transparent;
  color: var(--text-accent);
}
.jn-canvas .jn-btn:focus-visible {
  outline: none;
  box-shadow: var(--shadow-focus);
}

.jn-canvas .jn-link {
  display: inline-flex;
  align-items: center;
  gap: var(--space-4);
  color: var(--text-accent);
  font-weight: var(--weight-medium);
}

.jn-canvas .jn-ph {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  aspect-ratio: 16 / 10;
  border-radius: var(--radius-card);
  background: var(--surface-sunken);
  border: var(--border-hairline);
  color: var(--text-subtle);
}
.jn-canvas .jn-ph--square { aspect-ratio: 1 / 1; }
.jn-canvas .jn-ph--tall { aspect-ratio: 4 / 5; }
.jn-canvas .jn-ph--wide-flat { aspect-ratio: 16 / 7; }
.jn-canvas .jn-ph--round { border-radius: var(--radius-pill); }
.jn-canvas .jn-ph__icon { width: var(--space-40); height: var(--space-40); opacity: 0.5; }
/* Ajustement d'image (E2, BRIEF-42) : posé sur l'image reelle (le placeholder div
   n'a pas de contenu remplacable). cover recadre pour remplir, contain montre
   l'image entiere sans rogner. */
.jn-canvas img.jn-ph--fit-cover { object-fit: cover; }
.jn-canvas img.jn-ph--fit-contain { object-fit: contain; }

/* Logo client = placeholder wordmark Jenie mono (BRIEF-28, W2-9) : la VRAIE marque
   officielle = glyphe « J » (JenieMark) + « enie » (aligné sur JenieWordmark : Geist
   Bold, tracking serré), en une teinte discrète → mur de logos cohérent, jamais de
   faux logo tiers. currentColor → re-thématisable (neutre/DA). Le « enie » suit la
   cap-height du J (~1.27× ⇒ J = 0.79em du wordmark) ; alignement sur la ligne de base. */
.jn-canvas .jn-logo { display: inline-flex; align-items: baseline; color: var(--text-subtle); font-size: var(--text-xl); }
.jn-canvas .jn-logo__mark { height: 0.79em; width: auto; flex: none; }
.jn-canvas .jn-logo__name { font-weight: var(--weight-bold); letter-spacing: var(--tracking-tighter); }

/* Logo RÉEL du client (BRIEF-32) : slot NORMALISÉ — hauteur fixe (--logo-height),
   largeur libre plafonnée, ratio préservé (object-fit: contain) → JAMAIS étiré,
   quel que soit le format/ratio. Sur surface sombre (footer), le logo est posé sur
   une PASTILLE claire (jn-logo-chip) → toujours lisible, jamais invisible. */
.jn-canvas .jn-logo-img {
  display: block;
  height: var(--logo-height);
  width: auto;
  max-width: var(--logo-max-width);
  object-fit: contain;
}
/* BRIEF-226 (lot 3) : la pastille suit le token `--logo-chip-bg` émis par
   conceptCssVars sur les bandes profondes (fort/contraste/accent/pleine) —
   le NEUTRE LE PLUS CLAIR du Concept, réellement contrasté sur fond sombre
   (avant : `--surface-card`, la carte SOMBRE de la bande → pastille invisible,
   repro Elodie footer sombre + logo sombre). Bande claire : token absent →
   repli `--surface-card` = rendu strictement identique à avant. */
.jn-canvas .jn-logo-chip {
  display: inline-flex;
  align-items: center;
  background: var(--logo-chip-bg, var(--surface-card));
  padding: var(--space-8) var(--space-12);
  border-radius: var(--radius-md);
}

.jn-canvas {
  --surface-page: oklch(0.985 0.001 255);
  --surface-card: oklch(1 0 255);
  --surface-sunken: oklch(0.97 0.002 255);
  --surface-inset: oklch(0.952 0.003 255);
  --surface-inverse: oklch(0.145 0.005 255);
  --surface-accent: oklch(0.62 0.171 255);
  --surface-accent-subtle: oklch(0.975 0.012 255);
  --surface-accent-hover: oklch(0.69 0.166 255);
  --text-strong: oklch(0.145 0.005 255);
  --text-body: oklch(0.278 0.007 255);
  --text-muted: oklch(0.5 0.009 255);
  --text-subtle: oklch(0.5 0.009 255);
  --text-accent: oklch(0.5 0.158 255);
  --text-on-accent: oklch(0.145 0.005 255);
  --text-inverse: oklch(0.985 0.001 255);
  --text-inverse-muted: color-mix(in oklch, oklch(0.985 0.001 255) 72%, oklch(0.145 0.005 255));
  --overlay-scrim: color-mix(in oklch, oklch(0.145 0.005 255) 40%, transparent);
  --surface-media: oklch(0.612 0.008 255);
  --border-subtle: oklch(0.928 0.004 255);
  --border-default: oklch(0.888 0.004 255);
  --border-strong: oklch(0.64 0.006 255);
  --border-accent: oklch(0.5 0.158 255);
  --ring-accent: color-mix(in oklch, oklch(0.62 0.171 255) 35%, transparent);
  --glow-accent: 0 1px 2px hsl(var(--shadow-color) / 0.10), 0 8px 24px color-mix(in oklch, oklch(0.62 0.171 255) 28%, transparent);
  --gradient-accent: linear-gradient(135deg, oklch(0.62 0.171 255), oklch(0.395 0.13 255));
  --surface-gradient: oklch(0.145 0.005 255);
  --accent-500: oklch(0.62 0.171 255);
  --accent-600: oklch(0.5 0.158 255);
  --accent-700: oklch(0.395 0.13 255);
  --accent-800: oklch(0.275 0.091 255);
  --font-sans: 'Geist Variable', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --display-font: 'Geist Variable', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --type-scale: 1;
  --display-weight: 600;
  --display-tracking: var(--tracking-tighter);
  --display-leading: var(--leading-tight);
  --body-leading: var(--leading-relaxed);
  --display-transform: none;
  --btn-radius: var(--radius-control);
  --btn-fill: var(--surface-accent);
  --btn-shadow: var(--glow-accent);
  --radius-card: 8px;
  --radius-panel: 8px;
}
.jn-canvas .jn-scheme-1 {
  --surface-page: oklch(0.985 0.001 255);
  --surface-card: oklch(1 0 255);
  --surface-sunken: oklch(0.97 0.002 255);
  --surface-inset: oklch(0.952 0.003 255);
  --surface-inverse: oklch(0.145 0.005 255);
  --surface-accent: oklch(0.62 0.171 255);
  --surface-accent-subtle: oklch(0.975 0.012 255);
  --surface-accent-hover: oklch(0.69 0.166 255);
  --text-strong: oklch(0.145 0.005 255);
  --text-body: oklch(0.278 0.007 255);
  --text-muted: oklch(0.5 0.009 255);
  --text-subtle: oklch(0.5 0.009 255);
  --text-accent: oklch(0.5 0.158 255);
  --text-on-accent: oklch(0.145 0.005 255);
  --text-inverse: oklch(0.985 0.001 255);
  --text-inverse-muted: color-mix(in oklch, oklch(0.985 0.001 255) 72%, oklch(0.145 0.005 255));
  --overlay-scrim: color-mix(in oklch, oklch(0.145 0.005 255) 40%, transparent);
  --surface-media: oklch(0.612 0.008 255);
  --border-subtle: oklch(0.928 0.004 255);
  --border-default: oklch(0.888 0.004 255);
  --border-strong: oklch(0.64 0.006 255);
  --border-accent: oklch(0.5 0.158 255);
  --ring-accent: color-mix(in oklch, oklch(0.62 0.171 255) 35%, transparent);
  --glow-accent: 0 1px 2px hsl(var(--shadow-color) / 0.10), 0 8px 24px color-mix(in oklch, oklch(0.62 0.171 255) 28%, transparent);
  --gradient-accent: linear-gradient(135deg, oklch(0.62 0.171 255), oklch(0.395 0.13 255));
  --surface-gradient: oklch(0.145 0.005 255);
  --accent-500: oklch(0.62 0.171 255);
  --accent-600: oklch(0.5 0.158 255);
  --accent-700: oklch(0.395 0.13 255);
  --accent-800: oklch(0.275 0.091 255);
  --font-sans: 'Geist Variable', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --display-font: 'Geist Variable', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --type-scale: 1;
  --display-weight: 600;
  --display-tracking: var(--tracking-tighter);
  --display-leading: var(--leading-tight);
  --body-leading: var(--leading-relaxed);
  --display-transform: none;
  --btn-radius: var(--radius-control);
  --btn-fill: var(--surface-accent);
  --btn-shadow: var(--glow-accent);
  --radius-card: 8px;
  --radius-panel: 8px;
}
.jn-canvas .jn-scheme-2 {
  --hero-plein-sombre-bg: oklch(0.275 0.091 255);
  --hero-plein-sombre-tx: oklch(0.928 0.004 255);
  --hero-plein-sombre-title: oklch(0.985 0.001 255);
  --hero-plein-sombre-eyebrow: oklch(0.78 0.114 255);
  --logo-chip-bg: oklch(1 0 255);
  --logo-chip-pad: var(--space-4) var(--space-8);
  --logo-chip-radius: var(--radius-md);
  --surface-page: oklch(0.275 0.091 255);
  --surface-card: oklch(0.205 0.006 255);
  --surface-sunken: oklch(0.325 0.091 255);
  --surface-inset: oklch(0.205 0.006 255);
  --surface-inverse: oklch(0.145 0.005 255);
  --surface-accent: oklch(0.62 0.171 255);
  --surface-accent-subtle: oklch(0.275 0.091 255);
  --surface-accent-hover: oklch(0.69 0.166 255);
  --text-strong: oklch(0.985 0.001 255);
  --text-body: oklch(0.928 0.004 255);
  --text-muted: oklch(0.76 0.006 255);
  --text-subtle: oklch(0.76 0.006 255);
  --text-accent: oklch(0.78 0.114 255);
  --text-on-accent: oklch(0.145 0.005 255);
  --text-inverse: oklch(0.985 0.001 255);
  --text-inverse-muted: color-mix(in oklch, oklch(0.985 0.001 255) 72%, oklch(0.145 0.005 255));
  --overlay-scrim: color-mix(in oklch, oklch(0.145 0.005 255) 40%, transparent);
  --surface-media: oklch(0.612 0.008 255);
  --border-subtle: oklch(0.278 0.007 255);
  --border-default: oklch(0.398 0.008 255);
  --border-strong: oklch(0.56 0.009 255);
  --border-accent: oklch(0.5 0.158 255);
  --ring-accent: color-mix(in oklch, oklch(0.62 0.171 255) 35%, transparent);
  --glow-accent: none;
  --gradient-accent: linear-gradient(135deg, oklch(0.62 0.171 255), oklch(0.395 0.13 255));
  --surface-gradient: oklch(0.145 0.005 255);
  --accent-500: oklch(0.62 0.171 255);
  --accent-600: oklch(0.5 0.158 255);
  --accent-700: oklch(0.395 0.13 255);
  --accent-800: oklch(0.275 0.091 255);
  --font-sans: 'Geist Variable', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --display-font: 'Geist Variable', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --type-scale: 1;
  --display-weight: 600;
  --display-tracking: var(--tracking-tighter);
  --display-leading: var(--leading-tight);
  --body-leading: var(--leading-relaxed);
  --display-transform: none;
  --btn-radius: var(--radius-control);
  --btn-fill: var(--surface-accent);
  --btn-shadow: var(--glow-accent);
  --radius-card: 8px;
  --radius-panel: 8px;
}
.jn-canvas .jn-scheme-3 {
  --surface-page: oklch(0.975 0.012 285);
  --surface-card: oklch(1 0 255);
  --surface-sunken: oklch(0.925 0.012 285);
  --surface-inset: oklch(0.952 0.003 255);
  --surface-inverse: oklch(0.145 0.005 255);
  --surface-accent: oklch(0.62 0.171 255);
  --surface-accent-subtle: oklch(0.975 0.012 255);
  --surface-accent-hover: oklch(0.69 0.166 255);
  --text-strong: oklch(0.145 0.005 255);
  --text-body: oklch(0.278 0.007 255);
  --text-muted: oklch(0.5 0.009 255);
  --text-subtle: oklch(0.5 0.009 255);
  --text-accent: oklch(0.5 0.158 285);
  --text-on-accent: oklch(0.145 0.005 255);
  --text-inverse: oklch(0.985 0.001 255);
  --text-inverse-muted: color-mix(in oklch, oklch(0.985 0.001 255) 72%, oklch(0.145 0.005 255));
  --overlay-scrim: color-mix(in oklch, oklch(0.145 0.005 255) 40%, transparent);
  --surface-media: oklch(0.612 0.008 255);
  --border-subtle: oklch(0.928 0.004 255);
  --border-default: oklch(0.888 0.004 255);
  --border-strong: oklch(0.64 0.006 255);
  --border-accent: oklch(0.5 0.158 255);
  --ring-accent: color-mix(in oklch, oklch(0.62 0.171 255) 35%, transparent);
  --glow-accent: 0 1px 2px hsl(var(--shadow-color) / 0.10), 0 8px 24px color-mix(in oklch, oklch(0.62 0.171 255) 28%, transparent);
  --gradient-accent: linear-gradient(135deg, oklch(0.62 0.171 255), oklch(0.395 0.13 255));
  --surface-gradient: oklch(0.145 0.005 255);
  --accent-500: oklch(0.62 0.171 255);
  --accent-600: oklch(0.5 0.158 255);
  --accent-700: oklch(0.395 0.13 255);
  --accent-800: oklch(0.275 0.091 255);
  --font-sans: 'Geist Variable', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --display-font: 'Geist Variable', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --type-scale: 1;
  --display-weight: 600;
  --display-tracking: var(--tracking-tighter);
  --display-leading: var(--leading-tight);
  --body-leading: var(--leading-relaxed);
  --display-transform: none;
  --btn-radius: var(--radius-control);
  --btn-fill: var(--surface-accent);
  --btn-shadow: var(--glow-accent);
  --radius-card: 8px;
  --radius-panel: 8px;
}
.jn-canvas .jn-scheme-4 {
  --surface-page: oklch(0.975 0.012 255);
  --surface-card: oklch(1 0 255);
  --surface-sunken: oklch(0.925 0.012 255);
  --surface-inset: oklch(0.952 0.003 255);
  --surface-inverse: oklch(0.145 0.005 255);
  --surface-accent: oklch(0.62 0.171 255);
  --surface-accent-subtle: oklch(0.975 0.012 255);
  --surface-accent-hover: oklch(0.69 0.166 255);
  --text-strong: oklch(0.145 0.005 255);
  --text-body: oklch(0.278 0.007 255);
  --text-muted: oklch(0.5 0.009 255);
  --text-subtle: oklch(0.5 0.009 255);
  --text-accent: oklch(0.5 0.158 255);
  --text-on-accent: oklch(0.145 0.005 255);
  --text-inverse: oklch(0.985 0.001 255);
  --text-inverse-muted: color-mix(in oklch, oklch(0.985 0.001 255) 72%, oklch(0.145 0.005 255));
  --overlay-scrim: color-mix(in oklch, oklch(0.145 0.005 255) 40%, transparent);
  --surface-media: oklch(0.612 0.008 255);
  --border-subtle: oklch(0.928 0.004 255);
  --border-default: oklch(0.888 0.004 255);
  --border-strong: oklch(0.64 0.006 255);
  --border-accent: oklch(0.5 0.158 255);
  --ring-accent: color-mix(in oklch, oklch(0.62 0.171 255) 35%, transparent);
  --glow-accent: 0 1px 2px hsl(var(--shadow-color) / 0.10), 0 8px 24px color-mix(in oklch, oklch(0.62 0.171 255) 28%, transparent);
  --gradient-accent: linear-gradient(135deg, oklch(0.62 0.171 255), oklch(0.395 0.13 255));
  --surface-gradient: oklch(0.145 0.005 255);
  --accent-500: oklch(0.62 0.171 255);
  --accent-600: oklch(0.5 0.158 255);
  --accent-700: oklch(0.395 0.13 255);
  --accent-800: oklch(0.275 0.091 255);
  --font-sans: 'Geist Variable', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --display-font: 'Geist Variable', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --type-scale: 1;
  --display-weight: 600;
  --display-tracking: var(--tracking-tighter);
  --display-leading: var(--leading-tight);
  --body-leading: var(--leading-relaxed);
  --display-transform: none;
  --btn-radius: var(--radius-control);
  --btn-fill: var(--surface-accent);
  --btn-shadow: var(--glow-accent);
  --radius-card: 8px;
  --radius-panel: 8px;
}

/* Racine = conteneur + fond pleine largeur. La barre porte .jn-container
   (max-width --container-max + margin auto + gutter cqi, modèle BRIEF-26). */
.jn-canvas .jn-c-navbar { container: jn-section / inline-size; background: var(--surface-page); border-bottom: var(--border-hairline); }
.jn-canvas .jn-c-navbar__bar { display: flex; align-items: center; flex-wrap: wrap; gap: var(--space-24); row-gap: var(--space-12); padding-block: var(--space-16); }
.jn-canvas .jn-c-navbar__logo { font-size: var(--text-lg); font-weight: var(--weight-bold); letter-spacing: var(--tracking-tight); color: var(--text-strong); }
.jn-canvas .jn-c-navbar__panel { display: flex; align-items: center; gap: var(--space-32); margin-inline-start: auto; min-width: 0; }
.jn-canvas .jn-c-navbar__list { justify-content: flex-end; }
.jn-canvas .jn-c-navbar__cta { flex: none; }
@container jn-section (max-width: 48rem) {
  /* Tablette + mobile (W2-8) : burger à droite ; panneau pleine largeur sous la barre. */
  .jn-canvas .jn-c-navbar .jn-c-nav-burger { margin-inline-start: auto; }
  .jn-canvas .jn-c-navbar__panel { flex-basis: 100%; margin-inline-start: 0; align-items: stretch; }
}

/* Logo IMAGE sur bande sombre (BRIEF-91) : pastille claire TOKEN-DRIVEN — les
   tokens --logo-chip-* ne sont émis par conceptCssVars QUE sur les bandes
   profondes (fort/contraste/accent), ex. navbar d'ouverture « bande ». Bande
   claire → fallbacks inertes (transparent, 0) = rendu strictement identique.
   Mécanisme du footer (jn-logo-chip) porté par l'<img> elle-même, zéro HTML.
   content-box : le padding de la pastille s'ajoute AUTOUR du logo (hauteur
   normalisée --logo-height préservée, comme le span chip du footer). */
.jn-canvas [data-jn-nav] .jn-logo-img {
  background: var(--logo-chip-bg, transparent);
  padding: var(--logo-chip-pad, 0);
  border-radius: var(--logo-chip-radius, 0);
  box-sizing: content-box;
}
/* B233 (lot 2) : la bande qui porte une navbar passe AU-DESSUS de ses sœurs.
   Chaque wrapper .jn-section est un conteneur de requête (B140) donc un
   STACKING CONTEXT : sans ceci, le sous-menu déroulant (positionné DANS la
   bande navbar) se peignait SOUS la bande suivante — déroulant ouvert mais
   invisible, sur le canvas éditeur COMME sur le site publié (cas Elodie
   « ça bug toujours le menu ne s'ouvre pas »). position:relative sans offset
   + z-index : zéro layout modifié, rien ne change tant qu'aucun sous-menu
   ne dépasse de la bande. */
.jn-canvas .jn-section:has([data-jn-nav]) { position: relative; z-index: 20; }
.jn-canvas .jn-c-nav__list { display: flex; align-items: center; flex-wrap: wrap; gap: var(--space-8); row-gap: var(--space-4); }
.jn-canvas .jn-c-nav__item { position: relative; max-width: 100%; }
.jn-canvas .jn-c-nav__link {
  display: inline-flex;
  align-items: center;
  max-width: 100%;
  gap: var(--space-4);
  padding: var(--space-8) var(--space-12);
  border-radius: var(--radius-control);
  font-size: var(--text-base);
  font-weight: var(--weight-medium);
  color: var(--text-body);
  background: transparent;
  border: var(--border-hairline);
  border-color: transparent;
}
.jn-canvas .jn-c-nav__link:hover { color: var(--text-accent); background: var(--surface-accent-subtle); }
/* Libellé : labels longs (noms de page complets) tronqués proprement (W1-7). */
.jn-canvas .jn-c-nav__label { display: block; max-width: 18ch; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.jn-canvas .jn-c-nav__caret { width: var(--space-16); height: var(--space-16); }
.jn-canvas .jn-c-nav__submenu {
  position: absolute;
  inset-inline-start: 0;
  margin-block-start: var(--space-8);
  min-width: var(--container-sm);
  max-width: var(--container-sm);
  display: none;
  flex-direction: column;
  gap: var(--space-4);
  padding: var(--space-8);
  background: var(--surface-card);
  border: var(--border-hairline);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-lg);
}
.jn-canvas .jn-c-nav__item--has-menu:hover .jn-c-nav__submenu,
.jn-canvas .jn-c-nav__item--has-menu:focus-within .jn-c-nav__submenu { display: flex; }
.jn-canvas .jn-c-nav__submenu .jn-c-nav__link { border-radius: var(--radius-control); }
/* Sous-entrées (BRIEF-227) : noms de pages COMPLETS — dans un menu déroulant la
   place existe, la troncature 18ch de la barre ne s'applique pas. */
.jn-canvas .jn-c-nav__submenu .jn-c-nav__label { max-width: none; }

/* --- Burger (mobile) — caché en desktop ; le panneau se replie derrière lui
   UNIQUEMENT quand le JS publié a posé [data-jn-nav-on] (sinon panneau visible
   = progressive enhancement). --- */
.jn-canvas .jn-c-nav-burger {
  display: none;
  align-items: center;
  justify-content: center;
  width: var(--space-40);
  height: var(--space-40);
  border-radius: var(--radius-control);
  border: var(--border-hairline);
  border-color: transparent;
  background: transparent;
  color: var(--text-strong);
  flex: none;
}
.jn-canvas .jn-c-nav-burger:hover { background: var(--surface-accent-subtle); color: var(--text-accent); }
.jn-canvas .jn-c-nav-burger svg { width: var(--space-24); height: var(--space-24); }
/* Burger au seuil MEDIUM (~768px) : repli dès la TABLETTE et en mobile (W2-8) —
   en tablette/mobile la nav passe en burger ; desktop garde les liens inline. */
@container jn-section (max-width: 48rem) {
  .jn-canvas .jn-c-nav-burger { display: inline-flex; }
  .jn-canvas [data-jn-nav-menu] { flex-direction: column; align-items: stretch; width: 100%; gap: var(--space-8); }
  .jn-canvas .jn-c-nav__list { flex-direction: column; align-items: stretch; }
  .jn-canvas [data-jn-nav-on] [data-jn-nav-menu] { display: none; }
  .jn-canvas [data-jn-nav-on][data-jn-nav-open] [data-jn-nav-menu] { display: flex; }
  /* Sous-menu en mobile : déplié en place (pas de dropdown flottant). */
  .jn-canvas .jn-c-nav__submenu { position: static; min-width: 0; max-width: none; display: flex; padding-inline-start: var(--space-16); border: none; box-shadow: none; background: transparent; }
}

/* Racine = conteneur + fond pleine largeur ; gutter (cqi) porté par le wrapper interne. */
.jn-canvas .jn-c-footer { container: jn-section / inline-size; padding-block: var(--section-pad-dense, var(--space-64)); background: var(--surface-page); color: var(--text-body); }
.jn-canvas .jn-c-footer__inner { max-width: var(--container-max); margin-inline: auto; padding-inline: var(--gutter); display: flex; flex-direction: column; gap: var(--space-48); }
.jn-canvas .jn-c-footer__top { display: grid; grid-template-columns: 2fr 3fr; gap: var(--space-48); }
.jn-canvas .jn-c-footer--simple .jn-c-footer__top { grid-template-columns: 1fr; gap: var(--space-32); }
@container jn-section (max-width: 48rem) { .jn-canvas .jn-c-footer__top { grid-template-columns: 1fr; gap: var(--space-40); } }

.jn-canvas .jn-c-footer__brand { display: flex; flex-direction: column; gap: var(--space-12); }
.jn-canvas .jn-c-footer__logo { font-size: var(--text-lg); font-weight: var(--weight-bold); letter-spacing: var(--tracking-tight); color: var(--text-strong); }
.jn-canvas .jn-c-footer__tagline { font-size: var(--text-base); line-height: var(--leading-relaxed); color: var(--text-body); max-width: var(--container-sm); }

.jn-canvas .jn-c-footer__groups { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--space-32); }
.jn-canvas .jn-c-footer--simple .jn-c-footer__groups { grid-template-columns: 1fr; }
@container jn-section (max-width: 36rem) { .jn-canvas .jn-c-footer__groups { grid-template-columns: repeat(2, 1fr); } }
.jn-canvas .jn-c-footer__group { display: flex; flex-direction: column; gap: var(--space-12); }
.jn-canvas .jn-c-footer--simple .jn-c-footer__group { flex-direction: row; flex-wrap: wrap; gap: var(--space-20); align-items: center; }
.jn-canvas .jn-c-footer__group-title { font-size: var(--text-xs); font-weight: var(--weight-semibold); letter-spacing: var(--eyebrow-tracking); text-transform: uppercase; color: var(--text-muted); }
.jn-canvas .jn-c-footer--simple .jn-c-footer__group-title { display: none; }
.jn-canvas .jn-c-footer__link { font-size: var(--text-base); color: var(--text-body); }
.jn-canvas .jn-c-footer__link:hover { color: var(--text-strong); text-decoration: underline; text-underline-offset: var(--space-4); }

.jn-canvas .jn-c-footer__bottom { display: flex; flex-wrap: wrap; gap: var(--space-16); align-items: center; justify-content: space-between; padding-block-start: var(--space-32); border-top: var(--border-hairline); }
.jn-canvas .jn-c-footer__copyright { font-size: var(--text-sm); color: var(--text-muted); }
.jn-canvas .jn-c-footer__social { display: flex; gap: var(--space-8); }
.jn-canvas .jn-c-footer__social-link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--space-40);
  height: var(--space-40);
  border-radius: var(--radius-pill);
  border: var(--border-hairline);
  color: var(--text-body);
}
.jn-canvas .jn-c-footer__social-link:hover { color: var(--text-strong); border-color: var(--border-accent); }
.jn-canvas .jn-c-footer__social-link svg { width: var(--space-20); height: var(--space-20); }

/* Racine = conteneur + fond pleine largeur. Paddings v2 : le vertical vit sur la
   racine (rem, pas de piège cqi) ; l'inline sur le wrapper interne (convention). */
.jn-canvas .jn-c-hero01 { container: jn-section / inline-size; padding-block: var(--padding-section-large); background: var(--surface-page); color: var(--text-body); }
/* Wrapper interne : règles partagées HISSÉES dans la primitive jn-inner (B149). */
.jn-canvas .jn-c-hero01__layout { display: flex; align-items: center; gap: var(--space-80); }
.jn-canvas .jn-c-hero01__copy { flex: 1; display: flex; flex-direction: column; gap: var(--space-32); min-width: 0; }
.jn-canvas .jn-c-hero01__content { display: flex; flex-direction: column; gap: var(--space-24); }
.jn-canvas .jn-c-hero01__title {
  font-size: var(--heading-1);
  font-weight: var(--display-weight);
  letter-spacing: var(--display-tracking);
  line-height: var(--display-leading);
  color: var(--text-strong);
}
.jn-canvas .jn-c-hero01__subtitle { font-size: var(--text-medium); line-height: var(--leading-normal); color: var(--text-body); }
.jn-canvas .jn-c-hero01__actions { display: flex; flex-wrap: wrap; gap: var(--space-16); }
.jn-canvas .jn-c-hero01__media { flex: 1; min-width: 0; }
.jn-canvas .jn-c-hero01__media .jn-ph { width: 100%; }

/* Mobile (variante Mobile de la maquette) : empilement, image après le texte,
   valeurs -m. Bascule = CQ.medium (convention d'entre-deux provisoire, à
   affiner avec l'exploration responsive de Benjamin). */
@container jn-section (max-width: 48rem) {
  .jn-canvas .jn-c-hero01 { padding-block: var(--padding-section-large-m); }
  .jn-canvas .jn-c-hero01__layout { flex-direction: column; align-items: stretch; gap: var(--space-48); }
  .jn-canvas .jn-c-hero01__copy { gap: var(--space-24); }
  .jn-canvas .jn-c-hero01__content { gap: var(--space-20); }
  .jn-canvas .jn-c-hero01__title { font-size: var(--heading-1-m); }
  .jn-canvas .jn-c-hero01__subtitle { font-size: var(--text-medium-m); }
  .jn-canvas .jn-c-hero01__actions { gap: var(--space-12); }
}

/* Racine = conteneur + fond pleine largeur ; gutter (cqi) porté par le wrapper interne. */
.jn-canvas .jn-c-services { container: jn-section / inline-size; padding-block: var(--section-pad, var(--space-80)); background: var(--surface-page); }
.jn-canvas .jn-c-services__inner { max-width: var(--container-max); margin-inline: auto; padding-inline: var(--gutter); }
.jn-canvas .jn-c-services__head { display: flex; flex-direction: column; gap: var(--space-12); max-width: var(--container-md); margin-block-end: var(--space-48); }
.jn-canvas .jn-c-services__title { font-size: var(--text-2xl); font-weight: var(--display-weight); letter-spacing: var(--display-tracking); line-height: var(--display-leading); color: var(--text-strong); }
.jn-canvas .jn-c-services__subtitle { font-size: var(--text-lg); line-height: var(--leading-relaxed); color: var(--text-muted); }
.jn-canvas .jn-c-services__grid { display: grid; gap: var(--space-24); }
.jn-canvas .jn-c-services__grid--2 { grid-template-columns: repeat(2, 1fr); }
.jn-canvas .jn-c-services__grid--3 { grid-template-columns: repeat(3, 1fr); }
.jn-canvas .jn-c-services__grid--4 { grid-template-columns: repeat(4, 1fr); }
@container jn-section (max-width: 48rem) { .jn-canvas .jn-c-services__grid { grid-template-columns: repeat(2, 1fr); } }
@container jn-section (max-width: 36rem) { .jn-canvas .jn-c-services__grid { grid-template-columns: 1fr; } }
.jn-canvas .jn-c-services__card {
  display: flex;
  flex-direction: column;
  gap: var(--space-12);
  padding: var(--space-24);
  background: var(--surface-card);
  border: var(--border-hairline);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-sm);
}
.jn-canvas .jn-c-services__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--space-48);
  height: var(--space-48);
  border-radius: var(--radius-md);
  background: var(--surface-accent-subtle);
  color: var(--text-accent);
}
.jn-canvas .jn-c-services__icon svg { width: var(--space-24); height: var(--space-24); }
.jn-canvas .jn-c-services__card-title { font-size: var(--text-lg); font-weight: var(--weight-semibold); letter-spacing: var(--heading-tracking); color: var(--text-strong); overflow-wrap: anywhere; hyphens: auto; }
.jn-canvas .jn-c-services__desc { font-size: var(--text-base); line-height: var(--leading-relaxed); color: var(--text-muted); }
.jn-canvas .jn-c-services__link { display: inline-flex; align-items: center; gap: var(--space-8); margin-block-start: var(--space-4); color: var(--text-accent); font-weight: var(--weight-medium); }
.jn-canvas .jn-c-services__link svg { width: var(--space-16); height: var(--space-16); }

/* Racine = conteneur + fond pleine largeur ; padding vertical ici, gutter porté
   par le wrapper interne jn-inner (piège cqi, convention v2). */
.jn-canvas .jn-c-content03 { container: jn-section / inline-size; padding-block: var(--padding-section-large); background: var(--surface-page); color: var(--text-body); }
.jn-canvas .jn-c-content03__layout { display: flex; flex-direction: column; gap: var(--space-80); }
/* En-tête centré, plafonné 768 (Max Width/max-width-large). */
.jn-canvas .jn-c-content03__head { max-width: var(--max-width-large); margin-inline: auto; display: flex; flex-direction: column; align-items: center; text-align: center; gap: var(--space-16); }
.jn-canvas .jn-c-content03__head-text { display: flex; flex-direction: column; gap: var(--space-24); }
.jn-canvas .jn-c-content03__intro { font-size: var(--text-medium); line-height: var(--leading-normal); color: var(--text-body); }
/* Grille 4 colonnes ; hauteur des cartes ÉGALE par la rangée (align-items:stretch
   implicite en grid), pilotée par la carte la plus haute — jamais de hauteur figée. */
.jn-canvas .jn-c-content03__grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--space-24) var(--space-32); }
/* Carte : fond + bordure (détache la carte sur bande colorée) ; rayon PILOTÉ
   (liaison Radius/Small → --radius-card, zéroté en wireframe). */
.jn-canvas .jn-c-content03__card { display: flex; flex-direction: column; gap: var(--space-24); padding: var(--space-32); background: var(--surface-card); border: var(--border-hairline); border-radius: var(--radius-card); }
.jn-canvas .jn-c-content03__icon { color: var(--text-strong); }
.jn-canvas .jn-c-content03__icon svg { display: block; width: var(--space-48); height: var(--space-48); }
.jn-canvas .jn-c-content03__card-body { display: flex; flex-direction: column; gap: var(--space-16); }
.jn-canvas .jn-c-content03__card-title { font-size: var(--heading-4); font-weight: var(--weight-semibold); letter-spacing: var(--tracking-tight); line-height: var(--leading-snug); color: var(--text-strong); }
.jn-canvas .jn-c-content03__card-text { font-size: var(--text-medium); line-height: var(--leading-normal); color: var(--text-body); }
/* Lien de carte : poussé EN BAS (margin-top:auto → tous les liens alignés d'une
   carte à l'autre, hauteurs égales) et À GAUCHE (le <a> inline-flex ne s'étire pas
   dans ce bloc — sinon le justify-content:center de .jn-btn le centrait). Demande
   Benjamin 18/7. */
.jn-canvas .jn-c-content03__action { margin-block-start: auto; }

/* Étape intermédiaire (tablette) : 2 colonnes — responsable ICI (la maquette ne
   donne que Desktop + Mobile), sinon 4 cartes s'écrasent entre CQ.medium et CQ.wide. */
@container jn-section (max-width: 64rem) {
  .jn-canvas .jn-c-content03__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
/* Mobile (variante Mobile de la maquette) : 1 colonne, valeurs -m. */
@container jn-section (max-width: 48rem) {
  .jn-canvas .jn-c-content03 { padding-block: var(--padding-section-large-m); }
  .jn-canvas .jn-c-content03__layout { gap: var(--space-48); }
  .jn-canvas .jn-c-content03__head { gap: var(--space-12); }
  .jn-canvas .jn-c-content03__head-text { gap: var(--space-20); }
  .jn-canvas .jn-c-content03__intro { font-size: var(--text-medium-m); }
  .jn-canvas .jn-c-content03__grid { grid-template-columns: 1fr; gap: var(--space-20); }
  .jn-canvas .jn-c-content03__card { gap: var(--space-20); padding: var(--space-24); }
  .jn-canvas .jn-c-content03__card-body { gap: var(--space-12); }
  .jn-canvas .jn-c-content03__card-title { font-size: var(--heading-4-m); }
  .jn-canvas .jn-c-content03__card-text { font-size: var(--text-medium-m); }
}

.jn-canvas .jn-c-testimonial01 { container: jn-section / inline-size; padding-block: var(--padding-section-large); background: var(--surface-page); color: var(--text-body); }
/* Wrapper interne : cap/centrage/gutter hissés dans jn-inner (B149) — ne reste
   que le repère des flèches absolues. */
.jn-canvas .jn-c-testimonial01__inner { position: relative; }
.jn-canvas .jn-c-testimonial01__componant { display: flex; flex-direction: column; align-items: center; gap: var(--space-48); }
/* Pile de slides en GRILLE (une seule cellule) : hauteur stable (= l'avis le
   plus haut, pas de saut de mise en page) + FONDU CROISÉ au changement (B146).
   L'inactif est aussi masqué aux clics/lecteurs (visibility, en fin de fondu).
   Dans l'éditeur le changement d'avis RE-REND la section (DOM neuf) → aucune
   animation n'y joue, comme voulu. */
.jn-canvas .jn-c-testimonial01__track { display: grid; justify-items: center; }
.jn-canvas .jn-c-testimonial01__slide {
  grid-area: 1 / 1;
  display: flex; flex-direction: column; align-items: center; gap: var(--space-32);
  max-width: var(--max-width-large); text-align: center;
  opacity: 0; visibility: hidden;
  transition: opacity var(--dur-slower) var(--ease-out), visibility 0s var(--dur-slower);
}
.jn-canvas .jn-c-testimonial01__slide.is-active { opacity: 1; visibility: visible; transition: opacity var(--dur-slower) var(--ease-out); }
.jn-canvas .jn-c-testimonial01__logo { height: var(--logo-height); }
.jn-canvas .jn-c-testimonial01__logo img { height: 100%; width: auto; }
.jn-canvas .jn-c-testimonial01__logo .jn-ph { height: 100%; width: auto; aspect-ratio: 5 / 3; }
.jn-canvas .jn-c-testimonial01__quote {
  margin: 0;
  font-size: var(--heading-5);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-tight);
  line-height: var(--leading-snug);
  color: var(--text-strong);
}
.jn-canvas .jn-c-testimonial01__avatar { display: flex; flex-direction: column; align-items: center; gap: var(--space-16); }
.jn-canvas .jn-c-testimonial01__face { width: 3.5rem; height: 3.5rem; border-radius: var(--radius-pill); overflow: hidden; }
.jn-canvas .jn-c-testimonial01__face .jn-ph, .jn-canvas .jn-c-testimonial01__face img { width: 100%; height: 100%; border-radius: var(--radius-pill); aspect-ratio: 1; object-fit: cover; }
.jn-canvas .jn-c-testimonial01__who { font-size: var(--text-regular); color: var(--text-strong); }
.jn-canvas .jn-c-testimonial01__precision { font-size: var(--text-regular); color: var(--text-body); }
.jn-canvas .jn-c-testimonial01__dots { display: flex; gap: var(--space-8); padding: var(--space-8); }
.jn-canvas .jn-c-testimonial01__dot { width: 0.5rem; height: 0.5rem; border-radius: var(--radius-pill); border: 0; padding: 0; background: var(--surface-card); cursor: pointer; }
.jn-canvas .jn-c-testimonial01__dot.is-active { background: var(--surface-accent); }
.jn-canvas .jn-c-testimonial01__arrow {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  display: flex; align-items: center; justify-content: center;
  width: 2.5rem; height: 2.5rem; padding: var(--space-8);
  border: var(--border-hairline); border-color: var(--border-default); border-radius: var(--radius-pill);
  background: transparent; color: var(--text-strong); cursor: pointer;
  transition: var(--transition-control);
}
.jn-canvas .jn-c-testimonial01__arrow:hover { background: var(--surface-sunken); border-color: var(--border-strong); }
.jn-canvas .jn-c-testimonial01__arrow svg { width: var(--space-24); height: var(--space-24); }
.jn-canvas .jn-c-testimonial01__arrow--prev { left: var(--padding-global); }
.jn-canvas .jn-c-testimonial01__arrow--next { right: var(--padding-global); }

/* Mobile (variante Mobile de la maquette) : mêmes couches, valeurs -m. */
@container jn-section (max-width: 48rem) {
  .jn-canvas .jn-c-testimonial01 { padding-block: var(--padding-section-large-m); }
  .jn-canvas .jn-c-testimonial01__componant { gap: var(--space-32); }
  .jn-canvas .jn-c-testimonial01__slide { gap: var(--space-24); }
  .jn-canvas .jn-c-testimonial01__quote { font-size: var(--heading-5-m); }
  .jn-canvas .jn-c-testimonial01__avatar { gap: var(--space-12); }
  /* Mobile : flèches CACHÉES (variante Figma, 17/7) — navigation = points + glissement tactile (behavior). */
  .jn-canvas .jn-c-testimonial01__arrow { display: none; }
}

/* Racine = conteneur + fond pleine largeur ; gutter (cqi) porté par __inner. */
.jn-canvas .jn-c-faq { container: jn-section / inline-size; padding-block: var(--section-pad, var(--space-80)); background: var(--surface-page); }
.jn-canvas .jn-c-faq__inner { max-width: var(--container-max); margin-inline: auto; padding-inline: var(--gutter); }
.jn-canvas .jn-c-faq__head { display: flex; flex-direction: column; gap: var(--space-12); max-width: var(--container-md); margin-block-end: var(--space-48); }
.jn-canvas .jn-c-faq--centre .jn-c-faq__head { margin-inline: auto; text-align: center; align-items: center; }
.jn-canvas .jn-c-faq__title { font-size: var(--text-2xl); font-weight: var(--display-weight); letter-spacing: var(--display-tracking); line-height: var(--display-leading); color: var(--text-strong); }
.jn-canvas .jn-c-faq__subtitle { font-size: var(--text-lg); line-height: var(--leading-relaxed); color: var(--text-muted); }

/* Liste d'items repliables */
.jn-canvas .jn-c-faq__list { display: grid; gap: var(--space-12); }
.jn-canvas .jn-c-faq--centre .jn-c-faq__list { max-width: var(--container-md); margin-inline: auto; }
.jn-canvas .jn-c-faq--deux-colonnes .jn-c-faq__list { grid-template-columns: 1fr 1fr; gap: var(--space-16) var(--space-40); align-items: start; }
@container jn-section (max-width: 48rem) { .jn-canvas .jn-c-faq--deux-colonnes .jn-c-faq__list { grid-template-columns: 1fr; } }

/* Item = <details> : barre fine soulignée, ZÉRO carte (pas de fond/bordure pleine). */
.jn-canvas .jn-c-faq__item { border-block-end: var(--border-hairline); }
.jn-canvas .jn-c-faq__q {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-16);
  padding-block: var(--space-20);
  font-size: var(--text-lg);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--heading-tracking);
  color: var(--text-strong);
  cursor: pointer;
  list-style: none; /* masque le triangle natif (on fournit le chevron) */
}
.jn-canvas .jn-c-faq__q::-webkit-details-marker { display: none; }
.jn-canvas .jn-c-faq__q-label { overflow-wrap: anywhere; hyphens: auto; }
.jn-canvas .jn-c-faq__q:hover { color: var(--text-accent); }
.jn-canvas .jn-c-faq__q:focus-visible { outline: none; box-shadow: var(--shadow-focus); border-radius: var(--radius-control); }
.jn-canvas .jn-c-faq__chevron { width: var(--space-20); height: var(--space-20); color: var(--text-muted); flex: none; transition: var(--transition-control); }
.jn-canvas .jn-c-faq__item[open] .jn-c-faq__chevron { transform: rotate(180deg); }
.jn-canvas .jn-c-faq__a { padding-block-end: var(--space-20); font-size: var(--text-base); line-height: var(--leading-relaxed); color: var(--text-muted); max-width: var(--container-sm); }

/* Racine = conteneur + fond pleine largeur ; gutter (cqi) porté par le wrapper interne. */
.jn-canvas .jn-c-about { container: jn-section / inline-size; padding-block: var(--section-pad, var(--space-80)); background: var(--surface-page); }
.jn-canvas .jn-c-about__inner { max-width: var(--container-max); margin-inline: auto; padding-inline: var(--gutter); }
.jn-canvas .jn-c-about--texte-image .jn-c-about__inner {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-64);
  align-items: center;
}
@container jn-section (max-width: 48rem) {
  .jn-canvas .jn-c-about--texte-image .jn-c-about__inner { grid-template-columns: 1fr; gap: var(--space-48); }
}
.jn-canvas .jn-c-about--texte .jn-c-about__inner { max-width: var(--container-md); }
.jn-canvas .jn-c-about__copy { display: flex; flex-direction: column; gap: var(--space-16); }
.jn-canvas .jn-c-about__title { font-size: var(--text-2xl); font-weight: var(--display-weight); letter-spacing: var(--display-tracking); line-height: var(--display-leading); color: var(--text-strong); }
.jn-canvas .jn-c-about__text { font-size: var(--text-md); line-height: var(--leading-relaxed); color: var(--text-body); }
.jn-canvas .jn-c-about__stats { display: flex; flex-wrap: wrap; gap: var(--space-32); margin-block-start: var(--space-16); }
.jn-canvas .jn-c-about__stat { display: flex; flex-direction: column; gap: var(--space-4); }
.jn-canvas .jn-c-about__stat-value { font-size: var(--text-3xl); font-weight: var(--weight-bold); letter-spacing: var(--tracking-tight); color: var(--text-accent); }
.jn-canvas .jn-c-about__stat-label { font-size: var(--text-sm); color: var(--text-muted); }

/* Racine = conteneur + fond pleine largeur ; gutter (cqi) porté par le wrapper interne. */
.jn-canvas .jn-c-contact { container: jn-section / inline-size; padding-block: var(--section-pad, var(--space-80)); background: var(--surface-page); }
.jn-canvas .jn-c-contact__inner { max-width: var(--container-max); margin-inline: auto; padding-inline: var(--gutter); }
.jn-canvas .jn-c-contact__head { display: flex; flex-direction: column; gap: var(--space-12); max-width: var(--container-md); margin-block-end: var(--space-48); }
.jn-canvas .jn-c-contact__title { font-size: var(--text-2xl); font-weight: var(--display-weight); letter-spacing: var(--display-tracking); line-height: var(--display-leading); color: var(--text-strong); }
.jn-canvas .jn-c-contact__intro { font-size: var(--text-lg); line-height: var(--leading-relaxed); color: var(--text-muted); }
.jn-canvas .jn-c-contact__cols { display: grid; grid-template-columns: 3fr 2fr; gap: var(--space-48); align-items: start; }
.jn-canvas .jn-c-contact__cols--single { grid-template-columns: 1fr; }
@container jn-section (max-width: 48rem) { .jn-canvas .jn-c-contact__cols { grid-template-columns: 1fr; gap: var(--space-40); } }

.jn-canvas .jn-c-contact__form { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-16); }
.jn-canvas .jn-c-contact__field { display: flex; flex-direction: column; gap: var(--space-8); }
.jn-canvas .jn-c-contact__field--wide { grid-column: 1 / -1; }
.jn-canvas .jn-c-contact__label { font-size: var(--text-sm); font-weight: var(--weight-medium); color: var(--text-body); }
.jn-canvas .jn-c-contact__input,
.jn-canvas .jn-c-contact__textarea {
  width: 100%;
  padding: var(--space-12) var(--space-16);
  font: inherit;
  font-size: var(--text-base);
  color: var(--text-strong);
  background: var(--surface-card);
  border: var(--border-hairline);
  border-color: var(--border-default);
  border-radius: var(--radius-control);
}
.jn-canvas .jn-c-contact__textarea { min-height: var(--space-128); resize: vertical; }
/* Liste déroulante (E15) : même peau que les inputs (tokens, AA garanti par le moteur). */
.jn-canvas .jn-c-contact__select {
  width: 100%;
  padding: var(--space-12) var(--space-16);
  font: inherit;
  font-size: var(--text-base);
  color: var(--text-strong);
  background: var(--surface-card);
  border: var(--border-hairline);
  border-color: var(--border-default);
  border-radius: var(--radius-control);
}
/* Case à cocher (E15) : rangée horizontale pleine largeur, coche aux couleurs du site. */
.jn-canvas .jn-c-contact__field--check { flex-direction: row; align-items: center; gap: var(--space-12); }
.jn-canvas .jn-c-contact__checkbox { width: var(--space-20); height: var(--space-20); flex: none; accent-color: var(--text-accent); }
/* Widget anti-robots optionnel (inerte sans clé — BRIEF-101). */
.jn-canvas .jn-c-contact__captcha { grid-column: 1 / -1; }
.jn-canvas .jn-c-contact__submit { grid-column: 1 / -1; }

.jn-canvas .jn-c-contact__aside { display: flex; flex-direction: column; gap: var(--space-24); }
.jn-canvas .jn-c-contact__coords { display: flex; flex-direction: column; gap: var(--space-12); }
.jn-canvas .jn-c-contact__coord { display: flex; flex-direction: column; gap: var(--space-4); }
.jn-canvas .jn-c-contact__coord-label { font-size: var(--text-xs); font-weight: var(--weight-semibold); letter-spacing: var(--eyebrow-tracking); text-transform: uppercase; color: var(--text-subtle); }
.jn-canvas .jn-c-contact__coord-value { font-size: var(--text-md); color: var(--text-body); }
.jn-canvas .jn-c-contact__hours { display: flex; flex-direction: column; gap: var(--space-8); }
.jn-canvas .jn-c-contact__hour { display: flex; justify-content: space-between; gap: var(--space-16); font-size: var(--text-base); }
.jn-canvas .jn-c-contact__hour-day { color: var(--text-body); }
.jn-canvas .jn-c-contact__hour-time { color: var(--text-muted); }
.jn-canvas .jn-c-contact__map {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-8);
  width: 100%;
  aspect-ratio: 3 / 2;
  border-radius: var(--radius-card);
  background: var(--surface-sunken);
  border: var(--border-hairline);
  color: var(--text-subtle);
  font-size: var(--text-sm);
}
.jn-canvas .jn-c-contact__map svg { width: var(--space-24); height: var(--space-24); }
/* Carte réelle (BRIEF-177) : repli en colonne (épingle + libellé + lien OSM) ;
   Leaflet remplace le contenu au montage (classe jn-map--live posée par le script). */
.jn-canvas .jn-c-contact__map { flex-direction: column; position: relative; overflow: hidden; }
.jn-canvas .jn-c-contact__map-link { font-size: var(--text-sm); color: var(--text-accent); text-decoration: underline; text-underline-offset: var(--space-4); }
/* Épingle Leaflet (divIcon SVG maison, zéro PNG embarqué) : couleur aux tokens. */
.jn-canvas .jn-map-pin { color: var(--text-accent); }
.jn-canvas .jn-map-pin svg { width: var(--space-32); height: var(--space-32); }

.jn-canvas .jn-c-contact__req { color: var(--text-accent); margin-inline-start: var(--space-4); font-weight: var(--weight-semibold); }
/* HONEYPOT (BRIEF-68) : hors écran, jamais display:none (certains bots l'évitent). */
.jn-canvas .jn-c-contact__hp { position: absolute; left: -9999px; top: auto; width: 1px; height: 1px; overflow: hidden; }
/* Statut d'envoi (succès/erreur) — hérite des tokens de la section. */
.jn-canvas .jn-c-contact__status { grid-column: 1 / -1; margin: 0; font-size: var(--text-base); line-height: var(--leading-relaxed); color: var(--text-strong); }
.jn-canvas .jn-c-contact__status[data-jn-form-err] { color: var(--text-accent); }

/* === Animation d'entrée au scroll — aperçu/build uniquement (BRIEF-63) === */
/* Repli : sans la classe d'armement (JS absent/échoué), TOUT reste visible. */
@media (prefers-reduced-motion: no-preference) {
  .jn-canvas.jn-anim-armed[data-jn-anim] .jn-section {
    opacity: 0;
    transform: translateY(1.25rem);
    transition: opacity var(--dur-slower) var(--ease-out),
                transform var(--dur-slower) var(--ease-out);
    transition-delay: calc(var(--jn-i, 0) * 60ms);
    will-change: opacity, transform;
  }
  .jn-canvas.jn-anim-armed[data-jn-anim] .jn-section.jn-in {
    opacity: 1;
    transform: none;
  }
  /* Stagger INTRA-section (grilles/étapes/paliers) : enfants directs du conteneur.
     Générique → aucun composant à modifier. Léger, plafonné (5 pas). */
  .jn-canvas.jn-anim-armed[data-jn-anim] .jn-section.jn-in [class*="__grid"] > *,
  .jn-canvas.jn-anim-armed[data-jn-anim] .jn-section.jn-in [class*="__steps"] > *,
  .jn-canvas.jn-anim-armed[data-jn-anim] .jn-section.jn-in [class*="__cards"] > *,
  .jn-canvas.jn-anim-armed[data-jn-anim] .jn-section.jn-in [class*="__tiers"] > * {
    animation: jn-rise var(--dur-slow) var(--ease-out) both;
  }
  .jn-canvas.jn-anim-armed[data-jn-anim] .jn-section.jn-in [class*="__grid"] > *:nth-child(1),
  .jn-canvas.jn-anim-armed[data-jn-anim] .jn-section.jn-in [class*="__steps"] > *:nth-child(1),
  .jn-canvas.jn-anim-armed[data-jn-anim] .jn-section.jn-in [class*="__cards"] > *:nth-child(1),
  .jn-canvas.jn-anim-armed[data-jn-anim] .jn-section.jn-in [class*="__tiers"] > *:nth-child(1) { animation-delay: 0.04s; }
  .jn-canvas.jn-anim-armed[data-jn-anim] .jn-section.jn-in [class*="__grid"] > *:nth-child(2),
  .jn-canvas.jn-anim-armed[data-jn-anim] .jn-section.jn-in [class*="__steps"] > *:nth-child(2),
  .jn-canvas.jn-anim-armed[data-jn-anim] .jn-section.jn-in [class*="__cards"] > *:nth-child(2),
  .jn-canvas.jn-anim-armed[data-jn-anim] .jn-section.jn-in [class*="__tiers"] > *:nth-child(2) { animation-delay: 0.12s; }
  .jn-canvas.jn-anim-armed[data-jn-anim] .jn-section.jn-in [class*="__grid"] > *:nth-child(3),
  .jn-canvas.jn-anim-armed[data-jn-anim] .jn-section.jn-in [class*="__steps"] > *:nth-child(3),
  .jn-canvas.jn-anim-armed[data-jn-anim] .jn-section.jn-in [class*="__cards"] > *:nth-child(3),
  .jn-canvas.jn-anim-armed[data-jn-anim] .jn-section.jn-in [class*="__tiers"] > *:nth-child(3) { animation-delay: 0.20s; }
  .jn-canvas.jn-anim-armed[data-jn-anim] .jn-section.jn-in [class*="__grid"] > *:nth-child(4),
  .jn-canvas.jn-anim-armed[data-jn-anim] .jn-section.jn-in [class*="__steps"] > *:nth-child(4),
  .jn-canvas.jn-anim-armed[data-jn-anim] .jn-section.jn-in [class*="__cards"] > *:nth-child(4),
  .jn-canvas.jn-anim-armed[data-jn-anim] .jn-section.jn-in [class*="__tiers"] > *:nth-child(4) { animation-delay: 0.28s; }
  .jn-canvas.jn-anim-armed[data-jn-anim] .jn-section.jn-in [class*="__grid"] > *:nth-child(n+5),
  .jn-canvas.jn-anim-armed[data-jn-anim] .jn-section.jn-in [class*="__steps"] > *:nth-child(n+5),
  .jn-canvas.jn-anim-armed[data-jn-anim] .jn-section.jn-in [class*="__cards"] > *:nth-child(n+5),
  .jn-canvas.jn-anim-armed[data-jn-anim] .jn-section.jn-in [class*="__tiers"] > *:nth-child(n+5) { animation-delay: 0.34s; }

  @keyframes jn-rise {
    from { opacity: 0; transform: translateY(0.75rem); }
    to   { opacity: 1; transform: none; }
  }
}
/* prefers-reduced-motion: reduce → AUCUNE règle ci-dessus n'existe : contenu
   visible, zéro mouvement (pas de fenêtre de flash). */


.jn-canvas .jn-legal { padding-block: var(--section-pad, var(--space-80)); background: var(--surface-page); }
.jn-canvas .jn-legal__inner { max-width: var(--container-sm); margin-inline: auto; padding-inline: var(--gutter); }
.jn-canvas .jn-legal__title { font-size: var(--text-3xl); font-weight: var(--display-weight); letter-spacing: var(--display-tracking); line-height: var(--display-leading); color: var(--text-strong); margin-block-end: var(--space-32); }
.jn-canvas .jn-legal h2 { font-size: var(--text-xl); font-weight: var(--weight-semibold); color: var(--text-strong); margin-block: var(--space-32) var(--space-12); }
.jn-canvas .jn-legal p { font-size: var(--text-base); line-height: var(--leading-relaxed); color: var(--text-body); margin-block: var(--space-8); }



.jn-canvas .jn-legal-links { display: flex; gap: var(--space-8); justify-content: center; padding-block: var(--space-16); font-size: var(--text-sm); opacity: 0.75; }
.jn-canvas .jn-legal-links a { color: inherit; text-decoration: none; }
.jn-canvas .jn-legal-links a:hover { text-decoration: underline; }



.jn-canvas .jn-nap { margin: 0; text-align: center; padding-block-start: var(--space-16); font-size: var(--text-sm); opacity: 0.85; }
