/* ============================================================
   Configurateur de caissons — front

   TOUT CE QUI SE VOIT SE RÈGLE ICI. Les jetons ci-dessous sont la seule
   source de l'apparence : aucune couleur, aucune taille, aucune épaisseur
   de trait n'est écrite ailleurs dans ce fichier — tools/jetons.php le
   vérifie à chaque contrôle.

   Ils sont posés sur :root et non sur .ccx-app, parce que deux surfaces du
   configurateur vivent hors de lui : la loupe de décor et la fenêtre de
   demande spéciale sont ajoutées au <body> pour échapper à l'overflow:clip
   et aux z-index du thème. Des jetons scopés au bloc ne les atteindraient
   pas, et le client réglerait sa charte pour découvrir au premier clic une
   fenêtre restée dans l'ancien style.

   L'écran de réglages réécrit ces valeurs en ligne (includes/charte.php).
   Celles d'ici sont donc les valeurs d'usine, et rien d'autre.
   ============================================================ */

:root{
  /* ---------- La police, et l'échelle ----------
     Arial plutôt qu'une police chargée chez Google : une requête externe de
     moins, et plus aucune donnée envoyée à un tiers. Liberation Sans est
     métriquement identique à Arial, ce qui rattrape les machines qui ne
     l'ont pas. L'échelle multiplie toutes les tailles d'un coup — sans
     elle, « agrandir un peu tout » demanderait huit corrections. */
  --ccx-font: Arial, "Helvetica Neue", Helvetica, "Liberation Sans", sans-serif;
  --ccx-font-chiffre: var(--ccx-font);
  --ccx-echelle: 1;
  /* L'en-tête se retire côté serveur : ce jeton n'existe que pour que
     l'aperçu de l'écran de réglages puisse le montrer sans recharger. */
  --ccx-entete-d: flex;
  --ccx-base-size:13.5px;   /* ce dont hérite ce qui ne porte pas de rôle */

  /* ---------- Les couleurs ---------- */
  --ccx-paper:#FFFFFF;         /* fond principal */
  --ccx-surface:#FAFAFA;       /* fond secondaire (aperçu, en-tête) */
  --ccx-ink:#1a1a1a;           /* texte principal */
  --ccx-ink-soft:#707070;      /* texte secondaire */
  --ccx-ink-fort:#000000;      /* survol du bouton principal */
  --ccx-ink-mid:#4a4a4a;       /* traits techniques secondaires */
  --ccx-line:#E5E5E5;          /* traits fins */
  --ccx-line-strong:#a0a0a0;   /* traits marqués, et le dessin technique */
  --ccx-line-fond:#D5D5D5;     /* le fond du caisson, dans le dessin technique */
  --ccx-accent:#1a1a1a;        /* accent — monochrome par défaut */
  --ccx-accent-soft:#F0F0F0;   /* fond d'un choix retenu */
  --ccx-accent-ink:#1a1a1a;
  --ccx-warn:#8a6a2e;          /* contrainte imposée */
  --ccx-warn-soft:#F5EFE1;
  --ccx-alert:#B4341C;         /* hors plage */
  --ccx-alert-soft:#FBEAE4;
  --ccx-voile:rgba(20,20,20,.82);      /* derrière une fenêtre */
  --ccx-voile-doux:rgba(20,20,20,.6);  /* derrière la demande spéciale */
  --ccx-verre:rgba(255,255,255,.86);   /* pastille posée sur une photo */
  --ccx-verre-plein:rgba(255,255,255,.88);
  --ccx-vernis:rgba(255,255,255,.18);  /* le liseré intérieur d'une vignette */
  --ccx-atelier:#F7F7F5;               /* un message venu de l'atelier */
  --ccx-atelier-bord:#DcDcD8;

  /* ---------- Les huit rôles de texte ----------
     Un élément est AFFECTÉ à un rôle ; on règle le rôle, jamais l'élément.
     C'est ce qui tient la hiérarchie : deux titres d'étape ne peuvent plus
     diverger d'un demi-pixel parce qu'on les a réglés séparément. */

  /* Titre 1 — le titre du configurateur */
  --ccx-t1-size:17px;   --ccx-t1-weight:600; --ccx-t1-case:none;
  --ccx-t1-track:-.01em; --ccx-t1-color:var(--ccx-ink);

  /* Titre 2 — le titre d'une étape, et ceux de la colonne d'aperçu */
  --ccx-t2-size:11.5px; --ccx-t2-weight:600; --ccx-t2-case:uppercase;
  --ccx-t2-track:.1em;  --ccx-t2-color:var(--ccx-ink);

  /* Titre 3 — les sous-titres : « Nomenclature panneaux », « Total estimé » */
  --ccx-t3-size:12px;   --ccx-t3-weight:600; --ccx-t3-case:none;
  --ccx-t3-track:0;     --ccx-t3-color:var(--ccx-ink);

  /* Libellé — le nom d'un champ */
  --ccx-li-size:11.5px; --ccx-li-weight:500; --ccx-li-case:none;
  --ccx-li-track:0;     --ccx-li-color:var(--ccx-ink-soft);

  /* Bouton — le texte à l'intérieur d'un bouton de choix */
  --ccx-bt-size:12px;   --ccx-bt-weight:500; --ccx-bt-case:none;
  --ccx-bt-track:0;

  /* Courant — le récapitulatif, le tableau, le corps de texte */
  --ccx-co-size:11.5px; --ccx-co-weight:400; --ccx-co-case:none;
  --ccx-co-track:0;     --ccx-co-color:var(--ccx-ink);

  /* Note — l'aide, la précision, l'unité, le pied de page */
  --ccx-no-size:10.5px; --ccx-no-weight:400; --ccx-no-case:none;
  --ccx-no-track:0;     --ccx-no-color:var(--ccx-ink-soft);

  /* Chiffre — les cotes, les quantités, les prix.
     tabular-nums garde les colonnes alignées sans police monospace : c'est
     ce qui permet d'abandonner Space Mono sans déformer le tableau. */
  --ccx-ch-size:13px;   --ccx-ch-weight:400; --ccx-ch-track:0;
  --ccx-ch-color:var(--ccx-ink);

  /* Trois variantes assumées, parce que la hiérarchie les demande. */
  --ccx-prix-size:18px;     --ccx-prix-weight:700;   /* le total */
  --ccx-th-size:9.5px;                                /* l'en-tête du tableau */
  --ccx-mini-size:10px;                               /* nom de vignette, badge */
  --ccx-ref-size:9px;                                 /* la référence nuancier */
  --ccx-t1-fenetre:16px;                              /* le titre d'une fenêtre */
  --ccx-nom-grand:15px;                               /* un décor en grand format */
  --ccx-ds-ref-size:14px;                             /* la référence d'une demande */
  --ccx-icone:24px; --ccx-icone-lg:26px;              /* fermer, et parcourir */

  /* ---------- Les quatre niveaux de bouton ----------
     repos · survol · sélectionné · désactivé. L'état SÉLECTIONNÉ n'est pas
     une finition : pour le niveau 3, c'est lui qui dit au client ce qu'il a
     choisi. */

  /* Bouton 1 — l'action qui engage : « Ajouter au panier » */
  --ccx-b1-bg:var(--ccx-ink);        --ccx-b1-ink:var(--ccx-paper);
  --ccx-b1-bord:transparent;         --ccx-b1-bord-w:0px;      --ccx-b1-bord-style:solid;
  --ccx-b1-bg-hover:var(--ccx-ink-fort);
  --ccx-b1-size:12.5px;              --ccx-b1-weight:600;
  --ccx-b1-case:none;                --ccx-b1-track:.02em;
  --ccx-b1-r:6px;
  --ccx-b1-ombre:0 1px 2px rgba(16,16,16,.05), 0 12px 28px -14px rgba(16,16,16,.14);

  /* Bouton 2 — l'action qui propose : « + Tiroir », « + Ajouter un caisson » */
  --ccx-b2-bg:var(--ccx-paper);      --ccx-b2-ink:var(--ccx-ink-soft);
  --ccx-b2-bord:var(--ccx-line-strong); --ccx-b2-bord-w:1px;    --ccx-b2-bord-style:solid;
  --ccx-b2-bord-hover:var(--ccx-ink);   --ccx-b2-ink-hover:var(--ccx-ink);
  --ccx-b2-size:11.5px;              --ccx-b2-weight:400;
  --ccx-b2-r:6px;

  /* Bouton 3 — le choix, de loin le plus nombreux */
  --ccx-b3-bg:var(--ccx-paper);      --ccx-b3-ink:var(--ccx-ink);
  --ccx-b3-bord:var(--ccx-line);     --ccx-b3-bord-w:1px;       --ccx-b3-bord-style:solid;
  --ccx-b3-bord-hover:var(--ccx-line-strong);
  --ccx-b3-bg-on:var(--ccx-accent-soft); --ccx-b3-ink-on:var(--ccx-ink);
  --ccx-b3-bord-on:var(--ccx-ink);   --ccx-b3-weight-on:600;
  --ccx-b3-r:6px;
  /* Contour d'UN bouton précis, par exception au reste du groupe : par
     défaut un simple alias du contour de groupe ci-dessus, qu'un attribut
     `style` posé sur ce seul bouton (includes/front.php, ccx_opt_style_attr)
     vient éventuellement recouvrir. */
  --ccx-opt-bord:var(--ccx-b3-bord); --ccx-opt-bord-on:var(--ccx-b3-bord-on);

  /* Bouton 4 — icônes et liens */
  --ccx-b4-ink:var(--ccx-ink-soft);  --ccx-b4-ink-hover:var(--ccx-ink);
  --ccx-b4-bord:var(--ccx-line);     --ccx-b4-bord-w:1px;       --ccx-b4-bord-style:solid;
  --ccx-b4-r:4px;

  /* ---------- Les sept familles de cadres ----------
     Une épaisseur à 0 retire le trait SANS que la mise en page bouge : les
     marges intérieures restent. C'est « enlever les cadres », demandé tel
     quel. */
  --ccx-cadre-bloc-w:1px;    --ccx-cadre-bloc-c:var(--ccx-line);   --ccx-cadre-bloc-r:8px;
  --ccx-cadre-etape-w:1px;   --ccx-cadre-etape-c:var(--ccx-line);  --ccx-cadre-etape-r:8px;
  --ccx-cadre-carte-w:1px;   --ccx-cadre-carte-c:var(--ccx-line);  --ccx-cadre-carte-r:8px;
  --ccx-cadre-champ-w:1px;   --ccx-cadre-champ-c:var(--ccx-line);  --ccx-cadre-champ-r:6px;
  --ccx-cadre-tableau-w:1px; --ccx-cadre-tableau-c:var(--ccx-line);
  --ccx-cadre-vignette-w:1px;--ccx-cadre-vignette-c:var(--ccx-line-strong); --ccx-cadre-vignette-r:3px;
  --ccx-cadre-bloc-ombre:0 1px 2px rgba(16,16,16,.05), 0 12px 28px -14px rgba(16,16,16,.14);
  --ccx-cadre-carte-ombre:0 1px 2px rgba(16,16,16,.035);
  --ccx-cadre-etape-ombre:0 1px 2px rgba(16,16,16,.04);

  /* ---------- Rayons, mouvement, anneau de focus ----------
     L'anneau de focus n'est pas réglable : c'est lui qui rend le
     configurateur utilisable au clavier. */
  --ccx-r-xs:4px; --ccx-r-sm:6px; --ccx-r:8px; --ccx-r-lg:14px; --ccx-r-pilule:100px;
  --ccx-ring:0 0 0 3px rgba(26,26,26,.14);
  --ccx-ease:cubic-bezier(.2,.7,.3,1);
  --ccx-dur:.16s;
  --ccx-shadow-lift:0 2px 4px rgba(16,16,16,.06), 0 18px 36px -16px rgba(16,16,16,.2);
}

/* Les anciens noms restent en vie le temps d'une version : un thème enfant
   qui les surchargeait ne casse pas du jour au lendemain. */
