/* ==========================================================================
   Mon panier
   Habillage visuel de la page WooCommerce "Panier" (page-panier.php +
   shortcode [woocommerce_cart]) — repris de
   claude-design-reference/Mon panier/Panier.dc.html.
   Cible uniquement les classes natives WooCommerce (table du panier,
   quantité, suppression, coupon, récapitulatif, messages) : aucune
   fonctionnalité n'est recréée ici.
   ========================================================================== */

/* --------------------------------------------------------------------
   Conteneur de page (page-panier.php)
   -------------------------------------------------------------------- */
.panier {
    background-color: var(--universim-black);
    padding: clamp(28px, 5vh, 60px) clamp(18px, 4vw, 64px) clamp(56px, 9vh, 110px);
}

.panier__container {
    max-width: 1440px;
    margin: 0 auto;
}

/* Flash blanc au retrait d'un article (et, plus largement, à toute action
   AJAX du panier : changement de quantité, coupon...) : cart.js (natif
   WooCommerce, non modifié) bloque visuellement le formulaire et le
   récapitulatif pendant la requête via jQuery blockUI, avec
   overlayCSS:{background:'#fff', opacity:0.6} — un rectangle blanc
   semi-transparent plaqué sur tout le panier le temps de la réponse
   (quelques centaines de ms), très visible sur un site presque
   entièrement noir. C'est un style posé en JS via .css(), donc INLINE :
   seul !important permet de le remplacer sans toucher à WooCommerce. */
.blockUI.blockOverlay {
    background: rgba(0, 0, 0, 0.55) !important;
    opacity: 1 !important;
}

.panier__breadcrumb {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: clamp(20px, 3vh, 32px);
    font-size: 12.5px;
    color: rgba(255, 255, 255, 0.36);
}

.panier__breadcrumb a {
    color: rgba(255, 255, 255, 0.36);
    text-decoration: none;
    transition: color var(--universim-transition);
}

.panier__breadcrumb a:hover,
.panier__breadcrumb a:focus-visible {
    color: var(--universim-gold);
}

.panier__breadcrumb [aria-current="page"] {
    color: rgba(255, 255, 255, 0.62);
}

.panier__header {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: clamp(12px, 2vw, 32px);
    padding-bottom: clamp(18px, 2.6vh, 28px);
    border-bottom: 1px solid rgba(255, 255, 255, 0.09);
    margin-bottom: clamp(28px, 4.4vh, 48px);
}

.panier__header-text {
    min-width: 0;
}

.panier__kicker {
    font-family: Outfit, sans-serif;
    font-size: 10.5px;
    letter-spacing: 0.28em;
    text-transform: uppercase;
    color: rgba(255, 255, 255, 0.34);
    margin-bottom: 10px;
}

.panier__title {
    margin: 0;
    font-family: Outfit, sans-serif;
    font-weight: 200;
    font-size: clamp(30px, 3.6vw, 52px);
    line-height: 1.02;
    letter-spacing: -0.03em;
    color: var(--universim-white);
}

.panier__intro {
    margin: 0 0 4px auto;
    font-size: 13.5px;
    line-height: 1.65;
    color: rgba(255, 255, 255, 0.46);
    max-width: 50ch;
    white-space: nowrap;
}

@media (max-width: 640px) {
    .panier__intro {
        margin-left: 0;
        max-width: none;
        white-space: normal;
    }
}

/* --------------------------------------------------------------------
   Messages WooCommerce (wc_print_notices — succès/erreur/info, ex.
   "Produit ajouté au panier", coupon invalide...)
   -------------------------------------------------------------------- */
/* .woocommerce-notices-wrapper (woocommerce_before_cart) est un enfant
   direct de .woocommerce, au même niveau que .woocommerce-cart-form et
   .cart-collaterals : sans grid-column, la grille 2 colonnes du panier
   rempli le compte comme un 3ᵉ item et décale tout le reste d'une
   colonne (constaté dans Chrome après une mise à jour de quantité — le
   message "Panier mis à jour" pousse alors la liste de produits dans la
   colonne du récapitulatif). Toujours en pleine largeur, au-dessus. */
.woocommerce-notices-wrapper {
    grid-column: 1 / -1;
}

.woocommerce-notices-wrapper:empty {
    display: none;
}

.woocommerce-message,
.woocommerce-error,
.woocommerce-info {
    list-style: none;
    margin: 0 0 clamp(20px, 3vh, 28px);
    padding: 16px 20px;
    border-radius: 3px;
    border: 1px solid;
    font-size: 14px;
    line-height: 1.6;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 12px 20px;
}

.woocommerce-message {
    background-color: rgba(127, 209, 160, 0.08);
    border-color: rgba(127, 209, 160, 0.35);
    color: #cdeedc;
}

.woocommerce-error {
    background-color: rgba(224, 106, 106, 0.08);
    border-color: rgba(224, 106, 106, 0.35);
    color: #f3c7c7;
}

.woocommerce-error li {
    list-style: none;
}

.woocommerce-info {
    background-color: rgba(255, 255, 255, 0.03);
    border-color: rgba(255, 255, 255, 0.14);
    color: rgba(255, 255, 255, 0.72);
}

.woocommerce-message a:not(.button):not(.wc-forward),
.woocommerce-error a:not(.button):not(.wc-forward),
.woocommerce-info a:not(.button):not(.wc-forward) {
    color: inherit;
    font-weight: 600;
    text-decoration: underline;
    text-underline-offset: 2px;
}

.woocommerce-message a:not(.button):not(.wc-forward):hover,
.woocommerce-error a:not(.button):not(.wc-forward):hover,
.woocommerce-info a:not(.button):not(.wc-forward):hover {
    color: var(--universim-gold);
}

