/* =========================================================================
   Feuille de style commune a toutes les pages de 3DMaking.

   Contient UNIQUEMENT ce qui etait strictement identique sur les 9 pages :
   les variables de design (couleurs, rayons, ombres) et le menu lateral.
   Le reste du style vit encore dans le <style> de chaque page, qui est
   charge APRES ce fichier : une page peut donc toujours redefinir une
   valeur pour elle seule (c est le cas de --ring sur moderation.html).

   POUR CHANGER LE THEME DU SITE : modifier les variables ci-dessous, une
   seule fois, plutot que les 9 fichiers HTML.
   ========================================================================= */

:root{
  /* Le site est TOUJOURS sombre, aucune variante claire — sans ceci, les
     widgets natifs du navigateur (liste deroulante d'un <select> ouverte,
     entre autres) se rendent avec le theme clair par defaut du systeme
     d'exploitation, ignorant les couleurs `background`/`color` posees sur
     <option> : fond blanc illisible, surlignage au survol pris depuis la
     couleur d'accentuation Windows plutot que la charte du site. Corrige
     le 2026-08-18 (signale par l'utilisateur sur .topbar-printer-select,
     mais touchait tout <select> du site de la meme facon). */
  color-scheme: dark;

  /* Fonds, du plus sombre au plus clair. Teinte verte tres legere, calee
     sur le vert de marque (avant : gris violace, herite du template
     d'origine et sans rapport avec la charte). */
  --ink: #0A0D0B;
  --surface: #121814;
  --surface-2: #19221C;
  --surface-3: #212D25;

  /* Bordures */
  --line: rgba(255,255,255,0.08);
  --line-strong: rgba(255,255,255,0.14);

  /* Accent — vert de la marque. Actions et interactions UNIQUEMENT,
     jamais les alertes (voir --danger). */
  --accent: #175E24;
  --accent-soft: rgba(23,94,36,0.18);
  /* Meme famille de vert, mais assez clair pour rester lisible SUR un fond
     sombre. --accent (2,28:1 sur le panneau du menu) passe sous le minimum
     de 3:1 recommande pour un element graphique : reserve-le aux fonds
     pleins et aux bordures, pas aux petits traits comme les icones. */
  --accent-bright: #22c55e;

  /* Accent secondaire — dore, associe aux Polys dans toute l'interface */
  --accent-2: #f2b134;
  --accent-2-soft: rgba(242,177,52,0.16);

  /* Etats */
  --danger: #FF6467;
  --danger-soft: rgba(255,100,103,0.14);
  --warning: #f59e0b;
  --warning-soft: rgba(245,158,11,0.14);
  --ok: #34d399;
  --ok-soft: rgba(52,211,153,0.14);

  /* Texte, du plus lisible au plus discret */
  --text: #F8FAFC;
  --text-2: #9EB3A6;
  --text-3: #586B5F;

  /* Formes et effets. Angles carres partout (charte 2026-08-16, refonte
     visuelle) — avant : 10px/8px, arrondis. */
  --radius: 0px;
  --radius-sm: 0px;
  --shadow: 0 1px 3px rgba(0,0,0,0.5), 0 12px 32px -8px rgba(0,0,0,0.75);
  --ring: 0 0 0 3px rgba(34,197,94,0.35);

  /* Couleurs de role (badges) */
  --role-admin: #FF6467;
  --role-admin-soft: rgba(255,100,103,0.14);
  --role-mod: #1F7A3F;
  --role-mod-soft: rgba(31,122,63,0.16);
  --role-printer: #175E24;
  --role-printer-soft: rgba(23,94,36,0.16);
  /* Bêta-testeur : le jaune de la boutique de Polys (--accent-2 #f2b134),
     demandé explicitement. Écrit en dur plutôt qu'en var(--accent-2) pour que
     le soft correspondant existe sous la même forme que les 3 autres rôles. */
  --role-beta: #F2B134;
  --role-beta-soft: rgba(242,177,52,0.16);
  --mod: #1F7A3F;
  --mod-soft: rgba(31,122,63,0.16);
}

/* --- Reset et menu lateral (identiques sur toutes les pages) --- */
*{box-sizing:border-box;}
#sideNavHandle{
    width:46px; flex:0 0 auto;
    display:flex; align-items:center; justify-content:center;
    background:linear-gradient(180deg, rgba(255,255,255,.035), rgba(255,255,255,0)), var(--surface);
    border-right:1px solid var(--line);
    color:var(--text-2); cursor:pointer; transition:color .15s ease;
  }
#sideNavHandle svg{width:18px; height:18px;}
#sideNavPanel{
    width:0; overflow:hidden; flex:0 0 auto;
    background:var(--surface); border-right:1px solid var(--line); box-shadow:var(--shadow);
    transition:width .22s ease; display:flex; flex-direction:column; padding-top:18px;
  }
/* ⚠️ OUVERTURE AU CLIC UNIQUEMENT (2026-09-05, demande utilisateur : « au
   survol ça gêne certains utilisateurs »). Il y avait AUSSI `#sideNav:hover`
   ici — le menu se dépliait dès qu'on frôlait le bord gauche de l'écran, y
   compris en visant autre chose. La classe `.nav-open` est posée par le petit
   bloc JS présent dans chacune des 24 pages qui portent le menu (poignée =
   bascule, clic à l'extérieur ou Échap = fermeture) ; elle existait déjà pour
   le tactile, qui n'a pas de :hover, et devient désormais le SEUL chemin.
   ⚠️ Ne pas remettre `:hover` sur cette règle. Le survol reste sur la POIGNÉE
   seule (couleur d'accent, plus bas) : c'est l'indice qu'elle est cliquable,
   et il n'ouvre rien. */
  #sideNav.nav-open #sideNavPanel{width:min(276px, 86vw);}
#sideNavPanel .side-title{
    padding:0 20px 14px; margin-bottom:6px; border-bottom:1px solid var(--line);
    font-size:10.5px; letter-spacing:.14em; text-transform:uppercase;
    font-weight:800; color:var(--text-3); white-space:nowrap;
  }
/* Logo a la place du mot "Menu" (2026-08-20, demande utilisateur : le texte
   "Menu" faisait pauvre en tete du panneau). SVG vectoriel (logo-3DMaking-dark.svg)
   donc net a n'importe quelle taille — jamais de pixelisation.
   Agrandi le meme jour (largeur pleine du panneau plutot qu'une petite
   hauteur fixe) pour occuper quasiment tout l'espace disponible de l'en-tete,
   comme demande — width:100% s'adapte automatiquement a min(276px, 86vw). */
#sideNavPanel .side-title-logo{width:100%; height:auto; display:block;}
/* Entrees du menu : pastilles arrondies detachees des bords du panneau.
   La marge horizontale (8px) + le padding (12px) redonnent le meme retrait
   de texte qu'avant (20px), pour ne pas decaler l'alignement du menu. */
.side-link{
    display:flex; align-items:center; gap:12px;
    padding:11px 12px; margin:2px 8px; border-radius:var(--radius-sm);
    color:var(--text); text-decoration:none; font-size:13px; font-weight:650; white-space:nowrap;
    border-left:2px solid transparent; transition:background .15s ease, color .15s ease, border-color .15s ease;
  }
.side-group-toggle{display:flex; align-items:center; gap:12px; padding:11px 12px; margin:2px 8px; border-radius:var(--radius-sm); width:auto; background:none; border:none; border-left:2px solid transparent; text-align:left; font-family:inherit; color:var(--text); font-size:13px; font-weight:650; white-space:nowrap; cursor:pointer; transition:background .15s ease, color .15s ease, border-color .15s ease;}
.side-group-toggle:hover{background:var(--accent-soft); color:var(--accent); border-left-color:var(--accent);}
.side-group-toggle .side-chevron{margin-left:auto; width:14px; height:14px; opacity:.7; transition:transform .2s ease;}
.side-group-toggle.open .side-chevron{transform:rotate(90deg);}
.side-submenu{max-height:0; overflow:hidden; transition:max-height .22s ease;}
.side-submenu.open{max-height:160px;}
/* Meme retrait visuel qu'avant pour les sous-entrees : 12px de padding de
   base + 24px d'indentation. */
.side-sublink{padding-left:36px;}

/* Icones du menu, toujours vertes (voir --accent-bright : --accent serait
   trop sombre sur ce panneau pour rester lisible). Elles sont dessinees en
   stroke="currentColor", d'ou la simple propriete color. */
.side-link .side-icon, .side-group-toggle .side-icon{
    flex:0 0 auto; width:16px; height:16px; opacity:1;
    color:var(--accent-bright);
  }
.side-badge{margin-left:auto; font-size:9px; font-weight:800; letter-spacing:.04em; text-transform:uppercase; color:var(--text-3); background:var(--accent-soft); border-radius:var(--radius-sm); padding:2px 6px; white-space:nowrap;}

/* --- Cartes ------------------------------------------------------------ */
.card{
  position:relative; width:100%;
  background:var(--surface); border:1px solid var(--line);
  border-radius:var(--radius); box-shadow:var(--shadow);
  transition:border-color .15s ease, box-shadow .15s ease;
}
.card::before{
  content:''; position:absolute; inset:0 0 auto 0; height:1px;
  border-radius:var(--radius) var(--radius) 0 0;
  background:linear-gradient(90deg, transparent, rgba(255,255,255,.14) 20%, rgba(255,255,255,.14) 80%, transparent);
  pointer-events:none;
}
.card-title{
  margin:0; padding:13px 18px; border-bottom:1px solid var(--line);
  font-size:11px; letter-spacing:.14em; text-transform:uppercase;
  font-weight:750; color:var(--text-2);
  display:flex; align-items:center; gap:9px;
}
.card-title::before{
  content:''; width:7px; height:7px; border-radius:var(--radius-sm);
  flex:0 0 auto; background:var(--accent); box-shadow:0 0 0 3px var(--accent-soft);
}
.card-body{padding:18px;}
.card-compact .card-title, .card.compact .card-title{padding:9px 14px; font-size:10px;}
.card-compact .card-body, .card-body.compact{padding:13px 14px;}