.ccx-app{
  --paper:var(--ccx-paper); --surface:var(--ccx-surface);
  --ink:var(--ccx-ink); --ink-soft:var(--ccx-ink-soft);
  --line:var(--ccx-line); --line-strong:var(--ccx-line-strong);
  --accent:var(--ccx-accent); --accent-soft:var(--ccx-accent-soft);
  --accent-ink:var(--ccx-accent-ink);
  --warn:var(--ccx-warn); --warn-soft:var(--ccx-warn-soft);
  --alert:var(--ccx-alert); --alert-soft:var(--ccx-alert-soft);
  --r:var(--ccx-r); --r-xs:var(--ccx-r-xs); --r-sm:var(--ccx-r-sm); --r-lg:var(--ccx-r-lg);
  --ring:var(--ccx-ring); --ease:var(--ccx-ease); --dur:var(--ccx-dur);
  --shadow:var(--ccx-cadre-bloc-ombre); --shadow-lift:var(--ccx-shadow-lift);

  font-family:var(--ccx-font);
  color:var(--ccx-ink);
  background:var(--ccx-paper);
  line-height:1.45;
  font-size:calc(var(--ccx-base-size) * var(--ccx-echelle));

  max-width:1080px; margin:0 auto;
  border-radius:var(--ccx-cadre-bloc-r);
  /* overflow:clip découpe les coins arrondis SANS piéger le position:sticky
     du viewer (contrairement à overflow:hidden). hidden = repli navigateurs anciens. */
  overflow:hidden;
  overflow:clip;
  border:var(--ccx-cadre-bloc-w) solid var(--ccx-cadre-bloc-c);
  box-shadow:var(--ccx-cadre-bloc-ombre);
  -webkit-font-smoothing:antialiased;
}
.ccx-app *{box-sizing:border-box; margin:0; padding:0}
.ccx-app button{font:inherit; cursor:pointer; border:none; background:none; color:inherit; line-height:1}
.ccx-app input,.ccx-app select,.ccx-app output{font:inherit}
.ccx-app label{margin:0}
.ccx-app h1,.ccx-app h2,.ccx-app h3,.ccx-app .mono{font-family:var(--ccx-font); line-height:1.2}
.ccx-app .mono-num{font-family:var(--ccx-font-chiffre); font-variant-numeric:tabular-nums}
.ccx-app em{font-style:normal; opacity:.55; font-size:.9em; margin-left:2px}

/* ---------- Header ---------- */
.ccx-app .ccx-header{
  padding:16px 22px; border-bottom:var(--ccx-cadre-bloc-w) solid var(--ccx-cadre-bloc-c);
  display:var(--ccx-entete-d); align-items:baseline; gap:14px; flex-wrap:wrap;
  background:var(--ccx-surface);
}
.ccx-app .ccx-header h1{font-size:calc(var(--ccx-t1-size) * var(--ccx-echelle)); font-weight:var(--ccx-t1-weight); text-transform:var(--ccx-t1-case); letter-spacing:var(--ccx-t1-track); color:var(--ccx-t1-color)}
.ccx-app .ccx-header .tag{
  font-size:calc(var(--ccx-mini-size) * var(--ccx-echelle)); letter-spacing:.14em; text-transform:uppercase;
  color:var(--ccx-ink-soft); border:var(--ccx-b4-bord-w) solid var(--ccx-line-strong); border-radius:var(--ccx-r-pilule);
  padding:2px 8px; font-weight:var(--ccx-li-weight);
}
.ccx-app .ccx-header .sub{font-size:calc(var(--ccx-t3-size) * var(--ccx-echelle)); color:var(--ccx-ink-soft); margin-left:auto}

/* ---------- Bandeau de session ----------
   Le client arrive par un lien d'e-mail : il doit lire en une ligne où il est,
   et voir nommés les composants que l'atelier a ajoutés pour lui. */
.ccx-app .ccx-session{
  padding:14px 22px; border-bottom:1px solid var(--ccx-line);
  background:var(--ccx-accent-soft); font-size:calc(var(--ccx-b1-size) * var(--ccx-echelle));
}
.ccx-app .ccx-session p{margin:0 0 6px; color:var(--ccx-ink-soft)}
.ccx-app .ccx-session p:last-of-type{margin-bottom:0}
.ccx-app .ccx-session-h{display:flex; align-items:center; gap:10px; margin-bottom:5px}
.ccx-app .ccx-session-h strong{font-size:calc(var(--ccx-base-size) * var(--ccx-echelle)); color:var(--ccx-ink)}
.ccx-app .ccx-session-st{
  font-size:calc(var(--ccx-mini-size) * var(--ccx-echelle)); letter-spacing:.14em; text-transform:uppercase;
  border:1px solid var(--ccx-line-strong); border-radius:100px; padding:2px 8px; color:var(--ccx-ink-soft);
}
.ccx-app .ccx-session-sur{color:var(--ccx-ink)}
.ccx-app .ccx-session-fil{
  margin-top:8px; font-size:calc(var(--ccx-t3-size) * var(--ccx-echelle)); text-decoration:underline;
  text-underline-offset:3px; color:var(--ccx-ink);
}
.ccx-app .ccx-session--ferme{background:var(--ccx-warn-soft)}
.ccx-app .ccx-session-cta{
  display:inline-block; margin-top:4px; padding:7px 14px; border-radius:var(--ccx-r);
  background:var(--ccx-ink); color:var(--ccx-paper); text-decoration:none; font-size:calc(var(--ccx-b1-size) * var(--ccx-echelle)); font-weight:500;
}

/* ---------- Layout ---------- */
.ccx-app .wrap{display:grid; grid-template-columns:minmax(0,1fr) minmax(0,1.575fr); gap:0; align-items:start}
.ccx-app .config{padding:18px 22px 40px; min-width:0}
/* --ccx-header-offset = hauteur de l'en-tête fixe du thème (Divi ≈ 54px scrollé),
   utilisé comme dégagement en haut pour le panneau collant. Ajustable par thème. */
.ccx-app{ --ccx-header-offset:70px; }
/* Barre d'administration WordPress (utilisateur connecté) : +32px fixes en haut. */
.admin-bar .ccx-app{ --ccx-header-offset:102px; }

/* .viewer = colonne pleine hauteur : porte le fond + le trait de séparation.
   align-self:stretch donne au panneau collant à l'intérieur la marge pour rester
   collé sur toute la longueur du scroll. */
.ccx-app .viewer{
  align-self:stretch; padding:18px 22px 40px;
  border-left:var(--ccx-cadre-bloc-w) solid var(--ccx-cadre-bloc-c); background:var(--ccx-surface);
}
/* Toute la partie droite (aperçu + récap + débit) reste collée sous l'en-tête.
   Limitée à la hauteur visible : si le contenu dépasse, il défile à l'intérieur
   du panneau au lieu de sortir de l'écran. */
.ccx-app .viewer-sticky{
  position:sticky; top:var(--ccx-header-offset);
  max-height:calc(100vh - var(--ccx-header-offset) - 12px);
  overflow:auto;
  /* place pour la barre de défilement interne sans coller au texte */
  scrollbar-gutter:stable;
}
@media(max-width:920px){
  .ccx-app .wrap{grid-template-columns:1fr}
  .ccx-app .viewer{border-left:none; border-top:var(--ccx-cadre-bloc-w) solid var(--ccx-cadre-bloc-c)}
  /* Colonne unique : le panneau repasse dans le flux normal. */
  .ccx-app .viewer-sticky{position:static; max-height:none; overflow:visible}
}

/* ---------- Sections (accordéons via <details>) ---------- */
.ccx-app .section{
  margin-bottom:8px;
  border:var(--ccx-cadre-etape-w) solid var(--ccx-cadre-etape-c);
  border-radius:var(--ccx-cadre-etape-r);
  background:var(--ccx-paper);
}
.ccx-app .section > .head{
  display:flex; align-items:center; gap:10px;
  padding:12px 14px;
  cursor:pointer;
  list-style:none; /* retire le triangle par défaut */
  user-select:none;
  position:relative;
}
.ccx-app .section > .head::-webkit-details-marker{display:none}
.ccx-app .section > .head::after{
  content:''; position:absolute; right:14px; top:50%;
  width:8px; height:8px;
  border-right:1.5px solid var(--ccx-ink-soft);
  border-bottom:1.5px solid var(--ccx-ink-soft);
  transform:translateY(-70%) rotate(-45deg);
  transition:transform .18s ease;
}
.ccx-app .section[open] > .head::after{
  transform:translateY(-30%) rotate(45deg);
}
.ccx-app .section > .head:hover{background:var(--ccx-surface)}
.ccx-app .section[open] > .head{border-bottom:var(--ccx-cadre-etape-w) solid var(--ccx-cadre-etape-c)}
.ccx-app .section .num{
  font-family:var(--ccx-font-chiffre); font-size:calc(var(--ccx-no-size) * var(--ccx-echelle));
  font-variant-numeric:tabular-nums; color:var(--ccx-no-color);
  border:var(--ccx-cadre-etape-w) solid var(--ccx-cadre-etape-c); background:var(--ccx-paper);
  width:22px; height:22px; display:grid; place-items:center; border-radius:3px; flex:none;
}
.ccx-app .section h2{font-size:calc(var(--ccx-t2-size) * var(--ccx-echelle)); text-transform:var(--ccx-t2-case); letter-spacing:var(--ccx-t2-track); font-weight:var(--ccx-t2-weight); color:var(--ccx-t2-color)}
.ccx-app .section > *:not(.head){padding-left:14px; padding-right:14px}
.ccx-app .section > .head + .ccx-regle-msgs + *{padding-top:14px}
.ccx-app .section > *:not(.head):last-child{padding-bottom:14px}
/* Le dernier enfant réel d'une étape est parfois une alerte encore masquée
   (dim-alert, forced-note) ou un champ conditionnel (.hidden) : la règle
   ci-dessus lui donne alors sa marge à lui, invisible, et l'étape se
   retrouve collée à son cadre bas. C'est l'élément visible juste avant qui
   doit la porter. */
.ccx-app .section > *:has(+ .dim-alert:last-child:not(.on)),
.ccx-app .section > *:has(+ .forced-note:last-child:not(.on)),
.ccx-app .section > *:has(+ .hidden:last-child){padding-bottom:14px}
.ccx-app .section .hint{font-size:calc(var(--ccx-no-size) * var(--ccx-echelle)); font-weight:var(--ccx-no-weight); color:var(--ccx-no-color); margin:0 0 8px 0}

/* Case Plinthe (checkbox inline sous socle) */
.ccx-app .ccx-plinthe{
  display:inline-flex; align-items:center; gap:8px;
  margin-top:10px; padding:6px 10px;
  border:1px solid var(--ccx-line); border-radius:4px; background:var(--ccx-paper);
  cursor:pointer; font-size:calc(var(--ccx-t3-size) * var(--ccx-echelle));
  transition:.12s;
}
.ccx-app .ccx-plinthe:hover{border-color:var(--ccx-line-strong)}
.ccx-app .ccx-plinthe input{accent-color:var(--ccx-ink); margin:0}
.ccx-app .ccx-plinthe:has(input:checked){border-color:var(--ccx-ink); background:var(--ccx-accent-soft); font-weight:500}
.ccx-app .ccx-plinthe.hidden{display:none}
.ccx-app .ccx-pieds-size.hidden{display:none}
.ccx-app .ccx-patins-size.hidden{display:none}

/* ---------- Controls ---------- */
.ccx-app .field{margin-bottom:12px}
.ccx-app .field > label{display:block; font-size:calc(var(--ccx-li-size) * var(--ccx-echelle)); font-weight:var(--ccx-li-weight); text-transform:var(--ccx-li-case); letter-spacing:var(--ccx-li-track); color:var(--ccx-li-color); margin-bottom:5px}
.ccx-app .field > label.group-title{font-size:calc(var(--ccx-t3-size) * var(--ccx-echelle)); font-weight:var(--ccx-t3-weight); text-transform:var(--ccx-t3-case); letter-spacing:var(--ccx-t3-track); color:var(--ccx-t3-color)}
.ccx-app .dims{display:grid; grid-template-columns:repeat(3,1fr); gap:8px}
.ccx-app .dims .unit{position:relative}
.ccx-app .dims .unit label{display:block; font-size:calc(var(--ccx-no-size) * var(--ccx-echelle)); font-weight:var(--ccx-no-weight); color:var(--ccx-no-color); margin-bottom:4px}
.ccx-app .dims .unit span{position:absolute; right:9px; top:calc(50% + 8px); transform:translateY(-50%); font-size:calc(var(--ccx-no-size) * var(--ccx-echelle)); color:var(--ccx-no-color); font-family:var(--ccx-font-chiffre); pointer-events:none}
.ccx-app input[type=number]{
  width:100%; font-family:var(--ccx-font-chiffre);
  font-size:calc(var(--ccx-ch-size) * var(--ccx-echelle));
  font-weight:var(--ccx-ch-weight); letter-spacing:var(--ccx-ch-track);
  font-variant-numeric:tabular-nums;
  padding:7px 28px 7px 10px;
  border:var(--ccx-cadre-champ-w) solid var(--ccx-cadre-champ-c); border-radius:var(--ccx-r-xs);
  background:var(--ccx-paper); color:var(--ccx-ch-color); height:auto; line-height:normal;
  transition:border-color .12s;
}
.ccx-app input[type=number]:hover{border-color:var(--ccx-line-strong)}
.ccx-app input[type=number]:focus{outline:none; border-color:var(--ccx-ink); box-shadow:0 0 0 1px var(--ccx-ink)}
.ccx-app input[type=number].out-of-range{border-color:var(--ccx-alert); background:var(--ccx-alert-soft)}