.woocommerce-message a.button,
.woocommerce-error a.button,
.woocommerce-info a.button,
.woocommerce-message a.wc-forward,
.woocommerce-info a.wc-forward {
    order: 2;
    margin-left: auto;
    flex: 0 0 auto;
    padding: 9px 20px;
    border-radius: 999px;
    border: 1px solid rgba(255, 201, 60, 0.34);
    background-color: rgba(255, 201, 60, 0.05);
    color: var(--universim-gold);
    font-family: Outfit, sans-serif;
    font-size: 12.5px;
    font-weight: 500;
    text-decoration: none;
    transition: background-color var(--universim-transition), color var(--universim-transition);
}

.woocommerce-message a.button:hover,
.woocommerce-error a.button:hover,
.woocommerce-info a.button:hover,
.woocommerce-message a.wc-forward:hover,
.woocommerce-info a.wc-forward:hover {
    background-color: var(--universim-gold);
    color: var(--universim-black);
}

/* --------------------------------------------------------------------
   Grille panier rempli : liste de produits + récapitulatif
   -------------------------------------------------------------------- */
/* "Total panier" élargi (plancher 300px -> 400px, ratio 1.55/0.85 ->
   1.3/1) : trop étroit auparavant pour que "GLOBTEL 50 GO"/"GLOBTEL 20 GO"
   tiennent sur une ligne dans le récapitulatif. "Votre sélection" reste
   la colonne principale (toujours nettement plus large), sans aller
   jusqu'à un partage 50/50. */
.woocommerce {
    display: grid;
    grid-template-columns: minmax(0, 1.3fr) minmax(380px, 1fr);
    gap: clamp(24px, 3.6vw, 64px);
    align-items: start;
}

/* Placement explicite plutôt que compter sur le placement automatique :
   déjà vu deux fois sur ce site que Chrome peut mal placer les enfants
   directs d'une grille dans certains cas précis (navigation "Mon compte",
   pseudo-éléments ici même) — plus sûr de fixer les 2 colonnes. */
.woocommerce-cart-form {
    grid-column: 1;
}

.cart-collaterals {
    grid-column: 2;
}

@media (max-width: 940px) {
    .woocommerce-cart-form,
    .cart-collaterals {
        grid-column: 1;
    }
}

@media (max-width: 940px) {
    .woocommerce {
        grid-template-columns: minmax(0, 1fr);
    }
}

/* Repère de section "Votre sélection", ajouté en CSS pur (::before sur le
   formulaire) plutôt qu'un override de template pour un simple libellé. */
.woocommerce-cart-form::before {
    content: "Votre sélection";
    display: block;
    margin-bottom: clamp(14px, 2vh, 20px);
    padding-bottom: clamp(14px, 2vh, 20px);
    border-bottom: 1px solid rgba(255, 255, 255, 0.09);
    font-family: Outfit, sans-serif;
    font-size: 11px;
    letter-spacing: 0.22em;
    text-transform: uppercase;
    color: rgba(255, 255, 255, 0.55);
}

/* --------------------------------------------------------------------
   Table du panier (cart/cart.php, non surchargé) restylée en grille de
   lignes produit. thead conservé pour les lecteurs d'écran (contexte des
   colonnes) mais masqué visuellement — le libellé de section ci-dessus
   et les cartes suffisent visuellement.
   -------------------------------------------------------------------- */
.woocommerce-cart-form__contents {
    width: 100%;
    border-collapse: collapse;
}

/* Spécificité (2 classes + 3 éléments) délibérée : woocommerce.css impose
   déjà padding:9px 12px + line-height:1.5em + border-top à toute cellule
   de "table.shop_table" (2 classes + 2 éléments) — c'est ce padding natif,
   pas une largeur de colonne insuffisante, qui grignotait ~24px sur la
   cellule .product-name et forçait "GLOBTEL 50 GO"/"GLOBTEL 20 GO" à
   passer sur 2 lignes malgré une colonne assez large. L'espacement entre
   colonnes est déjà géré par column-gap sur la ligne (grid), donc
   padding:0 ici plutôt qu'un simple ajustement.
   border-top:0 : chaque <td> (logo, nom, prix, quantité, sous-total,
   suppression) porte sinon son propre filet natif — d'où les petits
   traits qui traversaient la ligne à des hauteurs différentes selon la
   cellule. Le vrai séparateur entre deux produits reste celui posé sur
   la ligne elle-même (.woocommerce-cart-form__cart-item), pas touché
   ici. */
.woocommerce-cart table.cart tr td {
    padding: 0;
    border-top: 0;
    line-height: 1.3;
}

.shop_table.cart thead {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
}

.shop_table.cart,
.shop_table.cart tbody {
    display: block;
    width: 100%;
}

/* Hiérarchie voulue par ligne produit (identique à toutes les largeurs,
   seules les proportions s'adaptent — voir le palier 560px plus bas) :
     nom du forfait                                    [x]
     prix unitaire (une seule fois, sous le nom)
     ──────────────────────────────────────────────────
     Quantité                    Total
     [ -  2  + ]                 29,98 € / mois
   4 colonnes (thumb + 2 demi-colonnes de contenu + retrait) plutôt que
   des "grid-template-areas" : product-quantity et product-subtotal
   doivent se partager la même ligne en 2 blocs égaux alors que
   product-name/product-price doivent occuper toute la largeur de
   contenu au-dessus — un besoin que les zones nommées ne permettent pas
   (chaque zone nommée ne peut être qu'un seul rectangle). */
