/* components.css — briques partagées par plusieurs pages : en-tête de page, cadre
   d'image cliquable, titre/prix/pastille de carte, boutons, liens, flèches de
   défilement, sélecteur de quantité. */

.page-header {
    text-align: center;
    margin-bottom: 32px;
}

/* Titre de page : même taille partout (le lien à droite du panier et du paiement,
   ou le message d'une page vide, n'y change rien). */
.page-header h1,
.title-row h1,
.empty-state h1 {
    font-size: 40px;
}

.page-header .page-intro {
    margin: 12px auto 0;
    max-width: 560px;
    color: var(--muted);
    font-size: 20px;
    line-height: 1.5;
    font-weight: 200;
}

/* Cadre d'image cliquable (galeries, "My work", produits similaires) : léger
   zoom sur place au survol, rogné par le cadre (overflow:hidden — sans
   display:block, un <a> inline ne rogne rien). Le zoom s'anime avec la
   transition de .fade-rise (images.css), portée par les mêmes images.
   L'image est en block : en inline elle laisse un blanc de ligne sous elle,
   dans lequel le zoom déborderait visiblement. Le zoom se déclenche au survol
   de toute la carte, pas seulement de l'image.
   Pas de aspect-ratio fixe ici : chaque page pose le ratio de ses images en
   style inline (dimensions réelles du tableau, catégorie du print...), ce qui
   réserve l'espace avant le chargement (pas de saut de mise en page) ;
   object-fit:cover recadre. */
.zoom-frame {
    display: block;
    overflow: hidden;
}

.zoom-frame img {
    display: block;
    width: 100%;
    object-fit: cover;
    background: var(--surface);
}

/* Seulement avec un vrai survol : sur écran tactile :hover reste collé après
   un tap. */
@media (hover: hover) {
    .zoom-frame:hover img,
    :is(.original-card, .print-card, .similar-card):hover .zoom-frame img {
        transform: scale(1.02);
    }
}

/* Titre d'une carte : lien comme l'image, souligné dès qu'on survole la carte
   pour signaler qu'elle est cliquable — même soulignement pour le titre d'une
   ligne du panier (.cart-line-title, plus bas). Le ::after du titre étire
   son lien sur toute la carte (lien étiré) : toute la surface est cliquable,
   curseur main compris, y compris le blanc autour du titre. */
.card-title {
    display: inline-block;
    font-family: "dazzle-unicase", sans-serif;
    font-weight: 300;
    text-decoration: none;
    text-underline-offset: 3px;
}

.original-card .card-title::after,
.print-card .card-title::after {
    content: "";
    position: absolute;
    inset: 0;
}

:is(.original-card, .print-card, .similar-card):hover .card-title,
.cart-line-title:hover {
    text-decoration: underline;
}

.price {
    color: var(--muted);
    margin-top: 6px;
}

/* Titre de section (h2) : rangées de la page prints, « You may also like ». Les
   marges sont propres à chaque page. */
.prints-category h2,
.similar h2 {
    font-family: "dazzle-unicase", sans-serif;
    font-weight: 500;
    font-size: 22px;
}

/* Sous-titre de page en greycliff (la police du texte) : pages policies et page
   de paiement. */
.policy-page h2,
.checkout-form h2,
.checkout-summary h2 {
    font-family: "greycliff-cf", sans-serif;
    font-weight: 500;
    font-size: 22px;
}

/* Pastille "SOLD OUT" / "OUT OF STOCK" des galeries : le prix est sous le
   titre, la pastille n'apparaît que pour un article indisponible. */
.card-badge {
    position: absolute;
    left: 12px;
    top: 12px;
    background: var(--bg);
    padding: 10px 14px;
    font-size: 12px;
    font-family: "dazzle-unicase", sans-serif;
    font-weight: 500;
    letter-spacing: .03em;
}