.ccx-app .dim-alert{
  display:none; margin-top:8px; padding:7px 10px;
  font-size:calc(var(--ccx-co-size) * var(--ccx-echelle));
  color:var(--ccx-alert); background:var(--ccx-alert-soft);
  border:var(--ccx-cadre-champ-w) solid var(--ccx-alert);
  border-radius:var(--ccx-r-xs);
}
.ccx-app .dim-alert.on{display:block}

/* segmented / pills — plan technique */
.ccx-app .seg{display:flex; flex-wrap:wrap; gap:5px}
.ccx-app .seg label{cursor:pointer; position:relative}
.ccx-app .seg input{position:absolute; opacity:0; pointer-events:none}
.ccx-app .seg span{
  display:block; text-align:center; padding:7px 12px;
  font-size:calc(var(--ccx-bt-size) * var(--ccx-echelle));
  font-weight:var(--ccx-bt-weight); text-transform:var(--ccx-bt-case); letter-spacing:var(--ccx-bt-track);
  border:var(--ccx-b3-bord-w) var(--ccx-b3-bord-style) var(--ccx-opt-bord); border-radius:var(--ccx-r-xs);
  background:var(--ccx-b3-bg); color:var(--ccx-b3-ink);
  transition:.12s; white-space:nowrap;
}
.ccx-app .seg span:hover{border-color:var(--ccx-b3-bord-hover)}
.ccx-app .seg input:checked + span{border-color:var(--ccx-opt-bord-on); background:var(--ccx-b3-bg-on); color:var(--ccx-b3-ink-on); font-weight:var(--ccx-b3-weight-on)}
.ccx-app .seg input:focus-visible + span{outline:2px solid var(--ccx-ink); outline-offset:2px}
.ccx-app .seg input:disabled + span{opacity:.35; cursor:not-allowed; background:var(--ccx-surface)}
.ccx-app .seg label.locked span{border-style:dashed}

.ccx-app .chips{display:flex; flex-wrap:wrap; gap:5px}
.ccx-app .chips label{cursor:pointer; position:relative}
.ccx-app .chips input{position:absolute; opacity:0; pointer-events:none}
.ccx-app .chips span{
  display:block; text-align:center; padding:7px 12px;
  font-size:calc(var(--ccx-bt-size) * var(--ccx-echelle));
  font-weight:var(--ccx-bt-weight); text-transform:var(--ccx-bt-case); letter-spacing:var(--ccx-bt-track);
  border:var(--ccx-b3-bord-w) var(--ccx-b3-bord-style) var(--ccx-opt-bord); border-radius:var(--ccx-r-xs);
  background:var(--ccx-b3-bg); color:var(--ccx-b3-ink);
  transition:.12s; white-space:nowrap;
}
.ccx-app .chips span:hover{border-color:var(--ccx-b3-bord-hover)}
.ccx-app .chips input:checked + span{border-color:var(--ccx-opt-bord-on); background:var(--ccx-b3-bg-on); color:var(--ccx-b3-ink-on); font-weight:var(--ccx-b3-weight-on)}
.ccx-app .chips input:disabled + span{opacity:.3}

.ccx-app .stepper{display:inline-flex; align-items:center; border:var(--ccx-cadre-champ-w) solid var(--ccx-cadre-champ-c); border-radius:var(--ccx-r-xs); overflow:hidden; background:var(--ccx-paper)}
.ccx-app .stepper button{width:30px; height:32px; font-size:calc(var(--ccx-b1-size) * var(--ccx-echelle) * 1.28); color:var(--ccx-ink)}
.ccx-app .stepper button:hover{background:var(--ccx-accent-soft)}
.ccx-app .stepper output{width:34px; text-align:center; font-family:var(--ccx-font-chiffre); font-size:calc(var(--ccx-ch-size) * var(--ccx-echelle)); font-variant-numeric:tabular-nums; color:var(--ccx-ch-color)}

.ccx-app .row{display:grid; grid-template-columns:1fr; gap:10px}
.ccx-app .row .field > label{font-weight:600; color:var(--ccx-ink)}
.ccx-app .subblock{margin-top:10px; padding:11px 12px}
.ccx-app .subblock.hidden{display:none}
.ccx-app .forced-note{font-size:calc(var(--ccx-no-size) * var(--ccx-echelle)); color:var(--ccx-warn); background:var(--ccx-warn-soft); padding:5px 8px; border-radius:var(--ccx-r-xs); margin-top:7px; display:none}
.ccx-app .forced-note.on{display:block}

/* Sous-catégorie tiroir (nested) */
.ccx-app .ccx-sub-block{margin-top:10px; padding-top:10px; border-top:1px dashed var(--ccx-line-strong)}
.ccx-app .ccx-sub-block.hidden{display:none}
.ccx-app .ccx-sub-block > label{font-size:calc(var(--ccx-no-size) * var(--ccx-echelle)); text-transform:uppercase; letter-spacing:.06em; font-weight:var(--ccx-li-weight); color:var(--ccx-li-color)}
.ccx-app #ccx-block-tiroir > label{font-size:calc(var(--ccx-li-size) * var(--ccx-echelle)); font-weight:var(--ccx-li-weight); color:var(--ccx-li-color); display:block; margin-bottom:5px}

/* ---------- Section 8 : Joues de finition ---------- */
.ccx-app .ccx-joues-list{display:flex; flex-direction:column; gap:10px}
.ccx-app .ccx-joues-empty{margin-top:6px}
.ccx-app .ccx-joue{padding:10px 12px; border:1px solid var(--ccx-line); border-radius:var(--ccx-r); background:var(--ccx-paper)}
.ccx-app .ccx-joue.is-active{border-color:var(--ccx-line-strong); background:var(--ccx-surface)}
.ccx-app .ccx-joue-toggle{display:flex; align-items:center; gap:8px; cursor:pointer; font-size:calc(var(--ccx-b1-size) * var(--ccx-echelle)); font-weight:600; color:var(--ccx-ink)}
.ccx-app .ccx-joue-toggle input{accent-color:var(--ccx-ink); margin:0}
.ccx-app .ccx-joue-params{margin-top:10px; padding-top:10px; border-top:1px dashed var(--ccx-line-strong); display:flex; flex-direction:column; gap:10px}
.ccx-app .ccx-joue-params .field{margin-bottom:0}
.ccx-app .ccx-debords{display:grid; grid-template-columns:repeat(4,1fr); gap:6px}
.ccx-app .ccx-deb{display:flex; flex-direction:column; gap:3px; align-items:center}
.ccx-app .ccx-deb > span{font-size:calc(var(--ccx-mini-size) * var(--ccx-echelle)); color:var(--ccx-ink-soft); font-family:var(--ccx-font-chiffre); font-variant-numeric:tabular-nums}
.ccx-app .ccx-deb input[type=number]{padding:6px 6px; text-align:center}
.ccx-app .ccx-joue-paused{border-style:dashed; background:var(--ccx-warn-soft); border-color:var(--ccx-warn)}
.ccx-app .ccx-joue-pause-msg{font-size:calc(var(--ccx-no-size) * var(--ccx-echelle)); color:var(--ccx-warn)}
.ccx-app .ccx-joue-muted{border-style:dashed; opacity:.6}
.ccx-app .ccx-joue-muted span{font-size:calc(var(--ccx-no-size) * var(--ccx-echelle)); color:var(--ccx-ink-soft)}


/* ---------- Vignettes couleur (échantillon matière) ----------
   La vignette porte la photo du décor si l'atelier en a chargé une ; la
   couleur reste dessous et sert de repli tant que l'image n'est pas arrivée.
   La loupe est un frère du <label>, jamais son enfant : dedans, le moindre
   clic dessus cocherait la teinte en même temps qu'il ouvre le grand format. */
.ccx-app .swatches{display:flex; flex-wrap:wrap; gap:10px}
.ccx-app .ccx-sw-wrap{position:relative; width:52px}
.ccx-app .swatches label{cursor:pointer; position:relative; display:block; width:100%}
.ccx-app .swatches input{position:absolute; opacity:0; pointer-events:none}
.ccx-app .swatches .sw{
  width:52px; height:52px;
  border-radius:var(--ccx-cadre-vignette-r);
  border:var(--ccx-cadre-vignette-w) solid var(--ccx-cadre-vignette-c);
  box-shadow:0 1px 2px rgba(0,0,0,.04), inset 0 -6px 10px rgba(0,0,0,.04);
  transition:.14s; display:block; position:relative;
  background-size:cover; background-position:center;
}
.ccx-app .swatches .sw::after{
  content:''; position:absolute; inset:2px;
  border-radius:2px;
  box-shadow:inset 0 0 0 1px var(--ccx-vernis);
  pointer-events:none;
}
.ccx-app .swatches input:checked + .sw{
  border-color:var(--ccx-ink);
  box-shadow:0 0 0 2px var(--ccx-ink), 0 1px 2px rgba(0,0,0,.04), inset 0 -6px 10px rgba(0,0,0,.04);
}
.ccx-app .swatches input:focus-visible + .sw{outline:2px solid var(--ccx-ink); outline-offset:3px}
.ccx-app .swatches .name{
  display:block; font-size:calc(var(--ccx-mini-size) * var(--ccx-echelle)); text-align:center; margin-top:5px;
  color:var(--ccx-no-color); line-height:1.2;
}
/* La référence nuancier : discrète sous le nom, mais c'est elle qui engage. */
.ccx-app .swatches .ref{
  display:block; font-family:var(--ccx-font-chiffre); font-variant-numeric:tabular-nums;
  font-size:calc(var(--ccx-ref-size) * var(--ccx-echelle)); text-align:center; margin-top:2px;
  color:var(--ccx-ink); letter-spacing:.02em; line-height:1.2;
}

/* Loupe : discrète au repos, franche au survol. Toujours visible au doigt,
   où il n'existe pas de survol pour la révéler. */
.ccx-app .ccx-zoom{
  position:absolute; top:3px; right:3px; z-index:2;
  width:20px; height:20px; padding:0;
  display:flex; align-items:center; justify-content:center;
  border-radius:3px;
  background:var(--ccx-verre); color:var(--ccx-ink);
  box-shadow:0 1px 3px rgba(0,0,0,.22); /* matière */
  opacity:0; transform:scale(.9); transition:.13s;
}
.ccx-app .ccx-zoom svg{width:13px; height:13px; display:block}
.ccx-app .ccx-sw-wrap:hover .ccx-zoom,
.ccx-app .ccx-zoom:focus-visible{opacity:1; transform:none}
.ccx-app .ccx-zoom:hover{background:var(--ccx-paper); box-shadow:0 2px 6px rgba(0,0,0,.28)} /* matière */
.ccx-app .ccx-zoom:focus-visible{outline:2px solid var(--ccx-ink); outline-offset:2px}
@media (hover:none){ .ccx-app .ccx-zoom{opacity:1; transform:none} }

/* ---------- Grand format d'un décor ----------
   Ce bloc n'est PAS scopé sous .ccx-app : la modale est posée sur le <body>
   pour échapper à l'overflow:clip du configurateur et aux z-index du thème.
   Elle redéclarait autrefois ses propres jetons, et restait donc dans
   l'ancien style quand l'atelier réglait sa charte. Elle lit désormais les
   jetons globaux, posés sur :root exactement pour cette raison. */