/* !important sur "display: grid" : woocommerce-smallscreen.css (feuille
   native de WooCommerce, chargée avec media="only screen and
   (max-width: 480px)") impose ".shop_table_responsive tr{display:block}"
   sous 480px — plus spécifique que notre simple ".woocommerce-cart-form__cart-item"
   (repéré en local : la grille disparaissait complètement sous 480px, la
   ligne retombant sur l'empilement générique de WooCommerce, avec ses
   propres libellés "Produit"/"Prix" et la vignette masquée). Cette même
   feuille impose aussi "td{text-align:right!important}" et masque
   ".product-thumbnail" : neutralisés ci-dessous, cellule par cellule. */
.woocommerce-cart-form__cart-item {
    position: relative;
    display: grid !important;
    grid-template-columns: clamp(90px, 8vw, 120px) minmax(0, 1fr) minmax(0, 1fr) 34px;
    column-gap: clamp(14px, 2vw, 22px);
    row-gap: 4px;
    padding: clamp(20px, 3vh, 30px) clamp(2px, 0.6vw, 10px);
    border-top: 1px solid rgba(255, 255, 255, 0.1);
    transition: background-color 0.45s ease;
}

.woocommerce-cart-form__cart-item .product-thumbnail {
    display: flex !important;
}

.woocommerce-cart-form__cart-item:hover {
    background-color: rgba(255, 255, 255, 0.014);
}

.woocommerce-cart-form__contents > tbody > tr:last-of-type.woocommerce-cart-form__cart-item {
    border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}

.woocommerce-cart-form__cart-item .product-thumbnail {
    grid-column: 1;
    grid-row: 1 / span 3;
    align-self: start;
}

.woocommerce-cart-form__cart-item .product-name {
    grid-column: 2 / 4;
    grid-row: 1;
    min-width: 0;
    text-align: left !important;
}

/* Prix unitaire repositionné directement sous le nom (au lieu de sa
   propre colonne à droite) : c'est la MÊME cellule WooCommerce
   (.product-price, valeur réelle), seulement déplacée en grille — aucune
   donnée dupliquée en PHP. */
.woocommerce-cart-form__cart-item .product-price {
    grid-column: 2 / 4;
    grid-row: 2;
    text-align: left !important;
}

.woocommerce-cart-form__cart-item .product-remove {
    grid-column: 4;
    grid-row: 1;
    justify-self: end;
}

/* Ligne "Quantité / Total" : séparée du nom+prix par un filet fin
   (border-top posé sur les 2 cellules — même ligne de grille, donc un
   seul trait continu visuellement). */
.woocommerce-cart-form__cart-item .product-quantity,
.woocommerce-cart-form__cart-item .product-subtotal {
    grid-row: 3;
    margin-top: 14px;
    padding-top: 14px;
    border-top: 1px solid rgba(255, 255, 255, 0.08);
}

.woocommerce-cart-form__cart-item .product-quantity {
    grid-column: 2;
    text-align: left !important;
}

.woocommerce-cart-form__cart-item .product-subtotal {
    grid-column: 3 / 5;
    text-align: right !important;
}

/* Repères "Quantité" / "Total" au-dessus des valeurs — .product-quantity
   récupère le data-title natif WooCommerce ("Quantité", déjà exact) ;
   .product-subtotal a pour data-title natif "Sous-total" (le nom réel de
   la colonne), remplacé ici par un simple libellé visuel "Total" — pur
   habillage, la valeur affichée dessous reste le vrai total de ligne
   WooCommerce. */
/* !important sur "content"/"display" : woocommerce.css intègre son
   propre empilement responsive natif de ce tableau (avec ses propres
   libellés ::before "Produit"/"Prix"/"Sous-total" à partir d'un certain
   palier étroit) — repéré en local sous ~400px, où ces libellés natifs
   reprenaient la main sur les nôtres (et faisaient réapparaître
   "Produit"/"Prix", jamais voulus ici). Seul un !important le bat de
   façon fiable à toutes les largeurs, même cause que .blockUI plus haut. */
.woocommerce-cart-form__cart-item .product-quantity::before,
.woocommerce-cart-form__cart-item .product-subtotal::before {
    display: block !important;
    float: none !important;
    margin-bottom: 8px;
    font-family: Outfit, sans-serif;
    font-size: 10.5px;
    font-weight: 400 !important;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: rgba(255, 255, 255, 0.34);
}

.woocommerce-cart-form__cart-item .product-quantity::before {
    content: attr(data-title) !important;
}

.woocommerce-cart-form__cart-item .product-subtotal::before {
    content: "Total" !important;
}

/* Le nom (déjà explicite en grand texte) et le prix unitaire (déjà juste
   sous le nom) n'ont besoin d'aucun libellé ::before — neutralise le
   même comportement responsive natif de WooCommerce pour ces 2 cellules
   ("Produit"/"Prix" ne doivent jamais apparaître ici). */
.woocommerce-cart-form__cart-item .product-name::before,
.woocommerce-cart-form__cart-item .product-price::before {
    content: none !important;
    display: none !important;
}

/* Logo Universim systématique (universim_cart_item_logo_thumbnail,
   functions.php — filtre woocommerce_cart_item_thumbnail), quel que soit
   le produit et qu'il ait ou non une image mise en avant : identité
   visuelle générique de cette zone, jamais un carré vide ni le
   placeholder WooCommerce générique. Directement sur le fond noir du
   panier — plus de cadre/bordure/fond autour : juste le logo, assez
   grand pour que le symbole et "UNIVERSIM TELECOM" soient lisibles,
   centré verticalement sur la ligne. */
.product-thumbnail {
    display: flex;
    align-items: center;
    justify-content: flex-start;
    width: 100%;
    height: clamp(64px, 6vw, 88px);
}

/* Spécificité (2 classes + 3 éléments) délibérée : woocommerce.css fige
   les vignettes du panier à 32px de large via ".woocommerce-cart
   table.cart img" (2 classes + 2 éléments) — c'est cette règle native,
   pas la mienne, qui rendait le logo minuscule malgré la taille donnée à
   son conteneur .product-thumbnail. */
