/* checkout.css — page de paiement (/checkout). Les champs sont ceux de Stripe
   (réglés dans checkout.js) ; ici : mise en page, liste des moyens de paiement
   et récapitulatif. */

.checkout-page {
    max-width: 1100px;
    margin: 0 auto;
}

/* Quatre cases dans la grille (titre, formulaire, bouton « Payer »,
   récapitulatif). `.checkout-scroll` (titre + formulaire) et `.checkout-footer`
   (récapitulatif + bouton) sont des enveloppes purement structurelles pour
   l'écran étroit (voir plus bas : la première y devient la zone qui défile, la
   seconde le pied fixe) — sur grand écran elles s'effacent (`display: contents`)
   pour laisser chacun de leurs enfants se placer directement dans cette grille,
   comme si l'enveloppe n'existait pas. Le titre ("Checkout" + "Back to cart")
   n'est donc plus un frère de `.checkout` mais son premier enfant, dans
   `.checkout-scroll` : il DOIT rester dans la grille de `.checkout` (pas hors
   d'elle comme avant) pour pouvoir migrer dans la zone défilante à l'étroit —
   `grid-column: 1 / -1` lui garde sa pleine largeur, par-dessus les deux
   colonnes. #pay-btn/.checkout-terms ne sont plus dans le <form> (voir
   checkout.js : `<button form="checkout-form">`, valide en HTML5 même hors de
   l'élément <form>) : les regrouper avec le récapitulatif dans
   `.checkout-footer` est ce qui permet aux deux de rejoindre ensemble le pied
   fixe à l'étroit, sans avoir à les faire cohabiter avec le formulaire. */
.checkout {
    display: grid;
    grid-template-columns: minmax(0, 500px) minmax(0, 1fr);
    column-gap: clamp(32px, 6vw, 80px);
    row-gap: 36px;
    align-items: start;
}

.checkout-scroll,
.checkout-footer {
    display: contents;
}

.checkout .title-row {
    grid-column: 1 / -1;
    grid-row: 1;
}

.checkout-form {
    grid-column: 1;
    grid-row: 2;
}

.checkout-actions {
    grid-column: 1;
    grid-row: 3;
}

.checkout-form section {
    margin-bottom: 36px;
}

/* Le dernier champ du formulaire ne doit plus garder son propre écart avant
   .checkout-actions (`row-gap` ci-dessus s'en charge déjà) : les deux
   s'additionnaient sinon (36 + 36px), un écart plus grand qu'ailleurs sur la
   page sans raison délibérée. */
.checkout-form section:last-child {
    margin-bottom: 0;
}

/* Sous-titres : voir components.css (greycliff 22px/500, comme les pages policies). */
.checkout-form h2,
.checkout-summary h2 {
    margin: 0 0 14px;
}

/* Bouton « Payer » : bouton principal du site (.btn.primary), sur toute la
   largeur (un <button> ne s'étire pas tout seul, même en display:flex).
   `gap` : espace entre le logo Apple Pay et « Pay » une fois ce moyen choisi
   (updatePayButtonLabel, checkout.js) — sans effet sur le texte seul des
   deux autres moyens (un unique nœud de texte n'a rien à espacer). */
.checkout-actions .btn {
    display: flex;
    width: 100%;
    gap: 6px;
}

.checkout-terms {
    margin: 12px 0 0;
    color: var(--muted);
    font-size: 12px;
    line-height: 1.6;
}

/* Moyens de paiement en liste verticale : un titre (rond de sélection, nom,
   logo) suivi de ses champs sur fond gris, qui se déroulent quand le moyen est
   choisi. Seul le titre du moyen choisi est cerclé de noir. */
.pay-methods {
    position: relative;
    isolation: isolate;
}

/* Bordure grise de la liste, dessinée PAR-DESSUS le contenu (et non en border) :
   le cadre noir du titre choisi, encore au-dessus, la recouvre ainsi pixel pour
   pixel. */