body.ccx-lb-lock{overflow:hidden}
.ccx-lb{
  position:fixed; inset:0; z-index:2147483000;
  display:flex; align-items:center; justify-content:center;
  font-family:var(--ccx-font); font-size:calc(var(--ccx-base-size) * var(--ccx-echelle)); line-height:1.45;
  color:var(--ccx-ink);
}
.ccx-lb[hidden]{display:none}
.ccx-lb *{box-sizing:border-box; margin:0; padding:0}
.ccx-lb button{font:inherit; cursor:pointer; border:none; background:none; color:inherit; line-height:1}
.ccx-lb-bd{position:absolute; inset:0; background:var(--ccx-voile)}
.ccx-lb-panel{
  position:relative; z-index:1;
  width:min(880px,92vw);
  background:var(--ccx-paper); border-radius:var(--ccx-r);
  box-shadow:0 24px 60px rgba(0,0,0,.4); /* matière */
  display:grid; grid-template-columns:auto 1fr auto; grid-template-rows:1fr auto;
  overflow:hidden;
}
.ccx-lb-stage{
  grid-column:2; grid-row:1;
  display:flex; align-items:center; justify-content:center;
  background:var(--ccx-surface); min-height:200px; padding:14px;
}
.ccx-lb-img{max-width:100%; max-height:min(66vh,560px); display:block; border-radius:3px}
.ccx-lb-flat{
  width:100%; height:min(46vh,320px); border-radius:3px;
  border:1px solid var(--ccx-line-strong);
  display:flex; align-items:flex-end; justify-content:center; padding:10px;
}
.ccx-lb-flat span{
  font-size:calc(var(--ccx-no-size) * var(--ccx-echelle)); color:var(--ccx-ink); background:var(--ccx-verre-plein);
  border-radius:3px; padding:3px 8px;
}
.ccx-lb-nav{
  grid-row:1; align-self:stretch;
  width:42px; font-size:calc(var(--ccx-icone-lg) * var(--ccx-echelle)); color:var(--ccx-ink-soft);
  background:var(--ccx-paper); transition:.13s;
}
.ccx-lb-nav[hidden]{display:none}
.ccx-lb-prev{grid-column:1}
.ccx-lb-next{grid-column:3}
.ccx-lb-nav:hover{background:var(--ccx-accent-soft); color:var(--ccx-ink)}
.ccx-lb-nav:focus-visible{outline:2px solid var(--ccx-ink); outline-offset:-3px}
.ccx-lb-bar{
  grid-column:1 / -1; grid-row:2;
  display:flex; align-items:center; justify-content:space-between; gap:14px;
  padding:12px 16px; border-top:1px solid var(--ccx-line); flex-wrap:wrap;
}
.ccx-lb-meta{display:flex; align-items:baseline; gap:10px; flex-wrap:wrap}
.ccx-lb-name{font-family:var(--ccx-font); font-size:calc(var(--ccx-nom-grand) * var(--ccx-echelle)); font-weight:600}
.ccx-lb-ref{
  font-family:var(--ccx-font-chiffre); font-variant-numeric:tabular-nums; font-size:calc(var(--ccx-no-size) * var(--ccx-echelle));
  border:1px solid var(--ccx-line-strong); border-radius:3px; padding:2px 7px; color:var(--ccx-ink);
}
.ccx-lb-ref[hidden]{display:none}
.ccx-lb-pick{
  border:1px solid var(--ccx-ink); background:var(--ccx-ink); color:var(--ccx-paper);
  border-radius:3px; padding:8px 16px; font-size:calc(var(--ccx-t3-size) * var(--ccx-echelle)); font-weight:600; transition:.13s;
}
.ccx-lb-pick:hover:not(:disabled){background:var(--ccx-ink-fort)}
.ccx-lb-pick:disabled{
  background:transparent; color:var(--ccx-ink-soft); border-color:var(--ccx-line-strong); cursor:default;
}
.ccx-lb-pick:focus-visible{outline:2px solid var(--ccx-ink); outline-offset:2px}
.ccx-lb-x{
  position:absolute; top:6px; right:8px; z-index:2;
  width:30px; height:30px; font-size:calc(var(--ccx-icone) * var(--ccx-echelle)); color:var(--ccx-ink);
  background:var(--ccx-verre-plein); border-radius:3px;
}
.ccx-lb-x:hover{background:var(--ccx-paper)}
.ccx-lb-x:focus-visible{outline:2px solid var(--ccx-ink); outline-offset:2px}

/* Sous 560 px les flèches latérales mangent la photo : on les met sous elle. */
@media (max-width:560px){
  .ccx-lb-panel{grid-template-columns:1fr 1fr; grid-template-rows:1fr auto auto}
  .ccx-lb-stage{grid-column:1 / -1; grid-row:1}
  .ccx-lb-nav{grid-row:2; height:40px; border-top:1px solid var(--ccx-line)}
  .ccx-lb-prev{grid-column:1}
  .ccx-lb-next{grid-column:2}
  .ccx-lb-bar{grid-row:3; justify-content:center; text-align:center}
}
/* ---------- Viewer ---------- */
.ccx-app .viewer h2{font-size:calc(var(--ccx-t2-size) * var(--ccx-echelle)); text-transform:var(--ccx-t2-case); letter-spacing:var(--ccx-t2-track); color:var(--ccx-ink-soft); margin-bottom:9px; font-weight:var(--ccx-t2-weight)}
.ccx-app .canvas{
  background:var(--ccx-paper);
  border:var(--ccx-cadre-carte-w) solid var(--ccx-cadre-carte-c); border-radius:var(--ccx-cadre-carte-r);
  padding:8px; margin-bottom:16px;
}
.ccx-app .canvas svg{display:block; width:100%; height:auto}

/* Halo noir sur pièce modifiée */
@keyframes ccx-pulse {
  0%   { opacity:0;   stroke-width:2; }
  30%  { opacity:.75; stroke-width:5; }
  100% { opacity:0;   stroke-width:2; }
}
.ccx-app .canvas .ccx-hl{
  fill:none; stroke:var(--ccx-ink); stroke-linejoin:round;
  animation:ccx-pulse 1.1s ease-out forwards;
  pointer-events:none;
}
/* Pulsation sur cellule modifiée (récap) */
.ccx-app .recap dd.ccx-hl-cell{
  border-radius:3px;
  animation:ccx-cell-pulse 1.1s ease-out forwards;
}
@keyframes ccx-cell-pulse {
  0%   { background:transparent; box-shadow:0 0 0 0 var(--ccx-accent-soft); }
  25%  { background:var(--ccx-accent-soft); box-shadow:0 0 0 3px var(--ccx-accent-soft); }
  100% { background:transparent; box-shadow:0 0 0 0 var(--ccx-accent-soft); }
}

.ccx-app .recap{background:var(--ccx-paper); border:var(--ccx-cadre-carte-w) solid var(--ccx-cadre-carte-c); border-radius:var(--ccx-cadre-carte-r); padding:14px 16px; margin-bottom:16px}
.ccx-app .recap dl{display:grid; grid-template-columns:auto 1fr; gap:5px 12px; font-size:calc(var(--ccx-t3-size) * var(--ccx-echelle))}
.ccx-app .recap dt{color:var(--ccx-no-color); font-weight:600}
.ccx-app .recap dd{text-align:right; font-weight:var(--ccx-li-weight); color:var(--ccx-co-color)}
.ccx-app .recap dd.hi{color:var(--ccx-ch-color); font-family:var(--ccx-font-chiffre)}

.ccx-app table{width:100%; border-collapse:collapse; font-size:calc(var(--ccx-co-size) * var(--ccx-echelle)); margin:0; background:transparent}
.ccx-app th,.ccx-app td{padding:7px 10px; text-align:left; border-bottom:var(--ccx-cadre-tableau-w) solid var(--ccx-cadre-tableau-c); color:var(--ccx-co-color); background:transparent}
.ccx-app th{font-size:calc(var(--ccx-th-size) * var(--ccx-echelle)); color:var(--ccx-no-color); font-weight:var(--ccx-t2-weight)}
.ccx-app td.n,.ccx-app th.n{text-align:right; font-family:var(--ccx-font-chiffre); font-variant-numeric:tabular-nums}
.ccx-app tbody tr:last-child td{border-bottom:none}

.ccx-app .wip{font-size:calc(var(--ccx-no-size) * var(--ccx-echelle)); color:var(--ccx-warn); background:var(--ccx-warn-soft); border:1px dashed var(--ccx-warn); border-radius:var(--ccx-r); padding:7px 10px}
.ccx-app .foot{margin-top:12px; font-size:calc(var(--ccx-no-size) * var(--ccx-echelle)); color:var(--ccx-no-color)}

/* ---------- Prix + panier ---------- */
.ccx-app .price{background:var(--ccx-paper); border:var(--ccx-cadre-carte-w) solid var(--ccx-cadre-carte-c); border-radius:var(--ccx-cadre-carte-r); padding:14px 16px}
.ccx-app .price .price-lines div{display:flex; justify-content:space-between; gap:12px; font-size:calc(var(--ccx-co-size) * var(--ccx-echelle)); color:var(--ccx-no-color); padding:2px 0}
.ccx-app .price .price-lines div > span{font-weight:600}
.ccx-app .price .price-lines b{font-family:var(--ccx-font-chiffre); font-variant-numeric:tabular-nums; font-weight:var(--ccx-li-weight); color:var(--ccx-ch-color); white-space:nowrap}
.ccx-app .price .price-total{display:flex; justify-content:space-between; align-items:baseline; gap:12px; border-top:var(--ccx-cadre-tableau-w) solid var(--ccx-cadre-tableau-c); margin-top:8px; padding-top:10px}
.ccx-app .price .price-lines:empty + .price-total{border-top:none; margin-top:0; padding-top:0}
.ccx-app .price .price-total span{font-size:calc(var(--ccx-t2-size) * var(--ccx-echelle)); text-transform:var(--ccx-t2-case); letter-spacing:var(--ccx-t2-track); color:var(--ccx-ink-soft); font-weight:var(--ccx-t2-weight)}
.ccx-app .price .price-total b{font-family:var(--ccx-font-chiffre); font-variant-numeric:tabular-nums; font-size:calc(var(--ccx-prix-size) * var(--ccx-echelle)); font-weight:var(--ccx-prix-weight); color:var(--ccx-ch-color); white-space:nowrap}
.ccx-app .cart-row{display:flex; align-items:stretch; gap:8px; margin-top:12px}
.ccx-app .cart-row .qty{display:flex; align-items:center; gap:6px; flex:none}
.ccx-app .cart-row .qty span{font-size:calc(var(--ccx-no-size) * var(--ccx-echelle)); color:var(--ccx-no-color); font-family:var(--ccx-font-chiffre)}
.ccx-app .cart-row .qty input{width:64px; padding:7px 10px}
.ccx-app .add-cart{
  flex:1; background:var(--ccx-b1-bg); color:var(--ccx-b1-ink);
  border:var(--ccx-b1-bord-w) var(--ccx-b1-bord-style) var(--ccx-b1-bord); border-radius:var(--ccx-b1-r);
  padding:10px 14px; font-weight:var(--ccx-b1-weight);
  font-size:calc(var(--ccx-b1-size) * var(--ccx-echelle));
  text-transform:var(--ccx-b1-case); letter-spacing:var(--ccx-b1-track);
  transition:.12s;
}
.ccx-app .add-cart:hover{background:var(--ccx-b1-bg-hover)}
.ccx-app .add-cart:disabled{opacity:.55; cursor:wait}
.ccx-app .cart-msg{display:none; margin-top:10px; font-size:calc(var(--ccx-co-size) * var(--ccx-echelle)); padding:7px 10px; border-radius:4px}
.ccx-app .cart-msg.ok{display:block; border:1px solid var(--ccx-ink); background:var(--ccx-accent-soft); color:var(--ccx-ink)}
.ccx-app .cart-msg.err{display:block; border:1px solid var(--ccx-alert); background:var(--ccx-alert-soft); color:var(--ccx-alert)}
.ccx-app .cart-msg a{color:inherit; font-weight:600}

/* ============================================================
   CAISSONS MULTIPLES — un bandeau au-dessus du formulaire : la liste des
   caissons du projet, celui en cours d'édition mis en évidence. Le
   formulaire et le viewer restent ceux d'un seul caisson à la fois — celui
   pointé par la carte active (docs/CDC-caissons-multiples.md §4).
   ============================================================ */