.woocommerce-cart table.cart tr .product-thumbnail img {
    display: block;
    width: auto;
    height: 100%;
    max-width: 100%;
    object-fit: contain;
}

.product-name {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 7px;
}

.product-name a {
    display: block;
    width: 100%;
    font-family: Outfit, sans-serif;
    font-size: clamp(16px, 1.5vw, 21px);
    font-weight: 400;
    letter-spacing: 0.01em;
    color: var(--universim-white);
    text-decoration: none;
}

.product-name a:hover {
    color: var(--universim-gold);
}

/* Prix unitaire — une seule fois, juste sous le nom du forfait (voir plus
   haut : même cellule .product-price WooCommerce, repositionnée en
   grille). Volontairement discret : c'est le total de ligne
   (.product-subtotal, plus bas) qui reste l'information forte. */
.product-price {
    font-size: 14px;
    color: rgba(255, 255, 255, 0.5);
    white-space: nowrap;
}

.product-price .woocommerce-Price-amount {
    font-family: Outfit, sans-serif;
    font-size: 14px;
    color: rgba(255, 255, 255, 0.5);
}

.product-subtotal {
    font-family: Outfit, sans-serif;
    font-size: clamp(19px, 1.8vw, 26px);
    font-weight: 300;
    letter-spacing: -0.02em;
    color: var(--universim-white);
    white-space: nowrap;
}

/* --------------------------------------------------------------------
   Quantité : input natif + boutons -/+ ajoutés en PHP (hooks
   woocommerce_before/after_quantity_input_field, functions.php) rendus
   fonctionnels par Assets/JS/panier.js.
   -------------------------------------------------------------------- */
.quantity {
    display: flex;
    align-items: center;
    gap: 2px;
    border: 1px solid rgba(255, 255, 255, 0.14);
    border-radius: 999px;
    width: fit-content;
}

.panier-qty__btn {
    cursor: pointer;
    background: none;
    border: 0;
    width: 32px;
    height: 32px;
    border-radius: 999px;
    color: rgba(255, 255, 255, 0.6);
    font-size: 15px;
    line-height: 1;
    transition: color var(--universim-transition), background-color var(--universim-transition);
}

.panier-qty__btn:hover,
.panier-qty__btn:focus-visible {
    color: var(--universim-gold);
    background-color: rgba(255, 255, 255, 0.05);
}

.quantity .qty {
    width: 30px;
    padding: 0;
    border: 0;
    background: none;
    text-align: center;
    font-family: Outfit, sans-serif;
    font-size: 14px;
    color: var(--universim-white);
    -moz-appearance: textfield;
}

.quantity .qty::-webkit-outer-spin-button,
.quantity .qty::-webkit-inner-spin-button {
    -webkit-appearance: none;
    margin: 0;
}

/* --------------------------------------------------------------------
   Suppression d'un produit — lien natif "remove" (×), discret, sans
   rouge agressif au repos, léger accent au survol seulement.
   !important nécessaire : woocommerce.css force la couleur rouge (repos
   ET survol, fond rouge plein au survol) via ".woocommerce a.remove" avec
   déjà !important — seul un autre !important peut la remplacer.
   -------------------------------------------------------------------- */
.product-remove a.remove {
    display: inline-flex !important;
    align-items: center;
    justify-content: center;
    width: 26px;
    height: 26px;
    font-size: 16px !important;
    border-radius: 50%;
    border: 1px solid rgba(255, 255, 255, 0.14);
    color: rgba(255, 255, 255, 0.4) !important;
    line-height: 1;
    text-decoration: none;
    transition: color var(--universim-transition), border-color var(--universim-transition), background-color var(--universim-transition);
}

.product-remove a.remove:hover,
.product-remove a.remove:focus-visible {
    color: #ff7a7a !important;
    border-color: rgba(255, 122, 122, 0.4);
    background-color: rgba(255, 122, 122, 0.1);
}

/* --------------------------------------------------------------------
   Ligne d'actions (coupon + mettre à jour le panier) — reste une
   <tr>/<td> normale (pas de classe dédiée à cibler pour la passer en
   display:block comme les lignes produit) ; un <td> peut devenir un
   conteneur flex sans que la ligne elle-même change de display.

   Marges internes : ".woocommerce-cart table.cart tr td { padding:0 }"
   plus haut compte en réalité pour 2 classes (.woocommerce-cart ET
   ".cart" sur table.cart) + 3 éléments — plus spécifique qu'un simple
   "td.actions" (1 classe + 1 élément) ou même qu'un premier correctif à
   2 classes seulement. Elle l'emportait donc, et la ligne d'actions se
   retrouvait collée au bord gauche ET au bord bas du grand cadre "Votre
   sélection" (0px de marge réelle, vérifié dans Chrome) — l'effet
   "quasiment collé aux bordures" signalé. Sélecteur renforcé à 3 classes
   pour reprendre la main, avec un vrai padding gauche/droite/bas — le
   cadre n'a pas de hauteur fixe (padding, pas de height), il s'agit donc
   toujours d'une marge qui s'adapte naturellement, quel que soit le
   nombre de produits. */
.woocommerce-cart .woocommerce-cart-form__contents td.actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 16px;
    padding: clamp(18px, 2.6vh, 24px) clamp(20px, 2.6vw, 32px) clamp(24px, 3.4vh, 32px);
}