.pay-methods::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 1;
    border: 1px solid var(--line);
    pointer-events: none;
}

.pay-head {
    position: relative;
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 16px;
    font-size: 15px;
    font-weight: 500;
    cursor: pointer;
    transition: background-color .25s ease;
}

.pay-method + .pay-method .pay-head {
    box-shadow: inset 0 1px 0 var(--line);
}

.pay-method.selected .pay-head {
    background: var(--surface);
}

.pay-head::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 2;
    border: 1px solid var(--text);
    opacity: 0;
    pointer-events: none;
    transition: opacity .25s ease;
}

.pay-method.selected .pay-head::after {
    opacity: 1;
}

.pay-brands {
    display: flex;
    gap: 6px;
    margin-left: auto;
}

.pay-brands svg {
    display: block;
    height: 22px;
    width: auto;
}

/* Déroulage : la hauteur passe de 0 à celle du contenu (grille 0fr → 1fr). Le
   contenu d'un moyen replié est aussi retiré du parcours au clavier. */
.pay-body {
    display: grid;
    grid-template-rows: 0fr;
    visibility: hidden;
    transition: grid-template-rows .3s ease, visibility 0s .3s;
}

.pay-method.selected .pay-body {
    grid-template-rows: 1fr;
    visibility: visible;
    transition: grid-template-rows .3s ease, visibility 0s;
}

.pay-clip {
    min-height: 0;
    overflow: hidden;
}

.pay-fields {
    padding: 16px;
    background: var(--surface);
}

.pay-fields p {
    margin: 0;
    font-size: 14px;
    font-weight: 300;
    color: var(--muted);
    text-align: center;
}

/* Un seul mode de livraison s'applique à la fois (selon le pays) : présenté
   comme une option déjà choisie. Le bouton radio remet à zéro les règles
   globales des <input> (largeur 100 %, marges), qui l'étireraient. */
.ship-option {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 14px 16px;
    border: 1px solid var(--text);
    background: var(--surface);
    font-size: 15px;
    font-weight: 500;
}

/* Rond de sélection dessiné à la main pour pouvoir l'animer : le point central
   grandit quand le bouton est coché. */
.ship-option input,
.pay-head input {
    position: relative;
    flex: none;
    width: 18px;
    height: 18px;
    margin: 0;
    padding: 0;
    border: 1.5px solid var(--field-label);
    border-radius: 50%;
    background: var(--bg);
    appearance: none;
    cursor: pointer;
    transition: border-color .2s ease;
}

.ship-option input::after,
.pay-head input::after {
    content: "";
    position: absolute;
    inset: 3px;
    border-radius: 50%;
    background: var(--text);
    transform: scale(0);
    transition: transform .2s ease;
}

.ship-option input:checked,
.pay-head input:checked {
    border-color: var(--text);
}

.ship-option input:checked::after,
.pay-head input:checked::after {
    transform: scale(1);
}

.ship-option span:first-of-type {
    flex: 1;
}

/* Récapitulatif : collé sous le header pendant qu'on remplit le formulaire.
   Le fond gris déborde à droite jusqu'au bord de l'écran (ombre décalée,
   rognée en haut et en bas par clip-path), comme un checkout classique.
   `grid-row: 2 / span 2` : occupe la hauteur des deux lignes de la seconde
   colonne (formulaire, puis bouton « Payer » dans .checkout-actions), sous le
   titre qui, lui, occupe seul la première ligne sur toute la largeur. */
.checkout-summary {
    grid-column: 2;
    grid-row: 2 / span 2;
    position: sticky;
    top: 88px;
    padding: 28px;
    background: var(--surface);
    box-shadow: 100vmax 0 0 var(--surface);
    clip-path: inset(0 -100vmax 0 0);
}

/* Titre du récapitulatif : sur grand écran un simple titre (le menu reste
   ouvert, voir checkout.js) ; sur écran étroit une ligne cliquable « Order
   summary v ........ total ». */