.ccx-app .ccx-multi{
  padding:14px 22px; border-bottom:1px solid var(--ccx-line); background:var(--ccx-surface);
}
.ccx-app .ccx-multi-head{display:flex; align-items:baseline; gap:10px; margin-bottom:8px}
.ccx-app .ccx-multi-head h2{font-size:calc(var(--ccx-co-size) * var(--ccx-echelle)); font-weight:600; color:var(--ccx-ink)}
.ccx-app .ccx-multi-total{margin-left:auto; font-family:var(--ccx-font-chiffre); font-variant-numeric:tabular-nums; font-size:calc(var(--ccx-b1-size) * var(--ccx-echelle)); color:var(--ccx-ink-soft)}
.ccx-app .ccx-multi-total b{color:var(--ccx-ink); font-weight:500}
.ccx-app .ccx-multi-list{display:flex; flex-direction:column; gap:6px}
.ccx-app .ccx-multi-item{
  display:flex; align-items:center; gap:8px; flex-wrap:wrap;
  background:var(--ccx-paper); border:1px solid var(--ccx-line); border-radius:4px; padding:7px 9px;
  cursor:pointer;
}
.ccx-app .ccx-multi-item:hover{border-color:var(--ccx-line-strong)}
.ccx-app .ccx-multi-item.is-actif{border-color:var(--ccx-ink); box-shadow:inset 0 0 0 1px var(--ccx-ink)}
.ccx-app .ccx-multi-rep{
  flex:none; width:20px; height:20px; border-radius:3px;
  background:var(--ccx-ink); color:var(--ccx-paper); font-family:var(--ccx-font-chiffre); font-variant-numeric:tabular-nums;
  font-size:calc(var(--ccx-no-size) * var(--ccx-echelle)); display:flex; align-items:center; justify-content:center;
}
.ccx-app .ccx-multi-nom{
  flex:1 1 160px; min-width:80px; border:1px solid transparent; background:transparent;
  font-size:calc(var(--ccx-b1-size) * var(--ccx-echelle)); color:var(--ccx-ink); padding:3px 5px; border-radius:3px;
}
.ccx-app .ccx-multi-nom::placeholder{color:var(--ccx-ink-soft)}
.ccx-app .ccx-multi-nom:hover,.ccx-app .ccx-multi-nom:focus{border-color:var(--ccx-line); background:var(--ccx-paper)}
.ccx-app .ccx-multi-cotes{font-size:calc(var(--ccx-no-size) * var(--ccx-echelle)); color:var(--ccx-ink-soft); font-family:var(--ccx-font-chiffre); font-variant-numeric:tabular-nums; white-space:nowrap}
.ccx-app .ccx-multi-qty{display:flex; align-items:center; gap:4px; flex:none}
.ccx-app .ccx-multi-qty span{font-size:calc(var(--ccx-mini-size) * var(--ccx-echelle)); color:var(--ccx-ink-soft); font-family:var(--ccx-font-chiffre); font-variant-numeric:tabular-nums}
.ccx-app .ccx-multi-qty input{width:44px; padding:4px 5px; font-size:calc(var(--ccx-co-size) * var(--ccx-echelle)); text-align:right; border:1px solid var(--ccx-line); border-radius:3px}
.ccx-app .ccx-multi-prix{font-family:var(--ccx-font-chiffre); font-variant-numeric:tabular-nums; font-size:calc(var(--ccx-t3-size) * var(--ccx-echelle)); color:var(--ccx-ink); white-space:nowrap; flex:none}
.ccx-app .ccx-multi-item button{
  flex:none; width:22px; height:22px;
  border:var(--ccx-b4-bord-w) var(--ccx-b4-bord-style) var(--ccx-b4-bord); border-radius:var(--ccx-cadre-vignette-r);
  background:var(--ccx-paper); color:var(--ccx-b4-ink);
  font-size:calc(var(--ccx-t3-size) * var(--ccx-echelle)); line-height:1; cursor:pointer;
}
.ccx-app .ccx-multi-item button:hover{border-color:var(--ccx-b4-ink-hover); color:var(--ccx-b4-ink-hover)}
.ccx-app .ccx-multi-rm:hover{border-color:var(--ccx-alert); color:var(--ccx-alert)}
.ccx-app .ccx-multi-add{
  display:inline-block; margin-top:8px;
  border:var(--ccx-b2-bord-w) dashed var(--ccx-b2-bord); border-radius:var(--ccx-b2-r);
  background:var(--ccx-b2-bg); color:var(--ccx-b2-ink);
  font-size:calc(var(--ccx-b2-size) * var(--ccx-echelle)); font-weight:var(--ccx-b2-weight);
  padding:6px 11px; cursor:pointer; font-family:inherit; transition:.12s;
}
.ccx-app .ccx-multi-add:hover{border-style:solid; border-color:var(--ccx-b2-bord-hover); color:var(--ccx-b2-ink-hover)}
@media(max-width:600px){
  .ccx-app .ccx-multi-item{gap:5px}
  .ccx-app .ccx-multi-cotes{display:none}
}

/* ---------- Mode « sur demande » (épaisseur hors stock) ---------- */
.ccx-app .field.hidden{display:none}
.ccx-app .cart-row.hidden{display:none}
.ccx-app a.ccx-mail-btn{
  display:flex; align-items:center; justify-content:center; text-align:center;
  text-decoration:none; color:var(--ccx-paper);
}
.ccx-app a.ccx-mail-btn:hover{color:var(--ccx-paper)}

/* ============================================================
   ORGANISATION DE FAÇADE — la hauteur du caisson se découpe en
   zones empilées. Une ligne = une zone, lisible d'un coup d'œil :
   son rang, ce qu'elle porte, sa hauteur, et de quoi la déplacer.
   ============================================================ */
.ccx-app .ccx-org{margin-top:14px}
.ccx-app .ccx-zones{display:flex; flex-direction:column; gap:6px; margin:8px 0}
.ccx-app .ccx-zone{
  display:flex; align-items:center; gap:6px; flex-wrap:wrap;
  background:var(--ccx-paper); border:1px solid var(--ccx-line); border-radius:4px; padding:6px 8px;
}
.ccx-app .ccx-z-rep{
  flex:none; width:20px; height:20px; border-radius:3px;
  background:var(--ccx-ink); color:var(--ccx-paper); font-family:var(--ccx-font-chiffre); font-variant-numeric:tabular-nums;
  font-size:calc(var(--ccx-no-size) * var(--ccx-echelle)); display:flex; align-items:center; justify-content:center;
}
.ccx-app .ccx-zone select{
  font-size:calc(var(--ccx-co-size) * var(--ccx-echelle)); padding:5px 7px; border:1px solid var(--ccx-line);
  border-radius:3px; background:var(--ccx-paper); color:var(--ccx-ink); max-width:132px;
}
.ccx-app .ccx-z-h{display:flex; align-items:center; gap:4px; flex:none}
.ccx-app .ccx-z-h input{width:64px; padding:5px 7px; font-size:calc(var(--ccx-co-size) * var(--ccx-echelle)); text-align:right}
.ccx-app .ccx-z-h span{font-size:calc(var(--ccx-mini-size) * var(--ccx-echelle)); color:var(--ccx-ink-soft); font-family:var(--ccx-font-chiffre); font-variant-numeric:tabular-nums}
.ccx-app .ccx-zone button{
  flex:none; width:22px; height:22px; border:1px solid var(--ccx-line);
  border-radius:3px; background:var(--ccx-paper); color:var(--ccx-ink-soft);
  font-size:calc(var(--ccx-t3-size) * var(--ccx-echelle)); line-height:1; cursor:pointer;
}
.ccx-app .ccx-zone button:hover{border-color:var(--ccx-ink); color:var(--ccx-ink)}
.ccx-app .ccx-z-rm:hover{border-color:var(--ccx-alert); color:var(--ccx-alert)}
.ccx-app .ccx-z-up{margin-left:auto}
.ccx-app .ccx-zone-add{display:flex; gap:6px; flex-wrap:wrap; margin-top:8px}
.ccx-app .ccx-zbtn{
  border:var(--ccx-b2-bord-w) dashed var(--ccx-b2-bord); border-radius:var(--ccx-b2-r);
  background:var(--ccx-b2-bg); color:var(--ccx-b2-ink);
  font-size:calc(var(--ccx-b2-size) * var(--ccx-echelle)); font-weight:var(--ccx-b2-weight);
  padding:6px 11px; cursor:pointer; font-family:inherit; transition:.12s;
}
.ccx-app .ccx-zbtn:hover{border-style:solid; border-color:var(--ccx-b2-bord-hover); color:var(--ccx-b2-ink-hover)}

/* ============================================================
   AGENCEMENT AVANCÉ — deux onglets, puis une carte par compartiment.

   Les onglets réemploient le vocabulaire du Bouton 3 : ce sont des choix,
   pas des actions, et le client doit les lire comme les autres boutons de
   choix de la page. Rien n'est écrit en dur ici — c'est ce que vérifie
   tools/jetons.php, et c'est ce qui fait que la charte les repeint.
   ============================================================ */
/* Le titre de la liste d'onglets : c'est le premier choix de la case, il se
   lit comme un sous-titre d'étape (rôle Titre 3) et non comme un libellé de
   champ. Centré avec les onglets qu'il coiffe. */
.ccx-app .ccx-eqtabs-titre{
  margin:16px 0 8px; text-align:center;
  font-size:calc(var(--ccx-t3-size) * var(--ccx-echelle));
  font-weight:var(--ccx-t3-weight); letter-spacing:var(--ccx-t3-track);
  text-transform:var(--ccx-t3-case); color:var(--ccx-t3-color);
}
.ccx-app .ccx-eqtabs{display:flex; justify-content:center; gap:6px; margin:0 0 14px; flex-wrap:wrap}
.ccx-app .ccx-eqtab{
  flex:none; padding:7px 16px; cursor:pointer; font-family:inherit;
  border:var(--ccx-b3-bord-w) var(--ccx-b3-bord-style) var(--ccx-b3-bord);
  border-radius:var(--ccx-b3-r); background:var(--ccx-b3-bg); color:var(--ccx-b3-ink);
  font-size:calc(var(--ccx-bt-size) * var(--ccx-echelle));
  font-weight:var(--ccx-bt-weight); letter-spacing:var(--ccx-bt-track);
  transition:.12s;
}
.ccx-app .ccx-eqtab:hover{border-color:var(--ccx-b3-bord-hover)}
.ccx-app .ccx-eqtab.on{
  background:var(--ccx-b3-bg-on); color:var(--ccx-b3-ink-on);
  border-color:var(--ccx-b3-bord-on); font-weight:var(--ccx-b3-weight-on);
}
.ccx-app .ccx-eqpane[hidden]{display:none}

.ccx-app .ccx-agenc{margin-top:4px}
.ccx-app .ccx-comps{display:flex; flex-direction:column; gap:8px; margin:8px 0}
.ccx-app .ccx-comp{
  background:var(--ccx-paper);
  border:var(--ccx-cadre-carte-w) solid var(--ccx-cadre-carte-c);
  border-radius:var(--ccx-cadre-carte-r);
  padding:8px 10px 10px;
}
.ccx-app .ccx-c-head{display:flex; align-items:center; gap:8px; flex-wrap:wrap}
.ccx-app .ccx-c-titre{
  font-size:calc(var(--ccx-t3-size) * var(--ccx-echelle));
  font-weight:var(--ccx-t3-weight); color:var(--ccx-t3-color);
}
/* La cote résolue vient du même calcul que le débit : elle se lit comme une
   cote, dans la police des chiffres. */
.ccx-app .ccx-c-cote{
  font-family:var(--ccx-font-chiffre); font-variant-numeric:tabular-nums;
  font-size:calc(var(--ccx-no-size) * var(--ccx-echelle)); color:var(--ccx-ink-soft);
}
.ccx-app .ccx-c-head button{
  flex:none; width:22px; height:22px; line-height:1; cursor:pointer;
  border:var(--ccx-b4-bord-w) var(--ccx-b4-bord-style) var(--ccx-b4-bord);
  border-radius:var(--ccx-b4-r); background:var(--ccx-paper); color:var(--ccx-b4-ink);
  font-size:calc(var(--ccx-t3-size) * var(--ccx-echelle));
}
.ccx-app .ccx-c-head button:hover:not(:disabled){border-color:var(--ccx-ink); color:var(--ccx-b4-ink-hover)}
.ccx-app .ccx-c-head button:disabled{opacity:.35; cursor:default}
.ccx-app .ccx-c-rm:hover:not(:disabled){border-color:var(--ccx-alert); color:var(--ccx-alert)}
.ccx-app .ccx-c-up{margin-left:auto}