/* --- Boutons, aide et messages d'erreur -------------------------------- */
.btn{
  display:inline-flex; align-items:center; justify-content:center; gap:7px;
  padding:9px 18px; background:var(--surface-3); color:var(--text);
  border:1px solid var(--line-strong); border-radius:var(--radius-sm);
  font-weight:650; font-size:13px; font-family:inherit; cursor:pointer;
  text-decoration:none;
  transition:background .14s ease, border-color .14s ease, color .14s ease, box-shadow .14s ease;
}
.btn:hover{border-color:#34d399; color:#34d399; background:var(--accent-soft);}
.btn-primary{
  background:var(--accent); border-color:transparent; color:#fff;
  font-weight:700; box-shadow:0 2px 8px rgba(23,94,36,0.4);
}
.btn-primary:hover{
  background:#1f7a31; border-color:transparent; color:#fff;
  box-shadow:0 4px 14px rgba(34,197,94,0.35);
}
.btn-row{display:flex; gap:10px; flex-wrap:wrap; align-items:center;}
.hint{font-size:11.5px; color:var(--text-3); margin-top:7px; line-height:1.45;}
/* display:none est FONCTIONNEL : le JS passe a block pour reveler l'erreur.
   Le design system proposait display:flex — applique tel quel, tous les
   messages d'erreur du site seraient affiches en permanence. */
.error-text{
  color:var(--danger); font-size:11.5px; font-weight:600;
  margin-top:6px; display:none;
}

/* --- Pastille de Polys, son infobulle, et badges de role ----------------- */
.balance-pill{
  margin-left:auto; font-size:11.5px; font-weight:750; letter-spacing:.02em;
  color:var(--accent-2); background:rgba(242,177,52,0.12);
  border:1px solid rgba(242,177,52,0.35); border-radius:var(--radius-sm);
  padding:5px 13px; white-space:nowrap; text-transform:none;
  position:relative; display:inline-flex; align-items:center; gap:6px;
  text-decoration:none; cursor:pointer;
  transition:background .15s ease, border-color .15s ease;
}
.balance-pill:hover{background:rgba(242,177,52,0.22); border-color:rgba(242,177,52,0.6);}
/* La pastille n'est plus cliquable (elle ne mène plus vers boutique.html) :
   on neutralise le curseur et l'effet :hover hérités de .balance-pill,
   sans toucher à l'apparence de base (voir #balancePill/#balancePillTopbar,
   qui n'ont plus de href). */
#balancePill, #balancePillTopbar{cursor:default;}
#balancePill:hover, #balancePillTopbar:hover{background:rgba(242,177,52,0.12); border-color:rgba(242,177,52,0.35);}
.balance-pill-tooltip{
  position:absolute; left:50%; top:calc(100% + 8px); transform:translate(-50%, 4px);
  background:var(--surface-3); border:1px solid var(--line-strong); color:var(--text);
  font-size:11px; font-weight:650; padding:6px 11px; border-radius:var(--radius-sm);
  white-space:nowrap; box-shadow:var(--shadow);
  text-transform:none; letter-spacing:normal;
  opacity:0; pointer-events:none;
  transition:opacity .15s ease, transform .15s ease; z-index:50;
}
.balance-pill:hover .balance-pill-tooltip{opacity:1; transform:translate(-50%, 0);}
/* Pastille imprimante Bambu Lab choisie (compte.html) — même forme que
   .balance-pill, variante verte pour la distinguer du solde de Polys
   (orange). Cachée par défaut (style="display:none" inline) : affichée en
   JS seulement une fois qu'on sait si l'utilisateur est connecté. */
.printer-pill{
  color:var(--ok); background:var(--ok-soft, rgba(52,211,153,0.12));
  border-color:rgba(52,211,153,0.35);
}
.printer-pill:hover{background:rgba(52,211,153,0.22); border-color:rgba(52,211,153,0.6);}

/* Sélecteur de matériau dans la barre du haut (topbar) — juste à gauche de
   .printer-pill sur les outils qui exportent en 3MF. <select> natif restylé
   (fond sombre au lieu du blanc par défaut du navigateur) plutôt qu'un
   composant maison : garde le comportement clavier/accessibilité natif.
   Caché par défaut (style="display:none" inline), affiché en JS une fois le
   compte chargé — même logique que .printer-pill.

   TOUT `!important` ci-dessous, dans .topbar-material-select ET
   .topbar-printer-select (base + :hover + :focus/:focus-visible) — décision
   ferme prise le 2026-08-18 après 2 fuites réelles causées par le CSS
   générique `select`/`select:focus`/`input:focus` que chacune des 6 pages
   outil définit pour SES PROPRES champs, avec des valeurs différentes d'une
   page à l'autre (héritées de gabarits copiés/collés séparément, jamais
   unifiés). Une règle de classe gagne déjà en spécificité sur les
   propriétés qu'elle déclare, mais (1) c'est facile d'en oublier une par
   erreur (vécu deux fois), et (2) rien n'empêche une page ACTUELLE ou
   FUTURE de déclarer un jour une règle encore plus spécifique. `!important`
   ici rend ces 2 composants réellement immunisés, sans condition : toute
   nouvelle page qui inclut ce balisage (voir le HTML identique déjà
   utilisé sur les 6 outils) affiche ce style, point final, quel que soit
   le CSS local qu'elle définit par ailleurs pour ses propres `<select>`.
   Si ce composant doit un jour changer d'apparence, modifier UNIQUEMENT
   ici — ne jamais recréer un style concurrent dans le <style> d'une page.

   Fond NEUTRE partout (base/hover/focus), pas de teinte verte — décision du
   2026-08-18 après un essai de fond vert permanent : Chrome/Windows ne
   respecte pas fiablement `background` posé sur chaque `<option>`
   individuellement et a tendance à peindre TOUT le popup natif ouvert en
   reprenant la couleur de fond du `<select>` lui-même (même mécanisme déjà
   rencontré sur `border-color`) — un fond vert donnait donc une liste
   déroulante entièrement lavée de vert, pas juste la ligne sélectionnée.
   La distinction imprimante/matériau reste visible via le texte et l'icône
   (verts pour l'imprimante), jamais via le fond. */
.topbar-material-select{
  appearance:none !important; -webkit-appearance:none !important; -moz-appearance:none !important;
  font-size:11.5px !important; font-weight:750 !important; letter-spacing:.02em !important; font-family:inherit !important;
  color:var(--ok) !important; background:var(--surface-2) !important;
  border:1px solid var(--line-strong) !important; border-radius:var(--radius-sm) !important;
  padding:5px 26px 5px 13px !important; white-space:nowrap !important; cursor:pointer !important;
  max-width:170px !important; text-overflow:ellipsis !important;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23888' stroke-width='2'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E") !important;
  background-repeat:no-repeat !important; background-position:right 6px center !important; background-size:14px !important;
  transition:background-color .15s ease, border-color .15s ease;
}
.topbar-material-select:hover{background:var(--surface-3) !important;}
.topbar-material-select:focus,
.topbar-material-select:focus-visible{outline:none !important; box-shadow:none !important; border-color:var(--line-strong) !important; background:var(--surface-2) !important;}
.topbar-material-select option{background:var(--surface-2); color:var(--text);}

/* Sélecteur d'imprimante dans la topbar — même composant que
   .topbar-material-select (voir les 2 commentaires `!important`/fond neutre
   ci-dessus, valables ici aussi), distinct uniquement par le texte/l'icône
   verts. Remplace l'ancien lien <a class="printer-pill"> vers compte.html :
   on change l'imprimante sans quitter l'outil, compte.html reste utilisable
   pour le même réglage. */
.topbar-printer-select{
  appearance:none !important; -webkit-appearance:none !important; -moz-appearance:none !important;
  font-size:11.5px !important; font-weight:750 !important; letter-spacing:.02em !important; font-family:inherit !important;
  color:var(--ok) !important; background:var(--surface-2) !important;
  border:1px solid var(--line-strong) !important; border-radius:var(--radius-sm) !important;
  padding:5px 26px 5px 13px !important; white-space:nowrap !important; cursor:pointer !important;
  max-width:170px !important; text-overflow:ellipsis !important;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2334d399' stroke-width='2'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E") !important;
  background-repeat:no-repeat !important; background-position:right 6px center !important; background-size:14px !important;
  transition:background-color .15s ease, border-color .15s ease;
}
.topbar-printer-select:hover{background:var(--surface-3) !important;}
.topbar-printer-select:focus,
.topbar-printer-select:focus-visible{outline:none !important; box-shadow:none !important; border-color:var(--line-strong) !important; background:var(--surface-2) !important;}
.topbar-printer-select option{background:var(--surface-2); color:var(--text);}

.role-badge{
  display:inline-flex; align-items:center; gap:6px; padding:4px 12px;
  border-radius:999px; font-size:11px; font-weight:800;
  letter-spacing:.03em; text-transform:uppercase;
}
.role-badge.admin{color:var(--role-admin); background:var(--role-admin-soft);}
.role-badge.moderator{color:var(--role-mod); background:var(--role-mod-soft);}
.role-badge.printer{color:var(--role-printer); background:var(--role-printer-soft);}
.role-badge.beta{color:var(--role-beta); background:var(--role-beta-soft);}

/* --- Socle commun des modales ------------------------------------------ */
.modal-overlay{
  display:none; position:fixed; inset:0; z-index:300;
  background:rgba(8,9,12,0.78);
  -webkit-backdrop-filter:blur(5px); backdrop-filter:blur(5px);
  align-items:center; justify-content:center; padding:16px;
}
.modal-overlay.open{display:flex;}
.modal{
  position:relative; width:360px; max-width:100%; padding:24px;
  background:var(--surface); border:1px solid var(--line-strong);
  border-radius:var(--radius); box-shadow:0 24px 60px -12px rgba(0,0,0,.9);
}
.modal-title{
  margin:0 0 16px; font-size:15px; font-weight:750; color:var(--text);
  display:flex; align-items:center; gap:8px;
}
.modal-close{
  position:absolute; top:12px; right:12px; width:28px; height:28px;
  background:transparent; border:none; color:var(--text-3);
  font-size:16px; cursor:pointer; border-radius:var(--radius-sm);
  display:flex; align-items:center; justify-content:center;
  transition:background .12s ease, color .12s ease;
}
.modal-close:hover{background:var(--surface-2); color:var(--text);}
.modal-switch{margin-top:12px; font-size:11.5px; color:var(--text-3); text-align:center;}
.modal-switch a{color:var(--accent-2); cursor:pointer; text-decoration:none;}
.modal-switch a:hover{text-decoration:underline;}

/* --- Menu lateral : etats (uniformises sur --accent) -------------------- */
#sideNav{position:fixed; inset:0 auto 0 0; z-index:100; display:flex; align-items:stretch;}
#sideNav:hover #sideNavHandle, #sideNav.nav-open #sideNavHandle{color:var(--accent);}
.side-link:hover{background:var(--accent-soft); color:var(--accent); border-left-color:var(--accent);}
.side-link.active{background:var(--accent-soft); color:var(--accent); border-left-color:var(--accent);}
/* width:auto et non 100% : avec la marge horizontale des pastilles, un
   bouton a 100% deborderait de 16px et son coin arrondi droit serait rogne
   par l'overflow:hidden du panneau. */
button.side-link{background:none; border:none; border-left:2px solid transparent; width:auto; text-align:left; font-family:inherit; cursor:pointer;}
.side-link.disabled{opacity:.45; cursor:not-allowed; pointer-events:none;}

/* =========================================================================
   MENU COMPTE (avatar + carte de profil au survol) — 2026-08-20
   =========================================================================
   Balisage et logique produits par assets/account-menu.js (module partagé,
   window.AccountMenu). Ce bloc CSS est la SOURCE UNIQUE du style de ce
   composant : ne jamais recréer un style concurrent dans le <style> d'une
   page — meme regle que .topbar-printer-select/.topbar-material-select plus
   haut, et pour la meme raison (chaque page a ses propres regles generiques
   heritees de gabarits copies/colles, une propriete non declaree ici peut
   fuir vers elles).

   Ce composant a d'abord ete duplique a la main sur 11 pages : 4 collisions
   de declaration reelles (ROLE_LABEL, AVATAR_URL_PREFIX, isSafeAvatarUrl,
   AVATAR_PRESETS charge deux fois) en sont sorties avant mutualisation.
   ========================================================================= */
.account-menu{position:relative; flex:0 0 auto; opacity:0; transition:opacity .15s ease;}
/* Revele seulement une fois l'etat connecte/deconnecte reellement connu
   (AccountMenu.setReady()) : sans ca le bouton vert "Mon compte" clignote une
   fraction de seconde avant de devenir l'avatar, a chaque chargement de page
   — signale par l'utilisateur le 2026-08-20 ("ca fait pas pro"). opacity et
   non display:none : la place reste reservee, aucun saut de mise en page. */
.account-menu.ready{opacity:1;}
.account-menu-trigger{padding:8px 16px; font-size:12.5px;}
.account-menu-trigger .account-avatar{display:none;}
/* Deconnecte : bouton rouge "Se connecter" (jamais vert, ca laissait croire
   a une session active — signale par l'utilisateur le 2026-08-24). Des que
   .is-user est ajoutee (AccountMenu.update()), les regles ci-dessous plus
   bas reprennent la main et retablissent le vert + l'avatar. */
.account-menu:not(.is-user) .account-menu-trigger{
  background:var(--danger); box-shadow:0 2px 8px rgba(255,100,103,0.35);
}
.account-menu:not(.is-user) .account-menu-trigger:hover{
  background:#e5484b; border-color:transparent; color:#fff;
  box-shadow:0 4px 14px rgba(255,100,103,0.4);
}
.account-menu.is-user .account-menu-trigger{
  width:40px; height:40px; padding:0; border-radius:50%; overflow:hidden;
  background:var(--surface-3); box-shadow:none; border:2px solid var(--accent);
  cursor:pointer;
}
.account-menu.is-user .account-menu-trigger:hover{border-color:#34d399; background:var(--surface-3);}
.account-menu.is-user .account-menu-trigger .account-menu-label{display:none;}
.account-menu.is-user .account-menu-trigger .account-avatar{display:flex;}
.account-avatar{
  width:100%; height:100%; border-radius:50%; overflow:hidden;
  align-items:center; justify-content:center;
  background:var(--surface-3); color:var(--text-2);
  font-size:15px; font-weight:800;
}
.account-avatar img{width:100%; height:100%; object-fit:cover;}
.account-avatar svg{width:100%; height:100%; display:block;}

/* La carte reste collee SANS ESPACE sous l'avatar (top:100%, pas de
   margin-top) : c'est elle qui doit rester continument survolee pendant que
   la souris descend depuis le rond. L'ecart visuel vient de son padding-top
   — un padding fait partie de la zone survolable, contrairement a une marge
   qui creerait un vrai trou. Bug vecu et corrige le 2026-08-20 : avec une
   marge, la carte se refermait avant d'etre atteignable. */
.account-hover-card{
  display:none; position:absolute; top:100%; right:0; padding-top:10px;
  width:286px; z-index:80;
  opacity:0; transform:translateY(-6px); pointer-events:none;
  transition:opacity .16s ease, transform .16s ease;
}
.account-hover-card-inner{
  padding:18px 16px 16px;
  background:var(--surface-3); border:1px solid var(--line-strong);
  border-radius:var(--radius); box-shadow:var(--shadow);
}
.account-menu.is-user .account-hover-card{display:block;}
.account-menu.is-user:hover .account-hover-card,
.account-menu.is-user:focus-within .account-hover-card{
  opacity:1; transform:translateY(0); pointer-events:auto;
}

/* --- En-tete : avatar + pseudo en gros, centres (demande explicite) ------ */
.am-head{display:flex; flex-direction:column; align-items:center; text-align:center; gap:9px;}
.am-avatar-lg{width:64px; height:64px; flex:0 0 auto; font-size:24px;}
.am-pseudo{
  font-weight:800; font-size:16px; color:var(--text); max-width:100%;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
.am-badges{display:flex; align-items:center; justify-content:center; gap:7px; flex-wrap:wrap;}
.am-level{
  display:inline-flex; align-items:center; gap:8px;
  padding:5px 13px; border-radius:999px;
  font-size:12px; font-weight:700; letter-spacing:.01em;
  border:1px solid rgba(242,177,52,.4); color:var(--accent-2); background:var(--accent-2-soft);
}
/* .am-card : scope générique du "corps de carte" produit par
   account-menu.js (cardBodyMarkup) — partagé par les 3 endroits où ce corps
   de carte est monté : la "Fiche personnelle" (carte de survol du menu
   compte, .account-hover-card-inner.am-card ; ET la carte statique de
   compte.html, #personalCardMount .am-card, voir AccountMenu.mountPersonalCard)
   ET la "Fiche publique" (.maker-card-modal .am-card de galerie.html, voir
   AccountMenu.buildPublicCard). Renommé depuis ".account-hover-card
   .role-badge" pour que le role-badge reste caché par défaut partout. */
.am-card .role-badge{display:none;}
.am-card .role-badge.visible{display:inline-flex;}

/* --- Niveau / XP : seuils et remises partages, voir levelFor() dans
       account-menu.js (source unique, plus de copie dans compte.html) ---- */
.am-discount{margin-top:12px; font-size:11.5px; color:var(--text-3); text-align:center;}
.am-discount strong{color:var(--text-2);}
.am-xp-track{
  margin-top:10px; height:8px; border-radius:999px;
  background:var(--surface-2); border:1px solid var(--line-strong); overflow:hidden;
}
.am-xp-fill{height:100%; background:var(--accent); border-radius:999px; transition:width .3s ease; width:0%;}
.am-xp-meta{display:flex; justify-content:space-between; gap:10px; font-size:11px; color:var(--text-3); margin-top:6px;}

/* --- Description (bio) — même rendu que l'ancien ".maker-bio" propre à
       galerie.html, remonté ici pour être partagé par les deux contextes. */
.am-bio{
  margin:12px 0 0; font-size:12.5px; color:var(--text-2); line-height:1.5;
  text-align:center; white-space:pre-wrap; word-break:break-word;
}
.am-bio:empty::before{content:'—'; color:var(--text-3);}

.am-stats{margin-top:14px; padding-top:12px; border-top:1px solid var(--line);}
.am-stat-row{display:flex; justify-content:space-between; align-items:center; gap:10px; font-size:12.5px; margin-bottom:8px;}
.am-stat-row:last-child{margin-bottom:0;}
.am-stat-row .am-stat-label{color:var(--text-2);}
.am-stat-row .am-stat-value{font-weight:750; font-variant-numeric:tabular-nums; display:inline-flex; align-items:center; gap:5px;}

/* --- Selecteurs imprimante + materiau ------------------------------------
   Memes composants que ceux de la barre du haut des 6 outils
   (.topbar-printer-select/.topbar-material-select, style ci-dessus reutilise
   tel quel). Seule difference assumee : ils occupent toute la largeur de la
   carte au lieu des 170px max de la topbar — d'ou ces 2 surcharges, posees
   ICI et pas dans une page, comme l'exige la regle de ces composants. */
.am-selects{margin-top:14px; display:flex; flex-direction:column; gap:8px;}
.account-hover-card .topbar-printer-select,
.account-hover-card .topbar-material-select{
  max-width:none !important; width:100% !important;
}

.account-hover-actions{display:flex; align-items:center; gap:10px; margin-top:14px;}
/* Juste la piece, volontairement sans cadre ni fond rond (contrairement a
   l'avatar) : une simple icone cliquable, pas un bouton. */
.poly-plans-icon-btn{
  display:flex; align-items:center; justify-content:center; flex:0 0 auto;
  width:26px; height:26px; padding:0; background:none; border:none; cursor:pointer;
  filter:brightness(1); transition:filter .15s ease, transform .1s ease;
}
.poly-plans-icon-btn svg{width:100%; height:100%;}
.poly-plans-icon-btn:hover{filter:brightness(1.25);}
.poly-plans-icon-btn:active{transform:scale(0.92);}
.account-hover-manage{flex:1; padding:9px 14px; font-size:12.5px; text-align:center;}
/* Bouton "Se déconnecter" tout en bas de la fiche personnelle (carte de
   survol uniquement) — séparé du reste par un filet, discret par défaut,
   rouge seulement au survol (jamais un bouton plein comme "Gérer mon
   compte", pour ne pas rivaliser visuellement avec l'action principale). */
.account-hover-signout{
  display:block; width:100%; margin-top:10px; padding-top:10px;
  border:none; border-top:1px solid var(--line);
  background:none; color:var(--text-3); font-size:12px; font-weight:600;
  text-align:center; cursor:pointer; transition:color .14s ease;
}
.account-hover-signout:hover{color:var(--danger);}

/* =========================================================================
   BARRE DU HAUT DES OUTILS 3D — 2026-08-20
   =========================================================================
   Demande explicite : les 6 outils doivent avoir EXACTEMENT la meme barre que
   la page d'accueil (pleine largeur, collante, logo a gauche, menu compte a
   droite), mais garnie de LEURS boutons (materiau, imprimante, Exporter,
   etat d'imprimabilite) au lieu des liens marketing.

   Selecteur `#topbar.app-topbar-tool` (id + classe) et non `.app-topbar-tool`
   seul : chacune des 6 pages definit deja sa propre regle `#topbar{...}` en
   carte (fond, bordure, radius, ombre) dans son <style> local, qui gagnerait
   sur une simple classe. Ces pages ne sont donc PAS a modifier cote CSS —
   il suffit d'ajouter la classe au <header id="topbar">.

   Le decalage negatif annule le padding de #app (16px, et 62px a gauche pour
   la poignee du menu lateral) pour que la barre touche les bords de la
   fenetre, comme sur l'accueil ou #page n'a aucun padding.
   ========================================================================= */
#topbar.app-topbar-tool{
  position:sticky; top:0; z-index:60;
  display:flex; align-items:center; gap:14px; flex-wrap:wrap; flex:0 0 auto;
  background:rgba(10,13,11,0.97);
  border:none; border-bottom:1px solid var(--line);
  border-radius:0; box-shadow:none;
  padding:4px 16px 4px 62px;
  margin:-16px -16px 0 -62px;
  width:calc(100% + 78px);
}
#topbar.app-topbar-tool .app-brand{display:flex; align-items:center; flex:0 0 auto; text-decoration:none;}
#topbar.app-topbar-tool .app-brand img{height:40px; width:auto; display:block;}
/* Pousse le menu compte tout a droite, comme sur l'accueil. .balance-pill a
   deja `margin-left:auto` : on le neutralise ici pour que ce soit le menu
   compte — et lui seul — qui soit repousse a droite, les autres commandes
   restant groupees a gauche a la suite du titre. */
#topbar.app-topbar-tool .balance-pill{margin-left:auto;}
#topbar.app-topbar-tool .account-menu{margin-left:0;}
@media (max-width:860px){
  #topbar.app-topbar-tool{
    padding:4px 12px 4px 56px;
    margin:-12px -12px 0 -56px;
    width:calc(100% + 68px);
  }
}

/* =========================================================================
   POPUP "PLANS POLYS" (achat de Polys via de vrais boutons PayPal) — 2026-08-20
   =========================================================================
   Utilisée par index.html + les 6 outils 3D (boutique.html a son propre
   .pack-card, plus large, pas concerné par ce bloc). Mutualisée ici après
   une régression réelle : lors du passage du menu compte à
   assets/account-menu.js le 2026-08-20, ce bloc CSS — jusque-là dupliqué par
   page comme le menu compte — a été supprimé PAR ERREUR sur les 6 outils (le
   script de nettoyage capturait tout entre le commentaire "Menu compte" et la
   première accolade fermante de .account-hover-balance, sans savoir que ce
   bloc-ci vivait entre les deux). La popup restait fonctionnelle (le clic
   PayPal marchait) mais s'affichait sans aucun style — passée inaperçue car
   jamais retestée visuellement après ce refactor précis. Centralisée ici pour
   que ça ne puisse plus se reproduire : plus aucune page ne porte sa propre
   copie de ce bloc. */
.poly-plans-sub{color:var(--text-3); font-size:12px; margin:-10px 0 16px;}
.poly-plan-row{
  display:flex; flex-direction:column; gap:10px;
  padding:12px 14px; margin-bottom:10px;
  background:var(--surface-2); border:1px solid var(--line);
  border-radius:var(--radius-sm); color:var(--text);
}
.poly-plan-row:last-child{margin-bottom:0;}
.poly-plan-row.featured{border-color:rgba(242,177,52,.45);}
.poly-plan-info{display:flex; align-items:center; justify-content:space-between; gap:12px;}
.poly-plan-name{font-size:12.5px; font-weight:750; display:flex; align-items:center; gap:6px; flex-wrap:wrap;}
.poly-plan-badge{
  font-size:9.5px; font-weight:750; padding:2px 7px; border-radius:999px;
  color:var(--accent-2); background:var(--ink); border:1px solid rgba(242,177,52,.5);
  text-transform:uppercase; letter-spacing:.03em;
}
.poly-plan-points{font-size:11.5px; color:var(--text-2); margin-top:3px; display:flex; align-items:center; gap:4px;}
.poly-plan-price{text-align:right; flex:0 0 auto;}
.poly-plan-price .now{font-size:15px; font-weight:800; display:block;}
.poly-plan-price .before{display:block; font-size:10.5px; color:var(--text-3); text-decoration:line-through;}
.poly-plan-pp{min-height:36px;}
.poly-plans-loading, .poly-plans-error{padding:16px 0; text-align:center; color:var(--text-3); font-size:12.5px;}

/* Mention légale de renoncement au droit de rétractation (art. L. 221-28 13°
   Code de la consommation), affichée UNE FOIS au-dessus de la liste des
   plans — avant tout clic sur un bouton PayPal, quel que soit le plan choisi.
   Même contenu que #withdrawalNotice sur boutique.html. */
.poly-plans-legal{
  font-size:10.5px; line-height:1.5; color:var(--text-3);
  padding:9px 12px; margin:0 0 14px;
  background:var(--surface-2); border:1px solid var(--line); border-radius:var(--radius-sm);
}

/* ---------------------------------------------------------------------------
   ZONE DE DÉPÔT D'IMAGE — produite par le type de champ `fichier` de
   assets/params-schema.js (2026-09-06, emporte-pièce à partir d'une image).
   Le style vit ICI, en un seul exemplaire, et jamais dans le <style> d'une
   page : c'est la règle déjà posée pour le menu compte et les sélecteurs de
   la barre du haut — un composant partagé n'a qu'une seule feuille de style,
   sinon chaque nouvelle page en redéfinit une variante qui dérive.
   --------------------------------------------------------------------------- */
.params-dropzone{
  border:1.5px dashed var(--line-strong); border-radius:var(--radius-sm);
  padding:14px 12px; text-align:center; cursor:pointer;
  font-size:11.5px; line-height:1.45; color:var(--text-3);
  background:var(--surface-2);
  transition:border-color .15s ease, color .15s ease, background .15s ease;
}
.params-dropzone:hover, .params-dropzone.is-survol{
  border-color:var(--accent-bright); color:var(--text-2);
}
.params-dropzone-statut{
  font-size:10.5px; line-height:1.45; color:var(--text-3); margin-top:6px;
}
.params-dropzone-statut:empty{display:none;}
.params-dropzone-statut.ok{color:var(--accent-bright);}
.params-dropzone-statut.ko{color:var(--danger);}

/* ---------------------------------------------------------------------------
   BASCULE À DEUX POSITIONS — produite par le type de champ `bascule` de
   assets/params-schema.js (2026-09-07, « Position de l'épingle » du
   marque-verre). Une case à cocher restait le bon réglage sur le fond, mais
   « Épingle à gauche du prénom » obligeait à déduire l'autre position ; deux
   boutons la nomment.
   Le vert actif reprend `.pv-mode-btn.active` de assets/plate-preview.js
   (fond vert vif, texte très sombre) : c'est déjà la façon dont ce site
   montre « la position choisie » dans la barre d'aperçu.
   --------------------------------------------------------------------------- */
.params-bascule{
  display:flex; gap:4px; padding:3px;
  background:var(--surface-2); border:1px solid var(--line);
  border-radius:var(--radius-sm);
}
.params-bascule-opt{
  flex:1; background:transparent; border:none;
  color:var(--text-3); font-family:inherit; font-size:11.5px; font-weight:700;
  /* Le meme rayon que la barre, et non un rayon reduit : certaines pages
     mettent deliberement --radius-sm a 0 (le marque-verre est tout en coins
     carres), et un `calc(... - 2px)` y devient NEGATIF, donc invalide, donc
     ignore en silence. */
  padding:7px 4px; border-radius:var(--radius-sm);
  cursor:pointer; transition:background .15s ease, color .15s ease;
}
.params-bascule-opt:hover{ background:rgba(255,255,255,.06); color:var(--text-2); }
.params-bascule-opt.is-actif{
  background:var(--accent-bright); color:#08210f;
  box-shadow:0 2px 8px rgba(34,197,94,.22);
}
/* `:focus-visible` et non `:focus` : la bascule s'utilise surtout à la souris,
   et un anneau après chaque clic serait du bruit. Au clavier il reste. */
.params-bascule-opt:focus-visible{
  outline:2px solid var(--accent-bright); outline-offset:2px;
}

/* Avertissement de droits en pied de menu d'export. Écrit d'abord en local
   dans le créateur de maillot (2026-08-20) ; posé ici quand l'emporte-pièce
   a pu partir d'une image importée (2026-09-06), pour ne pas en faire une
   3ᵉ copie. La règle locale du maillot reste en place et gagne (même
   sélecteur, feuille de page chargée après) — valeurs identiques. */
.dropdown-menu .rights-hint{
  padding:8px 15px; font-size:10px; line-height:1.4; color:var(--text-3);
  border-top:1px solid var(--line); cursor:default;
}

/* --- Sauvegardes de réglages « Mes créations » (assets/design-saves.js) ----
   Un seul jeu de styles pour les 13 outils. ⚠️ Aucun rayon dérivé par
   soustraction ici : `calc(var(--radius-sm) - 2px)` devient négatif — donc
   invalide, donc ignoré en silence — sur une page qui met ses rayons à 0,
   ce qui est le cas de tout le site depuis la charte du 16/08. On réutilise
   les variables telles quelles. */
.ds-modal-large{width:760px;}
.ds-champ{
  width:100%; margin-top:4px; padding:9px 11px;
  background:var(--surface-2); color:var(--text);
  border:1px solid var(--line-strong); border-radius:var(--radius-sm);
  font-family:inherit; font-size:13px;
}
.ds-champ:focus{outline:none; border-color:var(--accent-bright); box-shadow:var(--ring);}
.ds-quota{margin-top:7px; font-size:11px; color:var(--text-3);}
.ds-erreur{margin-top:7px; font-size:11.5px; color:var(--danger); line-height:1.45;}
.ds-avertissement{
  margin-top:10px; padding:8px 10px; font-size:11.5px; line-height:1.45;
  color:var(--warning); background:var(--warning-soft);
  border:1px solid rgba(245,158,11,0.35); border-radius:var(--radius-sm);
}

.ds-grille{
  display:grid; gap:12px;
  grid-template-columns:repeat(auto-fill, minmax(168px, 1fr));
  max-height:min(60vh, 520px); overflow-y:auto; padding-right:4px;
}
.ds-carte{
  display:flex; flex-direction:column; gap:6px; padding:9px;
  background:var(--surface-2); border:1px solid var(--line);
  border-radius:var(--radius-sm); cursor:pointer;
  transition:border-color .12s ease, background .12s ease;
}
.ds-carte:hover{border-color:var(--accent-bright); background:var(--accent-soft);}
.ds-vignette{
  aspect-ratio:4/3; background:#0c0e11; border:1px solid var(--line);
  border-radius:var(--radius-sm); overflow:hidden;
  display:flex; align-items:center; justify-content:center;
}
.ds-vignette img{width:100%; height:100%; object-fit:contain; display:block;}
.ds-vignette-vide::after{content:'—'; color:var(--text-3); font-size:18px;}
.ds-nom{
  font-size:12.5px; font-weight:650; color:var(--text);
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
.ds-date{font-size:10.5px; color:var(--text-3);}
.ds-actions{display:flex; gap:6px; margin-top:2px;}
.ds-mini{flex:1; font-size:10.5px; padding:5px 8px;}
.ds-suppr:hover{border-color:var(--danger); color:var(--danger); background:var(--danger-soft);}
/* Partage par lien privé (2026-09-10) */
.ds-partage-nom{margin:-4px 0 8px; font-size:12px; font-weight:650; color:var(--text-2); overflow-wrap:anywhere;}
.ds-lien-ligne{display:flex; gap:8px; margin-top:12px; align-items:stretch;}
.ds-lien-ligne .ds-champ{flex:1; min-width:0; font-family:ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size:11.5px;}
.ds-lien-ligne .btn{white-space:nowrap;}
.ds-liens-titre{margin-top:18px; font-size:10.5px; font-weight:800; letter-spacing:.06em; text-transform:uppercase; color:var(--text-3);}
.ds-liens{display:flex; flex-direction:column; gap:6px; margin-top:8px; max-height:190px; overflow-y:auto;}
.ds-lien-actif{display:flex; align-items:center; justify-content:space-between; gap:10px; padding:7px 10px; border:1px solid var(--line); border-radius:var(--radius-sm); background:var(--surface-2);}
.ds-lien-actif .ds-mini{flex:0 0 auto;}
@media (max-width:560px){ .ds-lien-ligne{flex-direction:column;} }

/* ---- Santé du site (panneau admin, 2026-09-10) ---- */
.sante-resume{display:inline-block; padding:6px 12px; border-radius:999px; font-size:12.5px; font-weight:800; margin-bottom:8px;}
.sante-ok{background:var(--accent-soft); color:var(--accent-bright);}
.sante-ko{background:var(--danger-soft); color:var(--danger);}
.sante-serveur{margin:0 0 10px;}
.sante-table td{vertical-align:top;}
.sante-etat-ok{color:var(--accent-bright); font-weight:700;}
.sante-etat-ko{color:var(--danger); font-weight:800;}
.sante-ligne-ko td{background:var(--danger-soft);}
.sante-ms{font-variant-numeric:tabular-nums; white-space:nowrap; color:var(--text-2);}
.sante-message{max-width:420px; overflow-wrap:anywhere;}
.sante-source{max-width:220px; overflow-wrap:anywhere; font-family:ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size:11px; color:var(--text-2);}
.photos-mod-actions{display:flex; gap:6px; flex-wrap:wrap;}

/* ---- Photos d'impression (compte → Feedback, 2026-09-10) ---- */
.pi-zone{flex-basis:100%; display:flex; align-items:center; gap:10px; flex-wrap:wrap; margin-top:6px;}
.pi-ajouter, .pi-retirer{font-size:11.5px; padding:5px 10px;}
.pi-statut{font-size:11.5px; font-weight:700; padding:4px 10px; border-radius:999px; background:var(--surface-3); color:var(--text-2);}
.pi-statut.pi-publie{background:var(--accent-soft); color:var(--accent-bright);}
.pi-statut.pi-refuse{background:var(--danger-soft); color:var(--danger);}
.pi-fichier{margin-top:12px; font-size:12px; color:var(--text-2); max-width:100%;}
.pi-apercu{display:block; max-width:100%; max-height:260px; margin-top:12px; border-radius:var(--radius-sm); border:1px solid var(--line); object-fit:contain; background:var(--surface-2);}
.pi-accord{margin-top:14px;}

/* ---- Cartes cadeaux (compte, 2026-09-10) ---- */
.cc-intro{margin-top:0;}
.cc-offrable{margin:10px 0 8px; font-size:13px; font-weight:650; color:var(--text);}
.cc-ligne{display:flex; gap:8px; align-items:stretch; flex-wrap:wrap;}
.cc-ligne .ds-champ{flex:1; min-width:150px;}
.cc-code{font-family:ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; letter-spacing:.08em;}
.cc-resultat{margin-top:14px; padding:12px; border:1px solid var(--accent-bright); border-radius:var(--radius-sm); background:var(--accent-soft);}
.cc-resultat-titre{font-size:12.5px; font-weight:700; margin-bottom:8px;}
.cc-code-affiche{font-family:ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-weight:700; letter-spacing:.06em; overflow-wrap:anywhere;}
.cc-code-grand{font-size:18px; color:var(--accent-bright); flex:1; align-self:center;}
.cc-liste{display:flex; flex-direction:column; gap:6px;}
.cc-carte{display:grid; grid-template-columns:minmax(0,1.4fr) auto minmax(0,1.6fr) auto; gap:12px; align-items:center; padding:8px 12px; border:1px solid var(--line); border-radius:var(--radius-sm); background:var(--surface-2); font-size:12.5px;}
.cc-carte .ds-mini{flex:0 0 auto;}
.cc-points{font-weight:800; font-variant-numeric:tabular-nums; white-space:nowrap;}
.cc-etat{color:var(--text-2);}
.cc-utilisee{opacity:.62;}
.ds-erreur.cc-ok{color:var(--accent-bright);}
@media (max-width:640px){ .cc-carte{grid-template-columns:1fr auto;} }
.boutique-cadeau{margin:16px 0 0; font-size:13px; color:var(--text-2); text-align:center;}
.boutique-cadeau a{color:var(--accent-bright);}

/* ---- Galerie : modèles officiels et photos de la communauté (2026-09-10) ---- */
.gc-section{width:100%; max-width:1080px; margin:0 0 26px;}
#galleryImpressions.gc-section{margin:34px 0 10px;}
.gc-entete{margin-bottom:12px;}
.gc-titre{margin:0; font-size:18px; font-weight:800; letter-spacing:-.01em;}
.gc-sous-titre{margin:4px 0 0; font-size:12.5px; color:var(--text-2);}
.gc-bande{display:grid; grid-auto-flow:column; grid-auto-columns:minmax(190px, 220px); gap:12px; overflow-x:auto; padding-bottom:6px; scroll-snap-type:x proximity;}
.gc-modele{display:flex; flex-direction:column; border:1px solid var(--line); border-radius:var(--radius-sm); overflow:hidden; background:var(--surface-2); text-decoration:none; color:var(--text); scroll-snap-align:start; transition:border-color .15s ease, transform .15s ease;}
.gc-modele:hover, .gc-modele:focus-visible{border-color:var(--accent-bright); transform:translateY(-2px);}
.gc-modele img{width:100%; aspect-ratio:1/1; object-fit:cover; display:block; background:var(--surface-3);}
.gc-modele-pied{display:flex; justify-content:space-between; align-items:center; gap:8px; padding:8px 10px; font-size:11.5px;}
.gc-outil{font-weight:700; white-space:nowrap; overflow:hidden; text-overflow:ellipsis;}
.gc-action{color:var(--accent-bright); font-weight:700; white-space:nowrap;}
.gc-photos{display:grid; grid-template-columns:repeat(auto-fill, minmax(200px, 1fr)); gap:14px;}
.gc-photo{margin:0; border:1px solid var(--line); border-radius:var(--radius-sm); overflow:hidden; background:var(--surface-2);}
.gc-photo img{width:100%; aspect-ratio:4/3; object-fit:cover; display:block;}
.gc-photo figcaption{display:flex; justify-content:space-between; gap:8px; padding:7px 10px; font-size:11.5px; color:var(--text-2);}
.gc-date{white-space:nowrap;}
.gc-note{margin:12px 0 0; font-size:12px; color:var(--text-3);}
.gal-badge-officiel{position:absolute; top:8px; left:8px; z-index:1; padding:3px 8px; border-radius:999px; background:var(--accent-bright); color:#06200f; font-size:10.5px; font-weight:800; letter-spacing:.02em; pointer-events:none;}
@media (prefers-reduced-motion: reduce){ .gc-modele{transition:none;} .gc-modele:hover{transform:none;} }

/* ---- Impression à la demande (outils, compte, admin — 2026-09-11) ---- */
.ds-modal-impression .modal{width:560px; max-width:94vw;}
.ds-imp-intro{margin-top:0;}
.ds-imp-apercu{display:block; max-width:100%; max-height:180px; margin:10px auto 4px; border-radius:var(--radius-sm); border:1px solid var(--line); background:#0c0e11;}
.ds-imp-form{display:grid; grid-template-columns:repeat(2, minmax(0,1fr)); gap:10px 12px; margin-top:10px;}
.ds-imp-form .ds-imp-droits, .ds-imp-form .hint, .ds-imp-form label:nth-of-type(3), .ds-imp-form label:nth-of-type(7){grid-column:1/-1;}
.ds-imp-champ{display:flex; flex-direction:column; gap:4px; font-size:11.5px; font-weight:650; color:var(--text-2); min-width:0;}
.ds-imp-champ .ds-champ{width:100%;}
.ds-imp-ok{margin-top:14px; padding:12px 14px; border-radius:var(--radius-sm); background:var(--accent-soft); font-size:13px; line-height:1.5;}
.ds-imp-ok a{color:var(--accent-bright);}
@media (max-width:560px){ .ds-imp-form{grid-template-columns:1fr;} }
.cmd-liste{display:flex; flex-direction:column; gap:10px;}
.cmd-ligne, .cmd-admin-tete{display:flex; gap:14px; align-items:flex-start;}
.cmd-ligne{padding:12px; border:1px solid var(--line); border-radius:var(--radius-sm); background:var(--surface-2);}
.cmd-admin{padding:14px; border:1px solid var(--line); border-radius:var(--radius-sm); background:var(--surface-2); display:flex; flex-direction:column; gap:12px;}
.cmd-vignette{width:112px; height:84px; object-fit:contain; border-radius:6px; border:1px solid var(--line); background:#0c0e11; flex:0 0 auto;}
.cmd-info{display:flex; flex-direction:column; gap:5px; min-width:0; flex:1; align-items:flex-start;}
.cmd-titre{font-weight:800; font-size:13.5px;}
.cmd-date, .cmd-adresse{font-size:12px; color:var(--text-2); overflow-wrap:anywhere;}
.cmd-statut{display:inline-block; padding:3px 10px; border-radius:999px; font-size:11.5px; font-weight:700; background:var(--surface-3); color:var(--text-2);}
.cmd-statut.cmd-action{background:var(--accent-2-soft); color:var(--accent-2);}
.cmd-statut.cmd-ok{background:var(--accent-soft); color:var(--accent-bright);}
.cmd-statut.cmd-fin{opacity:.7;}
.cmd-prix{font-size:13px; font-weight:700; font-variant-numeric:tabular-nums;}
.cmd-note{font-size:12.5px; color:var(--text-2); white-space:pre-wrap; overflow-wrap:anywhere;}
.cmd-actions{display:flex; gap:8px; flex-wrap:wrap; margin-top:4px;}
.cmd-admin-form{display:grid; grid-template-columns:repeat(4, minmax(0,1fr)); gap:10px 12px;}
.cmd-admin-large{grid-column:1/-1;}
.cmd-etat{font-size:12.5px; color:var(--text-2);}
.cmd-prevenir{display:inline-flex; align-items:center; gap:6px; font-size:12.5px; color:var(--text-2); cursor:pointer;}
.cmd-payer{margin-top:6px; padding:12px; border:1px solid var(--line); border-radius:var(--radius-sm); background:var(--surface-3); display:flex; flex-direction:column; gap:10px; width:100%; max-width:420px;}
.cmd-payer-titre{font-weight:800; font-size:13.5px;}
.cmd-consent{display:flex; gap:8px; align-items:flex-start; font-size:12px; line-height:1.5; color:var(--text-2); cursor:pointer;}
.cmd-consent input{margin-top:2px; flex:0 0 auto;}
.cmd-estim{display:flex; flex-direction:column; gap:8px; padding:10px 12px; border:1px dashed var(--line); border-radius:var(--radius-sm);}
.cmd-estim-sortie{display:flex; flex-direction:column; gap:3px; font-size:12.5px; color:var(--text-2); font-variant-numeric:tabular-nums;}
.cmd-estim-sortie strong{color:var(--text); font-size:14px;}
.cpt-section{display:flex; flex-direction:column; gap:10px; padding:14px; margin-top:12px; border:1px solid var(--line); border-radius:var(--radius-sm); background:var(--surface-2);}
.cpt-titre{font-weight:800; font-size:14px;}
.cpt-chiffres{display:grid; grid-template-columns:repeat(3, minmax(0,1fr)); gap:10px;}
.cpt-chiffre{display:flex; flex-direction:column; gap:2px; padding:10px 12px; border-radius:var(--radius-sm); background:var(--surface-3);}
.cpt-chiffre span{font-size:12px; color:var(--text-2);}
.cpt-chiffre strong{font-size:18px; font-variant-numeric:tabular-nums;}
.cpt-jauge-bloc{display:flex; flex-direction:column; gap:4px;}
.cpt-jauge-tete{display:flex; justify-content:space-between; gap:10px; flex-wrap:wrap; font-size:12.5px; color:var(--text-2);}
.cpt-jauge-tete strong{color:var(--text); font-variant-numeric:tabular-nums;}
.cpt-jauge{height:8px; border-radius:999px; background:var(--surface-3); overflow:hidden;}
.cpt-jauge-rempli{height:100%; border-radius:999px;}
.cpt-vert{background:var(--accent-bright);} .cpt-jaune{background:#eab308;} .cpt-orange{background:#f97316;} .cpt-rouge{background:#ef4444;}
.cpt-alerte{font-size:13px; font-weight:600; padding:8px 12px; border-radius:var(--radius-sm); background:var(--surface-3);}
.cpt-tableau{overflow-x:auto;}
.cpt-tableau table{width:100%; border-collapse:collapse; font-size:12.5px; font-variant-numeric:tabular-nums;}
.cpt-tableau th, .cpt-tableau td{padding:6px 8px; border-bottom:1px solid var(--line); text-align:left; vertical-align:top;}
.cpt-tableau th{color:var(--text-2); font-weight:700;}
.cpt-montant{width:90px !important; display:inline-block; margin-right:6px;}
@media (max-width:760px){ .cpt-chiffres{grid-template-columns:1fr;} }

/* ===== COMPTABILITÉ, refonte C1-C7 (2026-09-15) ============================
   ⚠️ Chaque classe qui pose un `display` a sa garde `[hidden]` : sans elle,
   l'attribut `hidden` (règle du navigateur) serait battu et le volet, le
   formulaire ou les réglages resteraient affichés (piège payé le 09/09). */
.cpt2-pile{display:flex; flex-direction:column; gap:16px;}
.cpt2-barre-haut{margin-bottom:14px;}
.cpt2-carte{background:var(--surface); border:1px solid var(--line); border-radius:var(--radius); padding:18px 20px; display:flex; flex-direction:column; gap:14px; min-width:0;}
.cpt2-declaration{border-color:color-mix(in srgb, var(--accent-2) 30%, var(--line));}
.cpt2-tete{display:flex; align-items:flex-start; justify-content:space-between; gap:12px; flex-wrap:wrap;}
.cpt2-tete h3{margin:2px 0 0; font-size:17px; font-weight:800; letter-spacing:-.01em;}
.cpt2-surtitre{font-size:10.5px; font-weight:750; letter-spacing:.11em; text-transform:uppercase; color:var(--text-3);}
.cpt2-actions{display:flex; align-items:center; gap:8px; flex-wrap:wrap;}
.cpt2-corps{display:flex; flex-direction:column; gap:12px;}
.cpt2-ligne{display:flex; align-items:center; gap:8px; flex-wrap:wrap;}
.cpt2-entre{justify-content:space-between;}
.cpt2-tuiles{display:grid; grid-template-columns:repeat(3, minmax(0,1fr)); gap:12px;}
.cpt2-tuile{display:flex; flex-direction:column; gap:3px; padding:13px 15px; border-radius:var(--radius-sm); background:var(--surface-2); border:1px solid var(--line); min-width:0;}
.cpt2-tuile strong{font-size:22px; font-weight:800; font-variant-numeric:tabular-nums; letter-spacing:-.01em;}
.cpt2-tuile-orange{border-color:color-mix(in srgb, var(--accent-2) 40%, var(--line));}
.cpt2-tuile-orange strong{color:var(--accent-2);}
.cpt2-lbl{font-size:10.5px; font-weight:750; letter-spacing:.09em; text-transform:uppercase; color:var(--text-3);}
.cpt2-detail{font-size:12px; color:var(--text-2);}
.cpt2-grand{font-size:26px; font-weight:800; font-variant-numeric:tabular-nums;}
.cpt2-num{font-family:'JetBrains Mono', ui-monospace, Consolas, monospace; font-variant-numeric:tabular-nums; font-size:12.5px;}
.cpt2-vert{color:var(--accent-bright);} .cpt2-orange{color:var(--accent-2);} .cpt2-rouge{color:var(--danger);}
.cpt2-puce{display:inline-flex; align-items:center; gap:5px; font-size:11.5px; font-weight:700; padding:3px 9px; border-radius:999px; background:var(--surface-3); color:var(--text-2); white-space:nowrap; vertical-align:middle;}
.cpt2-puce-vert{background:var(--ok-soft); color:var(--accent-bright);}
.cpt2-puce-orange{background:var(--accent-2-soft); color:var(--accent-2);}
.cpt2-puce-rouge{background:var(--danger-soft); color:var(--danger);}
.cpt2-puce-bleu{background:rgba(124,184,255,.13); color:#7cb8ff;}
.cpt2-reglages{display:flex; align-items:flex-end; gap:10px; flex-wrap:wrap; padding:12px; border-radius:var(--radius-sm); background:var(--surface-2); border:1px dashed var(--line-strong);}
.cpt2-reglages[hidden], .cpt2-form[hidden], .cpt2-volet[hidden], .cpt2-saisie[hidden], .cpt-tableau[hidden], .cpt2-graphe[hidden]{display:none !important;}
.cpt2-champ{display:flex; flex-direction:column; gap:4px; min-width:130px;}
/* Le panneau pose width:100% sur tous les input/select : dans une ligne d'actions, ils reprennent leur taille. */
.cpt2-ligne .ds-champ, .cpt2-actions .ds-champ{width:auto;}
.cpt2-champ .ds-champ{width:100%;}
.cpt2-legende{display:flex; gap:14px; flex-wrap:wrap; font-size:12px; color:var(--text-2); align-items:center;}
.cpt2-legende i{display:inline-block; width:10px; height:10px; border-radius:3px; margin-right:6px; vertical-align:-1px;}
.cpt2-graphe svg{display:block; max-width:100%; height:auto;}
.cpt2-deux{display:grid; grid-template-columns:1fr 1fr; gap:14px;}
.cpt2-deux-inegal{grid-template-columns:1.35fr 1fr;}
.cpt2-bloc{display:flex; flex-direction:column; gap:12px; padding:14px; border-radius:var(--radius-sm); background:var(--surface-2); border:1px solid var(--line); min-width:0;}
.cpt2-bloc h4{margin:0; font-size:14px; font-weight:800;}
.cpt2-jauge{display:flex; flex-direction:column; gap:6px;}
.cpt2-jauge-tete{display:flex; justify-content:space-between; gap:10px; flex-wrap:wrap; font-size:12.5px; color:var(--text-2);}
.cpt2-jauge-tete strong{color:var(--text); font-variant-numeric:tabular-nums;}
.cpt2-barre{position:relative; height:8px; border-radius:999px; background:var(--surface-3);}
.cpt2-barre i{position:absolute; top:0; bottom:0; left:0; border-radius:999px; min-width:3px;}
.cpt2-rempli-vert{background:var(--accent-bright);} .cpt2-rempli-orange{background:#f97316;} .cpt2-rempli-rouge{background:#ef4444;}
.cpt2-barre em{position:absolute; top:-4px; width:2px; height:16px; border-radius:2px; background:var(--accent-2); transform:translateX(-1px);}
.cpt2-calendrier{display:grid; grid-template-columns:repeat(6, minmax(0,1fr)); gap:8px;}
.cpt2-mois{display:flex; flex-direction:column; gap:6px; padding:10px; border-radius:var(--radius-sm); background:var(--surface-2); border:1px solid var(--line); min-width:0;}
.cpt2-courant{border-color:color-mix(in srgb, var(--accent-bright) 50%, var(--line));}
.cpt2-futur{opacity:.5;}
.cpt2-mois-nom{font:inherit; font-weight:750; font-size:13px; text-align:left; background:none; border:none; color:var(--text); padding:0; cursor:pointer;}
.cpt2-mois-nom:hover{color:var(--accent-bright);}
.cpt2-coches{display:flex; gap:5px; flex-wrap:wrap;}
.cpt2-coche{font:inherit; font-size:10.5px; font-weight:700; padding:2px 8px; border-radius:999px; border:1px dashed var(--line-strong); background:none; color:var(--text-3); cursor:pointer;}
.cpt2-coche.fait{border-style:solid; border-color:transparent; background:var(--ok-soft); color:var(--accent-bright);}
.cpt2-coche:disabled{cursor:default;}
.cpt2-export{padding-top:12px; border-top:1px solid var(--line);}
.cpt2-filtre{font:inherit; font-size:12px; font-weight:700; padding:5px 11px; border-radius:999px; border:1px solid var(--line); background:var(--surface-2); color:var(--text-2); cursor:pointer; white-space:nowrap;}
.cpt2-filtre.actif{background:var(--ok-soft); border-color:transparent; color:var(--accent-bright);}
.cpt2-recherche{margin-left:auto; width:min(260px, 100%) !important;}
.cpt2-factures{display:grid; grid-template-columns:minmax(0,1fr); gap:14px; align-items:start;}
.cpt2-factures.avec-volet{grid-template-columns:minmax(0,1fr) 340px;}
.cpt2-ligne-facture{cursor:pointer;}
.cpt2-ligne-facture:hover td{background:rgba(255,255,255,.03);}
.cpt2-ligne-facture.choisie td{background:var(--accent-soft);}
.cpt2-ligne-facture:focus-visible{outline:2px solid var(--accent-bright); outline-offset:-2px;}
.cpt2-volet{position:sticky; top:16px; display:flex; flex-direction:column; gap:10px; padding:14px; border-radius:var(--radius-sm); background:var(--surface-2); border:1px solid var(--line-strong); box-shadow:-18px 0 40px -28px rgba(0,0,0,.8);}
.cpt2-volet-tete{justify-content:space-between;}
.cpt2-lignes{display:flex; flex-direction:column; gap:4px; padding:8px 0; border-top:1px solid var(--line); border-bottom:1px solid var(--line);}
.cpt2-consequence{font-size:12.5px; line-height:1.45; padding:9px 11px; border-radius:var(--radius-sm); background:var(--surface-3);}
.cpt2-saisie{width:120px !important;}
.cpt2-fermer{padding:3px 8px !important; font-size:12px !important; background:none !important; border-color:transparent !important; color:var(--text-3) !important;}
.cpt2-fermer:hover{color:var(--danger) !important;}
.btn-danger-doux{background:var(--danger-soft) !important; border-color:transparent !important; color:var(--danger) !important; margin-left:auto;}
.btn-danger-doux:disabled{opacity:.5;}
.cpt2-form{display:grid; grid-template-columns:repeat(auto-fit, minmax(150px,1fr)); gap:10px; align-items:end; padding:12px; border-radius:var(--radius-sm); background:var(--surface-3);}
.cpt2-total{padding-top:8px; border-top:1px solid var(--line-strong); font-size:15px;}
.cpt2-table-marges td, .cpt2-table-marges th{white-space:nowrap;}
@media (max-width:1100px){ .cpt2-calendrier{grid-template-columns:repeat(4, minmax(0,1fr));} .cpt2-factures.avec-volet{grid-template-columns:1fr;} }
@media (max-width:760px){ .cpt2-tuiles, .cpt2-deux, .cpt2-deux-inegal{grid-template-columns:1fr;} .cpt2-calendrier{grid-template-columns:repeat(2, minmax(0,1fr));} .cpt2-recherche{margin-left:0;} }

/* --- Cloche de notifications (assets/notifications.js, migration 94) --------
   Posée dans .topbar-actions, ENTRE la pastille de Polys et le menu compte.
   Le panneau se cale sur la droite : sur mobile il occupe la largeur utile
   moins deux gouttières, jamais plus, pour ne pas déborder de l'écran. */
.notif{position:relative; display:flex; align-items:center;}
.notif-bouton{position:relative; display:grid; place-items:center; width:36px; height:36px; padding:0;
  border:1px solid var(--line); border-radius:999px; background:var(--surface-2); color:var(--text-2); cursor:pointer;
  transition:color .15s ease, border-color .15s ease;}
.notif-bouton:hover{color:var(--accent-bright); border-color:var(--accent-bright);}
.notif-bouton.notif-actif{color:var(--text);}
.notif-pastille{position:absolute; top:-3px; right:-3px; min-width:17px; height:17px; padding:0 4px;
  border-radius:999px; background:var(--accent-bright); color:#06210F; font-size:10.5px; font-weight:800;
  line-height:17px; text-align:center; font-variant-numeric:tabular-nums;}
.notif-panneau{position:absolute; top:calc(100% + 10px); right:0; width:min(360px, calc(100vw - 32px));
  background:var(--surface); border:1px solid var(--line); border-radius:var(--radius-sm);
  box-shadow:0 18px 40px -20px rgba(0,0,0,.55); z-index:60; overflow:hidden;}
.notif-tete{display:flex; align-items:center; justify-content:space-between; gap:10px;
  padding:11px 14px; border-bottom:1px solid var(--line); font-size:14px;}
.notif-tout-lu{font:inherit; font-size:12px; font-weight:600; color:var(--accent-bright);
  background:none; border:none; padding:0; cursor:pointer;}
.notif-tout-lu:disabled{color:var(--text-3); cursor:default;}
.notif-liste{max-height:min(60vh, 420px); overflow-y:auto;}
.notif-item{display:flex; gap:11px; padding:11px 14px; border-bottom:1px solid var(--line);
  color:var(--text); text-decoration:none;}
.notif-item:last-child{border-bottom:none;}
a.notif-item:hover{background:var(--surface-2);}
.notif-item-neuve{background:color-mix(in srgb, var(--accent-bright) 8%, transparent);}
.notif-item-ico{flex:0 0 auto; font-size:15px; line-height:1.35;}
.notif-item-corps{display:flex; flex-direction:column; gap:2px; min-width:0;}
.notif-item-titre{font-size:13.5px; font-weight:700; line-height:1.35;}
.notif-item-texte{font-size:12.5px; color:var(--text-2); line-height:1.45;}
.notif-item-date{font-size:11.5px; color:var(--text-3);}
.notif-vide{padding:22px 16px; text-align:center; font-size:13px; color:var(--text-2);}
.notif-pied{padding:10px 14px; border-top:1px solid var(--line); text-align:center;}
.notif-pied a{font-size:12.5px; font-weight:600; color:var(--accent-bright); text-decoration:none;}
.notif-pied a:hover{text-decoration:underline;}
@media (max-width:520px){ .notif-panneau{position:fixed; top:60px; right:12px; left:12px; width:auto;} }

/* --- Tableau de bord admin (assets/admin-tableau-bord.js, migration 94) ----- */
.tb-entete{display:flex; align-items:center; gap:14px; margin-bottom:16px;}
.tb-logo{height:34px; width:auto; flex:0 0 auto;}
.tb-eyebrow{font-size:11.5px; font-weight:700; letter-spacing:.12em; text-transform:uppercase; color:var(--accent-bright);}
.tb-titre{margin:0; font-size:22px; font-weight:800; letter-spacing:-.01em;}
.tb-entete .btn{margin-left:auto;}
.tb-grille{display:grid; grid-template-columns:repeat(2, minmax(0, 1fr)); gap:14px; align-items:start;}
.tb-colonne{display:flex; flex-direction:column; gap:14px; min-width:0;}
.tb-tuiles{display:grid; grid-template-columns:repeat(4, minmax(0,1fr)); gap:12px; margin-bottom:14px;}
.tb-tuile{display:flex; flex-direction:column; gap:3px; padding:13px 15px; border-radius:var(--radius-sm); background:var(--surface-2); border:1px solid var(--line);}
.tb-tuile-lbl{font-size:10.5px; font-weight:750; letter-spacing:.1em; text-transform:uppercase; color:var(--text-3);}
.tb-tuile strong{font-size:22px; font-weight:800; letter-spacing:-.01em; font-variant-numeric:tabular-nums;}
.tb-tuile-orange strong{color:var(--accent-2);}
.tb-tuile-rouge strong{color:var(--danger);}
.tb-tuile-vert strong{color:var(--accent-bright);}
@media (max-width:700px){ .tb-tuiles{grid-template-columns:1fr 1fr;} }
/* La boîte « À traiter » (refonte A6) : la couleur du point dit l'urgence. */
.tb-atraiter{border-color:color-mix(in srgb, var(--accent-2) 35%, var(--line));}
.tb-inbox{display:grid; grid-template-columns:auto minmax(0,1fr) auto; gap:10px; align-items:center; padding:9px 0; border-top:1px solid var(--line);}
.tb-inbox:first-child{border-top:none;}
.tb-inbox-point{width:9px; height:9px; border-radius:50%; background:var(--text-3); box-shadow:0 0 0 3px rgba(255,255,255,.05);}
.tb-inbox-rouge .tb-inbox-point{background:var(--danger); box-shadow:0 0 0 3px var(--danger-soft);}
.tb-inbox-orange .tb-inbox-point{background:var(--accent-2); box-shadow:0 0 0 3px var(--accent-2-soft);}
.tb-inbox-texte{display:flex; flex-direction:column; gap:1px; min-width:0;}
.tb-inbox-texte strong{font-size:13px; font-weight:700; overflow-wrap:anywhere;}
.tb-inbox-texte span{font-size:12px; color:var(--text-2); overflow-wrap:anywhere;}
.tb-inbox-btn{padding:5px 10px !important; font-size:11.5px !important; white-space:nowrap;}
/* Cartes « en direct » adoptées de l'ancienne colonne de gauche (refonte A2). */
.tb-direct .user-list-empty{padding:4px 0;}
@media (max-width:700px){ .tb-grille{grid-template-columns:1fr;} }
/* Cartes de validation posées dans une demi-colonne du tableau de bord : on
   resserre leurs tableaux pour que les boutons d'action restent visibles sans
   défilement horizontal (boutons empilés, cellules moins espacées). */
.tb-colonne .cost-table{font-size:12.5px;}
.tb-colonne .cost-table th, .tb-colonne .cost-table td{padding-right:6px;}
.tb-colonne .gal-mod-thumb{width:40px; height:40px;}
.tb-colonne .photos-mod-actions{flex-direction:column; align-items:stretch; gap:4px;}
.tb-colonne .photos-mod-actions .btn, .tb-colonne #tdModBody .btn{padding:4px 8px; font-size:11.5px;}
/* La colonne « Statut » des photos redit le filtre, et les boutons proposés disent
   déjà où en est la photo : dans la demi-colonne, elle cède sa place aux actions. */
.tb-colonne #photosModCard th:nth-child(5), .tb-colonne #photosModBody td:nth-child(5){display:none;}
.tb-carte{background:var(--surface-2); border:1px solid var(--line); border-radius:var(--radius-sm); padding:16px 18px;}
.tb-carte-tete{display:flex; align-items:center; justify-content:space-between; gap:10px; margin-bottom:12px;}
.tb-carte-tete h3{margin:0; font-size:14px; font-weight:800; letter-spacing:.01em;}
.tb-carte-orange{border-color:color-mix(in srgb, #f59e0b 45%, var(--line));}
.tb-carte-rouge{border-color:color-mix(in srgb, #ef4444 50%, var(--line));}
.tb-lien{font:inherit; font-size:12px; font-weight:600; color:var(--accent-bright); background:none; border:none; padding:0; cursor:pointer;}
.tb-lien:hover{text-decoration:underline;}
.tb-chiffres{display:grid; grid-template-columns:repeat(auto-fit, minmax(96px,1fr)); gap:10px; margin-bottom:12px;}
.tb-chiffre{display:flex; flex-direction:column; gap:2px; padding:9px 11px; border-radius:var(--radius-sm); background:var(--surface-3);}
.tb-chiffre strong{font-size:17px; font-variant-numeric:tabular-nums;}
.tb-chiffre span{font-size:11.5px; color:var(--text-2); line-height:1.3;}
.tb-liste{display:flex; flex-direction:column;}
.tb-item{display:grid; grid-template-columns:auto 1fr auto; gap:10px; align-items:baseline; padding:7px 0; border-top:1px solid var(--line); font-size:13px;}
.tb-item:first-child{border-top:none;}
.tb-item-quoi{font-size:11px; font-weight:800; text-transform:uppercase; letter-spacing:.05em; color:var(--accent-bright);}
.tb-item-nom{color:var(--text); min-width:0; overflow-wrap:anywhere;}
.tb-item-date{font-size:11.5px; color:var(--text-3); white-space:nowrap; font-variant-numeric:tabular-nums;}
.tb-vide{font-size:13px; color:var(--text-2); padding:6px 0;}
.tb-alerte{font-size:12.5px; font-weight:600; padding:8px 11px; border-radius:var(--radius-sm); background:var(--surface-3); margin-bottom:10px;}
.tb-jauge-bloc{display:flex; flex-direction:column; gap:4px; margin-top:9px;}
.tb-jauge-tete{display:flex; justify-content:space-between; gap:10px; font-size:12px; color:var(--text-2);}
.tb-jauge-tete strong{color:var(--text); font-variant-numeric:tabular-nums;}
.tb-jauge{height:7px; border-radius:999px; background:var(--surface-3); overflow:hidden;}
.tb-jauge-rempli{height:100%; border-radius:999px; background:var(--accent-bright);}
.tb-orange-fond{background:#f59e0b;} .tb-rouge-fond{background:#ef4444;}
.tb-rouge{color:#f87171;}
.tb-pastille{width:12px; height:12px; border-radius:50%; border:1px solid var(--line); background:var(--surface-3); display:inline-block;}
.tb-ligne-sante{font-size:12.5px; color:var(--text-2); margin-bottom:8px;}

.tb-inters{display:flex; flex-direction:column; gap:4px;}
.tb-inter{display:flex; align-items:center; gap:11px; padding:7px 0; border-top:1px solid var(--line); cursor:pointer;}
.tb-inter:first-child{border-top:none;}
.tb-inter-texte{display:flex; flex-direction:column; gap:1px; min-width:0;}
.tb-inter-nom{font-size:13px; font-weight:600;}
.tb-inter-etat{font-size:11.5px; color:var(--text-3);}
.tb-inter-etat.tb-vert{color:var(--accent-bright);}
.tb-raccourcis{display:grid; grid-template-columns:repeat(auto-fit, minmax(130px,1fr)); gap:8px;}
.tb-raccourci{display:flex; align-items:center; gap:8px; padding:9px 11px; border:1px solid var(--line);
  border-radius:var(--radius-sm); background:var(--surface-3); color:var(--text); font-size:12.5px;
  font-weight:600; text-decoration:none; font-family:inherit; cursor:pointer; text-align:left;}
.tb-raccourci:hover{border-color:var(--accent-bright); color:var(--accent-bright);}
.tb-raccourci-ico{font-size:15px;}

/* --- WebGL indisponible (assets/webgl-secours.js) --------------------------- */
.webgl-secours{position:fixed; left:50%; transform:translateX(-50%); bottom:18px; z-index:9999;
  width:min(520px, calc(100vw - 24px)); display:flex; flex-direction:column; gap:8px;
  padding:14px 16px; border-radius:var(--radius-sm); border:1px solid var(--line);
  background:var(--surface); box-shadow:0 18px 40px -18px rgba(0,0,0,.7);}
.webgl-secours strong{font-size:14px;}
.webgl-secours-texte{font-size:13px; color:var(--text-2); line-height:1.5;}
.webgl-secours-actions{display:flex; gap:8px; flex-wrap:wrap;}

/* --- Stock de bobines (assets/admin-stock.js) ------------------------------- */
.stock-ligne{padding:11px 0; border-top:1px solid var(--line);}
.stock-ligne:first-child{border-top:none;}
.stock-archivee{opacity:.55;}
.stock-tete{display:flex; align-items:center; gap:9px; font-size:13.5px; margin-bottom:6px;}
.stock-pastille{width:14px; height:14px; border-radius:50%; border:1px solid var(--line); background:var(--surface-3); flex:0 0 auto;}
.stock-reste{margin-left:auto; font-size:12.5px; color:var(--text-2); font-variant-numeric:tabular-nums;}
.stock-bas-texte{color:#f87171; font-weight:700;}
.stock-jauge{height:7px; border-radius:999px; background:var(--surface-3); overflow:hidden; margin-bottom:8px;}
.stock-jauge-rempli{height:100%; border-radius:999px; background:var(--accent-bright);}
.stock-jauge-rempli.stock-bas{background:#ef4444;}
.stock-form{display:grid; grid-template-columns:repeat(auto-fit, minmax(120px,1fr)); gap:10px; margin-top:14px;}
.stock-champ{display:flex; flex-direction:column; gap:4px;}
.stock-champ .ds-champ{width:100%;}

/* Centre de notifications (compte.html) : mêmes lignes, sans le cadre flottant. */
.notif-centre{display:flex; flex-direction:column; border:1px solid var(--line); border-radius:var(--radius-sm); overflow:hidden;}
.notif-centre .notif-item{border-bottom:1px solid var(--line);}
.notif-centre-vide{padding:26px 16px; text-align:center; color:var(--text-2); font-size:13.5px;}
.notif-reglages{display:flex; flex-wrap:wrap; gap:10px 18px; margin-top:14px;}
.notif-reglages label{display:flex; align-items:center; gap:7px; font-size:13px; color:var(--text-2);}
.cmd-consent.cmd-consent-alerte{color:var(--accent-2); font-weight:600;}
.cmd-bandeau{padding:10px 14px; margin-bottom:12px; border-radius:var(--radius-sm); background:var(--accent-soft); color:var(--accent-bright); font-size:13px; font-weight:600;}
@media (max-width:760px){ .cmd-admin-form{grid-template-columns:1fr 1fr;} .cmd-ligne, .cmd-admin-tete{flex-direction:column;} }

@media (max-width:600px){
  .ds-modal-large{width:100%;}
  .ds-grille{grid-template-columns:repeat(auto-fill, minmax(132px, 1fr));}
}

/* Boutons « Sauvegarder » / « Mes créations » de la barre du haut. Leur
   APPARENCE est recopiée en ligne depuis #resetModelBtn au montage (voir
   assets/design-saves.js) — les outils ne l'habillent pas tous pareil, le QR
   code le fait par sélecteur d'id sans aucune classe. Ne reste ici que le
   survol, qu'un style calculé ne transporte pas. */
.ds-topbar-btn:hover:not(:disabled){
  border-color:var(--accent-bright) !important;
  color:var(--accent-bright) !important;
}
.ds-topbar-btn:disabled{opacity:.55; cursor:default;}

/* ===== Étalonnage du TD (Chromaplaque) ====================================
   Posé ici et jamais dans le <style> d'une page : même règle que le menu
   compte, les sélecteurs de la barre du haut et le module de sauvegardes.
   Préfixe `cp-et-` pour qu'aucune de ces règles ne puisse en toucher d'autres.
   ========================================================================== */
.cp-et-modal{width:520px; max-width:100%; max-height:88vh; overflow:auto;}
.cp-et-titre{margin:18px 0 6px; font-size:12.5px; font-weight:750; color:var(--text);
  border-top:1px solid var(--line); padding-top:12px;}
.cp-et-boutons{display:flex; gap:8px; margin-top:10px; flex-wrap:wrap;}
.cp-et-boutons .secondary-btn{flex:1 1 180px;}
.cp-et-fichier{display:block; width:100%; margin-top:10px; font-size:11.5px; color:var(--text-3);}
/* `touch-action:none` est OBLIGATOIRE : sans lui, un glissement au doigt fait
   défiler la page au lieu de tracer le cadre, et l'étalonnage devient
   inutilisable sur téléphone — or c'est justement l'appareil qui prend la photo. */
.cp-et-toile{display:block; width:100%; margin-top:10px; border:1px solid var(--line-strong);
  border-radius:var(--radius-sm); background:var(--surface-1); cursor:crosshair;
  touch-action:none;}
.cp-et-sortie{margin-top:8px; min-height:34px;}
.cp-et-td{margin:0; font-size:16px; font-weight:800; color:var(--accent-bright);}
.cp-et-echec{margin:6px 0 0; font-size:11.5px; line-height:1.45; color:#f0a0a0;}
.cp-et-marches{display:flex; gap:3px; margin-top:10px;}
.cp-et-marche{flex:1; height:16px; border-radius:2px; border:1px solid var(--line);}
.cp-et-select{flex:0 0 140px; padding:8px 10px; font-size:12px;
  background:var(--surface-2); color:var(--text);
  border:1px solid var(--line-strong); border-radius:var(--radius-sm);}
.cp-et-rappel{margin:10px 0 0; padding:8px 10px; font-size:11.5px; line-height:1.45;
  color:var(--text-2); background:var(--surface-1);
  border-left:3px solid var(--line-strong); border-radius:var(--radius-sm);}

/* ===== Sélecteur de filaments (Chromaplaque) =============================== */
.cp-fi-modal{width:560px; max-width:100%; max-height:88vh; display:flex; flex-direction:column;}
.cp-fi-barre{display:flex; gap:8px; margin-top:10px;}
.cp-fi-recherche{flex:1; padding:8px 10px; font-size:12px;
  background:var(--surface-2); color:var(--text);
  border:1px solid var(--line-strong); border-radius:var(--radius-sm);}
.cp-fi-liste{margin-top:10px; overflow:auto; max-height:46vh; min-height:120px;
  border:1px solid var(--line); border-radius:var(--radius-sm); padding:4px;}
.cp-fi-ligne{display:flex; align-items:center; gap:10px; width:100%; text-align:left;
  padding:7px 8px; background:transparent; border:none; border-radius:var(--radius-sm);
  cursor:pointer; color:var(--text);}
.cp-fi-ligne:hover{background:var(--surface-2);}
/* Contour clair sur la pastille : sans lui, un filament noir devient invisible
   sur le fond sombre du site, et un blanc se confond avec les cartes. */
.cp-fi-pastille{flex:0 0 22px; height:22px; border-radius:50%;
  border:1px solid var(--line-strong); box-shadow:inset 0 0 0 1px rgba(255,255,255,.14);}
.cp-fi-texte{display:flex; flex-direction:column; min-width:0;}
.cp-fi-nom{font-size:12px; font-weight:650; color:var(--text);
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;}
.cp-fi-meta{font-size:10.5px; color:var(--text-3);
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;}
/* D'ou vient le TD affiche. Une valeur PUBLIEE par le fabricant et une
   estimation a un facteur 2 pres ne doivent pas se lire pareil : sans cette
   distinction, la seconde passe pour la premiere. La sobre est l'estimation
   (le cas courant), la verte est la valeur sure (le cas rare). */
.cp-fi-src{align-self:flex-start; margin:2px 0 1px; padding:1px 6px;
  font-size:10px; font-weight:650; letter-spacing:.2px; border-radius:999px;
  color:var(--text-3); background:var(--surface-2);
  border:1px solid var(--line); white-space:nowrap;}
.cp-fi-src-sur{color:var(--accent-bright); border-color:var(--accent-bright);
  background:transparent;}
/* Deux sources independantes qui s'accordent : c'est ce qu'on a de plus sur. */
.cp-fi-src-double{border-width:2px;}
/* Deux sources qui se CONTREDISENT. On ne tranche pas en silence : la ligne le
   dit, et l'ambre se lit comme une reserve sans crier a l'erreur — il n'y a pas
   de faute, juste une incertitude qu'il faut voir. */
.cp-fi-src-doute{color:#e0a355; border-color:#e0a355; background:transparent;}
.cp-fi-credits{font-size:10px; opacity:.75; margin-top:6px;}
.cp-fi-credits a{color:inherit; text-decoration:underline;}

/* ===== Onglets de la barre laterale d'un outil =============================
   ⚠️ CES REGLES SONT LA COPIE EXACTE de celles que 9 outils portent DEJA dans
   leur propre bloc <style> (marque-verre, QR, lightbox, vase...). Elles sont
   posees ici pour que le 10e outil a onglets (Chromaplaque) n'en fasse pas une
   10e copie -- meme raison que .cp-fi-*, le type `bascule` de params-schema et
   la zone de depot de fichier : le style d'un mecanisme PARTAGE vit dans
   style.css, jamais dans le <style> d'une page.

   ⚠️⚠️ ET ELLES NE CHANGENT RIEN AUX 9 AUTRES PAGES : leur bloc <style> est
   place APRES ce fichier dans le document, donc a specificite egale ce sont
   leurs regles qui gagnent. Verifie a l'ecran avant de committer. Ne pas
   « nettoyer » les copies inline sans refaire cette verification page par page.

   ℹ️ .sidebar-content n'est PAS repris ici : chaque outil le definit deja, et
   le redefinir risquerait de bouger une mise en page eprouvee. */
.tabs-nav{display:flex; padding:8px 12px; gap:6px;
  background-color:var(--surface-2); border-bottom:1px solid var(--border);}
.tab-btn{flex:1; background:transparent; border:none; color:var(--text-muted);
  font-size:.75rem; font-weight:700; padding:8px 4px;
  border-radius:var(--radius-sm); cursor:pointer; transition:all .2s;
  display:flex; align-items:center; justify-content:center; gap:6px;}
.tab-btn:hover{color:var(--text-main); background:rgba(255,255,255,.05);}
.tab-btn.active{background:var(--surface-1); color:var(--accent);
  box-shadow:0 2px 8px rgba(0,0,0,.3); border:1px solid var(--border);}
.tab-pane{display:none; flex-direction:column; gap:14px;}
.tab-pane.active{display:flex;}

/* ===== La pile en image (Chromaplaque) =====================================
   La bande se lit COMME LA PIECE : le bas touche le plateau, le haut est ce
   qu'on voit. C'est ce sens-la qui rend la regle d'ordre evidente. */
.cp-pile{display:flex; gap:10px; align-items:stretch; margin:10px 0 4px;}
.cp-pile-bande{flex:0 0 34px; display:flex; flex-direction:column;
  border:1px solid var(--line-strong); border-radius:var(--radius-sm);
  overflow:hidden; background:var(--surface-1);}
.cp-pile-seg{width:100%; flex:0 0 auto;
  /* Un lisere clair entre les bandes : deux filaments voisins de teintes
     proches seraient indiscernables sans lui, et c'est justement le cas ou on
     a besoin de les distinguer. */
  box-shadow:inset 0 -1px 0 rgba(255,255,255,.22);}
/* Une bande VIDE (le filament ne s'imprime jamais) doit se voir : c'est
   exactement la configuration qui pose probleme. Hachures, pas une couleur. */
.cp-pile-seg-vide{background-image:repeating-linear-gradient(45deg,
  rgba(255,80,80,.85) 0 4px, rgba(0,0,0,.35) 4px 8px) !important;}
.cp-pile-lignes{flex:1; display:flex; flex-direction:column; justify-content:flex-start;
  gap:3px; min-width:0;}
.cp-pile-li{display:flex; align-items:center; gap:7px; font-size:11px;
  color:var(--text-2); min-width:0;}
.cp-pile-li-past{flex:0 0 12px; height:12px; border-radius:3px;
  border:1px solid var(--line-strong);}
.cp-pile-li-nom{flex:1; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;}
.cp-pile-li-ep{flex:0 0 auto; font-variant-numeric:tabular-nums; color:var(--text-3);}
.cp-pile-li-vide{color:#e0605f; font-weight:650;}

/* Un filament = UN bloc, au lieu de trois reglages eparpilles. */
.cp-fil-bloc{border:1px solid var(--line); border-radius:var(--radius-sm);
  padding:8px 10px 4px; margin-top:8px; background:var(--surface-1);}
.cp-fil-tete{display:flex; align-items:center; gap:8px; margin-bottom:6px;}
.cp-fil-past{flex:0 0 16px; height:16px; border-radius:4px;
  border:1px solid var(--line-strong); box-shadow:inset 0 0 0 1px rgba(255,255,255,.14);}
.cp-fil-nom{flex:1; font-size:11.5px; font-weight:650; color:var(--text);}
.cp-fil-ep{font-size:11px; color:var(--text-3); font-variant-numeric:tabular-nums;}
.cp-fil-ep-vide{color:#e0605f; font-weight:650;}
/* Le TD est replie : c'est le seul reglage de physicien de la page, et il a
   desormais une valeur publiee ou estimee dans la plupart des cas. Replier
   n'est PAS retirer -- le champ reste dans le DOM, donc dans les sauvegardes. */
.cp-fil-avance{margin:2px 0 6px;}
.cp-fil-avance>summary{cursor:pointer; font-size:10.5px; color:var(--text-3);
  list-style:none; padding:3px 0;}
.cp-fil-avance>summary::-webkit-details-marker{display:none;}
.cp-fil-avance>summary::before{content:'▸ '; }
.cp-fil-avance[open]>summary::before{content:'▾ ';}
.cp-fil-avance>summary:hover{color:var(--text-2);}
/* Le millimetre a cote du numero de couche : une couche est un compte
   abstrait, et son sens CHANGE des qu'on touche la hauteur de couche. */
.cp-fil-mm{color:var(--text-3); font-weight:400; font-variant-numeric:tabular-nums;}
/* Valeur en euros d'un prix en Polys — assets/prix-polys.js (2026-09-10) */
.prix-euros{opacity:.72; font-weight:500; font-size:.92em; white-space:nowrap;}
/* Avis « modèle de la galerie chargé » — assets/design-saves.js (2026-09-10) */
.ds-avis{position:fixed; left:50%; bottom:24px; transform:translateX(-50%); z-index:10000;
  max-width:min(560px, 92vw); padding:12px 16px; font-size:13px; line-height:1.45;
  color:var(--text); background:var(--surface-3); border:1px solid var(--accent-bright);
  border-radius:var(--radius-sm); box-shadow:0 12px 32px -8px rgba(0,0,0,.7);
  transition:opacity .35s ease;}
.ds-avis-fin{opacity:0;}
@media (prefers-reduced-motion: reduce){ .ds-avis{transition:none;} }
/* CGV : encadré de la garantie légale de conformité (2026-09-10) */
.legal-encadre{margin:0 0 10px; padding:12px 14px; border:1px solid var(--line-strong);
  border-radius:var(--radius-sm); background:var(--surface-2);}
.legal-encadre p:last-child{margin-bottom:0;}
/* Consentement avant paiement — voir assets/consentement-achat.js (2026-09-10) */
.consent-achat{display:flex; gap:9px; align-items:flex-start; margin:0 0 12px; padding:10px 12px;
  font-size:11.5px; line-height:1.5; color:var(--text-2); cursor:pointer;
  background:var(--surface-2); border:1px solid var(--line-strong); border-radius:var(--radius-sm);}
.consent-achat input{flex:0 0 auto; margin:2px 0 0; width:15px; height:15px; accent-color:var(--accent-bright);}
.consent-achat a{color:var(--accent-2);}
.consent-achat-apres{margin:18px 0 0;}
.consent-achat-alerte{border-color:#e05555; box-shadow:0 0 0 2px rgba(224,85,85,.25);}
/* Chromaplaque — liste des changements de filament (2026-09-10) */
.cp-chg-liste{margin:6px 0 10px 18px; padding:0; font-size:12.5px; line-height:1.55; color:var(--text-2);}
.cp-chg-liste li{margin-bottom:5px; font-variant-numeric:tabular-nums;}
.cp-chg-past{display:inline-block; width:11px; height:11px; margin-right:7px; vertical-align:-1px;
  border:1px solid var(--line-strong); border-radius:3px;}
.cp-chg-vide{color:#e0a355;}

/* ===== Bibliotheque de filaments (Chromaplaque) ============================ */
.cp-bi-modal{width:560px; max-width:100%; max-height:88vh; display:flex; flex-direction:column;}
.cp-bi-barre{display:flex; align-items:center; gap:8px; margin-top:10px;}
.cp-bi-liste{margin-top:10px; overflow:auto; max-height:52vh; min-height:110px;
  border:1px solid var(--line); border-radius:var(--radius-sm); padding:4px;}
.cp-bi-ligne{display:flex; align-items:center; gap:10px; padding:7px 8px;
  border-radius:var(--radius-sm);}
.cp-bi-ligne:hover{background:var(--surface-2);}
.cp-bi-ligne .cp-fi-texte{flex:1;}
.cp-bi-mini{flex:0 0 auto; padding:5px 10px !important; font-size:11px !important;}
.cp-bi-suppr{flex:0 0 auto; width:28px; height:28px; background:transparent;
  border:1px solid var(--line); border-radius:var(--radius-sm);
  color:var(--text-3); cursor:pointer; font-size:13px;}
.cp-bi-suppr:hover{color:#f0a0a0; border-color:#f0a0a0;}
.cp-bi-alerte{font-size:10.5px; color:#e8c07a; margin-top:2px;}
/* Bibliothèque reliée au catalogue, sélecteurs de la pile (2026-09-14).
   ⚠️ Chaque bloc qui porte un display a sa règle [hidden] : display:flex écrase
   l'attribut hidden (piège payé sur le panneau admin et l'aperçu 2D). */
.cp-bi-actions{display:flex; flex-wrap:wrap; gap:8px; margin-top:10px;}
.cp-bi-form{display:flex; flex-wrap:wrap; align-items:center; gap:8px; margin-top:10px; padding:10px;
  border:1px solid var(--line); border-radius:var(--radius-sm);}
.cp-bi-form[hidden]{display:none !important;}
.cp-bi-form input[type="text"]{flex:1 1 200px; min-width:0;}
.cp-bi-form input[type="color"]{width:40px; height:32px; padding:0; border:none; background:transparent; cursor:pointer;}
.cp-bi-info{font-size:11px; color:var(--text-3); margin:8px 0 0; line-height:1.45;}
.cp-bi-partage{align-self:flex-start; margin-top:3px; padding:1px 8px; font-size:10.5px; background:transparent;
  color:var(--text-2); border:1px solid var(--line); border-radius:999px; cursor:pointer;}
.cp-bi-partage:hover{color:var(--text); border-color:var(--line-strong);}
.cp-couleur-masquee{display:none !important;}
.cp-fil-biblio{display:flex; flex-direction:column; gap:4px; margin:4px 0 8px;}
.cp-fil-biblio-lab{font-size:11px; color:var(--text-3); font-weight:600;}
.cp-fil-biblio-select{width:100%; padding:7px 9px; font-size:12.5px;}
.cp-fil-biblio-note{font-size:10.5px; color:var(--text-3); line-height:1.4;}
.cp-et-partage{display:flex; align-items:center; gap:6px; font-size:11.5px; color:var(--text-2); margin-top:6px;}
.cp-et-partage[hidden]{display:none !important;}
.cp-et-enregistrer{display:flex; gap:8px; margin-top:10px;}
.cp-et-enregistrer input{flex:1; padding:8px 10px; font-size:12px;
  background:var(--surface-2); color:var(--text);
  border:1px solid var(--line-strong); border-radius:var(--radius-sm);}

/* --- Auto-test connecté du panneau admin (2026-09-12) ---------------------- */
.autotest{display:flex; flex-direction:column; gap:2px; font-size:13px;}
.autotest-famille{margin:12px 0 4px; font-size:11px; letter-spacing:.12em; text-transform:uppercase;
  font-weight:800; color:var(--text-3);}
.autotest-ligne{display:grid; grid-template-columns:18px minmax(0,1fr) minmax(0,auto); gap:10px;
  align-items:baseline; padding:6px 8px; border-radius:var(--radius-sm); background:var(--surface-2);}
.autotest-etat{font-weight:800; color:var(--accent-bright); text-align:center;}
.autotest-ligne.autotest-ko .autotest-etat{color:var(--danger);}
.autotest-nom{min-width:0;}
.autotest-detail{min-width:0; color:var(--text-3); font-size:12px; text-align:right;
  overflow-wrap:anywhere;}
.autotest-bilan{padding:9px 12px; border-radius:var(--radius-sm); font-weight:800; margin-bottom:6px;}
.autotest-bilan.autotest-vert{background:rgba(34,197,94,.12); color:var(--accent-bright);}
.autotest-bilan.autotest-rouge{background:rgba(239,68,68,.12); color:var(--danger);}
@media (max-width:620px){
  .autotest-ligne{grid-template-columns:18px minmax(0,1fr);}
  .autotest-detail{grid-column:2; text-align:left;}
}

/* ===== FICHE D'UN COMPTE (refonte A4, 2026-09-15) ========================== */
#ficheCompteMount{display:flex; flex-direction:column; gap:16px;}
.fc-ligne{display:flex; align-items:center; gap:10px; flex-wrap:wrap;}
.fc-entre{justify-content:space-between;}
.fc-titre{margin:0; font-size:15px; font-weight:800;}
.fc-fort{font-weight:700;}
.fc-recherche{width:min(320px, 100%) !important;}
.fc-detail{display:flex; flex-direction:column; gap:14px; padding-top:6px;}
.fc-ident{display:flex; align-items:center; gap:14px; padding:14px; border-radius:var(--radius-sm); background:var(--surface-2); border:1px solid var(--line);}
.fc-avatar{width:48px; height:48px; flex:0 0 48px; border-radius:50%; display:grid; place-items:center; background:var(--accent); color:#fff; font-size:20px; font-weight:800; box-shadow:0 0 0 3px var(--accent-soft);}
.fc-ident-texte{display:flex; flex-direction:column; gap:3px; min-width:0;}
.fc-pseudo{margin:0; font-size:19px; font-weight:800; letter-spacing:-.01em;}
.fc-tuiles{display:grid; grid-template-columns:repeat(4, minmax(0,1fr)); gap:10px;}
.fc-gestes{display:flex; gap:8px; flex-wrap:wrap;}
.fc-gestes .btn[aria-expanded="true"]{border-color:var(--accent-bright); color:var(--accent-bright);}
.fc-panneau{display:flex; flex-direction:column; gap:8px; padding:12px; border-radius:var(--radius-sm); background:var(--surface-3); border:1px solid var(--line-strong);}
.fc-panneau[hidden]{display:none !important;}
.fc-form{display:flex; align-items:flex-end; gap:10px; flex-wrap:wrap;}
.fc-form .cpt2-champ{min-width:180px;}
.fc-onglets{padding-top:4px;}
.fc-annuaire{max-height:420px; overflow-y:auto;}
.fc-annuaire th{position:sticky; top:0; background:var(--surface);}
@media (max-width:760px){ .fc-tuiles{grid-template-columns:1fr 1fr;} }

/* ===== RECHERCHE Ctrl+K (refonte A3) ====================================== */
.pal-voile{position:fixed; inset:0; z-index:9000; background:rgba(4,7,5,.62); display:flex; justify-content:center; align-items:flex-start; padding:12vh 16px 16px;}
.pal-voile[hidden]{display:none !important;}
.pal-boite{width:min(620px, 100%); background:var(--surface); border:1px solid var(--line-strong); border-radius:14px; box-shadow:0 30px 80px -20px rgba(0,0,0,.85); overflow:hidden; display:flex; flex-direction:column; max-height:72vh;}
.pal-champ{display:flex; align-items:center; gap:10px; padding:13px 16px; border-bottom:1px solid var(--line);}
.pal-champ svg{width:18px; height:18px; color:var(--text-3); flex:0 0 18px;}
.pal-champ input{flex:1 1 auto; width:auto !important; background:none !important; border:none !important; box-shadow:none !important; padding:4px 0 !important; font-size:16px !important; color:var(--text);}
.pal-champ kbd, .pal-pied kbd{font:600 10.5px 'JetBrains Mono', ui-monospace, monospace; padding:1px 6px; border-radius:5px; border:1px solid var(--line-strong); color:var(--text-2);}
.pal-resultats{overflow-y:auto; padding:6px 8px 8px;}
.pal-groupe{font-size:10px; font-weight:750; letter-spacing:.11em; text-transform:uppercase; color:var(--text-3); padding:10px 10px 4px;}
.pal-item{display:flex; align-items:center; gap:10px; width:100%; padding:8px 10px; border-radius:8px; border:none; background:none; color:var(--text); font:inherit; font-size:13.5px; text-align:left; cursor:pointer;}
.pal-item.actif, .pal-item:hover{background:var(--accent-soft);}
.pal-ico{width:26px; height:26px; flex:0 0 26px; border-radius:7px; display:grid; place-items:center; background:var(--surface-3); font-size:13px;}
.pal-texte{flex:1 1 auto; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;}
.pal-texte small{color:var(--text-3); margin-left:6px;}
.pal-indice{font-size:11.5px; color:var(--text-3); white-space:nowrap;}
.pal-vide{padding:18px 12px; color:var(--text-3); font-size:13px;}
.pal-pied{display:flex; gap:14px; padding:8px 14px; border-top:1px solid var(--line); font-size:11.5px; color:var(--text-3);}

/* ===== COMMANDES EN COLONNES (refonte A5) ================================== */
.cmd-pipeline{display:grid; grid-template-columns:repeat(5, minmax(0,1fr)); gap:10px; margin:4px 0 14px;}
.cmd-pipeline[hidden]{display:none !important;}
.cmd-col{display:flex; flex-direction:column; gap:8px; padding:10px; border-radius:var(--radius-sm); background:var(--surface-2); border:1px solid var(--line); min-width:0;}
.cmd-col.attente{opacity:.78;}
.cmd-col-tete{display:flex; align-items:center; justify-content:space-between; gap:8px; font-size:12px; font-weight:750;}
.cmd-col-nb{font-size:11px; font-weight:800; padding:1px 8px; border-radius:999px; background:var(--surface-3); color:var(--text-2);}
.cmd-col-nb.chaud{background:var(--accent-2-soft); color:var(--accent-2);}
.cmd-mini{display:flex; flex-direction:column; gap:6px; padding:9px; border-radius:8px; background:var(--surface); border:1px solid var(--line); font:inherit; color:var(--text); text-align:left; cursor:pointer;}
.cmd-mini:hover{border-color:var(--accent-bright);}
.cmd-mini-tete{display:flex; gap:8px; align-items:center; min-width:0;}
.cmd-mini-tete img{width:32px; height:32px; flex:0 0 32px; object-fit:cover; border-radius:6px; background:var(--surface-3);}
.cmd-mini-titre{font-size:12.5px; font-weight:750;}
.cmd-mini-sous{font-size:11.5px; color:var(--text-3); overflow:hidden; text-overflow:ellipsis; white-space:nowrap;}
.cmd-mini-action{font-size:11.5px; font-weight:750; color:var(--accent-bright);}
.cmd-mini-action.retard{color:var(--danger);}
.cmd-col-vide{font-size:12px; color:var(--text-3); padding:4px 2px;}
.cmd-admin.cmd-flash{box-shadow:0 0 0 2px var(--accent-bright); transition:box-shadow .6s ease;}
@media (max-width:1100px){ .cmd-pipeline{grid-template-columns:repeat(3, minmax(0,1fr));} }
@media (max-width:700px){ .cmd-pipeline{grid-template-columns:1fr;} }

/* ===== SESSION D'IMPRESSION (2026-09-15) =================================== */
.cmd-session{display:flex; flex-direction:column; gap:10px; padding:12px 14px; margin:4px 0 14px;
  border-radius:var(--radius-sm); background:var(--surface-2); border:1px solid var(--accent-bright);}
.cmd-session[hidden]{display:none !important;}
.cmd-session-tete{display:flex; align-items:baseline; gap:10px; flex-wrap:wrap;}
.cmd-session-tete h4{margin:0; font-size:14px; font-weight:800;}
.cmd-session-lignes{display:flex; flex-direction:column; gap:2px; max-height:230px; overflow-y:auto;}
.cmd-session-ligne{display:flex; align-items:center; gap:9px; padding:4px 6px; border-radius:6px; font-size:12.5px; cursor:pointer;}
.cmd-session-ligne:hover{background:var(--surface-3);}
.cmd-session-txt{flex:1 1 auto; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; color:var(--text-2);}
.cmd-session-txt strong{color:var(--text);}
.cmd-session-manque{color:var(--danger); font-weight:700;}
.cmd-session-juste{color:var(--warning); font-weight:700; font-size:12.5px;}
.cmd-session-voir{flex:0 0 auto; background:none; border:none; padding:2px 6px; font:inherit; font-size:11.5px;
  color:var(--accent-bright); cursor:pointer; text-decoration:underline;}
.cmd-session-totaux{font-size:13px; font-weight:750; font-variant-numeric:tabular-nums;}
.cmd-session-verdict{display:flex; flex-direction:column; gap:3px; font-size:12.5px;}
.cmd-session-barre{flex-wrap:wrap; align-items:center; gap:8px;}

/* ===== MON COMPTE, refonte M1-M5 (2026-09-15) ============================== */
.ce-espace{display:grid; grid-template-columns:minmax(0,340px) minmax(0,1fr); gap:16px; align-items:start; padding:16px;}
.ce-colonne{display:flex; flex-direction:column; gap:16px; min-width:0;}
.ce-bloc-haut{padding:16px 16px 0;}
.ce-bloc-haut:empty{display:none;}
#pane-creations{padding:16px;}
.ce-grand{font-size:28px; font-weight:800; letter-spacing:-.01em; font-variant-numeric:tabular-nums;}
.ce-liste{display:flex; flex-direction:column;}
.ce-action{display:flex; align-items:center; justify-content:space-between; gap:12px; padding:10px 0; border-top:1px solid var(--line);}
.ce-action:first-child{border-top:none;}
.ce-reprendre{display:grid; grid-template-columns:repeat(3, minmax(0,1fr)); gap:10px;}
.ce-reprise{display:flex; align-items:center; gap:10px; padding:10px; border-radius:var(--radius-sm); background:var(--surface-2); border:1px solid var(--line); color:var(--text); text-decoration:none; min-width:0;}
.ce-reprise:hover{border-color:var(--accent-bright);}
.ce-reprise strong{display:block; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; font-size:13px;}
/* Sans min-width:0, le bloc de texte d'un élément flex ne se rétrécit pas : le nom débordait de la carte. */
.ce-reprise > div{min-width:0; flex:1 1 auto;}
.ce-vign{display:grid; place-items:center; aspect-ratio:4/3; width:100%; max-width:100%; overflow:hidden; background:radial-gradient(circle at 50% 40%, #2c3d31, #151d17); font-size:30px;}
.ce-vign img{width:100%; height:100%; object-fit:cover; display:block;}
.ce-vign-petite{width:44px; height:44px; flex:0 0 44px; aspect-ratio:auto; border-radius:8px; font-size:20px;}
/* Frise de commande (M1, M4) */
.ce-frise{display:grid; grid-template-columns:repeat(6, minmax(0,1fr)); margin:8px 0 4px;}
.ce-frise div{position:relative; display:flex; flex-direction:column; align-items:center; gap:5px; font-size:11px; color:var(--text-3); text-align:center;}
.ce-frise div::before{content:''; position:absolute; top:7px; left:-50%; right:50%; height:2px; background:var(--surface-3);}
.ce-frise div:first-child::before{display:none;}
.ce-frise div.fait::before, .ce-frise div.ici::before{background:var(--accent-bright);}
.ce-frise i{position:relative; z-index:1; width:12px; height:12px; border-radius:50%; background:var(--surface-3); border:2px solid var(--surface);}
.ce-frise .fait i{background:var(--accent-bright);}
.ce-frise .ici i{background:var(--surface); border-color:var(--accent-bright); box-shadow:0 0 0 3px var(--accent-soft);}
.ce-frise .fait, .ce-frise .ici{color:var(--text);}
.ce-main{font-size:12.5px; color:var(--text-2); margin-top:2px;}
.ce-main-vous{color:var(--accent-2); font-weight:700;}
/* Portefeuille (M2) */
.ce-deux-inegal{grid-template-columns:minmax(0,.9fr) minmax(0,1.4fr);}
.ce-repartition{display:flex; height:10px; border-radius:999px; overflow:hidden; background:var(--surface-3);}
.ce-repartition i{display:block; height:100%;}
.ce-achetes, .ce-point-achetes{background:var(--accent-bright);}
.ce-offerts, .ce-point-offerts{background:var(--accent-2);}
.ce-point-depenses{background:var(--text-3);}
.ce-point{display:inline-block; width:8px; height:8px; border-radius:50%; margin-right:7px; vertical-align:1px;}
/* Mes créations (M3) */
.ce-creations{display:grid; grid-template-columns:repeat(auto-fill, minmax(200px, 1fr)); gap:12px;}
.ce-crea{position:relative; display:flex; flex-direction:column; border-radius:var(--radius-sm); overflow:visible; background:var(--surface-2); border:1px solid var(--line);}
.ce-crea > .ce-vign{border-radius:var(--radius-sm) var(--radius-sm) 0 0; aspect-ratio:16/10; max-height:170px;}
.ce-crea-bas{display:flex; flex-direction:column; gap:6px; padding:10px 11px 11px; min-width:0;}
.ce-crea-bas strong{overflow:hidden; text-overflow:ellipsis; white-space:nowrap;}
.ce-plus{padding:6px 10px !important;}
.ce-menu{position:absolute; right:10px; bottom:48px; z-index:5; display:flex; flex-direction:column; min-width:170px; padding:6px; border-radius:9px; background:var(--surface-3); border:1px solid var(--line-strong); box-shadow:0 16px 36px -14px rgba(0,0,0,.85);}
.ce-menu[hidden]{display:none !important;}
.ce-menu-item{font:inherit; font-size:12.5px; text-align:left; padding:7px 10px; border-radius:6px; border:none; background:none; color:var(--text); cursor:pointer;}
.ce-menu-item:hover, .ce-menu-item:focus-visible{background:var(--accent-soft); outline:none;}
.ce-danger{color:var(--danger);}
/* Niveaux (M5) */
.ce-marches{display:grid; grid-template-columns:repeat(11, minmax(0,1fr)); gap:6px; align-items:end;}
.ce-marche{display:flex; flex-direction:column; align-items:center; gap:4px; font-size:11px; color:var(--text-3);}
.ce-marche b{display:block; width:100%; border-radius:6px 6px 2px 2px; background:var(--surface-3);}
.ce-marche.fait b{background:var(--accent-bright);}
.ce-marche.ici b{background:linear-gradient(to top, var(--accent-bright) 60%, var(--surface-3) 60%); box-shadow:0 0 0 2px var(--accent-soft);}
.ce-marche.ici{color:var(--text); font-weight:700;}
.ce-marche-remise{font-size:10px;}
/* Avis */
.ce-avis{position:fixed; left:50%; bottom:18px; transform:translateX(-50%); z-index:10000; max-width:calc(100vw - 32px); padding:10px 14px; border-radius:10px; background:#18261c; border:1px solid rgba(34,197,94,.35); color:var(--text); font-size:13px; box-shadow:0 18px 40px -16px rgba(0,0,0,.85);}
.ce-avis-erreur{background:#2a1718; border-color:rgba(255,100,103,.45);}
@media (max-width:900px){ .ce-espace{grid-template-columns:1fr;} .ce-reprendre{grid-template-columns:1fr;} .ce-deux-inegal{grid-template-columns:1fr;} }
@media (max-width:560px){ .ce-marches{gap:3px;} .ce-marche-remise{display:none;} .ce-frise{font-size:10px;} }

/* Bandeau du re-téléchargement verrouillé (migration 106). Posé au-dessus de
   l'aperçu par design-saves.js : il doit se voir sans discussion, parce qu'il
   explique pourquoi tous les réglages sont grisés. */
.ds-reexport{display:flex; flex-wrap:wrap; align-items:center; gap:10px 14px;
  margin:0 0 14px; padding:12px 15px; border-radius:10px;
  border:1px solid color-mix(in srgb, var(--accent-bright) 45%, var(--line));
  background:color-mix(in srgb, var(--accent-bright) 10%, var(--surface));
  color:var(--text); font-size:13.5px;}
.ds-reexport strong{flex:0 0 auto; color:var(--accent-bright); font-size:14px;}
.ds-reexport span{flex:1 1 260px; color:var(--text-2); line-height:1.5;}
.ds-reexport .btn{flex:0 0 auto;}
@media (max-width:560px){ .ds-reexport{gap:8px;} .ds-reexport span{flex:1 1 100%;} }

/* ===== MODÉRER PAR LOT (2026-09-16) ======================================== */
.lot-barre{display:flex; align-items:center; gap:12px; flex-wrap:wrap; margin:8px 0 10px;
  padding:8px 12px; border-radius:var(--radius-sm); background:var(--surface-2); border:1px solid var(--accent-bright);}
.lot-barre[hidden]{display:none !important;}
.lot-tout{display:flex; align-items:center; gap:6px; font-size:12.5px; font-weight:700; cursor:pointer;}
.lot-compte{font-size:12.5px; color:var(--text-2); font-variant-numeric:tabular-nums;}
.fc-note{display:flex; flex-direction:column; gap:6px; padding:12px 14px; margin:12px 0;
  border-radius:var(--radius-sm); background:var(--surface-2); border:1px dashed var(--line);}
.fc-note label{font-size:12px; font-weight:750; color:var(--text-2);}

/* ===== COÛT DE LA MATIÈRE SOUS L'APERÇU (2026-09-16) ======================= */
/* ⚠️ pointer-events:auto OBLIGATOIRE : #pvSpecs est en pointer-events:none pour
   laisser tourner la vue 3D derrière lui. Sans ce rappel, le sélecteur de
   matériau serait visible et INCLIQUABLE — le défaut exact de « Estimer poids
   et temps », trouvé en production et pas au banc. */
.cout-matiere{display:flex; flex-direction:column; gap:5px; margin:8px 0 0; padding:8px 9px;
  border-radius:8px; background:var(--surface-2); border:1px solid var(--line); pointer-events:auto;}
.cout-matiere[hidden]{display:none !important;}
.cm-tete{display:flex; align-items:baseline; justify-content:space-between; gap:10px; font-size:12px; color:var(--text-3); font-weight:700;}
.cm-tete strong{font-size:15px; color:var(--accent-bright); font-variant-numeric:tabular-nums;}
.cm-select{width:100%; font:inherit; font-size:11.5px; padding:3px 6px; border-radius:6px;
  background:var(--surface); color:var(--text); border:1px solid var(--line);}
.cm-detail{font-size:11px; color:var(--text-3); font-variant-numeric:tabular-nums;}
.cm-note{font-size:10.5px; color:var(--text-3); line-height:1.4;}

/* ===== QUOTA PLEIN : PROPOSER PLUTÔT QUE REFUSER (2026-09-16) ============== */
.ds-remplacer{display:flex; flex-direction:column; gap:7px; margin-top:12px; padding:11px 13px;
  border-radius:var(--radius-sm); background:var(--warning-soft); border:1px solid var(--warning); font-size:12.5px;}
.ds-remplacer[hidden]{display:none !important;}
.ds-remplacer-quoi{padding:7px 9px; border-radius:6px; background:var(--surface); font-size:12.5px;}
.ds-remplacer button{align-self:flex-start;}

/* ===== PAGE « NOUVEAUTÉS » (2026-09-16) ==================================== */
.nouv-liste{display:flex; flex-direction:column; gap:0; margin-top:14px;}
.nouv{display:grid; grid-template-columns:160px minmax(0,1fr); gap:18px; padding:18px 0; border-top:1px solid var(--line);}
.nouv:first-child{border-top:none;}
.nouv-date{font-size:12.5px; font-weight:750; color:var(--text-3); padding-top:3px;}
.nouv-corps h2{margin:0 0 6px; font-size:17px; font-weight:800;}
.nouv-corps p{margin:0; font-size:14px; line-height:1.6; color:var(--text-2);}
@media (max-width:700px){ .nouv{grid-template-columns:1fr; gap:4px;} }

/* ===== TROIS EXEMPLES POUR DÉMARRER (2026-09-16) =========================== */
.ex-depart{display:flex; flex-direction:column; gap:8px; margin:10px 0 0; padding:10px 12px;
  border-radius:var(--radius-sm); background:var(--surface-2); border:1px solid var(--line);}
.ex-tete{display:flex; align-items:center; justify-content:space-between; gap:10px; font-size:12.5px; color:var(--text-2);}
.ex-fermer{background:none; border:none; color:var(--text-3); font:inherit; cursor:pointer; padding:0 4px; line-height:1;}
.ex-fermer:hover{color:var(--text);}
.ex-grille{display:grid; grid-template-columns:repeat(auto-fit, minmax(96px, 1fr)); gap:10px;}
.ex-vignette{display:flex; flex-direction:column; gap:4px; text-decoration:none; color:var(--text-3); font-size:11px; text-align:center;}
.ex-vignette img{width:100%; aspect-ratio:1; object-fit:cover; border-radius:8px; background:var(--surface-3); border:1px solid var(--line);}
.ex-vignette:hover img{border-color:var(--accent-bright);}

/* ===== LIEN D'ÉVITEMENT (2026-09-16) ======================================= */
/* Hors écran tant qu'il n'a pas le focus — jamais `display:none`, qui le
   retirerait aussi de l'ordre de tabulation et le rendrait donc inutile. */
.a11y-evitement{position:absolute; left:-9999px; top:0; z-index:9999;
  padding:10px 16px; border-radius:0 0 8px 0; font-weight:700; font-size:14px;
  background:var(--accent-bright, #4ADE80); color:#06110A; text-decoration:none;}
.a11y-evitement:focus{left:0;}