.slider-nav {
    display: flex;
    justify-content: center;
    align-items: center;
    gap: 18px;
    margin-top: 14px;
    font-size: 13px;
    color: var(--muted);
}

/* Chiffres à chasse fixe : sans ça, un "1" (plus étroit que les autres
   chiffres dans une fonte à chasse variable) fait légèrement sauter les
   flèches de chaque côté (`justify-content: center`) dès qu'on avance ou
   recule au-delà de "1/n". */
.slider-count {
    font-variant-numeric: tabular-nums;
}

.slider-nav[hidden] {
    display: none;
}

.slider-nav button {
    display: inline-flex;
    padding: 6px 10px;
    background: none;
    color: var(--text);
}

.slider-nav button:disabled {
    color: var(--disabled);
    cursor: default;
}

/* Rangée d'actions d'une fiche produit : stepper de quantité et bouton côte à côte. */
.product-actions {
    display: flex;
    gap: 12px;
    margin-top: 24px;
}

/* Bouton (secondaire) : contour noir, se remplit au survol. Hauteur alignée sur
   --control-h pour matcher le stepper de quantité juste à côté ; centrage par
   flex (fiable quel que soit le texte : "Add to cart" / "Added ✓" / "Out of
   stock"). */
.btn {
    flex: 1;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    height: var(--control-h);
    padding: 0 20px;
    background: var(--bg);
    color: var(--text);
    border: 1px solid var(--text);
    text-decoration: none;
    font-size: 15px;
    font-weight: 500;
    letter-spacing: .04em;
    cursor: pointer;
    outline: 1px solid transparent;
    outline-offset: 2px;
    transition: background .15s ease, color .15s ease, outline-color .15s ease;
}

.btn:hover {
    background: var(--text);
    color: var(--bg);
}

/* Bouton principal : action directe (envoyer, passer au paiement, payer), plein
   noir, à la hauteur des champs de saisie. Les autres .btn sont secondaires
   (ajouter au panier, se déplacer). Au survol, le fond ne change pas : un contour
   noir se détache du bouton. */
.btn.primary {
    height: var(--field-h);
    background: var(--text);
    color: var(--bg);
}

.btn.primary:hover {
    outline-color: var(--text);
}

.btn:disabled {
    background: var(--bg);
    color: var(--muted);
    border-color: var(--disabled);
    cursor: not-allowed;
    pointer-events: none;
}

.btn.primary:disabled {
    background: var(--text);
    color: var(--bg);
    border-color: var(--text);
    opacity: .5;
}

.btn.added:disabled {
    background: var(--text);
    color: var(--bg);
    border-color: var(--text);
}

.text-link {
    display: inline-block;
    margin-top: 14px;
    font-size: 14px;
    text-decoration: underline;
    text-underline-offset: 3px;
    transition: color .15s ease;
}

.text-link:hover {
    color: var(--muted);
}

/* Rangée à défilement horizontal (doigt/molette) avec accroche par carte,
   partagée par la galerie prints (.prints-grid, catalog.css) et le slider
   mobile des fiches produit (.slider-track, product.css) — les deux ne
   diffèrent que par leur `gap`/`padding-inline`, gardés dans leur feuille. */
.scroll-row-x {
    display: flex;
    overflow-x: auto;
    /* Sans ça, `overflow-x: auto` force `overflow-y` à `auto` aussi (règle
       CSS : un seul axe ne peut pas rester `visible` si l'autre ne l'est
       pas) — un scroll vertical apparaissait pendant le fondu + translateY
       d'un texte qui dépasse temporairement la hauteur de la rangée. */
    overflow-y: hidden;
    scroll-snap-type: x mandatory;
    scrollbar-width: none;
}

.scroll-row-x::-webkit-scrollbar {
    display: none;
}

/* Liens au milieu d'un texte : soulignés. */
.accordion-body a,
.product-shipping a,
.cart-summary-note a,
.policy-page a,
.checkout-terms a,
.contact-page p a,
.empty-state p a {
    text-decoration: underline;
    text-underline-offset: 3px;
}