.ccx-app .ccx-c-body{display:flex; align-items:flex-end; gap:10px; flex-wrap:wrap; margin-top:9px}
.ccx-app .ccx-c-mm,.ccx-app .ccx-c-num,.ccx-app .ccx-c-sel{display:flex; flex-direction:column; gap:3px}
.ccx-app .ccx-c-mm > span:first-child,
.ccx-app .ccx-c-num > span:first-child,
.ccx-app .ccx-c-sel > span:first-child{
  font-size:calc(var(--ccx-li-size) * var(--ccx-echelle));
  font-weight:var(--ccx-li-weight); color:var(--ccx-li-color);
}
.ccx-app .ccx-c-mm{position:relative}
.ccx-app .ccx-c-mm input{
  width:88px; padding:5px 26px 5px 7px; text-align:right;
  font-size:calc(var(--ccx-co-size) * var(--ccx-echelle));
}
.ccx-app .ccx-c-u{
  position:absolute; right:7px; bottom:6px; pointer-events:none;
  font-size:calc(var(--ccx-mini-size) * var(--ccx-echelle)); color:var(--ccx-ink-soft);
  font-family:var(--ccx-font-chiffre);
}
.ccx-app .ccx-c-sel select{
  font-size:calc(var(--ccx-co-size) * var(--ccx-echelle)); padding:5px 7px;
  border:var(--ccx-cadre-champ-w) solid var(--ccx-cadre-champ-c);
  border-radius:var(--ccx-cadre-champ-r); background:var(--ccx-paper); color:var(--ccx-ink);
  max-width:150px;
}
/* Un compteur fermé par une règle : grisé, mais toujours lisible — le client
   doit voir CE QU'IL Y A dedans (un « 0 », un « 2 ») autant que le fait qu'il
   n'y touche pas. Le titre de l'étiquette porte le motif. */
.ccx-app .ccx-c-num.is-off{opacity:.45}
.ccx-app .ccx-c-num.is-off .stepper button{cursor:not-allowed}
.ccx-app .ccx-comp-add{margin-top:2px}
.ccx-app .forced-note#ccx-agenc-note.on{display:block}

@media (max-width:640px){
  .ccx-app .ccx-c-body{gap:8px}
  .ccx-app .ccx-c-mm input{width:76px}
  .ccx-app .ccx-c-sel select{max-width:100%}
}

/* ============================================================
   SOCLE & TIROIRS — ce que le client doit savoir avant de commander :
   la plage de réglage d'un vérin, la hauteur utile d'un tiroir, et
   les conditions d'installation que sa hauteur déclenche.
   ============================================================ */
.ccx-app .ccx-socle-note{font-size:calc(var(--ccx-no-size) * var(--ccx-echelle)); color:var(--ccx-ink-soft); margin-top:5px}
.ccx-app .ccx-socle-note:empty{display:none}
.ccx-app #ccx-tiroir-info{font-size:calc(var(--ccx-no-size) * var(--ccx-echelle)); color:var(--ccx-ink-soft); margin-top:8px}
.ccx-app .ccx-alerte{
  margin-top:6px; font-size:calc(var(--ccx-no-size) * var(--ccx-echelle)); color:var(--ccx-warn);
  background:var(--ccx-warn-soft); border:1px solid var(--ccx-warn);
  border-radius:4px; padding:6px 9px;
}
.ccx-app .forced-note#ccx-zones-note.on,
.ccx-app .forced-note#ccx-vue-alerte.on{display:block}

/* ============================================================
   JOUES — personnalisation des chants. Les arêtes que l'atelier
   n'a pas déverrouillées restent visibles mais inertes : le client
   voit qu'elles sont plaquées, sans pouvoir les décocher.
   ============================================================ */
.ccx-app .ccx-perso{
  display:inline-flex; align-items:center; gap:6px; font-size:calc(var(--ccx-co-size) * var(--ccx-echelle));
  color:var(--ccx-ink); margin:2px 0 7px; cursor:pointer;
}
.ccx-app .ccx-chants label.ccx-chant-fixe{opacity:.5}
.ccx-app .ccx-chants input:disabled + span{cursor:default}
.ccx-app .ccx-chant-decor{
  font-size:calc(var(--ccx-co-size) * var(--ccx-echelle)); padding:6px 8px; border:1px solid var(--ccx-line);
  border-radius:3px; background:var(--ccx-paper); color:var(--ccx-ink); width:100%; max-width:280px;
}

/* Détail d'une ligne de prix : « 6 × Vérin 100 mm », « 0,60 ml × 22,50 €/ml ». */
.ccx-app .price .price-lines em{
  font-style:normal; font-weight:400; color:var(--ccx-ink); font-size:calc(var(--ccx-no-size) * var(--ccx-echelle));
  font-family:var(--ccx-font-chiffre); font-variant-numeric:tabular-nums;
}
.ccx-app .ccx-lien{
  background:none; border:0; padding:0; font:inherit; color:inherit;
  text-decoration:underline; text-underline-offset:2px; cursor:pointer;
}

/* ============================================================
   DEMANDE SPÉCIALE — le projet part entier, et l'échange se
   poursuit dans cette même fenêtre. Posée sur le <body> comme le
   grand format : .ccx-app porte overflow:clip et vit sous un thème
   aux z-index élevés.
   ============================================================ */
.ccx-ds{position:fixed; inset:0; z-index:100000; display:flex; align-items:center; justify-content:center; padding:16px}
.ccx-ds[hidden]{display:none}
.ccx-ds-bd{position:absolute; inset:0; background:var(--ccx-voile-doux); backdrop-filter:blur(2px)}
.ccx-ds-panel{
  position:relative; background:var(--ccx-paper); border-radius:12px; width:min(620px, calc(100vw - 32px));
  max-height:calc(100vh - 48px); display:flex; flex-direction:column;
  box-shadow:0 24px 60px -20px rgba(0,0,0,.45), 0 0 0 1px rgba(0,0,0,.04); /* matière */
  font-family:var(--ccx-font); color:var(--ccx-ink);
  animation:ccx-ds-in .18s ease;
}
@keyframes ccx-ds-in{from{opacity:0; transform:translateY(6px) scale(.99)} to{opacity:1; transform:none}}
.ccx-ds-head{
  display:flex; align-items:center; justify-content:space-between;
  padding:16px 20px; border-bottom:1px solid var(--ccx-line);
}
.ccx-ds-head h2{margin:0; font-family:var(--ccx-font); font-size:calc(var(--ccx-t1-fenetre) * var(--ccx-echelle)); font-weight:600; letter-spacing:-.01em}
.ccx-ds-x{
  background:none; border:0; font-size:calc(var(--ccx-icone) * var(--ccx-echelle) * .84); line-height:1; cursor:pointer; color:var(--ccx-b4-ink); padding:4px;
  width:28px; height:28px; display:flex; align-items:center; justify-content:center; border-radius:6px;
  transition:background-color .12s, color .12s;
}
.ccx-ds-x:hover{color:var(--ccx-ink); background:var(--ccx-accent-soft)}
.ccx-ds-body{padding:18px 20px 20px; overflow-y:auto}
.ccx-ds-lead{margin:0 0 12px; font-size:calc(var(--ccx-b1-size) * var(--ccx-echelle)); line-height:1.55; color:var(--ccx-ink-mid)}

/* ---------- Étapes — où en est la demande, d'un coup d'œil ---------- */
.ccx-ds-steps{display:flex; margin-bottom:18px}
.ccx-ds-step{
  flex:1; position:relative; display:flex; flex-direction:column; align-items:center;
  text-align:center; gap:6px;
}
.ccx-ds-step:not(:first-child)::before{
  content:''; position:absolute; top:11px; left:-50%; width:100%; height:1px; background:var(--ccx-line); z-index:0;
}
.ccx-ds-step--fait:not(:first-child)::before,
.ccx-ds-step--en-cours:not(:first-child)::before{background:var(--ccx-ink)}
.ccx-ds-step-dot{
  position:relative; z-index:1; width:22px; height:22px; border-radius:50%; flex:none;
  display:flex; align-items:center; justify-content:center;
  font-family:var(--ccx-font-chiffre); font-variant-numeric:tabular-nums; font-size:calc(var(--ccx-mini-size) * var(--ccx-echelle)); font-weight:600;
  border:1.5px solid var(--ccx-line); color:var(--ccx-line-strong); background:var(--ccx-paper);
  transition:border-color .15s, background-color .15s, color .15s, box-shadow .15s;
}
.ccx-ds-step--en-cours .ccx-ds-step-dot{
  border-color:var(--ccx-ink); color:var(--ccx-ink); box-shadow:0 0 0 4px var(--ccx-accent-soft);
}
.ccx-ds-step--fait .ccx-ds-step-dot{border-color:var(--ccx-ink); background:var(--ccx-ink); color:var(--ccx-paper)}
.ccx-ds-step-lbl{font-size:calc(var(--ccx-no-size) * var(--ccx-echelle)); color:var(--ccx-line-strong); font-weight:500}
.ccx-ds-step--en-cours .ccx-ds-step-lbl{color:var(--ccx-ink); font-weight:700}
.ccx-ds-step--fait .ccx-ds-step-lbl{color:var(--ccx-ink-mid)}

.ccx-ds-resume{margin-bottom:14px}
.ccx-ds-resume b{
  display:block; font-size:calc(var(--ccx-mini-size) * var(--ccx-echelle)); text-transform:uppercase; letter-spacing:.1em;
  color:var(--ccx-ink-soft); margin-bottom:6px;
}
.ccx-ds-recap dl{display:grid; grid-template-columns:auto 1fr; gap:4px 12px; font-size:calc(var(--ccx-co-size) * var(--ccx-echelle)); margin:0}
.ccx-ds-recap dt{color:var(--ccx-ink-soft)}
.ccx-ds-recap dd{margin:0; text-align:right; font-weight:500}

.ccx-ds-l{display:block; margin-bottom:11px}
.ccx-ds-l > span{display:block; font-size:calc(var(--ccx-no-size) * var(--ccx-echelle)); color:var(--ccx-ink-soft); margin-bottom:4px}
.ccx-ds-l input, .ccx-ds-l textarea{
  width:100%; border:1px solid var(--ccx-line); border-radius:6px; padding:9px 11px;
  font-family:inherit; font-size:calc(var(--ccx-ch-size) * var(--ccx-echelle)); color:var(--ccx-ink); background:var(--ccx-paper);
  transition:border-color .12s;
}
.ccx-ds-l input:focus, .ccx-ds-l textarea:focus{outline:2px solid var(--ccx-ink); outline-offset:-1px; border-color:var(--ccx-ink)}
.ccx-ds-check{display:flex; gap:8px; align-items:flex-start; font-size:calc(var(--ccx-co-size) * var(--ccx-echelle)); color:var(--ccx-ink-mid); margin-bottom:12px}
.ccx-ds-check input{margin-top:2px; flex:none}

/* Pot de miel : jamais vu ni atteint par un client, seulement par un robot.
   Retiré du flux ET du parcours clavier — un champ simplement transparent se
   remplirait à la saisie automatique et bloquerait de vraies demandes. */
.ccx-hp{
  position:absolute !important; width:1px; height:1px; padding:0; margin:-1px;
  overflow:hidden; clip:rect(0 0 0 0); clip-path:inset(50%); white-space:nowrap; border:0;
}

.ccx-ds-err{display:none; font-size:calc(var(--ccx-co-size) * var(--ccx-echelle)); color:var(--ccx-alert); background:var(--ccx-alert-soft);
  border:1px solid var(--ccx-alert); border-radius:6px; padding:7px 10px; margin-bottom:10px}
.ccx-ds-err.on{display:block}
.ccx-ds-send{
  width:100%; background:var(--ccx-ink); color:var(--ccx-paper); border:0; border-radius:6px;
  padding:11px 14px; font-family:inherit; font-size:calc(var(--ccx-ch-size) * var(--ccx-echelle)); font-weight:600; cursor:pointer;
  transition:background-color .12s, transform .12s;
}
.ccx-ds-send:hover{background:var(--ccx-ink-fort); transform:translateY(-1px)}
.ccx-ds-send:active{transform:none}
.ccx-ds-send:disabled{opacity:.55; cursor:wait; transform:none}
a.ccx-ds-send{display:block; text-align:center; text-decoration:none}