.summary-toggle {
    display: flex;
    align-items: center;
    gap: 8px;
    list-style: none;
    cursor: default;
}

.summary-toggle::-webkit-details-marker {
    display: none;
}

.summary-toggle h2 {
    margin: 0 0 14px;
}

.summary-chevron,
.summary-toggle-total {
    display: none;
}

/* Seule la liste défile : le sous-total/la livraison/le total (.summary-totals,
   hors de ce conteneur) restent toujours visibles, même avec beaucoup
   d'articles. Plafond fixe (~3 articles et demi) plutôt que dépendant de la
   hauteur d'écran : simple et prévisible, pas de calcul à recaler si les
   totaux changent de hauteur.
   Padding vertical à l'intérieur (pas à l'extérieur) : la pastille de
   quantité (.summary-qty, décalée de -8px au-dessus de la vignette) a besoin
   de cette marge DANS la zone qui défile, sinon elle se fait rogner par
   `overflow-y` dès la première image, avant même tout défilement. */
.summary-lines-scroll {
    max-height: 280px;
    overflow-y: auto;
    /* 20px : même écart que celui du bas (.summary-totals, padding-top ci-dessous,
       entre le filet et "Subtotal") — un seul rythme d'espacement cohérent
       autour des deux filets. */
    padding: 20px 0;
}

.summary-lines {
    list-style: none;
    margin: 0;
    padding: 0;
}

.summary-lines li {
    display: grid;
    grid-template-columns: auto 1fr auto;
    align-items: center;
    gap: 16px;
    margin-bottom: 16px;
    font-size: 15px;
}

/* Sans ça, le dernier article cumule son propre écart (16px ci-dessus) ET le
   padding-bottom de la zone de défilement (12px), pour un total incohérent
   avec l'écart entre deux articles. */
.summary-lines li:last-child {
    margin-bottom: 0;
}

.summary-thumb {
    position: relative;
}

.summary-thumb img {
    display: block;
    width: 64px;
    height: 64px;
    object-fit: cover;
    background: var(--surface);
}

/* Même police/graisse que la pastille du panier dans le header (.cart-badge,
   base.css) : sans-serif générique plutôt que la fonte de marque du site,
   plus lisible à cette taille. */
.summary-qty {
    position: absolute;
    top: -8px;
    right: -8px;
    display: grid;
    place-items: center;
    min-width: 20px;
    height: 20px;
    border-radius: 10px;
    background: var(--text);
    color: var(--bg);
    font-size: 12px;
    font-family: sans-serif;
}

/* Même graisse que le titre d'une ligne du panier (.cart-line-title, cart.css). */
.summary-item-title {
    font-weight: 400;
}

.summary-size {
    margin-top: 4px;
    color: var(--muted);
    font-size: 13px;
}

/* Pas de margin-top ici (le padding-bottom de .summary-lines-scroll ci-dessus
   fait déjà cet écart quand la liste tient entière) : quand elle ne tient
   pas, le filet touche directement la zone de défilement plutôt que de
   laisser un vide entre l'article coupé et lui — la liste donne alors
   l'impression de continuer derrière le filet, plutôt que de s'arrêter
   dans le vide. */
.summary-totals {
    margin: 0;
    padding-top: 20px;
    border-top: 1px solid var(--line);
}

/* `+ div` (pas juste `div`) : sans ça la première ligne (juste après le
   padding-top ci-dessus) recevait AUSSI ce margin-top, cumulant deux écarts
   différents (20 + 10 = 30px) au lieu d'un seul écart cohérent. */
.summary-totals div + div {
    margin-top: 10px;
}

.summary-totals div {
    display: flex;
    justify-content: space-between;
}

.summary-totals dt,
.summary-totals dd {
    margin: 0;
}

.summary-totals .summary-total {
    margin-top: 16px;
    font-size: 22px;
    font-weight: 500;
}