/* display:contents : .coupon disparaît de l'arbre de boîtes, ses enfants
   (champ, bouton "Appliquer" et, une fois injecté par cart.js, le message
   d'erreur #coupon-error-notice) deviennent des items flex directs de
   td.actions. Nécessaire car cart.js (natif WooCommerce, non modifié)
   ajoute le message d'erreur de coupon COMME DERNIER ENFANT DE .coupon :
   en flexbox normal, .coupon grandissait alors verticalement et
   repoussait "Mettre à jour le panier" (item suivant dans td.actions)
   vers le bas — c'est le déplacement d'interface signalé. Une fois les
   enfants remontés au niveau de td.actions, le message reçoit order:99 +
   flex-basis 100% (voir plus bas) pour retomber sur sa propre ligne sous
   les 3 contrôles, qui eux gardent une position fixe. */
.coupon {
    display: contents;
}

.coupon label {
    display: none;
}

#coupon_code {
    width: 190px;
    background-color: var(--universim-field-bg);
    border: 1px solid var(--universim-field-border);
    border-radius: 999px;
    padding: 11px 18px;
    font-family: Poppins, system-ui, sans-serif;
    font-weight: 300;
    font-size: 13.5px;
    color: var(--universim-white);
    transition: border-color 0.35s ease, box-shadow 0.35s ease;
}

#coupon_code:focus {
    outline: none;
    border-color: rgba(255, 201, 60, 0.6);
    box-shadow: 0 0 0 3px rgba(255, 201, 60, 0.09);
}

#coupon_code::placeholder {
    color: rgba(255, 255, 255, 0.3);
}

/* Zone dédiée pour le message de coupon invalide (voir commentaire sur
   .coupon plus haut) : flex-basis 100% force son retour à la ligne sous
   le champ + les 2 boutons, order:99 la garantit toujours en dernier même
   si elle est techniquement avant "Mettre à jour le panier" dans le DOM.
   Fond légèrement différencié du noir de fond, liseré doré très discret,
   texte blanc — pas de rouge — avec un petit repère "[ ! ]" doré au lieu
   d'un bloc d'alerte voyant. Marges généreuses de tous côtés pour ne
   jamais toucher le cadre du panier.
   Sélecteur par ID (#coupon-error-notice, l'id posé par cart.js) plutôt
   que par classe : woocommerce.css cible ce même message via
   ".woocommerce-cart table.cart td.actions .coupon .coupon-error-notice"
   (couleur rouge, marge 8px, texte réduit...) — 5 classes + 2 éléments,
   plus spécifique qu'une simple classe. Un id bat n'importe quel nombre
   de classes, donc c'est la façon la plus sûre de reprendre la main sans
   dupliquer toute la chaîne de sélecteurs de WooCommerce. */
#coupon-error-notice {
    order: 99;
    flex: 1 1 100%;
    clear: none;
    float: none;
    width: auto;
    text-align: left;
    margin: 18px 0 0;
    padding: 13px 20px;
    border-radius: 8px;
    border: 1px solid rgba(255, 201, 60, 0.2);
    background-color: rgba(255, 255, 255, 0.025);
    color: rgba(255, 255, 255, 0.82);
    font-size: 13.5px;
    line-height: 1.6;
}

#coupon-error-notice::before {
    content: "[ ! ]";
    margin-right: 8px;
    color: var(--universim-gold);
    font-family: Outfit, sans-serif;
    font-weight: 600;
}

td.actions button.button {
    cursor: pointer;
    padding: 11px 24px;
    border-radius: 999px;
    border: 1px solid rgba(255, 255, 255, 0.18);
    background-color: transparent;
    color: rgba(255, 255, 255, 0.78);
    font-family: Outfit, sans-serif;
    font-size: 13px;
    font-weight: 500;
    transition: border-color var(--universim-transition), color var(--universim-transition);
}

td.actions button[name="apply_coupon"] {
    background-color: rgba(255, 201, 60, 0.05);
    border-color: rgba(255, 201, 60, 0.34);
    color: var(--universim-gold);
}

td.actions button.button:hover,
td.actions button.button:focus-visible {
    border-color: rgba(255, 255, 255, 0.4);
    color: var(--universim-white);
}

td.actions button[name="apply_coupon"]:hover,
td.actions button[name="apply_coupon"]:focus-visible {
    background-color: var(--universim-gold);
    border-color: var(--universim-gold);
    color: var(--universim-black);
}

/* "Mettre à jour le panier" : WooCommerce (cart.js natif, non modifié)
   active/désactive réellement ce bouton — repéré et vérifié en local :
   changer la quantité (bouton +/- ou saisie directe) déclenche bien
   l'événement "change" natif et retire l'attribut disabled avant l'envoi
   du formulaire. Le bouton semblait "rester grisé" uniquement parce
   qu'aucun style ne distinguait visuellement ses deux états — corrigé
   ici, sans toucher au fonctionnement réel du bouton. */
td.actions button[name="update_cart"]:disabled {
    cursor: not-allowed;
    opacity: 0.42;
}

td.actions button[name="update_cart"]:disabled:hover,
td.actions button[name="update_cart"]:disabled:focus-visible {
    border-color: rgba(255, 255, 255, 0.18);
    color: rgba(255, 255, 255, 0.78);
}

td.actions button[name="update_cart"]:not(:disabled) {
    background-color: rgba(255, 201, 60, 0.05);
    border-color: rgba(255, 201, 60, 0.34);
    color: var(--universim-gold);
}

td.actions button[name="update_cart"]:not(:disabled):hover,
td.actions button[name="update_cart"]:not(:disabled):focus-visible {
    background-color: var(--universim-gold);
    border-color: var(--universim-gold);
    color: var(--universim-black);
}

/* --------------------------------------------------------------------
   Continuer mes achats — ajouté via le hook woocommerce_after_cart_table
   (universim_cart_continue_shopping_link dans functions.php), URL réelle
   de la Boutique.
   -------------------------------------------------------------------- */
.panier-continue {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    margin-top: clamp(22px, 3vh, 32px);
    font-size: 13.5px;
    color: rgba(255, 255, 255, 0.5);
    text-decoration: none;
}

