/* Widget de devis 3D — style moderne. Toutes les couleurs/tailles sont des VARIABLES surchargées
   par la page « Style » (admin) via un <style> inline (a3dpq_style_inline_css).
   Les variables sont posées sur .a3dpq-quote-root ET .a3dpq-widget : ainsi le SÉLECTEUR DE MODE (hors du widget,
   dans .a3dpq-quote-root) hérite des mêmes couleurs/arrondis (sinon ses cartes restent sans style). */
.a3dpq-quote-root,
.a3dpq-widget {
    /* Texte & base */
    --a3d-text: #1f2937;           /* texte principal et titres */
    --a3d-muted: #6b7280;          /* texte secondaire / détails */
    --a3d-error: #9b231b;          /* messages d'erreur */
    /* Couleur principale & sélection */
    --a3d-accent: #f5a623;         /* couleur principale */
    --a3d-accent-d: #e0911a;       /* principale au survol */
    --a3d-sel-ring: #f8d9a6;       /* halo des éléments sélectionnés (cartes, sélecteurs) */
    /* Boutons */
    --a3d-btn-bg: #f5a623;
    --a3d-btn-text: #1f2937;
    --a3d-btn-hover: #e0911a;
    --a3d-btn-radius: 12px;
    /* Cartes (fichiers) */
    --a3d-bg: #ffffff;             /* fond des cartes */
    --a3d-border: #e2e6ea;         /* bordures */
    --a3d-border-w: 1px;           /* épaisseur des bordures */
    --a3d-radius: 14px;            /* arrondi des cartes */
    --a3d-card-pad: 12px;          /* marge intérieure des cartes */
    --a3d-card-gap: 12px;          /* espace entre les cartes */
    --a3d-card-shadow: 0 6px 18px -8px rgba(17, 24, 39, .18);  /* ombre des cartes (ou none) */
    /* Sélecteurs */
    --a3d-sel-bg: #ffffff;         /* fond de la gâchette */
    --a3d-radius-sel: 14px;        /* arrondi de la gâchette */
    --a3d-panel-bg: #ffffff;       /* fond du panneau déroulant */
    --a3d-radius-panel: 10px;      /* arrondi du panneau */
    --a3d-opt-hover: #f6f8fa;      /* option survolée */
    --a3d-opt-sel: #fff7e9;        /* option sélectionnée */
    /* Prix & remises */
    --a3d-price: #e0911a;          /* prix */
    --a3d-struck: #9aa1a9;         /* prix barré */
    --a3d-success: #1d7a34;        /* remise / message positif (texte) */
    --a3d-success-bg: #e7f6ec;     /* pastille remise (fond) */
    --a3d-success-border: #bfe6cb; /* pastille remise (bordure) */
    /* Alertes & surcharges */
    --a3d-warn: #9b531b;           /* surcharge / incitation (texte) */
    --a3d-warn-bg: #fdeede;        /* pastille surcharge (fond) */
    --a3d-warn-border: #f1cfa3;    /* pastille surcharge (bordure) */
    /* Cartes de délai */
    --a3d-deliv-bg: #ffffff;
    --a3d-deliv-radius: 12px;
    /* Infobulles */
    --a3d-tip-bg: #ffffff;
    --a3d-tip-text: #4b5563;
    --a3d-tip-border: #e2e6ea;
    /* Total, frais & dropzone */
    --a3d-total-bg: #f6fbf6;
    --a3d-total-border: #cfe8cf;
    --a3d-fees-bg: #fafbfc;
    --a3d-dz-bg: #fafbfc;
    --a3d-prog-track: #eef0f2;     /* fond de la barre de progression */
    --a3d-prog-bar: #f4d3a0;       /* barre de progression — amber DOUX (moins saturé que l'accent, plus reposant) */
    --a3d-prog-bar-d: #edc382;     /* barre de progression — extrémité droite du dégradé */
    /* Disposition */
    --a3d-maxw: 720px;             /* largeur max du widget */
    font-family: inherit;
}
/* La largeur max + le centrage ne s'appliquent QU'AU widget (pas à .a3dpq-quote-root, qui contient aussi le
   sélecteur de mode et ne doit pas être bridé — surtout en mode 2 colonnes où le widget remplit son conteneur). */
.a3dpq-widget { max-width: var(--a3d-maxw); margin: 0 auto; }
/* Polices = celles du site : les contrôles de formulaire n'héritent pas par défaut, on force l'héritage. */
.a3dpq-widget input, .a3dpq-widget button, .a3dpq-widget select, .a3dpq-widget textarea { font-family: inherit; }
.a3dpq-form { display: flex; flex-direction: column; gap: 18px; }

/* Sections */
.a3dpq-section { display: flex; flex-direction: column; gap: 10px; }
.a3dpq-section-title { margin: 0; font-size: .95rem; font-weight: 700; color: var(--a3d-text); }