@media (max-width: 1000px) { /* lg */
    /* Plein cadre, comme le panier à 600px (voir CLAUDE.md, "Panier empilé") :
       le titre ET le formulaire défilent ENSEMBLE dans une même fenêtre
       (`.checkout-scroll`, pour laisser le plus de place possible au
       formulaire — contrairement au panier, où le titre reste fixe : le
       formulaire de paiement a beaucoup plus de champs que la liste du
       panier), le récapitulatif ET le bouton « Payer » (`.checkout-footer`)
       restent TOUJOURS visibles en bas de l'écran (au-dessus de la barre
       d'outils de Safari sur iPhone, `env(safe-area-inset-bottom)`). Même
       recette que .cart-page : #app perd son padding habituel et sa hauteur
       suit celle du contenu (`flex:1` sans base fixe) — .checkout-page prend
       le relais avec les siens. `flex: none` + `height` explicites sont TOUS
       LES DEUX nécessaires sur #app, pas juste l'un des deux : voir le
       commentaire détaillé de `#app:has(.cart-page...)` dans cart.css,
       exactement le même mécanisme (`flex-basis: 0%` implicite d'un `flex: 1`
       sans base ignore sinon complètement `height`).
       `100svh`, pas `100dvh` (corrigé après un signalement : un grand espace
       blanc apparaissait entre le header et le formulaire pendant le scroll
       sur mobile) — même cause que pour le hero de la home (voir CLAUDE.md,
       "100svh, pas 100dvh") : `dvh` recalcule cette hauteur EN CONTINU
       pendant que la barre d'adresse se rétracte au scroll, donc pendant
       qu'on défile DANS `.checkout-scroll` (`flex:1`, dont la hauteur suit
       directement celle de #app). Ici le titre défile AVEC le formulaire
       (contrairement au panier, où il est `flex:none`, hors de la zone qui
       grandit) : `#app`/`.checkout-scroll` qui grandissent pendant qu'on
       défile dedans exposaient du vide sous le contenu déjà affiché, le
       temps que le navigateur rattrape le `scrollTop`. `svh` (hauteur
       "petite", barre d'adresse supposée déployée) fixe cette hauteur une
       fois pour toutes, recalculée seulement à un vrai redimensionnement. */
    #app:has(.checkout-page:not(.empty-state)) {
        flex: none;
        height: 100svh;
        padding: 0;
    }

    /* Un seul enfant (`.checkout`) à cette largeur (le titre a rejoint
       `.checkout-scroll`, plus bas) : pas besoin de flex ici, juste lui
       laisser toute la hauteur. PAS de padding-top ici (contrairement au
       panier, `.cart-page`) : voir le commentaire de `.checkout-scroll`
       plus bas pour pourquoi ce même 88px doit vivre À L'INTÉRIEUR de la
       zone qui défile plutôt qu'au-dessus. */
    .checkout-page:not(.empty-state) {
        height: 100%;
        padding: 0 16px calc(16px + env(safe-area-inset-bottom));
    }

    /* `.checkout-scroll`/`.checkout-footer` redeviennent de vraies boîtes (plus
       `display: contents`, réservé au grand écran) : la grille de `.checkout`
       cède la place à une colonne flex de deux blocs, chacun un simple bloc
       normal en interne (le titre suivi du formulaire dans le premier ; le
       récapitulatif suivi du bouton dans le second — l'ordre du DOM suffit,
       pas besoin de `order`). `row-gap: 0` : `row-gap` s'applique aussi à
       flex (pas seulement grid) — sans ce reset, les 36px de la grille grand
       écran restaient actifs ici, entre `.checkout-scroll` et
       `.checkout-footer` (un espace vide "sans raison" en plus du filet du
       bas de `.checkout-scroll`, bug déjà rencontré une fois). Le filet en bas
       de `.checkout-scroll` et le padding en haut de `.checkout-footer`, plus
       bas, font déjà l'écart voulu à eux deux (même principe que
       `#cart-lines`/`.cart-bottom`, cart.css — un seul repère visuel plutôt
       qu'un espace flottant en plus). */
    .checkout {
        display: flex;
        flex-direction: column;
        align-items: stretch;
        row-gap: 0;
        min-height: 0;
        height: 100%;
        max-width: 500px;
        margin-inline: auto;
        width: 100%;
    }

    .checkout-scroll,
    .checkout-footer {
        display: block;
    }

    /* Seul ce bloc défile : `min-height: 0` est indispensable (un enfant flex
       ne rétrécit pas sous son contenu par défaut, ce qui empêcherait
       `overflow-y: auto` de jouer son rôle — le bloc pousserait la hauteur de
       `.checkout` au lieu de défiler dans l'espace qui lui est laissé, même
       piège que `#cart-lines`, cart.css). `overflow-x: hidden` EN PLUS de
       `overflow-y: auto` : poser un seul axe à une valeur autre que `visible`
       fait recalculer l'AUTRE axe en `auto` par la spécification CSS — sans ce
       `hidden` explicite, le moindre contenu ne serait-ce qu'1px plus large
       que le formulaire (un champ Stripe, sa liste de suggestions...) faisait
       apparaître un ascenseur horizontal sur toute cette zone. Le filet du bas
       est ici, sur le conteneur qui défile (pas sur `.checkout-footer` qui
       suit) — comme `#cart-lines { border-bottom }` — pour que le contenu
       défilant disparaisse pile à son niveau, sans laisser de bande vide entre
       la fin du formulaire et le filet. */
    .checkout-scroll {
        flex: 1;
        min-height: 0;
        overflow-y: auto;
        overflow-x: hidden;
        border-bottom: 1px solid var(--line);
        /* Le décalage sous le header (64px + 24px d'air, comme partout
           ailleurs) DOIT être un padding de CE conteneur (celui qui défile),
           pas de `.checkout-page` au-dessus de lui (essayé d'abord, l'ancienne
           recette) : un padding-top posé sur l'ANCÊTRE, hors de la zone
           `overflow-y: auto`, crée une bande statique qui ne défile jamais —
           le formulaire disparaissait alors pile au bord haut de
           `.checkout-scroll` (à 88px du haut, sous cette bande mate), pas
           sous le header (64px), un "cran" visible entre les deux, différent
           du reste du site où TOUT le contenu (padding-top de #app compris)
           fait partie du même flux qui défile et vient se faire recouvrir par
           le header. En mettant ce padding ICI, à l'intérieur du conteneur
           qui défile, il fait partie du contenu défilant comme n'importe quel
           autre : le formulaire remonte à travers lui en scrollant et vient
           disparaître exactement sous le header, comme sur une page normale
           (signalé une fois, corrigé). */
        padding-top: 88px;
    }

    .checkout .title-row {
        margin-bottom: 32px;
    }

    .checkout-form {
        /* Un peu d'air avant le filet : le dernier champ ne garde plus son
           propre écart (.checkout-form section:last-child, plus haut, pensé
           pour le row-gap de la grille grand écran) et la zone de défilement
           s'arrêterait sinon pile sur le dernier champ. */
        padding-bottom: 36px;
    }

    /* Pied fixe : même écart après le filet que celui du panier (16px,
       #cart-lines/.cart-bottom, cart.css), pour une seule convention
       d'espacement "après un filet de bas de zone défilante" sur le site. */
    .checkout-footer {
        flex: none;
        padding-top: 16px;
    }

    /* Récapitulatif déroulant, fermé au départ (syncSummary, checkout.js) —
       plus sticky en haut de page : il rejoint maintenant le bouton « Payer »
       dans le pied fixe, juste au-dessus de lui. Son propre filet du bas et
       l'écart avant lui (14px) reprennent exactement `.cart-note-details`
       (panier, cart.css), qui sépare ainsi son propre champ repliable du
       total/bouton qui le suit — même écart, pas juste le même principe. */
    .checkout-summary {
        position: static;
        padding: 0 0 14px;
        background: none;
        box-shadow: none;
        clip-path: none;
        border-bottom: 1px solid var(--line);
    }

    /* Déroulage du panneau (lignes + totaux) EN PLACE, dans le flux — pas en
       overlay par-dessus le formulaire comme avant (qui n'a plus de sens ici :
       le pied fixe a toute la place voulue pour grandir, ça réduit juste
       d'autant la fenêtre de défilement du formulaire au-dessus, exactement
       comme .cart-note-details/.cart-bottom). Même technique que .pay-body
       plus haut (grille 0fr → 1fr) plutôt qu'`animateDetails` : le panneau
       reste un FRÈRE de <details>, pas son enfant (voir le commentaire de
       checkout.js sur le `content-visibility` natif d'un <details> qui se
       ferme), donc `animateDetails` — qui anime la hauteur du <details>
       lui-même — n'a rien à animer ici. Le fondu d'opacité, séparé et plus
       COURT que celui de la hauteur, évite qu'un contenu qui dépasse de sa
       boîte (`.summary-qty`, décalée de -8px au-dessus de la vignette) reste
       visible, rogné à mi-hauteur, pendant la toute fin du repli — sans lui,
       ce fragment de pastille restait visible jusqu'à la dernière frame avant
       de disparaître d'un coup (bug déjà rencontré une fois). Ouverture :
       fondu retardé (le temps que la boîte ait assez grandi pour ne plus rien
       rogner) plutôt qu'instantané. */
    .summary-panel {
        display: grid;
        grid-template-rows: 0fr;
        visibility: hidden;
        opacity: 0;
        transition: grid-template-rows .3s ease, opacity .15s ease, visibility 0s .3s;
    }

    .summary-panel.open {
        grid-template-rows: 1fr;
        visibility: visible;
        opacity: 1;
        transition: grid-template-rows .3s ease, opacity .15s ease .15s, visibility 0s;
    }

    @media (prefers-reduced-motion: reduce) {
        .summary-panel,
        .summary-panel.open {
            transition: none;
        }
    }

    /* Rogné pendant l'animation de hauteur (grille 0fr), comme .pay-clip.
       PAS de padding ici : un padding posé directement sur l'élément qui doit
       collapser à 0 ne collapse jamais entièrement (contrairement à celui d'un
       DESCENDANT, que l'`overflow: hidden` du parent peut, lui, rogner en
       entier) — laissé par erreur ici lors du passage à cette recette, ça
       maintenait le panneau fermé à 20px de haut au lieu de 0, un espace vide
       "sans raison" visible entre le filet du haut et « Order summary »
       (l'espace après le filet du haut, .checkout-footer, s'additionnait à ce
       reste de hauteur). L'écart voulu après la liste (quand le panneau est
       ouvert) vient déjà de `.summary-lines-scroll { padding: 20px 0 }`, plus
       haut — un DESCENDANT, qui collapse correctement avec le reste. */
    .summary-panel-scroll {
        min-height: 0;
        overflow: hidden;
    }

    /* Même padding que `.cart-note-toggle` (panier, cart.css) — harmonise les
       deux barres repliables du site plutôt que les 16px, propres à cette
       page, qui gonflaient inutilement sa hauteur (voir le commentaire de
       .summary-panel-scroll ci-dessus). */
    .summary-toggle {
        padding: 4px 0;
        cursor: pointer;
    }

    .summary-toggle h2 {
        margin: 0;
        font-size: 17px;
        font-weight: 400;
    }

    /* Décalée vers le bas : le centre visuel du texte (hauteur des minuscules)
       est plus bas que le centre de sa ligne, sur laquelle flex aligne la flèche. */
    .summary-chevron {
        display: block;
        position: relative;
        top: 2px;
        transition: transform .15s ease;
    }

    .summary-box[open] .summary-chevron {
        transform: rotate(180deg);
    }

    .summary-toggle-total {
        display: block;
        margin-left: auto;
        font-size: 17px;
        font-weight: 500;
    }
}