/* Quantity stepper "[-] qty [+]" (fiche print + lignes du panier) : simple
   cadre fin, boutons transparents — plus de fond noir/gris qui changeait
   selon l'état. L'état "au plancher/plafond" ne fait que griser le symbole.
   Les symboles "-"/"+" ne sont PAS des caractères de police (glyphes de
   tailles/centrages différents) : deux barres CSS de même longueur
   (`--qty-icon-size`), positionnées en calc() sur des pixels entiers plutôt que
   par translate(-50%) (qui tombe sur un demi-pixel avec une barre de 1px et
   la rend floue). */
.qty-stepper {
    display: inline-flex;
    align-items: stretch;
    height: var(--control-h);
    border: 1px solid var(--muted);
    flex-shrink: 0;
}

.qty-btn {
    position: relative;
    width: var(--control-h);
    height: 100%;
    background: transparent;
    color: var(--text);
    border: 0;
    padding: 0;
    cursor: pointer;
}

.qty-btn:hover {
    background: var(--hover-bg);
}

.qty-btn:disabled {
    color: var(--disabled);
    background: transparent;
    cursor: not-allowed;
    pointer-events: none;
}

.qty-btn::before,
.qty-btn::after {
    content: '';
    position: absolute;
    background: currentColor;
}

/* Barre horizontale : le "-" à elle seule, la branche du "+" avec ::after. */
.qty-btn::before {
    width: var(--qty-icon-size);
    height: 1px;
    left: calc(50% - var(--qty-icon-size) / 2);
    top: calc(50% - .5px);
}

.qty-increment::after {
    width: 1px;
    height: var(--qty-icon-size);
    left: calc(50% - .5px);
    top: calc(50% - var(--qty-icon-size) / 2);
}

.qty-stepper .qty-input {
    width: 44px;
    height: 100%;
    text-align: center;
    background: transparent;
    color: var(--text);
    font-weight: 300;
    border: 0;
    margin: 0;
    padding: 0;
    -moz-appearance: textfield;
}

.qty-stepper .qty-input:disabled {
    color: var(--muted);
}

/* Stepper entièrement grisé (print épuisé). */
.qty-stepper:has(.qty-input:disabled) {
    border-color: var(--disabled);
}

.qty-stepper .qty-input::-webkit-outer-spin-button,
.qty-stepper .qty-input::-webkit-inner-spin-button {
    -webkit-appearance: none;
    margin: 0;
}

/* Titre de page + lien à droite (panier, paiement). */
.title-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 16px;
}

/* .text-link porte un margin-top pensé pour son autre usage (sous un bouton,
   fiche produit print) : ici, à côté du h1 dans une ligne déjà centrée par
   align-items, ce même margin le décale visiblement plus bas que le titre. */
.title-row .text-link {
    margin-top: 0;
}

/* Page sans contenu (panier vide, page introuvable...) : message centré, bouton en
   dessous. */
.empty-state {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 28px;
    text-align: center;
}

.empty-state p {
    margin: 0;
}

/* Message affiché pendant le chargement du catalogue ou d'un paiement. */
.loading-message {
    text-align: center;
    color: var(--muted);
    padding: 80px 0;
}

/* Message sous un formulaire : erreur (paiement, contact) ou confirmation d'envoi. */
.form-error,
.form-success {
    margin: 12px 0 0;
    font-size: 14px;
    font-weight: 300;
}

.form-error {
    color: var(--error);
}

/* Boutons qui ne s'étirent pas dans une colonne : largeur de leur texte. */
.empty-state .btn,
.similar-more .btn,
.home-work-actions .btn,
.contact-form .btn {
    flex: none;
    min-width: 160px;
    padding: 0 40px;
}

@media (max-width: 600px) { /* sm */
    .page-header h1,
    .title-row h1,
    .empty-state h1 {
        font-size: 28px;
    }
}