.panier-continue:hover {
    color: var(--universim-gold);
}

/* --------------------------------------------------------------------
   Récapitulatif (cart/cart-totals.php, non surchargé)
   -------------------------------------------------------------------- */
.cart-collaterals {
    min-width: 0;
}

/* Un seul cadre fermé pour tout le bloc : celui-ci. Rien à l'intérieur
   (liste d'articles, sous-total, total) ne doit avoir sa propre bordure —
   uniquement des filets fins entre les groupes (voir plus bas). */
.cart_totals {
    position: sticky;
    top: 100px;
    display: flex;
    flex-direction: column;
    gap: clamp(20px, 2.8vh, 28px);
    padding: clamp(32px, 3vw, 40px);
    border: 1px solid rgba(255, 255, 255, 0.1);
    background-color: rgba(255, 255, 255, 0.014);
}

@media (max-width: 940px) {
    .cart_totals {
        position: static;
        top: auto;
    }
}

/* order explicite sur chaque enfant direct de .cart_totals : le détail des
   articles (universim_cart_totals_item_list, functions.php) est injecté
   via le hook woocommerce_before_cart_totals, donc avant le <h2> dans le
   DOM — pas de hook natif entre le <h2> et le <table> pour l'insérer au
   bon endroit sans override. Réordonné visuellement en flex plutôt que de
   surcharger cart-totals.php pour un simple déplacement de bloc. */
.cart_totals h2 {
    order: 1;
    position: relative;
    margin: 0;
    padding-left: 15px;
    font-family: Outfit, sans-serif;
    font-size: 11px;
    letter-spacing: 0.22em;
    text-transform: uppercase;
    color: rgba(255, 255, 255, 0.6);
}

.cart_totals h2::before {
    content: "";
    position: absolute;
    left: 0;
    top: 50%;
    transform: translateY(-50%);
    width: 5px;
    height: 5px;
    border-radius: 50%;
    background-color: var(--universim-gold);
}

/* Détail des articles (nom + prix), au-dessus du sous-total. */
.panier-summary-items {
    order: 2;
    display: flex;
    flex-direction: column;
    gap: 12px;
    padding-bottom: clamp(18px, 2.6vh, 24px);
    border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}

.panier-summary-item {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 16px;
}

.panier-summary-item__name {
    font-size: 14px;
    line-height: 1.4;
    color: var(--universim-white);
}

.panier-summary-item__price {
    flex: 0 0 auto;
    font-family: Outfit, sans-serif;
    font-size: 14px;
    color: rgba(255, 255, 255, 0.7);
    white-space: nowrap;
}

/* table/tbody blockifiés avant de passer les <tr> en flex : sans ça, le
   moteur de table (toujours actif sur <table>/<tbody> par défaut) mesure
   mal la hauteur des lignes flex et les superpose (constaté dans Chrome :
   la ligne "Total" chevauchait la valeur du sous-total). Même cause que
   la table du panier plus haut.
   Spécificité (3 classes) délibérée sur tout ce bloc : woocommerce.css
   contient une feuille de règles DÉDIÉE à cette table précise —
   ".woocommerce-cart .cart-collaterals .cart_totals table ..." (3 classes
   + 1-2 éléments) — nettement plus spécifique que ".cart_totals ..." seul
   malgré un chargement plus tardif ici (padding, line-height:1.5em,
   border-top et même width:35% sur les <th> y sont imposés). Repris à
   l'identique (3 classes + éléments) pour être sûr de gagner partout,
   plutôt qu'un correctif propriété par propriété.
   border:0 en plus ici : ".woocommerce table.shop_table" (règle générale,
   pas spécifique à cette page) entoure la table entière d'une bordure —
   c'était le "cadre dans le cadre" signalé : un second rectangle fermé
   autour du sous-total/total, à l'intérieur du grand cadre "Total
   panier". Un seul cadre fermé désormais, le grand. */
.woocommerce-cart .cart-collaterals .cart_totals table,
.woocommerce-cart .cart-collaterals .cart_totals tbody {
    display: block;
    width: 100%;
}

.woocommerce-cart .cart-collaterals .cart_totals table {
    order: 3;
    border: 0;
    border-collapse: collapse;
    margin: 0;
    padding: 0;
}

.cart_totals tr {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 16px;
}

.woocommerce-cart .cart-collaterals .cart_totals table th,
.woocommerce-cart .cart-collaterals .cart_totals table td {
    width: auto;
    padding: 6px 0;
    border: 0;
    text-align: left;
    font-weight: 400;
    line-height: 1.3;
    vertical-align: baseline;
}

.cart_totals tr.cart-subtotal th,
.cart_totals tr.cart-discount th {
    font-size: 13.5px;
    color: rgba(255, 255, 255, 0.5);
}

.cart_totals tr.cart-subtotal td,
.cart_totals tr.cart-discount td {
    font-family: Outfit, sans-serif;
    font-size: 14.5px;
    color: rgba(255, 255, 255, 0.85);
}

.woocommerce-cart .cart-collaterals .cart_totals .discount td,
.cart_totals tr.cart-discount td {
    color: var(--universim-gold);
}

.cart_totals tr.cart-discount .woocommerce-remove-coupon {
    margin-left: 8px;
    color: rgba(255, 255, 255, 0.4);
    text-decoration: underline;
}

/* Ligne "Expédition initiale" (cart-totals.php, non modifié) : sa cellule
   contient une phrase complète ("Les options de livraison seront mises à
   jour lors de la commande.") + le lien "Calculer les frais
   d'expédition" — beaucoup trop pour tenir à droite d'un libellé sur la
   même ligne (texte cassé sur de nombreuses lignes, repéré en
   production). Le libellé passe donc au-dessus de son contenu, comme la
   section RIO/Livraison de la page Commande, plutôt que de rester à
   côté : le contenu profite alors de toute la largeur de la carte. */