.ccx-ds-ref{display:flex; align-items:baseline; gap:10px; flex-wrap:wrap; margin-bottom:12px}
.ccx-ds-ref b{font-family:var(--ccx-font-chiffre); font-variant-numeric:tabular-nums; font-size:calc(var(--ccx-ds-ref-size) * var(--ccx-echelle))}
.ccx-ds-statut{
  font-size:calc(var(--ccx-mini-size) * var(--ccx-echelle)); text-transform:uppercase; letter-spacing:.08em;
  background:var(--ccx-accent-soft); border-radius:100px; padding:3px 9px; color:var(--ccx-ink-mid); font-weight:600;
}
.ccx-ds-date{font-size:calc(var(--ccx-no-size) * var(--ccx-echelle)); color:var(--ccx-ink-soft)}
.ccx-ds-msgs{display:flex; flex-direction:column; gap:9px; margin-bottom:14px}
.ccx-ds-msg{border:1px solid var(--ccx-line); border-radius:8px; padding:10px 12px; font-size:calc(var(--ccx-b1-size) * var(--ccx-echelle))}
.ccx-ds-msg--atelier{background:var(--ccx-atelier); border-color:var(--ccx-atelier-bord)}
.ccx-ds-msg-h{display:flex; justify-content:space-between; gap:10px; margin-bottom:4px; font-size:calc(var(--ccx-no-size) * var(--ccx-echelle)); color:var(--ccx-ink-soft)}
.ccx-ds-msg-h b{color:var(--ccx-ink); font-size:calc(var(--ccx-co-size) * var(--ccx-echelle))}
.ccx-ds-msg-b{line-height:1.5}
.ccx-ds-note{font-size:calc(var(--ccx-no-size) * var(--ccx-echelle)); color:var(--ccx-ink-soft); margin:10px 0 0}

@media (max-width:640px){
  .ccx-ds-panel{width:calc(100vw - 16px); max-height:calc(100vh - 24px)}
  .ccx-app .ccx-zone{gap:5px}
  .ccx-app .ccx-zone select{max-width:100%; flex:1 1 110px}
}

/* ============================================================
   MODERNISATION — 1.3.0

   Une couche posée après tout le reste plutôt qu'une réécriture : le langage
   visuel ne change pas (monochrome, trait de plan technique), ce sont les
   gestes qui se précisent. Rayons harmonisés sur une échelle, un seul anneau
   de focus partout, une seule courbe de transition, des ombres en deux plans,
   et le mouvement qui s'efface pour qui l'a demandé.
   ============================================================ */
.ccx-app{
  --r-xs:4px;
  --r-sm:6px;
  --r:8px;
  --r-lg:14px;
  /* L'anneau de focus : visible sur fond clair comme sur une pastille sombre,
     et jamais confondu avec la bordure « sélectionné ». */
  --ring:0 0 0 3px rgba(26,26,26,.14);
  --ease:cubic-bezier(.2,.7,.3,1);
  --dur:.16s;
  --shadow:0 1px 2px rgba(16,16,16,.05), 0 12px 28px -14px rgba(16,16,16,.14);
  --shadow-lift:0 2px 4px rgba(16,16,16,.06), 0 18px 36px -16px rgba(16,16,16,.2);
  -webkit-font-smoothing:antialiased;
}

/* Un seul geste de focus, sur tout ce qui se pointe au clavier. */
.ccx-app :is(input,select,textarea,button,a,summary):focus-visible{
  outline:2px solid var(--ccx-ink); outline-offset:2px;
}
.ccx-app .seg input:focus-visible + span,
.ccx-app .chips input:focus-visible + span{outline:2px solid var(--ccx-ink); outline-offset:2px}
.ccx-app .swatches input:focus-visible + .sw{outline:2px solid var(--ccx-ink); outline-offset:3px}

/* Champs et boutons : mêmes rayons, même courbe. */
.ccx-app input[type=number],
.ccx-app .stepper,
.ccx-app .ccx-zone select,
.ccx-app .ccx-plinthe,
.ccx-app .seg span,
.ccx-app .chips span,
.ccx-app .ccx-zbtn,
.ccx-app .add-cart{border-radius:var(--ccx-r-sm)}
.ccx-app input[type=number]:focus{outline:none; border-color:var(--ccx-ink); box-shadow:var(--ccx-ring)}
.ccx-app .seg span,.ccx-app .chips span,.ccx-app .swatches .sw,
.ccx-app .ccx-plinthe,.ccx-app .ccx-zbtn,.ccx-app .add-cart,.ccx-app .section > .head{
  transition:border-color var(--ccx-dur) var(--ccx-ease), background-color var(--ccx-dur) var(--ccx-ease),
             box-shadow var(--ccx-dur) var(--ccx-ease), transform var(--ccx-dur) var(--ccx-ease), color var(--ccx-dur) var(--ccx-ease);
}

/* Les cartes de la colonne d'aperçu prennent de la profondeur, très peu. */
.ccx-app .canvas,.ccx-app .recap,.ccx-app .price{
  border-radius:var(--ccx-r); box-shadow:var(--ccx-cadre-carte-ombre);
}
.ccx-app .section{border-radius:var(--ccx-r)}
.ccx-app .section[open]{box-shadow:var(--ccx-cadre-etape-ombre)}
.ccx-app .section > .head::after{transition:transform var(--ccx-dur) var(--ccx-ease)}

/* Les chiffres s'alignent en colonne : un prix qui change ne fait plus danser
   la ligne au caractère près. */
.ccx-app .price .price-total b,
.ccx-app .price .price-lines b,
.ccx-app td.n,.ccx-app .recap dd.hi,.ccx-app .stepper output{font-variant-numeric:tabular-nums}

/* Pastilles de décor : l'état choisi est un anneau franc, pas une ombre
   empilée sur une autre — et le survol soulève à peine. */
.ccx-app .swatches .sw{border-radius:var(--ccx-r-sm); box-shadow:inset 0 -6px 12px rgba(0,0,0,.05)}
.ccx-app .swatches label:hover .sw{transform:translateY(-1px); box-shadow:var(--ccx-shadow-lift), inset 0 -6px 12px rgba(0,0,0,.05)}
.ccx-app .swatches input:checked + .sw{
  border-color:var(--ccx-ink);
  box-shadow:0 0 0 2px var(--ccx-ink), inset 0 -6px 12px rgba(0,0,0,.05);
}
.ccx-app .seg span:hover,.ccx-app .chips span:hover{transform:translateY(-1px)}
.ccx-app .seg input:checked + span,.ccx-app .chips input:checked + span{transform:none}

/* Le bouton principal : un appui qui se sent, une attente qui se voit. */
.ccx-app .add-cart{box-shadow:var(--ccx-b1-ombre)}
.ccx-app .add-cart:hover{background:var(--ccx-ink-fort); transform:translateY(-1px); box-shadow:var(--ccx-shadow-lift)}
.ccx-app .add-cart:active{transform:translateY(0); box-shadow:var(--ccx-b1-ombre)}

/* ---------- L'attente, dans le bouton ----------
   « cursor:wait » posait le sablier du système sur tout l'écran, à côté du
   bouton, sans jamais dire de quoi on attendait la fin. L'indicateur revient
   là où se passe l'attente ; le bouton garde sa largeur, rien ne saute. */
@keyframes ccx-spin{to{transform:rotate(360deg)}}
.ccx-app .add-cart:disabled,
.ccx-ds-send:disabled{cursor:default; opacity:.72; transform:none}
.ccx-app .add-cart.is-busy::before,
.ccx-ds-send.is-busy::before{
  content:''; display:inline-block; vertical-align:-2px; margin-right:8px;
  width:12px; height:12px; border-radius:50%;
  border:2px solid currentColor; border-top-color:transparent;
  animation:ccx-spin .7s linear infinite;
}

/* ============================================================
   NOUVEAUTÉS DE LA SESSION

   L'atelier a ajouté un composant pour ce client : la section respire, une
   bulle la nomme et pointe vers son contenu, la pastille porte un point.
   Trois pulsations, puis le repère reste — clignoter sans fin, c'est du bruit.
   ============================================================ */
@keyframes ccx-neuf-halo{
  0%   {box-shadow:0 0 0 0 rgba(26,26,26,.22)}
  70%  {box-shadow:0 0 0 7px rgba(26,26,26,0)}
  100% {box-shadow:0 0 0 0 rgba(26,26,26,0)}
}
@keyframes ccx-neuf-respire{
  0%,100% {background:var(--ccx-surface)}
  50%     {background:var(--ccx-accent-soft)}
}

.ccx-app .ccx-neuf-sec{border-color:var(--ccx-line-strong)}
.ccx-app .ccx-neuf-sec > .head{animation:ccx-neuf-respire 1.9s var(--ccx-ease) 3}
.ccx-app .ccx-neuf-sec > .head h2{color:var(--ccx-ink)}

/* La bulle : dans l'en-tête de la section, à gauche du chevron. Sa pointe
   descend vers le contenu — c'est là qu'il faut regarder. */
.ccx-app .ccx-neuf-bulle{
  position:relative; margin-left:auto; margin-right:22px;
  display:inline-flex; align-items:center; gap:6px;
  padding:4px 10px; border-radius:100px;
  background:var(--ccx-ink); color:var(--ccx-paper);
  font-family:inherit; font-size:calc(var(--ccx-no-size) * var(--ccx-echelle)); font-weight:600; letter-spacing:.02em;
  white-space:nowrap; border:0; cursor:pointer;
  box-shadow:var(--ccx-cadre-carte-ombre);
}
.ccx-app .ccx-neuf-bulle::after{
  content:''; position:absolute; left:16px; bottom:-3px;
  width:8px; height:8px; background:var(--ccx-ink); transform:rotate(45deg); border-radius:1px;
}
.ccx-app .ccx-neuf-bulle:hover{background:var(--ccx-ink-fort)}
.ccx-app .ccx-neuf-point{
  width:6px; height:6px; border-radius:50%; background:var(--ccx-paper); flex:none;
  animation:ccx-neuf-halo 1.9s var(--ccx-ease) infinite;
}

/* La pastille ou le segment concerné : un anneau, et un point qui le pointe. */
.ccx-app .ccx-sw-wrap.ccx-neuf .sw,
.ccx-app .seg label.ccx-neuf > span{
  border-color:var(--ccx-ink);
  animation:ccx-neuf-halo 1.9s var(--ccx-ease) 3;
}
.ccx-app .seg label.ccx-neuf{position:relative}
.ccx-app .ccx-sw-wrap.ccx-neuf::before,
.ccx-app .seg label.ccx-neuf::before{
  content:''; position:absolute; z-index:3; top:-3px; left:-3px;
  width:9px; height:9px; border-radius:50%;
  background:var(--ccx-ink); box-shadow:0 0 0 2px var(--ccx-paper);
  pointer-events:none;
}

/* Le bandeau de session renvoie vers ces repères. */
.ccx-app .ccx-session-ou{color:var(--ccx-ink-soft); font-weight:400}
.ccx-app .ccx-session-fil{
  border-radius:var(--ccx-r-sm); padding:7px 12px; background:var(--ccx-paper);
  border:1px solid var(--ccx-line-strong); text-decoration:none;
  transition:border-color var(--ccx-dur) var(--ccx-ease), background-color var(--ccx-dur) var(--ccx-ease);
}
.ccx-app .ccx-session-fil:hover{border-color:var(--ccx-ink); background:var(--ccx-paper)}

/* ---------- La fenêtre d'échange ----------
   Elle est posée sur le <body>, hors de .ccx-app : elle n'héritait donc pas du
   box-sizing du configurateur, et ses champs en largeur 100 % ajoutaient leurs
   marges intérieures par-dessus — 24 px de trop, qui mangeaient la marge de
   droite et débordaient du panneau au doigt. .ccx-lb a la même règle. */
.ccx-ds, .ccx-ds *{box-sizing:border-box}
.ccx-ds-bd{backdrop-filter:blur(6px) saturate(1.1); background:rgba(18,18,18,.5)}
.ccx-ds-panel{border-radius:var(--r-lg,14px); animation:ccx-ds-in .22s cubic-bezier(.2,.7,.3,1)}
.ccx-ds-l input, .ccx-ds-l textarea{border-radius:6px}
.ccx-ds-l input:focus, .ccx-ds-l textarea:focus{
  outline:none; border-color:var(--ccx-ink); box-shadow:var(--ccx-ring);
}
.ccx-ds-send{border-radius:var(--ccx-b1-r); box-shadow:var(--ccx-b1-ombre)}
.ccx-ds-send:active{transform:translateY(0)}
.ccx-ds-note a{color:var(--ccx-ink); word-break:break-all}

/* Au doigt, la fenêtre devient une feuille qui monte du bas : le pouce y
   atteint le bouton, et l'échange garde toute la hauteur. */