/* Cartes matériau */
.a3dpq-mat-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(110px, 1fr)); gap: 10px; }
.a3dpq-mat-card {
    display: flex; flex-direction: column; align-items: center; gap: 6px; padding: 12px 8px;
    border: 2px solid var(--a3d-border); border-radius: 12px; background: var(--a3d-bg); cursor: pointer;
    transition: border-color .15s, box-shadow .15s, transform .05s; font: inherit;
}
.a3dpq-mat-card:hover { border-color: var(--a3d-accent); }
.a3dpq-mat-card.is-selected { border-color: var(--a3d-accent); box-shadow: 0 0 0 3px var(--a3d-sel-ring); }
.a3dpq-mat-thumb { width: 54px; height: 54px; border-radius: 10px; overflow: hidden; display: flex; align-items: center; justify-content: center; background: #f4f6f8; font-size: 26px; }
.a3dpq-mat-thumb img { width: 100%; height: 100%; object-fit: cover; }
.a3dpq-mat-name { font-size: .85rem; font-weight: 600; text-align: center; line-height: 1.2; }
.a3dpq-mat-desc { margin: 0; color: var(--a3d-muted); font-size: .88rem; }

/* Couleurs */
.a3dpq-color-choices { display: flex; flex-wrap: wrap; gap: 10px; }
.a3dpq-color-chip {
    width: 34px; height: 34px; border-radius: 50%; border: 2px solid #fff; cursor: pointer;
    box-shadow: 0 0 0 1px var(--a3d-border); padding: 0;
}
.a3dpq-color-chip.is-selected { box-shadow: 0 0 0 2px var(--a3d-accent); transform: scale(1.08); }

/* Finitions */
.a3dpq-finish-choices { display: flex; flex-direction: column; gap: 12px; }
.a3dpq-finish-cat-title { font-size: .82rem; font-weight: 700; color: var(--a3d-muted); text-transform: uppercase; letter-spacing: .03em; margin-bottom: 6px; }
.a3dpq-finish-pills { display: flex; flex-wrap: wrap; gap: 8px; }
.a3dpq-finish-pill {
    display: inline-flex; flex-direction: column; gap: 1px; border: 1px solid var(--a3d-border); border-radius: 10px;
    padding: 7px 12px; cursor: pointer; transition: border-color .15s, background .15s;
}
.a3dpq-finish-pill:hover { border-color: var(--a3d-accent); }
.a3dpq-finish-pill:has(input:checked) { border-color: var(--a3d-accent); background: var(--a3d-opt-sel); }
.a3dpq-finish-pill input { margin-right: 6px; }
.a3dpq-finish-pill-label { font-weight: 600; font-size: .9rem; }
.a3dpq-finish-pill-desc { font-size: .78rem; color: var(--a3d-muted); }

/* Message d'introduction (au-dessus de l'upload, mode 1 ET mode 2) : présente les modes au client.
   Masqué automatiquement dès qu'un fichier est chargé (.a3dpq-has-files sur le widget / la racine technique). */
.a3dpq-intro { margin: 0 0 14px; padding: 14px 16px; border: 1px solid var(--a3d-border); border-left: 4px solid var(--a3d-accent); border-radius: var(--a3d-radius); background: var(--a3d-panel-bg); box-shadow: var(--a3d-card-shadow); }
.a3dpq-intro-title { font-weight: 800; font-size: 1.02rem; color: var(--a3d-text); margin-bottom: 4px; }
.a3dpq-intro-body { font-size: .92rem; line-height: 1.55; color: var(--a3d-muted); }
.a3dpq-has-files .a3dpq-intro { display: none; }   /* dès qu'un fichier est chargé, on laisse la place aux cartes */

/* Dropzone */
.a3dpq-dropzone {
    position: relative;
    border: 2px dashed var(--a3d-border);
    border-radius: var(--a3d-radius);
    background: var(--a3d-dz-bg);
    padding: 32px 20px;
    text-align: center;
    cursor: pointer;
    transition: border-color .2s, background .2s, transform .05s;
}
.a3dpq-dropzone:hover { border-color: var(--a3d-accent); background: var(--a3d-dz-bg); }
.a3dpq-dropzone:focus-visible { outline: 2px solid var(--a3d-accent); outline-offset: 2px; }
.a3dpq-dragover { border-color: var(--a3d-accent); background: var(--a3d-opt-sel); transform: scale(1.01); }
.a3dpq-dz-icon { color: var(--a3d-accent); margin-bottom: 8px; }
.a3dpq-dz-img { max-width: 100%; max-height: 180px; border-radius: 12px; margin: 0 auto 12px; display: block; object-fit: contain; }
.a3dpq-dz-text { font-size: 1.05rem; line-height: 1.45; color: var(--a3d-text); }
.a3dpq-dz-text b { font-weight: 700; }
.a3dpq-dz-hint { color: var(--a3d-muted); font-size: .85rem; margin-top: 6px; }
.a3dpq-dz-file {
    display: flex; align-items: center; justify-content: center; gap: 10px;
    font-weight: 600;
}
/* L'attribut hidden doit l'emporter sur les display ci-dessus (sinon le nom reste affiché). */
.a3dpq-dropzone [hidden] { display: none !important; }
.a3dpq-dz-clear {
    border: 0; background: #eee; border-radius: 50%; width: 24px; height: 24px;
    cursor: pointer; line-height: 1; font-size: 13px;
}
.a3dpq-dz-clear:hover { background: #f3c6c6; }

/* Viewer 3D */
.a3dpq-viewer {
    display: none;
    width: 100%;
    height: var(--a3d-viewer-h, 360px);   /* hauteur paramétrable (réglage Disposition) */
    border-radius: var(--a3d-radius);
    overflow: hidden;
    position: relative;   /* ancre les overlays absolus (barre d'échelle, test de solidité) dans le viewer */
    background: #f4f6f8;
    border: 1px solid var(--a3d-border);
}
.a3dpq-viewer--active { display: block; }
.a3dpq-viewer canvas { display: block; width: 100% !important; height: 100% !important; }

/* ----- Barre d'échelle (overlay en bas à gauche, mise à jour au zoom/orbite) ----- */
/* Non cliquable (pointer-events:none) pour ne pas gêner OrbitControls ; petit fond semi-opaque pour la lisibilité
   par-dessus le modèle. Le trait (border-bottom) représente la longueur ronde calculée par viewer.js. */
/* La visibilité de ces overlays est pilotée par viewer.js via style.display (none/block) -> mise en page en BLOC. */
/* Barre d'échelle DIRECTEMENT dans le viewer (sans encart) : ombre blanche pour rester lisible sur fond clair ou sombre. */
.a3dpq-scalebar {
    position: absolute; left: 12px; bottom: 12px; z-index: 3; pointer-events: none;
    display: none; text-align: center;
    color: #1f2937; font-size: .82rem; font-weight: 700; line-height: 1.2; white-space: nowrap;
    text-shadow: 0 1px 2px rgba(255, 255, 255, .95), 0 0 3px rgba(255, 255, 255, .95);
}
.a3dpq-scalebar-label { display: block; text-align: center; margin-bottom: 4px; }
/* Trait horizontal centré sous le libellé, ticks aux extrémités ; largeur (= longueur réelle à l'écran) posée par viewer.js. */
/* display:block INDISPENSABLE : c'est un <span> (inline par défaut, où width est IGNORÉ -> le trait restait réduit à ses bordures). */
.a3dpq-scalebar-line { display: block; height: 9px; margin: 0 auto; border-left: 2px solid #1f2937; border-right: 2px solid #1f2937; border-bottom: 3px solid #1f2937; box-sizing: border-box; filter: drop-shadow(0 0 1px rgba(255, 255, 255, .95)); }

/* ----- Mode « Test de solidité » (épaisseur de paroi -> couleurs) ----- */
/* Toggle : petit bouton overlay en haut (cliquable -> pointer-events auto) ; sobre, cohérent avec le viewer. */
.a3dpq-stress-toggle {
    position: absolute; top: 10px; right: 10px; z-index: 4; pointer-events: auto;
    display: none; align-items: center; gap: 6px;
    padding: 6px 10px; border: 1px solid var(--a3d-border); border-radius: 8px;
    background: rgba(255, 255, 255, .9); color: var(--a3d-text);
    font: inherit; font-size: .8rem; font-weight: 700; cursor: pointer; line-height: 1;
    box-shadow: 0 1px 4px rgba(0, 0, 0, .12); transition: border-color .15s, background .15s;
}
.a3dpq-stress-toggle:hover { border-color: var(--a3d-accent); }
.a3dpq-stress-toggle--on { border-color: var(--a3d-accent); background: var(--a3d-opt-sel); }
.a3dpq-stress-toggle:disabled { opacity: .5; cursor: not-allowed; }
/* Bouton « maillage » (overlay fil de fer) — icône carrée, en HAUT À GAUCHE, à DROITE du bouton « aperçu léger ». */
.a3dpq-wire-toggle {
    position: absolute; top: 10px; left: 52px; z-index: 4; pointer-events: auto;
    display: none; align-items: center; justify-content: center;
    width: 34px; height: 34px; padding: 0; border: 1px solid var(--a3d-border); border-radius: 8px;
    background: rgba(255, 255, 255, .9); color: var(--a3d-text); cursor: pointer;
    box-shadow: 0 1px 4px rgba(0, 0, 0, .12); transition: border-color .15s, background .15s, color .15s;
}
.a3dpq-wire-toggle:hover { border-color: var(--a3d-accent); }
.a3dpq-wire-toggle--on { border-color: var(--a3d-accent); background: var(--a3d-opt-sel); color: var(--a3d-accent); }
/* Bouton « aperçu léger » (vignette figée au lieu du modèle 3D animé) — icône carrée, EN PREMIER (le plus à gauche). */
.a3dpq-light-toggle {
    position: absolute; top: 10px; left: 10px; z-index: 4; pointer-events: auto;
    display: none; align-items: center; justify-content: center;
    width: 34px; height: 34px; padding: 0; border: 1px solid var(--a3d-border); border-radius: 8px;
    background: rgba(255, 255, 255, .9); color: var(--a3d-text); cursor: pointer;
    box-shadow: 0 1px 4px rgba(0, 0, 0, .12); transition: border-color .15s, background .15s, color .15s;
}
.a3dpq-light-toggle:hover { border-color: var(--a3d-accent); }
.a3dpq-light-toggle.is-active { border-color: var(--a3d-accent); background: var(--a3d-opt-sel); color: var(--a3d-accent); }
/* Statut d'analyse (overlay centré en haut) pendant le calcul des épaisseurs. */
.a3dpq-stress-status {
    position: absolute; top: 10px; left: 50%; transform: translateX(-50%); z-index: 5; pointer-events: none;
    display: none; padding: 5px 11px; border-radius: 999px;
    background: rgba(31, 41, 55, .85); color: #fff; font-size: .74rem; font-weight: 700; white-space: nowrap;
}
/* Bouton ARRÊTER l'analyse (sous le statut, centré, cliquable). */
.a3dpq-stress-stop {
    position: absolute; top: 38px; left: 50%; transform: translateX(-50%); z-index: 6; pointer-events: auto;
    display: none; padding: 5px 12px; border: 0; border-radius: 999px;
    background: #dd2233; color: #fff; font: inherit; font-size: .74rem; font-weight: 700; line-height: 1;
    cursor: pointer; box-shadow: 0 1px 4px rgba(0, 0, 0, .2);
}
.a3dpq-stress-stop:hover { background: #c01b2b; }
/* Légende : encart en bas à droite (titre + barre dégradée + valeur du seuil). Non cliquable. */
.a3dpq-stress-legend {
    position: absolute; right: 10px; bottom: 10px; z-index: 3; pointer-events: none;
    display: none; width: 150px; padding: 8px 10px; border-radius: 8px;
    background: rgba(255, 255, 255, .9); color: var(--a3d-text);
    font-size: .72rem; line-height: 1.3;
    box-shadow: 0 1px 6px rgba(0, 0, 0, .14);
}
.a3dpq-stress-legend > * + * { margin-top: 5px; }
.a3dpq-stress-legend-title { font-weight: 800; font-size: .74rem; color: var(--a3d-text); }
/* Barre = dégradé rouge (trop fin) -> vert (correct). */
.a3dpq-stress-bar { height: 8px; border-radius: 999px; background: linear-gradient(90deg, var(--a3d-error), var(--a3d-success)); }
.a3dpq-stress-labels { display: flex; justify-content: space-between; gap: 6px; }
.a3dpq-stress-label { font-size: .68rem; font-weight: 700; color: var(--a3d-muted); }
.a3dpq-stress-labels .a3dpq-stress-label:first-child { color: var(--a3d-error); }
.a3dpq-stress-labels .a3dpq-stress-label:last-child { color: var(--a3d-success); }
.a3dpq-stress-thr { color: var(--a3d-muted); }

/* ----- Disposition dynamique (réglage GÉNÉRAL « Disposition ») : sections placées en colonnes par l'admin ----- */
/* Colonnes = piles verticales ; l'espacement (gap configurable) -> une section masquée ne laisse AUCUN trou. */
.a3dpq-layout { display: flex; flex-direction: column; gap: var(--a3d-section-gap, 14px); }
.a3dpq-col-left, .a3dpq-col-right { display: flex; flex-direction: column; gap: var(--a3d-section-gap, 14px); min-width: 0; }
.a3dpq-section { min-width: 0; }
/* Le gap des colonnes gère l'espacement : on neutralise les anciennes marges hautes des sections (sinon double espace). */
.a3dpq-section.a3dpq-fees, .a3dpq-section.a3dpq-summary, .a3dpq-section.a3dpq-global-msg { margin-top: 0; }
/* Zone des cartes fichiers = encadrée comme les autres sections (bordure + marge interne). */
.a3dpq-section[data-section="files"] {
    display: flex; flex-direction: column; gap: 10px;
    padding: 14px 16px; border: 1px solid var(--a3d-border); border-radius: var(--a3d-radius);
    background: var(--a3d-fees-bg);
}
.a3dpq-section[data-section="files"] > .a3dpq-files-bar { margin-top: 0; }
/* Mode 2 colonnes : largeurs paramétrables (viewer/upload à gauche, reste à droite par défaut). */
.a3dpq-widget.a3dpq-split .a3dpq-layout { flex-direction: row; flex-wrap: wrap; gap: 20px; align-items: flex-start; }
.a3dpq-widget.a3dpq-split .a3dpq-col-left { flex: 0 0 var(--a3d-col-left, 380px); max-width: 100%; }
.a3dpq-widget.a3dpq-split .a3dpq-col-right { flex: 1 1 var(--a3d-col-right, 460px); }
/* En 2 colonnes : le widget remplit toute la largeur de son conteneur (colonne Divi) ; la « largeur max » du Style
   (--a3d-maxw, pensée pour le mode empilé) ne doit pas brider la mise en page côte à côte. Le flex-wrap empile
   naturellement dès que la largeur disponible ne suffit plus aux 2 colonnes (repli responsive basé sur la largeur réelle). */
.a3dpq-widget.a3dpq-split { max-width: none; }
/* PLEINE LARGEUR partout (choix produit) : le mode 1 vide (zone d'upload) ET les modes 2 & 3 occupent la MÊME largeur
   que le mode 1 avec fichiers (pas de bridage à --a3d-maxw). */
.a3dpq-widget.a3dpq-split:not(.a3dpq-has-files) { max-width: none; }
.a3dpq-widget.a3dpq-technical,
.a3dpq-widget.a3dpq-guided { max-width: none; }
/* Au chargement (aucun fichier) : seule la zone d'upload reste -> on masque la zone des cartes ; en mode 2 colonnes,
   les deux colonnes passent pleine largeur pour que celle contenant l'upload occupe toute la place. */
.a3dpq-widget:not(.a3dpq-has-files) .a3dpq-section[data-section="files"] { display: none; }
.a3dpq-widget.a3dpq-split:not(.a3dpq-has-files) .a3dpq-col-left,
.a3dpq-widget.a3dpq-split:not(.a3dpq-has-files) .a3dpq-col-right { flex-basis: 100%; }
/* Au chargement, la colonne qui ne contient PAS la zone de dépôt est masquée (pas d'espace vide ; upload pleine largeur).
   :has() est largement supporté ; si absent, le pire cas est un léger espace sous l'upload (sans casse). */
.a3dpq-widget:not(.a3dpq-has-files) .a3dpq-col-left:not(:has([data-section="upload"])),
.a3dpq-widget:not(.a3dpq-has-files) .a3dpq-col-right:not(:has([data-section="upload"])) { display: none; }
/* Zone des cartes : hauteur paramétrable + défilement (--a3d-cards-h:none = pas de limite). */
.a3dpq-files-scroll { max-height: var(--a3d-cards-h, none); overflow-y: auto; overflow-x: hidden; }
.a3dpq-files-scroll > .a3dpq-files { margin-top: 0; }
/* (L'empilement sous le breakpoint est injecté en CSS inline par a3dpq_layout_inline_css.) */

/* Options */
.a3dpq-row { display: flex; gap: 14px; flex-wrap: wrap; }
.a3dpq-row .a3dpq-field { flex: 1 1 160px; }
.a3dpq-field { display: flex; flex-direction: column; gap: 6px; }
.a3dpq-field label { font-weight: 600; font-size: .9rem; }
.a3dpq-form select {
    padding: 10px 12px; border: 1px solid var(--a3d-border); border-radius: 10px;
    background: var(--a3d-sel-bg); font-size: .95rem;
}
.a3dpq-form select:focus { outline: 2px solid var(--a3d-accent); outline-offset: 1px; }

/* Bouton : par DÉFAUT il hérite du style des boutons du THÈME du site (classe .button ajoutée au markup). Le style
   PERSONNALISÉ (couleurs/arrondi via --a3d-btn-*) n'est appliqué QUE si « Utiliser le style des boutons du thème » est
   DÉCOCHÉ dans la page Style → règles émises alors par a3dpq_style_inline_css. Ici : seulement le comportement. */
.a3dpq-btn { cursor: pointer; transition: background .2s, transform .05s; }
.a3dpq-btn:active:not(:disabled) { transform: translateY(1px); }
.a3dpq-btn:disabled { opacity: .5; cursor: not-allowed; }

/* Barre de progression — le texte est CENTRÉ sur toute la piste (indépendant du % de remplissage,
   sinon à faible % il déborde à gauche et devient invisible). */
.a3dpq-progress {
    position: relative; margin-top: 8px; background: var(--a3d-prog-track); border-radius: 10px; overflow: hidden; height: 30px;
}
.a3dpq-progress-bar {
    position: absolute; left: 0; top: 0; height: 100%; width: 0;
    background: linear-gradient(90deg, var(--a3d-accent), var(--a3d-accent-d));
    transition: width .2s ease;
}
.a3dpq-progress-text {
    position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
    color: var(--a3d-text); font-size: .85rem; font-weight: 700; white-space: nowrap; z-index: 1; pointer-events: none;
}

/* ----- Multi-fichiers : liste de cartes ----- */
.a3dpq-files { margin-top: 14px; display: flex; flex-direction: column; gap: var(--a3d-card-gap); }
.a3dpq-fc {
    border: var(--a3d-border-w) solid var(--a3d-border); border-radius: var(--a3d-radius); background: var(--a3d-bg); padding: var(--a3d-card-pad) calc(var(--a3d-card-pad) + 2px);
    box-shadow: var(--a3d-card-shadow);
    /* Clippe le FOND de la carte au rayon (sous la bordure) sans `overflow:hidden` : évite l'artefact de coin
       carré (fond plein des enfants pleine largeur visible dans le triangle entre la box rectangulaire et la
       bordure arrondie, accentué par le cerne box-shadow en `.is-active`). N'altère pas le flux des overlays. */
    background-clip: padding-box;
    transition: box-shadow .16s ease, transform .16s ease, border-color .15s ease;
}
/* NB : PAS de `transform` au survol — un transform crée un bloc de référence pour les `position:fixed` enfants,
   ce qui ferait « se balader » le panneau d'un sélecteur ouvert (overlay) au lieu de le coller au déclencheur. */
.a3dpq-fc:hover { box-shadow: 0 16px 32px -12px rgba(17, 24, 39, .28); }
.a3dpq-fc.is-active { border-color: var(--a3d-accent); box-shadow: 0 0 0 2px var(--a3d-sel-ring), 0 12px 26px -10px rgba(17, 24, 39, .24); }
.a3dpq-fc.is-active:hover { transform: none; box-shadow: 0 0 0 2px var(--a3d-sel-ring), 0 16px 32px -12px rgba(17, 24, 39, .28); }
.a3dpq-fc.is-err { border-color: #f0caca; background: #fdf7f7; }
.a3dpq-fc-head { display: flex; align-items: center; gap: 10px; }
.a3dpq-fc-thumb {
    width: 46px; height: 46px; flex: 0 0 46px; border-radius: 8px; background: #f4f6f8;
    display: flex; align-items: center; justify-content: center; font-size: 22px; overflow: hidden; cursor: pointer;
}
.a3dpq-fc-thumb img { width: 100%; height: 100%; object-fit: cover; }
.a3dpq-fc-name { flex: 1 1 auto; min-width: 0; cursor: pointer; line-height: 1.25; }
.a3dpq-fc-fn { display: block; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.a3dpq-fc-name small { color: var(--a3d-muted); }
/* Mode 2 : bas de carte = dimensions (.a3dpq-fc-specs) + gélule de délai, côte à côte (éléments séparés). */
.a3dpq-tech-card .a3dpq-fc-binfo { display: flex; align-items: center; flex-wrap: wrap; gap: 4px 10px; }
.a3dpq-tech-card .a3dpq-fc-specs { margin-top: 0; }
.a3dpq-tech-card .a3dpq-fc-specs:empty, .a3dpq-tech-card .a3dpq-fc-leadwrap:empty { display: none; }
/* Unité du fichier : discrète, sous le nom ; masquée quand la carte est repliée. */
/* Réglages du fichier (unité + échelle) : « pilules » atomiques sous le nom, qui passent à la ligne par BLOC
   entier (jamais en plein milieu d'un champ). Masquées quand la carte est repliée. */
.a3dpq-fc-unitline { display: flex; align-items: center; flex-wrap: wrap; gap: 6px 14px; margin-top: 5px; min-width: 0; }
.a3dpq-fc:not(.is-active) .a3dpq-fc-unitline { display: none; }
.a3dpq-fc-xitem { display: inline-flex; align-items: center; gap: 5px; white-space: nowrap; cursor: default; }
.a3dpq-fc-unitlbl { font-size: .7rem; text-transform: uppercase; letter-spacing: .03em; color: var(--a3d-muted); font-weight: 700; }
.a3dpq-fc-unitsel { font-size: .78rem; color: var(--a3d-muted); border: 1px solid var(--a3d-border); border-radius: 6px; padding: 2px 4px; background: var(--a3d-sel-bg); max-width: 160px; }
/* Échelle : pilule [ 100 ] % (champ sans bordure DANS la pilule, suffixe % accolé). */
.a3dpq-fc-scalebox { display: inline-flex; align-items: center; border: 1px solid var(--a3d-border); border-radius: 6px; background: var(--a3d-sel-bg); padding-right: 6px; overflow: hidden; }
.a3dpq-fc-scale { width: 44px; border: 0; background: transparent; color: var(--a3d-text); font-size: .78rem; padding: 3px 2px 3px 6px; text-align: right; -moz-appearance: textfield; appearance: textfield; }
.a3dpq-fc-scale::-webkit-outer-spin-button, .a3dpq-fc-scale::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.a3dpq-fc-pct { font-size: .72rem; color: var(--a3d-muted); font-weight: 700; }
.a3dpq-fc-remove {
    flex: 0 0 auto; border: none; background: #f1f3f5; color: #555; width: 28px; height: 28px; border-radius: 50%;
    cursor: pointer; font-size: 14px; line-height: 1;
}
.a3dpq-fc-remove:hover { background: #f0caca; color: var(--a3d-error); }

.a3dpq-fc-controls { margin-top: 10px; display: flex; flex-direction: column; gap: 8px; }
.a3dpq-fc-row { display: flex; flex-wrap: wrap; gap: 10px; align-items: flex-start; }
.a3dpq-fc-field { display: flex; flex-direction: column; gap: 3px; flex: 1 1 160px; min-width: 0; }   /* min-width:0 INDISPENSABLE : sans lui, un trigger au libellé long (ex. plusieurs finitions, nowrap) empêche le champ de rétrécir et DÉBORDE la carte ; avec, width:100% + ellipsis du label s'appliquent */
.a3dpq-fc-lbl { font-size: .72rem; text-transform: uppercase; letter-spacing: .03em; color: var(--a3d-muted); font-weight: 700; }
.a3dpq-fc-field select { width: 100%; padding: 6px 8px; border: 1px solid var(--a3d-border); border-radius: 8px; background: var(--a3d-sel-bg); }
/* Couleurs : même hauteur que la gâchette du sélecteur matériau -> chips alignées au même niveau */
.a3dpq-fc-colors { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; align-content: center; min-height: 44px; }
.a3dpq-fc-chip { width: 22px; height: 22px; border-radius: 50%; border: 2px solid #fff; box-shadow: 0 0 0 1px #ccd; cursor: pointer; padding: 0; }
.a3dpq-fc-chip.is-selected { box-shadow: 0 0 0 2px var(--a3d-accent); }
.a3dpq-fc-finlabel { font-size: .72rem; text-transform: uppercase; letter-spacing: .03em; color: var(--a3d-muted); font-weight: 700; }
.a3dpq-fc-applyrow { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.a3dpq-fc-applyall { align-self: flex-start; background: none; border: none; color: var(--a3d-accent-d); cursor: pointer; font-size: .82rem; text-decoration: underline; padding: 2px 0; }
.a3dpq-single-file .a3dpq-fc-applyrow { display: none; }   /* un seul fichier : « Appliquer à tous » inutile */
/* Confirmation furtive « ✓ Appliqué » à côté du lien (apparition douce, disparaît au bout de ~2 s). */
.a3dpq-applied-ok { color: #1d7a34; font-size: .82rem; font-weight: 800; white-space: nowrap; animation: a3dpq-fadein .15s ease; }
@keyframes a3dpq-fadein { from { opacity: 0; } to { opacity: 1; } }

/* Prix/nudge/×qté/délai en PLEINE LARGEUR (status, au-dessus). Ligne du bas = info (specs ou prix replié) + quantité. */
.a3dpq-fc-status { width: 100%; min-width: 0; margin-top: 14px; }   /* sépare le prix du lien « Appliquer à tous » au-dessus */
.a3dpq-fc-status:empty { display: none; margin-top: 0; }
.a3dpq-fc-bottom { display: flex; flex-direction: row; align-items: flex-end; gap: 12px; margin-top: 8px; }
.a3dpq-fc-binfo { flex: 1 1 auto; min-width: 0; }
.a3dpq-fc-prog:not(:empty) { margin-top: 10px; }
.a3dpq-fc-progress { position: relative; height: 24px; background: var(--a3d-prog-track); border-radius: 8px; overflow: hidden; }
.a3dpq-fc-bar { position: absolute; left: 0; top: 0; height: 100%; width: 0; background: linear-gradient(90deg, var(--a3d-prog-bar), var(--a3d-prog-bar-d)); transition: width .3s linear; }
/* Phase « calcul » : stries qui défilent en continu -> la barre BOUGE toujours, même quand le % plafonne
   (durée réelle du slice inconnue) -> plus jamais l'impression d'un calcul figé. */
.a3dpq-fc-progress.is-calc .a3dpq-fc-bar { min-width: 10px; }
.a3dpq-fc-progress.is-calc .a3dpq-fc-bar::after {
    content: ""; position: absolute; inset: 0;
    background-image: linear-gradient(45deg, rgba(255,255,255,.15) 25%, rgba(255,255,255,0) 25%, rgba(255,255,255,0) 50%, rgba(255,255,255,.15) 50%, rgba(255,255,255,.15) 75%, rgba(255,255,255,0) 75%, rgba(255,255,255,0));
    background-size: 28px 28px; animation: a3dpq-prog-stripes 1.1s linear infinite;
}
@keyframes a3dpq-prog-stripes { from { background-position: 0 0; } to { background-position: 28px 0; } }
@media (prefers-reduced-motion: reduce) { .a3dpq-fc-progress.is-calc .a3dpq-fc-bar::after { animation: none; } }
.a3dpq-fc-ptext { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; font-size: .8rem; font-weight: 700; color: var(--a3d-text); }
.a3dpq-fc-price { font-size: 1.25rem; font-weight: 800; color: var(--a3d-price); }
.a3dpq-fc-specs { color: var(--a3d-muted); font-size: .85rem; margin-top: 2px; }
.a3dpq-fc-lead { color: var(--a3d-warn); font-size: .82rem; margin-top: 2px; }
.a3dpq-fc-error { color: var(--a3d-error); font-weight: 600; }
.a3dpq-fc-warnunit { margin-top: 6px; padding: 7px 10px; border-radius: 8px; background: var(--a3d-warn-bg); border: 1px solid var(--a3d-warn-border); color: var(--a3d-warn); font-size: .82rem; font-weight: 600; }

/* ----- Récapitulatif / total ----- */
/* Résumé EN COLONNE (boutons pleine largeur) : évite que « Tout ajouter » soit poussé à droite et que les boutons
   se cassent dans une colonne étroite (mode 2 colonnes). */
.a3dpq-summary { margin-top: 16px; padding: 14px 16px; border-radius: var(--a3d-radius); background: var(--a3d-total-bg); border: 1px solid var(--a3d-total-border); display: flex; flex-direction: column; align-items: stretch; gap: 12px; }
.a3dpq-total { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.a3dpq-total span { color: var(--a3d-muted); }
.a3dpq-total-val { font-size: 1.5rem; font-weight: 800; color: var(--a3d-price); }

/* ----- Remises sur quantité ----- */
.a3dpq-fc-old { color: var(--a3d-struck); text-decoration: line-through; font-size: .9rem; font-weight: 600; }
.a3dpq-fc-new { color: var(--a3d-success); font-weight: 800; }
.a3dpq-fc-badge { display: inline-block; background: var(--a3d-success-bg); color: var(--a3d-success); border: 1px solid var(--a3d-success-border); border-radius: 999px; padding: 1px 8px; font-size: .72rem; font-weight: 800; vertical-align: middle; }
.a3dpq-total-old { color: var(--a3d-struck); text-decoration: line-through; font-size: 1rem; font-weight: 600; }
.a3dpq-total-new { font-size: 1.5rem; font-weight: 800; color: var(--a3d-success); }

/* Incitation « Plus que X articles pour −Y % » + icône tooltip (cartes + total) */
.a3dpq-fc-nudge { margin-top: 3px; }
.a3dpq-total-nudge { display: inline-flex; align-items: center; }
/* nudge : le texte et l'icône ⓘ coulent INLINE -> l'icône reste juste après le texte, jamais sur sa propre ligne */
.a3dpq-nudge-wrap { display: block; font-size: .82rem; line-height: 1.55; }
.a3dpq-nudge-txt { color: var(--a3d-warn); font-weight: 600; }
.a3dpq-nudge-txt b { color: var(--a3d-warn); }
.a3dpq-tip { position: relative; display: inline-flex; vertical-align: middle; margin-left: 3px; }
.a3dpq-tip-btn { width: 18px; height: 18px; flex: 0 0 18px; border-radius: 50%; border: 1px solid var(--a3d-tip-border); background: var(--a3d-tip-bg); color: var(--a3d-tip-text); font-size: 11px; font-weight: 800; font-style: italic; line-height: 1; cursor: pointer; padding: 0; display: inline-flex; align-items: center; justify-content: center; }
.a3dpq-tip-btn:hover { border-color: var(--a3d-accent); color: var(--a3d-accent-d); }
/* OVERLAY (position:fixed) : le tooltip s'affiche PAR-DESSUS, jamais clippé par la zone scrollable des cartes
   (donc pas de scrollbar dans la section). Positionné en coordonnées viewport par positionTip (JS). */
.a3dpq-tip-pop { display: none; position: fixed; top: 0; left: 0; z-index: 9999; width: max-content; min-width: 160px; max-width: calc(100vw - 20px); padding: 9px 11px; background: var(--a3d-tip-bg); border: 1px solid var(--a3d-tip-border); border-radius: 10px; box-shadow: 0 8px 24px rgba(0,0,0,.13); white-space: normal; text-align: center; }
.a3dpq-fee-proc { color: var(--a3d-muted); font-weight: 600; font-size: .85em; }
.a3dpq-tip:hover .a3dpq-tip-pop, .a3dpq-tip.is-open .a3dpq-tip-pop { display: block; }
.a3dpq-tip-title { display: block; font-weight: 800; color: var(--a3d-success); font-size: .8rem; margin-bottom: 6px; }
.a3dpq-disc-tiers { display: inline-flex; flex-wrap: wrap; gap: 6px; vertical-align: middle; }
.a3dpq-tip-pop .a3dpq-disc-tiers { display: flex; flex-direction: column; gap: 4px; align-items: center; }   /* display:flex (pleine largeur) -> gélules CENTRÉES dans le corps du popover */
.a3dpq-disc-tier { display: inline-block; background: #f4f6f8; border: 1px solid #d7e3da; border-radius: 999px; padding: 2px 10px; font-size: .82rem; color: var(--a3d-tip-text); text-align: center; }
.a3dpq-disc-tier.is-active { background: var(--a3d-success); border-color: var(--a3d-success); color: #fff; font-weight: 800; }
/* Infobulle « délai » : petite carte MODERNE (en-tête accent = libellé du délai + corps) ; largeur bornée -> le texte
   s'enroule sur plusieurs lignes au lieu d'une seule longue ligne. */
/* Popover MODERNE partagé (infobulle délai + infobulle remises) : en-tête sobre (ardoise) + corps qui s'enroule. */
.a3dpq-tip-pop.a3dpq-pop { width: max-content; min-width: 0; max-width: min(260px, calc(100vw - 24px)); padding: 0; text-align: left; overflow: hidden; }
.a3dpq-pop-h { display: block; font-weight: 800; font-size: .82rem; color: #fff; background: #2b3240; padding: 7px 12px; }
.a3dpq-pop-b { display: block; font-size: .8rem; line-height: 1.5; color: var(--a3d-tip-text); padding: 9px 12px; white-space: normal; }

/* ----- Frais (section au-dessus du total) ----- */
.a3dpq-fees { margin-top: 12px; padding: 10px 14px; border-radius: var(--a3d-radius); background: var(--a3d-fees-bg); border: 1px solid var(--a3d-border); }
.a3dpq-fee-row { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; font-size: .95rem; color: var(--a3d-text); }
.a3dpq-fee-row + .a3dpq-fee-row { margin-top: 4px; }
.a3dpq-fee-label { color: var(--a3d-muted); }
.a3dpq-fee-val { font-weight: 700; white-space: nowrap; }
.a3dpq-fee-old { color: var(--a3d-struck); text-decoration: line-through; font-weight: 600; margin-right: 4px; }
.a3dpq-fee-free { color: var(--a3d-success); font-weight: 800; }
.a3dpq-fee-nudge { font-size: .82rem; color: var(--a3d-warn); margin-top: 2px; }
.a3dpq-fee-nudge b { color: var(--a3d-warn); }

/* ----- Cartes de délai de fabrication (remplacent le total) ----- */
.a3dpq-delivery { width: 100%; display: flex; flex-wrap: wrap; gap: 10px; }
.a3dpq-deliv-card { position: relative; flex: 1 1 140px; min-width: 128px; text-align: left; cursor: pointer; border: 2px solid var(--a3d-border); border-radius: var(--a3d-deliv-radius); background: var(--a3d-deliv-bg); padding: 10px 30px 10px 12px; display: flex; flex-direction: column; gap: 3px; transition: border-color .12s, box-shadow .12s; }   /* padding-right réserve la place de l'infobulle absolue (coin haut-droit) */
.a3dpq-deliv-cardtip { position: absolute; top: 8px; right: 8px; z-index: 2; line-height: 1; }   /* infobulle « délais » EN OVERLAY (hors flux) -> n'élargit pas la ligne du libellé */
.a3dpq-deliv-card:hover { border-color: var(--a3d-accent); }
.a3dpq-deliv-card.is-selected { border-color: var(--a3d-accent); box-shadow: 0 0 0 3px var(--a3d-sel-ring); background: var(--a3d-opt-sel); }
.a3dpq-deliv-top { display: flex; flex-wrap: wrap; align-items: center; gap: 3px 4px; }   /* gaps SERRÉS : la méta tient à côté du libellé tant qu'il y a la place, puis passe à la ligne */
.a3dpq-deliv-label { font-weight: 800; color: var(--a3d-text); white-space: nowrap; }   /* PAS de flex-grow : la méta reste collée au libellé (pas d'espace vide qui la repousse / la fait wrapper à tort) */
.a3dpq-deliv-mod { font-size: .72rem; font-weight: 800; border-radius: 999px; padding: 1px 7px; white-space: nowrap; flex-shrink: 0; }
.a3dpq-deliv-mod.up { color: var(--a3d-warn); background: var(--a3d-warn-bg); border: 1px solid var(--a3d-warn-border); }
.a3dpq-deliv-mod.down { color: var(--a3d-success); background: var(--a3d-success-bg); border: 1px solid var(--a3d-success-border); }
.a3dpq-deliv-days { font-size: .8rem; color: var(--a3d-muted); }
.a3dpq-deliv-detail { font-size: .66rem; color: var(--a3d-muted); opacity: .85; margin-top: 1px; line-height: 1.3; white-space: nowrap; }
.a3dpq-deliv-price { font-size: 1.15rem; font-weight: 800; color: var(--a3d-price); margin-top: 2px; }
/* Infobulle configurable « à propos des délais » (mode 1) : en-tête pleine largeur qui POUSSE l'icône ⓘ
   en haut à droite, au-dessus des cartes de délai (le conteneur .a3dpq-delivery est flex-wrap). */
.a3dpq-deliv-tiphdr { flex-basis: 100%; display: flex; justify-content: flex-end; }
.a3dpq-deliv-tip { color: var(--a3d-tip-text); line-height: 1.45; }

/* ----- Sélecteurs « évolués » (matériau / résolution / remplissage / finitions) ----- */
.a3dpq-rs { position: relative; min-width: 0; }   /* enfant flex du champ : doit pouvoir rétrécir pour que le trigger (width:100% + label ellipsis) ne déborde jamais la carte */
.a3dpq-rs-trigger { width: 100%; min-height: 44px; box-sizing: border-box; display: flex; align-items: center; gap: 9px; padding: 9px 12px; border: var(--a3d-border-w) solid var(--a3d-border); border-radius: var(--a3d-radius-sel); background: var(--a3d-sel-bg); cursor: pointer; text-align: left; font: inherit; line-height: 1.25; }
/* Certains thèmes imposent un border-radius aux <button> (même avec !important) -> on force le nôtre sur la gâchette. */
.a3dpq-widget .a3dpq-rs > .a3dpq-rs-trigger { border-radius: var(--a3d-radius-sel) !important; }
.a3dpq-rs-trigger:hover { border-color: var(--a3d-accent); }

/* ===== Anti-écrasement du thème sur les <button> =====
   La plupart de nos contrôles (boutons, cartes de délai, pastilles couleur, ⓘ, ✕, stepper) SONT des <button>,
   et beaucoup de thèmes leur imposent un border-radius (souvent !important). Sans cela : éléments carrés sur le
   FRONT alors qu'ils sont corrects en admin (pas de thème). On reforce notre arrondi (spécificité .a3dpq-widget
   + classe + !important). NB : les valeurs en variable suivent la page « Style ». */
/* (.a3dpq-btn : l'arrondi suit le thème par défaut ; l'arrondi custom est forcé par a3dpq_style_inline_css si « style
   des boutons du thème » est décoché.) */
.a3dpq-widget .a3dpq-deliv-card { border-radius: var(--a3d-deliv-radius) !important; }
.a3dpq-widget .a3dpq-mat-card { border-radius: 12px !important; }
.a3dpq-widget .a3dpq-fc-chip,
.a3dpq-widget .a3dpq-color-chip,
.a3dpq-widget .a3dpq-tip-btn,
.a3dpq-widget .a3dpq-fc-remove,
.a3dpq-widget .a3dpq-dz-clear { border-radius: 50% !important; }
.a3dpq-widget .a3dpq-del-sel { border-radius: 8px !important; }
.a3dpq-widget .a3dpq-qty { border-radius: 8px !important; }
.a3dpq-widget .a3dpq-qty button { border-radius: 0 !important; }
.a3dpq-rs.is-open .a3dpq-rs-trigger { border-color: var(--a3d-accent); box-shadow: 0 0 0 2px var(--a3d-sel-ring); }
.a3dpq-rs-thumb { flex: 0 0 auto; width: 24px; height: 24px; border-radius: 6px; overflow: hidden; background: #eef0f2; display: inline-flex; }
.a3dpq-rs-thumb img { width: 100%; height: 100%; object-fit: cover; }
.a3dpq-rs-lbl { flex: 1 1 auto; font-weight: 600; color: var(--a3d-text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.a3dpq-rs-caret { flex: 0 0 auto; color: var(--a3d-muted); font-size: .75rem; }
.a3dpq-rs-panel { display: none; position: absolute; z-index: 40; top: calc(100% + 5px); left: 0; width: 340px; max-width: calc(100vw - 24px); max-height: 340px; overflow-y: auto; overflow-x: hidden; box-sizing: border-box; background: var(--a3d-panel-bg); border: 1px solid var(--a3d-border); border-radius: var(--a3d-radius-panel); box-shadow: 0 14px 36px rgba(0,0,0,.16); padding: 5px; }
.a3dpq-rs.is-open .a3dpq-rs-panel { display: block; }
.a3dpq-rs-opt { display: flex; flex-direction: column; gap: 5px; padding: 9px 11px; border-radius: 8px; cursor: pointer; overflow-wrap: break-word; word-break: break-word; }
.a3dpq-rs-opt:hover { background: var(--a3d-opt-hover); }
.a3dpq-rs-opt.is-sel { background: var(--a3d-opt-sel); }
.a3dpq-rs-optlbl { font-weight: 700; color: var(--a3d-text); }
.a3dpq-rs-optbody { display: flex; align-items: flex-start; gap: 12px; }
.a3dpq-rs-opt .a3dpq-rs-thumb { flex: 0 0 auto; width: 64px; height: 64px; border-radius: 9px; align-items: center; justify-content: center; }
.a3dpq-rs-opt .a3dpq-rs-thumb.is-empty { background: #eef0f2; }
.a3dpq-rs-desc { flex: 1 1 auto; font-size: .82rem; color: var(--a3d-muted); line-height: 1.4; }

/* Multi-sélection (finitions) : compteur + en-têtes de catégorie + case à cocher */
.a3dpq-rms-count { flex: 0 0 auto; min-width: 20px; height: 20px; padding: 0 6px; border-radius: 999px; background: var(--a3d-accent); color: var(--a3d-btn-text); font-size: .74rem; font-weight: 800; display: inline-flex; align-items: center; justify-content: center; }
/* Bouton « ✕ » de réinitialisation des finitions (dans la gâchette du sélecteur, visible quand au moins 1 finition est cochée). */
.a3dpq-rms-clear { flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; width: 18px; height: 18px; border-radius: 50%; color: var(--a3d-muted); font-size: 11px; font-weight: 700; cursor: pointer; transition: color .12s, background .12s; }
.a3dpq-rms-clear:hover { color: var(--a3d-warn); background: var(--a3d-opt-hover); }
.a3dpq-rms-group { font-size: .72rem; font-weight: 800; text-transform: uppercase; letter-spacing: .03em; color: var(--a3d-muted); padding: 8px 11px 3px; }
.a3dpq-rms-opt { position: relative; padding-left: 36px; padding-right: 54px; }   /* padding-right = place pour la gélule de délai */
.a3dpq-rms-check { position: absolute; left: 11px; top: 10px; width: 18px; height: 18px; border: 2px solid #cbd2da; border-radius: 5px; background: #fff; }
/* Gélule « + N j » (délai supplémentaire de post-traitement) — même style que les badges ± % des cartes de délai. */
.a3dpq-rms-lead { font-size: .72rem; font-weight: 800; border-radius: 999px; padding: 1px 7px; white-space: nowrap; color: var(--a3d-warn); background: var(--a3d-warn-bg); border: 1px solid var(--a3d-warn-border); }
.a3dpq-rms-opt > .a3dpq-rms-lead { position: absolute; right: 11px; top: 9px; }
.a3dpq-rms-lead-trig { flex: 0 0 auto; }   /* gélule sur le sélecteur fermé (délai le + long sélectionné) */
.a3dpq-rms-opt.is-checked .a3dpq-rms-check { background: var(--a3d-accent); border-color: var(--a3d-accent); }
.a3dpq-rms-opt.is-checked .a3dpq-rms-check::after { content: "✓"; position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; font-size: 12px; font-weight: 900; color: var(--a3d-btn-text); }
/* Décalage hiérarchique : les options (déclinaisons sous le matériau de base / finitions sous leur catégorie) sont en retrait sous leur en-tête de groupe. */
.a3dpq-rsg-opt, .a3dpq-rms-opt { margin-left: 16px; }
/* En-têtes repliables (accordéon) : matériau de base (sélecteur groupé) + catégorie (sélecteur de finitions). */
.a3dpq-rsg-head { display: flex; align-items: center; gap: 8px; padding: 9px 11px; border-radius: 8px; cursor: pointer; }
.a3dpq-rsg-head:hover { background: var(--a3d-opt-hover); }
.a3dpq-rsg-headlbl { font-weight: 700; color: var(--a3d-text); }   /* nom du matériau de base : MÊME mise en forme partout */
.a3dpq-rsg-headmain { display: flex; flex-direction: column; gap: 2px; flex: 1 1 auto; min-width: 0; }   /* nom + description du matériau de base (sous le nom, visible même replié) */
.a3dpq-rsg-head .a3dpq-rs-desc { white-space: normal; }
.a3dpq-rsg-base { flex-direction: column; align-items: flex-start; gap: 5px; }
.a3dpq-rsg-base.is-sel { background: var(--a3d-opt-sel); }
.a3dpq-rsg-chev { margin-left: auto; color: var(--a3d-muted); transition: transform .15s; }
.a3dpq-rsg-acc.is-open > .a3dpq-rsg-chev, .a3dpq-rms-cat.is-open > .a3dpq-rsg-chev { transform: rotate(180deg); }
.a3dpq-rms-cat { display: flex; align-items: center; cursor: pointer; }
.a3dpq-rms-cat:hover { color: var(--a3d-text); }
.a3dpq-rms-catnb { display: inline-block; background: var(--a3d-accent); color: var(--a3d-btn-text); border-radius: 9px; padding: 0 6px; font-size: .7rem; }

/* ----- Dépendances parent/fils des finitions (verrou / requis par / inclut aussi) ----- */
/* Parent VERROUILLÉ par un fils coché : aspect grisé + curseur interdit, mais TOUJOURS visiblement coché
   (on n'altère ni la coche ni son fond accentué — seul le confort de clic est désactivé). */
.a3dpq-rms-opt.is-locked { opacity: .72; cursor: not-allowed; }
.a3dpq-rms-opt.is-locked:hover { background: transparent; }   /* pas de survol « cliquable » sur une option verrouillée */
/* Le cadenas 🔒 : discret, calé en haut à droite comme la gélule de délai (les deux ne coexistent pas sur un parent). */
.a3dpq-rms-lock { position: absolute; right: 13px; top: 10px; font-size: .8rem; line-height: 1; opacity: .8; }
/* Mentions sous l'option (« requis par … », « inclut aussi … ») : petites, sobres, atténuées. */
.a3dpq-rms-note { font-size: .72rem; line-height: 1.35; color: var(--a3d-muted); overflow-wrap: break-word; word-break: break-word; }
.a3dpq-rms-includes { color: var(--a3d-muted); opacity: .85; }   /* nuance par rapport à « requis par » */
.a3dpq-rms-reqby { color: var(--a3d-warn); }   /* « requis par » : met en avant la raison du verrou */
/* Parent verrouillé AYANT aussi un délai : le cadenas et la gélule « +N j » ne doivent pas se chevaucher. */
.a3dpq-rms-opt.is-locked { padding-right: 74px; }
.a3dpq-rms-opt.is-locked > .a3dpq-rms-lead { right: 36px; }
/* Refus de décoche d'un parent verrouillé : court flash + secousse (~600ms) pour signaler l'action interdite. */
.a3dpq-rms-deny { animation: a3dpq-rms-shake .6s ease; }
@keyframes a3dpq-rms-shake {
    0%, 100% { transform: translateX(0); background: transparent; }
    10% { background: var(--a3d-warn-bg); }
    20% { transform: translateX(-4px); }
    40% { transform: translateX(4px); }
    60% { transform: translateX(-3px); }
    80% { transform: translateX(3px); }
}
/* Badge sur l'en-tête d'une catégorie repliée contenant un parent auto-ajouté (verrouillé non visible). */
.a3dpq-rms-cat-req { display: inline-flex; align-items: center; justify-content: center; min-width: 16px; height: 16px; padding: 0 4px; margin-left: 4px; border-radius: 999px; background: var(--a3d-warn-bg); color: var(--a3d-warn); border: 1px solid var(--a3d-warn-border); font-size: .68rem; font-weight: 800; line-height: 1; }

/* Aperçu agrandi au survol des images marquées « agrandissable » */
.a3dpq-zoom { position: fixed; z-index: 9999; display: none; background: #fff; border: 1px solid var(--a3d-border); border-radius: 10px; box-shadow: 0 16px 40px rgba(0,0,0,.22); padding: 6px; pointer-events: none; }
.a3dpq-zoom img { display: block; max-width: 220px; max-height: 220px; border-radius: 6px; }
.a3dpq-addall { margin-left: 0; }
.a3dpq-addall:disabled { opacity: .55; cursor: not-allowed; }
/* Repli « demande de devis » (mode 1, quand le calcul instantané API échoue) — encart d'alerte + bouton standard. */
.a3dpq-fallback { flex-basis: 100%; display: flex; flex-direction: column; gap: 10px; padding: 12px 14px; border-radius: var(--a3d-radius); background: var(--a3d-warn-bg, #fdeede); border: 1px solid var(--a3d-warn-border, #f1cfa3); }
.a3dpq-fallback-msg { font-size: .95rem; line-height: 1.5; color: var(--a3d-warn, #9b531b); }
.a3dpq-fallback-btn { width: 100%; }
.a3dpq-cart-msg { flex-basis: 100%; }
.a3dpq-cart-msg.a3dpq-cart-ok { color: var(--a3d-success); }
.a3dpq-cart-msg.a3dpq-cart-err { color: var(--a3d-error); }
.a3dpq-global-msg { margin-top: 10px; padding: 8px 12px; border-radius: 8px; background: #fff7e6; border: 1px solid #f3e0b5; }
.a3dpq-global-msg.a3dpq-ok { background: var(--a3d-total-bg); border-color: var(--a3d-total-border); }

/* ----- Sélection / suppression multiple ----- */
.a3dpq-files-bar { margin-top: 12px; display: flex; align-items: center; gap: 14px; }
.a3dpq-selall { display: inline-flex; align-items: center; gap: 6px; color: var(--a3d-muted); font-size: .9rem; cursor: pointer; }
.a3dpq-del-sel { background: #f1f3f5; border: 1px solid #e0c3c3; color: var(--a3d-error); border-radius: 8px; padding: 6px 12px; cursor: pointer; font-size: .88rem; }
.a3dpq-del-sel:disabled { opacity: .5; cursor: not-allowed; }
/* Variante ICÔNE (corbeille) : bouton carré compact ; conserve background/border/color/:disabled ci-dessus.
   Le SVG corbeille tient à ~18px ; le tooltip est fourni par l'attribut `title` natif (« Effacer la sélection »). */
.a3dpq-del-sel--icon { display: inline-flex; align-items: center; justify-content: center; width: 34px; height: 34px; padding: 0; }
.a3dpq-del-sel--icon svg { width: 18px; height: 18px; display: block; }
.a3dpq-fc-pick { flex: 0 0 auto; width: 18px; height: 18px; cursor: pointer; }

/* Carte cliquable (prévisualisation) — les contrôles gardent leur curseur normal */
.a3dpq-fc { cursor: pointer; }
.a3dpq-fc input, .a3dpq-fc select { cursor: auto; }

/* ----- Cartes repliables (accordéon : une seule DÉPLIÉE = la carte active) ----- */
.a3dpq-fc:not(.is-active) .a3dpq-fc-params { display: none; }            /* repliée : contrôles masqués */
.a3dpq-fc:not(.is-active) { padding: 8px 12px; }                          /* repliée : compacte */
.a3dpq-fc:not(.is-active) .a3dpq-fc-head { margin-bottom: 0; }
.a3dpq-fc:not(.is-active) .a3dpq-fc-thumb { width: 38px; height: 38px; flex: 0 0 38px; font-size: 18px; }
.a3dpq-fc:not(.is-active) .a3dpq-fc-bottom { margin-top: 4px; }
.a3dpq-fc:not(.is-active) .a3dpq-fc-price { font-size: 1.05rem; }
.a3dpq-fc:not(.is-active) .a3dpq-fc-qtylbl { display: none; }             /* repliée : pas le libellé "Quantité" */
.a3dpq-fc.is-active { cursor: default; }                                  /* dépliée : corps non « cliquable » */
/* Résumé pleine largeur (carte repliée) : caché si vide ou si la carte est dépliée */
.a3dpq-fc-sum { width: 100%; font-size: .82rem; color: var(--a3d-muted); line-height: 1.4; margin: 2px 0; }
.a3dpq-fc-sum:empty { display: none; }
.a3dpq-fc.is-active .a3dpq-fc-sum { display: none; }

/* Quantité : stepper aligné à droite du bas de carte (même ligne que le prix) */
.a3dpq-qtywrap { flex: 0 0 auto; display: flex; flex-direction: row; align-items: center; gap: 8px; }
.a3dpq-fc-qtylbl { color: var(--a3d-muted); font-size: .72rem; text-transform: uppercase; letter-spacing: .03em; font-weight: 700; }
.a3dpq-qty { display: inline-flex; align-items: center; border: 1px solid var(--a3d-border); border-radius: 8px; overflow: hidden; background: #fff; }
.a3dpq-qty button { border: none; background: #f1f3f5; width: 32px; height: 34px; font-size: 18px; line-height: 1; cursor: pointer; color: #333; padding: 0; }
.a3dpq-qty button:hover { background: #e6e9ec; }
.a3dpq-qty input.a3dpq-fc-qty { width: 48px; height: 34px; border: none; border-left: 1px solid #eef0f2; border-right: 1px solid #eef0f2; text-align: center; font-weight: 700; -moz-appearance: textfield; appearance: textfield; }
.a3dpq-qty input.a3dpq-fc-qty::-webkit-outer-spin-button,
.a3dpq-qty input.a3dpq-fc-qty::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }

/* États carte */
.a3dpq-fc.is-draft { border-style: dashed; }
.a3dpq-fc-draft { color: var(--a3d-warn); font-size: .9rem; }
.a3dpq-fc-stale { color: #b0b6bd; text-decoration: line-through; }

/* ============================================================ Sélecteur de MODE de devis (3 cartes) ============ */
/* Chrome PARTAGÉ (instant/technique/accompagné). Classes nouvelles scopées .a3dpq-quote-root -> aucun impact mode 1.
   Les variables --a3d-* sont héritées de .a3dpq-quote-root (voir bloc tout en haut). */
.a3dpq-quote-root { font-family: inherit; }
/* Cartes MASQUÉES au chargement : révélées dès qu'un fichier est chargé (a3dpq-modes.js pose .a3dpq-has-files). */
.a3dpq-modes { display: none; grid-template-columns: repeat(3, 1fr); gap: 14px; max-width: 940px; margin: 0 auto 22px; }
.a3dpq-quote-root.a3dpq-has-files .a3dpq-modes,
.a3dpq-quote-root.a3dpq-show-modes .a3dpq-modes { display: grid; }   /* show-modes : entrée mode 3 « sans fichier » via le CTA */
.a3dpq-quote-root .a3dpq-mode-card {
    display: flex; flex-direction: column; align-items: flex-start; gap: 7px; text-align: left;
    padding: 18px 20px; border: 2px solid var(--a3d-border); border-radius: var(--a3d-radius) !important;
    background: var(--a3d-bg); color: var(--a3d-text); cursor: pointer; font: inherit; position: relative;
    box-shadow: 0 6px 18px -10px rgba(17, 24, 39, .18);
    transition: border-color .15s, box-shadow .18s, transform .12s, background .15s;
}
.a3dpq-quote-root .a3dpq-mode-card:hover:not(.is-disabled) { border-color: var(--a3d-accent); transform: translateY(-2px); box-shadow: 0 14px 28px -14px rgba(17, 24, 39, .28); }
.a3dpq-quote-root .a3dpq-mode-card.is-active { border-color: var(--a3d-accent); box-shadow: 0 0 0 3px var(--a3d-sel-ring), 0 10px 24px -14px rgba(17, 24, 39, .25); background: var(--a3d-opt-sel); }
.a3dpq-quote-root .a3dpq-mode-card.is-disabled { opacity: .5; cursor: not-allowed; box-shadow: none; }
/* Pastille de sélection (coche) en haut à droite de la carte active. */
.a3dpq-quote-root .a3dpq-mode-card.is-active::after { content: "✓"; position: absolute; top: 12px; right: 14px; width: 22px; height: 22px; border-radius: 50%; background: var(--a3d-accent); color: #fff; font-size: 13px; font-weight: 800; display: flex; align-items: center; justify-content: center; line-height: 1; }
.a3dpq-mode-card-title { font-weight: 800; font-size: 1.08rem; padding-right: 26px; }
.a3dpq-mode-card-desc { font-size: .86rem; color: var(--a3d-muted); line-height: 1.45; }
.a3dpq-mode-card-soon { position: absolute; top: 12px; right: 14px; font-size: .66rem; font-weight: 800; text-transform: uppercase; letter-spacing: .04em; color: var(--a3d-muted); border: 1px solid var(--a3d-border); border-radius: 999px; padding: 2px 8px; }
/* Volets : un seul visible à la fois. */
.a3dpq-mode-pane { display: none; }
.a3dpq-mode-pane.is-active { display: block; }
.a3dpq-mode-todo { padding: 44px 20px; text-align: center; color: var(--a3d-muted); border: 2px dashed var(--a3d-border); border-radius: var(--a3d-radius); background: var(--a3d-dz-bg); font-size: 1rem; }
@media (max-width: 640px) { .a3dpq-modes { grid-template-columns: 1fr; } }

/* ============================================================ Mode « Devis technique » (SANS prix) ============== */
/* Réutilise .a3dpq-widget + .a3dpq-dropzone + .a3dpq-fc + .a3dpq-deliv-card (mêmes styles que le mode 1). Quelques
   classes propres .a3dpq-tech-* en plus. Les cartes techniques sont REPLIABLES (accordéon) comme le mode 1 : seule la
   carte ACTIVE (.is-active) montre params/unité/quantité ; les autres affichent le résumé compact (.a3dpq-fc-sum). */
.a3dpq-technical { display: flex; flex-direction: column; gap: 16px; }
.a3dpq-tech-intro { margin: 0; color: var(--a3d-muted); font-size: .95rem; line-height: 1.5; }
/* Encart d'information (notification) en haut du mode « Devis technique » — couleurs réglables (page Style). */
.a3dpq-tech-notice { margin: 0; padding: 12px 14px; border-radius: var(--a3d-radius); font-size: .98rem; line-height: 1.5;
  background: var(--a3d-tech-notice-bg, #eef5ff); color: var(--a3d-tech-notice-text, #1f4e79); border: 1px solid var(--a3d-tech-notice-border, #c3dafe); }
.a3dpq-tech-files { display: flex; flex-direction: column; gap: var(--a3d-card-gap, 12px); }
.a3dpq-tech-files:empty { display: none; }
/* Carte technique ACTIVE = rétablit l'affichage des params/unité/libellé quantité (sinon masqués par les règles « repliée »). */
.a3dpq-fc.a3dpq-tech-card.is-active .a3dpq-fc-params { display: block; }
.a3dpq-fc.a3dpq-tech-card.is-active .a3dpq-fc-unitline { display: flex; }
.a3dpq-fc.a3dpq-tech-card.is-active .a3dpq-fc-qtylbl { display: block; }
.a3dpq-fc.a3dpq-tech-card.is-active .a3dpq-fc-bottom { margin-top: 14px; }
.a3dpq-tech-deliv-title, .a3dpq-tech-fees-title { font-weight: 700; font-size: .95rem; margin-bottom: 8px; color: var(--a3d-text); }
/* Mode 2 : le titre des délais porte l'infobulle ⓘ -> flex pour la pousser à droite (titre à gauche, tip à droite). */
.a3dpq-tech-deliv-title { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.a3dpq-tech-delivery .a3dpq-deliv-cards { display: flex; flex-wrap: wrap; gap: 10px; }
.a3dpq-tech-fees { padding: 12px 14px; border: 1px solid var(--a3d-border); border-radius: var(--a3d-radius); background: var(--a3d-fees-bg); }
.a3dpq-tech-fees .a3dpq-fee-row { padding: 2px 0; }
.a3dpq-tech-actions { display: flex; flex-direction: column; gap: 10px; }
.a3dpq-tech-actions .a3dpq-btn { width: 100%; }
.a3dpq-tech-msg { font-size: .9rem; }

/* ============================================================ Mode 3 « Devis accompagné » ====================== */
/* Appel à l'action « sans fichier » sous la dropzone (modes 1 & 2) — masqué dès qu'un fichier est chargé ou que la
   barre de modes est révélée. */
.a3dpq-guided-cta {
    display: flex; align-items: center; gap: 10px; width: 100%; margin: 12px 0 0; padding: 12px 16px;
    border: 1px dashed var(--a3d-border); border-radius: var(--a3d-radius); background: var(--a3d-panel-bg);
    color: var(--a3d-text); cursor: pointer; font: inherit; font-size: .95rem; text-align: left;
    transition: border-color .15s, background .15s, transform .12s;
}
.a3dpq-guided-cta:hover { border-color: var(--a3d-accent); transform: translateY(-1px); }
.a3dpq-guided-cta svg { flex: 0 0 auto; color: var(--a3d-accent); }
.a3dpq-has-files .a3dpq-guided-cta,
.a3dpq-quote-root.a3dpq-show-modes .a3dpq-guided-cta { display: none; }

/* Volet mode 3 : pile verticale. Réutilise .a3dpq-dropzone (dropzone facultative). */
.a3dpq-guided { display: flex; flex-direction: column; gap: 16px; }
.a3dpq-guided-list { display: flex; flex-direction: column; gap: 8px; }
.a3dpq-guided-list:empty { display: none; }
/* Ligne de fichier : case + nom + taille + croix. */
.a3dpq-guided-row {
    display: flex; align-items: center; gap: 10px; padding: 9px 12px;
    border: 1px solid var(--a3d-border); border-radius: var(--a3d-radius); background: var(--a3d-bg);
}
.a3dpq-guided-row.is-sel { border-color: var(--a3d-accent); background: var(--a3d-opt-sel); }
.a3dpq-guided-row-cb { flex: 0 0 auto; }
.a3dpq-guided-row-name { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 600; color: var(--a3d-text); }
.a3dpq-guided-row-size { flex: 0 0 auto; color: var(--a3d-muted); font-size: .85rem; }
.a3dpq-guided-row-del {
    flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 28px;
    border: 1px solid var(--a3d-border); border-radius: 50%; background: transparent; color: var(--a3d-error); cursor: pointer; line-height: 1; font-size: 16px;
}
.a3dpq-guided-row-del:hover { background: #fdecec; border-color: var(--a3d-error); }
/* Barre de sélection (tout sélectionner + corbeille). */
.a3dpq-guided-bar { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.a3dpq-guided-bar .a3dpq-selall { display: inline-flex; align-items: center; gap: 7px; font-size: .9rem; color: var(--a3d-muted); }
.a3dpq-guided-delsel { background: #f1f3f5; border: 1px solid #e0c3c3; color: var(--a3d-error); border-radius: 8px; cursor: pointer; }
.a3dpq-guided-delsel:disabled { opacity: .5; cursor: not-allowed; }
/* Champ description (obligatoire). */
.a3dpq-guided-desc-field { display: flex; flex-direction: column; gap: 6px; }
.a3dpq-guided-desc-label { font-weight: 700; color: var(--a3d-text); font-size: .98rem; }
.a3dpq-guided-desc-label .a3dpq-req { color: var(--a3d-error); }
.a3dpq-guided-desc {
    width: 100%; box-sizing: border-box; padding: 11px 13px; border: 1px solid var(--a3d-border);
    border-radius: var(--a3d-radius); background: var(--a3d-bg); color: var(--a3d-text); font: inherit; font-size: .95rem; line-height: 1.5; resize: vertical; min-height: 110px;
}
.a3dpq-guided-desc:focus { outline: none; border-color: var(--a3d-accent); box-shadow: 0 0 0 3px var(--a3d-sel-ring); }
.a3dpq-guided-desc.is-invalid { border-color: var(--a3d-error); box-shadow: 0 0 0 3px rgba(220, 53, 69, .15); }
/* Actions. */
.a3dpq-guided-actions { display: flex; flex-direction: column; gap: 10px; }
.a3dpq-guided-actions .a3dpq-guided-submit { width: 100%; }
.a3dpq-guided-msg { font-size: .9rem; }
.a3dpq-guided-msg.is-error { color: var(--a3d-error); }
/* Commentaire par fichier (carte) : bloc repliable, discret, replié par défaut. */
.a3dpq-fc-comment { margin: 8px 0 0; }
.a3dpq-fc-comment > summary { cursor: pointer; font-size: .85rem; color: var(--a3d-accent); list-style: none; display: inline-flex; align-items: center; gap: 5px; user-select: none; }
.a3dpq-fc-comment > summary::-webkit-details-marker { display: none; }
.a3dpq-fc-comment > summary::before { content: "+"; font-weight: 700; }
.a3dpq-fc-comment[open] > summary::before { content: "−"; }
.a3dpq-fc-comment-input { width: 100%; box-sizing: border-box; margin-top: 6px; padding: 8px 10px; border: 1px solid var(--a3d-border); border-radius: var(--a3d-radius); background: var(--a3d-bg); color: var(--a3d-text); font: inherit; font-size: .9rem; line-height: 1.45; resize: vertical; min-height: 56px; }
.a3dpq-fc-comment-input:focus { outline: none; border-color: var(--a3d-accent); box-shadow: 0 0 0 3px var(--a3d-sel-ring); }
/* Délais mode 3 (cartes), réutilise le style des cartes délai. */
.a3dpq-guided-delivery { margin: 0; }
.a3dpq-guided-delivery:empty { display: none; }
.a3dpq-guided-delivery .a3dpq-deliv-cards { display: flex; flex-wrap: wrap; gap: 10px; }
/* Section finale modes 2 & 3 (délai + bouton) — présentée comme la section du mode 1. */
.a3dpq-guided-summary, .a3dpq-tech-summary { display: flex; flex-direction: column; gap: 14px; }
.a3dpq-guided-summary .a3dpq-guided-actions, .a3dpq-tech-summary .a3dpq-tech-actions { margin: 0; }
/* Page de validation / panier / commande d'un DEVIS (mode 2 ET mode 3, même format) : on FIGE la largeur des colonnes
   du tableau (sinon une longue description élargit la 1re colonne et écrase la 2e). La classe body est posée par
   a3dpq_quote_page_context() et le CSS est chargé sur ces pages par a3dpq_quote_pages_enqueue(). */
body.a3dpq-quote-page table.shop_table { table-layout: fixed; width: 100%; }
body.a3dpq-quote-page table.shop_table th, body.a3dpq-quote-page table.shop_table td { word-break: break-word; overflow-wrap: anywhere; vertical-align: top; }
body.a3dpq-quote-page table.shop_table th:first-child, body.a3dpq-quote-page table.shop_table td:first-child { width: 50%; }
body.a3dpq-quote-page table.shop_table th:last-child, body.a3dpq-quote-page table.shop_table td:last-child { width: 50%; }
.a3dpq-tech-msg.a3dpq-warn { color: var(--a3d-warn); }
/* Indicateur « traitement en cours » (extraction d'archive ZIP) : spinner animé devant le texte. La décompression
   tourne en Web Worker (viewer.js) -> le thread principal ne gèle pas, donc le spinner reste bien animé. */
.a3dpq-global-msg.a3dpq-busy, .a3dpq-tech-msg.a3dpq-busy { display: flex; align-items: center; gap: 8px; }
.a3dpq-busy::before { content: ""; flex: 0 0 auto; width: 1em; height: 1em; border: 2px solid currentColor; border-right-color: transparent; border-radius: 50%; animation: a3dpq-spin .7s linear infinite; }
@keyframes a3dpq-spin { to { transform: rotate(360deg); } }
/* Carte « Traitement de l'archive… » : posée dans la zone fichiers DÈS le dépôt d'un gros zip (avant que les pièces
   n'apparaissent), pour montrer tout de suite que le fichier est bien pris en compte. Retirée à l'arrivée des cartes. */
.a3dpq-zip-loading { display: flex; align-items: center; justify-content: center; gap: 10px; padding: 18px 16px; color: var(--a3d-muted); font-size: .95rem; text-align: center; }
.a3dpq-zip-spin { flex: 0 0 auto; width: 18px; height: 18px; border: 2px solid currentColor; border-right-color: transparent; border-radius: 50%; animation: a3dpq-spin .7s linear infinite; }
.a3dpq-fc-unit { color: var(--a3d-muted); font-size: .82rem; }

/* Bouton « Calculer » */
.a3dpq-calc { background: var(--a3d-btn-bg); }
.a3dpq-calc:disabled { opacity: .55; cursor: not-allowed; }

/* Résultat */
.a3dpq-result { margin-top: 18px; padding: 20px; border-radius: var(--a3d-radius); }
.a3dpq-result.a3dpq-ok { background: var(--a3d-total-bg); border: 1px solid var(--a3d-total-border); }
.a3dpq-result.a3dpq-error { background: #fdf4f4; border: 1px solid #f0caca; color: var(--a3d-error); }
.a3dpq-price-row { display: flex; align-items: baseline; justify-content: space-between; flex-wrap: wrap; }
.a3dpq-price-label { font-size: 1rem; color: var(--a3d-muted); font-weight: 600; }
.a3dpq-price { font-size: 2.2rem; font-weight: 800; color: var(--a3d-price); }
.a3dpq-warn { background: #fff8e6; border: 1px solid #f0dca0; padding: 10px 12px; border-radius: 8px; margin: 12px 0; font-size: .9rem; }
.a3dpq-info { background: #eef6ff; border: 1px solid #bcdcff; padding: 10px 12px; border-radius: 8px; margin: 12px 0; font-size: .9rem; }
.a3dpq-specs { list-style: none; margin: 14px 0 0; padding: 0; }
.a3dpq-specs li { display: flex; justify-content: space-between; padding: 7px 0; border-top: 1px solid #e8efe8; }
.a3dpq-specs li span { color: var(--a3d-muted); }

.a3dpq-addcart { margin-top: 16px; width: 100%; }
.a3dpq-cart-msg { margin-top: 10px; font-weight: 600; }
.a3dpq-cart-msg.a3dpq-cart-ok { color: var(--a3d-success); }
.a3dpq-cart-msg.a3dpq-cart-err { color: var(--a3d-error); }
.a3dpq-cart-msg a { color: inherit; text-decoration: underline; }

/* Notification (style WooCommerce) affichée EN HAUT après ajout au panier (mode 1). Hors .a3dpq-widget -> non scopée. */
.a3dpq-wc-notice { display: flex; align-items: center; justify-content: space-between; gap: 18px; flex-wrap: wrap; margin: 0 0 18px; padding: 16px 22px; background: #f3fbef; border: 1px solid #cdeac0; border-left: 4px solid #46b450; border-radius: 6px; color: #2a4d1e; font-size: 24px; line-height: 1.4; }
.a3dpq-wc-notice .a3dpq-notice-text { flex: 1 1 auto; }
/* Le bouton « Voir le panier » garde le style des boutons du thème (.button) : on évite juste qu'il soit pleine largeur. */
.a3dpq-wc-notice .button { flex: 0 0 auto; width: auto; margin: 0; }

@media (max-width: 480px) {
    .a3dpq-viewer { height: 280px; }
    .a3dpq-price { font-size: 1.8rem; }
    /* Petit écran : libellé « Quantité » AU-DESSUS du stepper (au lieu d'à gauche) ; gain de place pour les specs. */
    .a3dpq-qtywrap { flex-direction: column; align-items: flex-end; gap: 3px; }
}