.cart_totals tr.woocommerce-shipping-totals {
    flex-direction: column;
    align-items: flex-start;
    gap: 8px;
}

.cart_totals tr.woocommerce-shipping-totals td {
    width: 100%;
}

.cart_totals .woocommerce-shipping-methods {
    margin: 0 0 4px;
    padding: 0;
    list-style: none;
    font-family: Outfit, sans-serif;
    font-size: 14.5px;
    color: rgba(255, 255, 255, 0.85);
}

.cart_totals .woocommerce-shipping-destination {
    margin: 0 0 6px;
    font-size: 12.5px;
    line-height: 1.6;
    color: rgba(255, 255, 255, 0.4);
}

.cart_totals .woocommerce-shipping-calculator a {
    font-size: 12.5px;
    color: var(--universim-gold);
    text-decoration: underline;
    text-underline-offset: 2px;
}

.cart_totals tr.order-total {
    align-items: flex-end;
    padding-top: clamp(16px, 2.4vh, 22px);
    margin-top: 6px;
    border-top: 1px solid rgba(255, 201, 60, 0.14);
}

.cart_totals tr.order-total th {
    font-size: 12px;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: rgba(255, 255, 255, 0.5);
}

/* Le montant final comme une seule unité visuelle : même taille/couleur
   pour le symbole monétaire et le nombre (plus de symbole détaché, plus
   petit et d'une autre couleur que le chiffre). */
.woocommerce-cart .cart-collaterals .cart_totals table tr.order-total td {
    font-family: Outfit, sans-serif;
    font-size: clamp(28px, 2.8vw, 38px);
    font-weight: 400;
    line-height: 1;
    letter-spacing: -0.02em;
    color: var(--universim-gold);
}

.cart_totals tr.order-total .woocommerce-Price-currencySymbol {
    font-size: 1em;
    color: inherit;
}

/* --------------------------------------------------------------------
   WooCommerce Subscriptions — classes confirmées par inspection en
   lecture seule de universim-telecom.com/panier/ (panier avec un
   produit vendu en abonnement) : tr.recurring-totals (en-tête "Totaux
   récurrents"), tr.cart-subtotal.recurring-total, tr.shipping.recurring-total
   (+ un suffixe de date généré dynamiquement, ex. "2026_10_03_monthly" —
   non utilisable comme sélecteur fixe), tr.order-total.recurring-total
   (qui contient aussi, en vrai <div class="first-payment-date">, la
   ligne "Premier renouvellement : [date]"). Absent de cet environnement
   local (aucun produit vendu en abonnement ici) : préparé pour
   correspondre exactement au DOM réel, à vérifier visuellement après
   déploiement. Aucun calcul, aucune date, aucun hook Subscriptions n'est
   modifié — uniquement la présentation, rendue nettement plus discrète
   que le total immédiat (.order-total sans .recurring-total, plus haut)
   pour respecter la hiérarchie demandée.
   -------------------------------------------------------------------- */
.cart_totals tr.recurring-totals {
    margin-top: clamp(14px, 2vh, 18px);
    padding-top: clamp(14px, 2vh, 18px);
    border-top: 1px solid rgba(255, 255, 255, 0.08);
}

.cart_totals tr.recurring-totals th {
    font-family: Outfit, sans-serif;
    font-size: 10.5px;
    font-weight: 500;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: rgba(255, 255, 255, 0.4);
}

.cart_totals tr.recurring-total:not(.order-total) th {
    font-size: 12.5px;
    color: rgba(255, 255, 255, 0.4);
}

.cart_totals tr.recurring-total:not(.order-total) td {
    font-family: Outfit, sans-serif;
    font-size: 13px;
    color: rgba(255, 255, 255, 0.6);
}

/* Total récurrent : visible, mais nettement plus petit que le total
   immédiat — spécificité (3 classes) volontaire pour gagner sur
   ".cart_totals tr.order-total" (2 classes, le total immédiat) défini
   plus haut, sans quoi le total récurrent hériterait du même très grand
   gabarit doré. Empilé (libellé, puis prix, puis date) plutôt qu'aligné
   à droite comme le total immédiat : sa cellule contient 2 informations
   (prix + date de renouvellement), pas une seule valeur. */
.cart_totals tr.order-total.recurring-total {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 4px;
    padding-top: clamp(10px, 1.6vh, 14px);
    margin-top: 4px;
    border-top: 0;
}

.cart_totals tr.order-total.recurring-total th {
    font-size: 10.5px;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: rgba(255, 255, 255, 0.4);
}

.woocommerce-cart .cart-collaterals .cart_totals table tr.order-total.recurring-total td {
    font-size: 17px;
    font-weight: 500;
    letter-spacing: normal;
    color: rgba(255, 255, 255, 0.88);
}

.cart_totals tr.order-total.recurring-total .first-payment-date {
    margin-top: 2px;
    font-family: Poppins, system-ui, sans-serif;
    font-size: 11px;
    font-weight: 400;
    color: rgba(255, 255, 255, 0.35);
}

.wc-proceed-to-checkout {
    order: 4;
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
    margin-top: clamp(12px, 2vh, 20px);
}