@keyframes ccx-ds-up{from{transform:translateY(14px); opacity:.6} to{transform:none; opacity:1}}
@media (max-width:640px){
  .ccx-ds{align-items:flex-end; padding:0}
  .ccx-ds-panel{
    width:100vw; max-width:100vw; max-height:92vh;
    border-radius:14px 14px 0 0;
    animation:ccx-ds-up .24s cubic-bezier(.2,.7,.3,1);
  }
  .ccx-ds-head{position:sticky; top:0; background:var(--ccx-paper); z-index:1}
  .ccx-ds-body{padding-bottom:max(20px, env(safe-area-inset-bottom))}
  .ccx-app .ccx-neuf-bulle{margin-right:20px; font-size:calc(var(--ccx-mini-size) * var(--ccx-echelle)); padding:3px 8px}
}

/* ---------- Mouvement réduit ----------
   Le repère doit rester lisible sans bouger : l'anneau et le point restent,
   seule l'animation s'arrête. */
@media (prefers-reduced-motion: reduce){
  .ccx-app *,.ccx-ds *{
    animation-duration:.001ms !important; animation-iteration-count:1 !important;
    transition-duration:.001ms !important; scroll-behavior:auto !important;
  }
  .ccx-app .ccx-neuf-sec > .head{background:var(--ccx-accent-soft)}
  .ccx-app .ccx-sw-wrap.ccx-neuf .sw,
  .ccx-app .seg label.ccx-neuf > span{box-shadow:0 0 0 3px rgba(26,26,26,.22)} /* matière */
}

/* ============================================================
   RÈGLES & CONDITIONS

   Ce que l'atelier a interdit, imposé ou signalé pour CETTE
   configuration. Le vocabulaire visuel est celui qui existait déjà :
   l'ambre de « .forced-note » pour une contrainte, le trait sec de
   « .dim-alert » pour un refus. Une règle n'invente pas une couleur
   de plus, elle réemploie celle que le client sait déjà lire.
   ============================================================ */

/* Ce qu'une règle retire du formulaire disparaît vraiment : masqué à
   l'écran ET refusé par le serveur, jamais l'un sans l'autre. */
.ccx-app .ccx-masque{display:none !important}

/* Bandeau d'étape */
.ccx-app .ccx-regle-msgs{display:none}
.ccx-app .ccx-regle-msgs.on{display:block; padding:12px 18px 0}
.ccx-app .ccx-regle-msg{
  font-size:calc(var(--ccx-co-size) * var(--ccx-echelle)); line-height:1.5; padding:8px 10px; border-radius:4px;
  border-left:2px solid var(--ccx-line-strong); background:var(--ccx-surface); color:var(--ccx-ink-soft);
}
.ccx-app .ccx-regle-msg + .ccx-regle-msg{margin-top:6px}
.ccx-app .ccx-regle-msg--attention{
  border-left-color:var(--ccx-warn); background:var(--ccx-warn-soft); color:var(--ccx-warn);
}

/* « Imposé par la règle … » — même ambre que les contraintes existantes */
.ccx-app .ccx-regle-note{
  font-size:calc(var(--ccx-no-size) * var(--ccx-echelle)); color:var(--ccx-warn); background:var(--ccx-warn-soft);
  padding:5px 8px; border-radius:4px; margin-top:7px;
}

/* Un champ verrouillé se lit encore, mais ne se clique plus. */
.ccx-app .seg label input:disabled + span,
.ccx-app .chips label input:disabled + span{opacity:.45; cursor:not-allowed}
.ccx-app .seg label input:disabled:checked + span,
.ccx-app .chips label input:disabled:checked + span{opacity:1}
.ccx-app .stepper button:disabled{opacity:.35; cursor:not-allowed}

/* Refus : le motif, puis la demande spéciale qui prend le relais. */
.ccx-app .ccx-regle-blocage{display:none; margin:10px 0 0}
.ccx-app .ccx-regle-blocage.on{display:block}
.ccx-app .ccx-regle-blocage div{
  font-size:calc(var(--ccx-co-size) * var(--ccx-echelle)); line-height:1.5; padding:9px 11px; border-radius:4px;
  background:var(--ccx-warn-soft); color:var(--ccx-warn); border-left:2px solid var(--ccx-warn);
}
.ccx-app .ccx-regle-blocage div + div{margin-top:6px}
.ccx-app .ccx-regle-blocage b{font-weight:600}
.ccx-app .add-cart:disabled{opacity:.4; cursor:not-allowed}
/* Quand le panier est fermé, la demande spéciale devient le geste principal. */
.ccx-app .ccx-special-row--seule .ccx-special-btn{
  background:var(--ccx-ink); color:var(--ccx-paper); border-color:var(--ccx-ink);
}

/* Un caisson qu'une règle refuse : le projet entier échouerait au panier, on
   le signale sur sa carte plutôt qu'à l'envoi. */
.ccx-app .ccx-multi-item.is-refuse{border-color:var(--ccx-warn); background:var(--ccx-warn-soft)}
.ccx-app .ccx-multi-item.is-refuse .ccx-multi-prix{color:var(--ccx-warn); text-decoration:line-through}

/* Repère de l'aperçu en direct : l'écran de réglages allume cette classe un
   instant sur l'élément qu'un réglage vient de toucher, pendant qu'il zoome
   dessus (assets/js/ccx-admin.js, initCharte). Aucun état du configurateur
   ne la pose de lui-même — elle n'existe que pour ce dialogue avec l'écran
   de réglages. Le même anneau que le clavier utilise déjà sur un champ. */
.ccx-apercu-cible{outline:var(--ccx-ring); outline-offset:3px; border-radius:var(--ccx-r-xs)}

/* ============================================================
   PAGE « MON COMPTE » — mes commandes, mes informations.

   Aucune valeur d'apparence propre : la page emprunte les jetons du
   configurateur, si bien que régler la charte la règle aussi. Les rôles
   suivent la lecture de la maquette — t1 pour le titre de page, t2 pour un
   titre de bloc, li pour une étiquette, ch pour la colonne de droite.
   Voir docs/CDC-mon-compte.md § 7.
   ============================================================ */
.ccx-app.ccx-compte{padding:16px}
/* `cadre="non"` : la section Divi porte déjà son cadre et son fond, deux
   emboîtés feraient un cerne. On retire les nôtres, pas la typographie. */
.ccx-app.ccx-compte--nu{border:none; box-shadow:none; background:none; padding:0; max-width:none}

.ccx-app .ccx-compte-titre{
  font-size:calc(var(--ccx-t1-size) * var(--ccx-echelle));
  font-weight:var(--ccx-t1-weight); text-transform:var(--ccx-t1-case);
  letter-spacing:var(--ccx-t1-track); color:var(--ccx-t1-color);
  margin-bottom:14px;
}

.ccx-app .ccx-compte-bloc{
  border:var(--ccx-cadre-carte-w) solid var(--ccx-cadre-carte-c);
  border-radius:var(--ccx-cadre-carte-r);
  box-shadow:var(--ccx-cadre-carte-ombre);
  background:var(--ccx-paper);
  padding:12px 14px;
}
.ccx-app .ccx-compte-bloc + .ccx-compte-bloc{margin-top:12px}
.ccx-app .ccx-compte-tete{cursor:pointer; list-style:none; display:flex; align-items:center; gap:8px}
.ccx-app .ccx-compte-tete::-webkit-details-marker{display:none}
/* La flèche de la maquette : posée en CSS, elle tourne à l'ouverture sans
   qu'une ligne de JavaScript ait à connaître ce bloc. */
.ccx-app .ccx-compte-tete::after{
  content:''; margin-left:auto; width:7px; height:7px;
  border-right:1.5px solid var(--ccx-ink-soft); border-bottom:1.5px solid var(--ccx-ink-soft);
  transform:rotate(45deg) translateY(-2px); transition:transform var(--ccx-dur) var(--ccx-ease);
}
.ccx-app .ccx-compte-bloc[open] > .ccx-compte-tete::after{transform:rotate(-135deg) translateY(-2px)}
.ccx-app .ccx-compte-tete h2{
  font-size:calc(var(--ccx-t2-size) * var(--ccx-echelle));
  font-weight:var(--ccx-t2-weight); text-transform:var(--ccx-t2-case);
  letter-spacing:var(--ccx-t2-track); color:var(--ccx-t2-color);
}
.ccx-app .ccx-compte-corps{margin-top:10px}

.ccx-app .ccx-compte-cmd + .ccx-compte-cmd{
  margin-top:12px; padding-top:12px;
  border-top:var(--ccx-cadre-tableau-w) solid var(--ccx-cadre-tableau-c);
}

/* La ligne « étiquette … valeur » de la maquette, avec son filet de points :
   c'est un composant, répété, pas trois mises en page. */
.ccx-app .ccx-compte-ligne{display:flex; align-items:baseline; gap:6px; padding:2px 0}
.ccx-app .ccx-compte-etiquette{
  font-size:calc(var(--ccx-li-size) * var(--ccx-echelle));
  font-weight:var(--ccx-li-weight); text-transform:var(--ccx-li-case);
  letter-spacing:var(--ccx-li-track); color:var(--ccx-li-color);
  white-space:nowrap;
}
.ccx-app .ccx-compte-valeur{
  margin-left:auto; text-align:right;
  font-size:calc(var(--ccx-ch-size) * var(--ccx-echelle));
  font-weight:var(--ccx-ch-weight); letter-spacing:var(--ccx-ch-track);
  color:var(--ccx-ch-color);
}
/* Le filet de points qui relie les deux moitiés. Il occupe l'espace libre,
   donc il se réduit de lui-même quand la valeur est longue. */
.ccx-app .ccx-compte-ligne::before{
  content:''; flex:1 1 auto; order:1; align-self:flex-end; min-width:12px;
  border-bottom:var(--ccx-cadre-tableau-w) dotted var(--ccx-cadre-tableau-c);
  transform:translateY(-3px);
}
.ccx-app .ccx-compte-ligne .ccx-compte-valeur{order:2; margin-left:0}

.ccx-app .ccx-compte-ligne--tete .ccx-compte-etiquette{
  font-size:calc(var(--ccx-t3-size) * var(--ccx-echelle));
  font-weight:var(--ccx-t3-weight); text-transform:var(--ccx-t3-case);
  letter-spacing:var(--ccx-t3-track); color:var(--ccx-t3-color);
}
.ccx-app .ccx-compte-ligne--prix .ccx-compte-valeur{font-weight:600}

.ccx-app .ccx-compte-detail{margin:6px 0 4px; padding-left:10px;
  border-left:var(--ccx-cadre-tableau-w) solid var(--ccx-cadre-tableau-c)}
.ccx-app .ccx-compte-detail-t{
  display:block; margin-bottom:2px;
  font-size:calc(var(--ccx-t3-size) * var(--ccx-echelle));
  font-weight:var(--ccx-t3-weight); color:var(--ccx-t3-color);
}

.ccx-app .ccx-compte-note{
  font-size:calc(var(--ccx-no-size) * var(--ccx-echelle));
  font-weight:var(--ccx-no-weight); color:var(--ccx-no-color); line-height:1.5;
}
/* Une action secondaire : le niveau de bouton 2, celui qui propose. */
.ccx-app .ccx-compte-action{
  display:inline-block; margin-top:8px; padding:6px 12px; text-decoration:none;
  background:var(--ccx-b2-bg); color:var(--ccx-b2-ink);
  border:var(--ccx-b2-bord-w) var(--ccx-b2-bord-style) var(--ccx-b2-bord); border-radius:var(--ccx-b2-r);
  font-size:calc(var(--ccx-b2-size) * var(--ccx-echelle)); font-weight:var(--ccx-b2-weight);
  transition:border-color var(--ccx-dur) var(--ccx-ease), color var(--ccx-dur) var(--ccx-ease);
}
.ccx-app .ccx-compte-action:hover{border-color:var(--ccx-b2-bord-hover); color:var(--ccx-b2-ink-hover)}
.ccx-app .ccx-compte-lien{
  display:inline-block; margin-top:10px;
  font-size:calc(var(--ccx-no-size) * var(--ccx-echelle)); color:var(--ccx-no-color);
}

/* Au doigt, la valeur passe sous son étiquette plutôt que de se comprimer :
   « 600 × 720 × 500 mm » coupé en deux ne veut plus rien dire. */
@media (max-width:420px){
  .ccx-app .ccx-compte-ligne{flex-wrap:wrap}
  .ccx-app .ccx-compte-ligne::before{display:none}
  .ccx-app .ccx-compte-valeur{margin-left:0; text-align:left; flex-basis:100%}
}