/* Boutons de paiement express injectés par les passerelles actives DANS
   CE MÊME conteneur (woocommerce_proceed_to_checkout, hook natif que
   notre bouton "Valider la commande" utilise déjà) — confirmé par
   inspection en lecture seule de la production :
     - WooCommerce PayPal Payments : .wc-ppcp-cart-payments__container
       (bouton PayPal, actif, toujours fourni par ce plugin)
     - WooCommerce Stripe Gateway (PAS WooPayments, désactivé) :
       #wc-stripe-express-checkout-element (bouton "Link", actif)
   Ni l'un ni l'autre n'avait "disparu" : les deux sont bien présents et
   fonctionnels en production, seulement débordés hors du cadre visible
   de la carte — ".wc-proceed-to-checkout" (flex row) sans flex-wrap
   forçait notre "Valider la commande" (flex:1) et ces conteneurs à se
   partager une seule ligne trop étroite. Sélecteur générique (tout enfant
   direct qui n'est pas notre bouton) plutôt que de nommer chaque plugin :
   fonctionne quelle que soit la passerelle active, y compris si elle
   change plus tard — sans jamais styler l'intérieur de leurs composants
   sécurisés. */
.wc-proceed-to-checkout > *:not(.checkout-button) {
    flex: 1 1 100%;
    max-width: 100%;
}

.wc-ppcp-cart-or {
    margin: 2px 0;
    font-family: Outfit, sans-serif;
    font-size: 12px;
    text-align: center;
    color: rgba(255, 255, 255, 0.4);
}

/* Spécificité (3 classes + 1 élément) délibérée : woocommerce.css stylise
   déjà tout a.button (gris/texte foncé) via ".woocommerce :where(...)
   a.button" (2 classes + 1 élément après neutralisation du :where()) —
   même cause que les boutons de "Mon compte". */
.woocommerce-cart .wc-proceed-to-checkout a.checkout-button {
    flex: 1 1 100%;
    text-align: center;
    text-decoration: none;
    padding: 17px 28px;
    border-radius: 999px;
    background-color: var(--universim-gold);
    color: var(--universim-black);
    font-family: Outfit, sans-serif;
    font-size: 15px;
    font-weight: 600;
    letter-spacing: 0.01em;
    box-shadow: 0 14px 38px -18px rgba(245, 179, 1, 0.6);
    transition: transform var(--universim-transition), box-shadow var(--universim-transition), background-color var(--universim-transition);
}

.woocommerce-cart .wc-proceed-to-checkout a.checkout-button:hover,
.woocommerce-cart .wc-proceed-to-checkout a.checkout-button:focus-visible {
    background-color: var(--universim-gold-hover);
    transform: translateY(-1px);
    box-shadow: 0 20px 46px -18px rgba(245, 179, 1, 0.8);
    color: var(--universim-black);
}

/* --------------------------------------------------------------------
   Panier vide (woocommerce/cart/cart-empty.php, surchargé)
   -------------------------------------------------------------------- */
.panier-empty {
    grid-column: 1 / -1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    text-align: center;
    gap: 20px;
    min-height: min(56vh, 520px);
    padding: clamp(40px, 8vh, 90px) clamp(16px, 4vw, 40px);
}

.panier-empty__icon {
    width: 56px;
    height: 56px;
    border-radius: 50%;
    border: 1px solid rgba(255, 255, 255, 0.16);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: rgba(255, 255, 255, 0.45);
}

.panier-empty__title {
    margin: 0;
    font-family: Outfit, sans-serif;
    font-weight: 200;
    font-size: clamp(26px, 3vw, 40px);
    letter-spacing: -0.025em;
    color: var(--universim-white);
}

.panier-empty__text {
    margin: 0;
    font-size: 14.5px;
    line-height: 1.75;
    color: rgba(255, 255, 255, 0.46);
    max-width: 60ch;
}

.panier-empty__cta {
    display: inline-block;
    margin-top: 10px;
    padding: 17px 34px;
    border-radius: 999px;
    background-color: var(--universim-gold);
    color: var(--universim-black);
    text-decoration: none;
    font-family: Outfit, sans-serif;
    font-size: 15px;
    font-weight: 600;
    box-shadow: 0 14px 38px -18px rgba(245, 179, 1, 0.55);
    transition: transform var(--universim-transition), box-shadow var(--universim-transition), background-color var(--universim-transition);
}

.panier-empty__cta:hover,
.panier-empty__cta:focus-visible {
    background-color: var(--universim-gold-hover);
    transform: translateY(-1px);
    color: var(--universim-black);
}


/* --------------------------------------------------------------------
   Responsive — même hiérarchie qu'en desktop (nom+prix en haut,
   Quantité/Total en dessous) à toutes les largeurs, voir plus haut :
   seules les proportions changent ici.
   -------------------------------------------------------------------- */
@media (max-width: 720px) {
    .woocommerce-cart-form__cart-item {
        grid-template-columns: 62px minmax(0, 1fr) minmax(0, 1fr) 30px;
        padding: 20px 4px;
    }
}

/* Sous 460px, Quantité et Total n'ont plus la place de rester côte à
   côte (sélecteur -/+ + texte du total) sans se comprimer : ils passent
   l'un sous l'autre, pleine largeur. */
@media (max-width: 460px) {
    .woocommerce-cart-form__cart-item {
        grid-template-columns: 52px minmax(0, 1fr) 30px;
        row-gap: 10px;
    }

    .woocommerce-cart-form__cart-item .product-name,
    .woocommerce-cart-form__cart-item .product-price {
        grid-column: 2 / 3;
    }

    .woocommerce-cart-form__cart-item .product-remove {
        grid-column: 3;
    }

    .woocommerce-cart-form__cart-item .product-quantity,
    .woocommerce-cart-form__cart-item .product-subtotal {
        grid-column: 2 / 4;
    }

    .woocommerce-cart-form__cart-item .product-quantity {
        grid-row: 3;
    }

    .woocommerce-cart-form__cart-item .product-subtotal {
        grid-row: 4;
        text-align: left;
    }

    td.actions {
        flex-direction: column;
        align-items: stretch;
    }

    #coupon_code {
        width: 100%;
    }
}
