/* shop.css — galeries (originals/prints), fiche produit, panier. */

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

.page-header 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;
}

/* Grid & Cards ----------------------------------------------------------- */
/* Mosaïque originals : positionnement calculé en JS (layoutMasonry,
   js/pages/originals.js), pas des colonnes CSS (column-count). Les colonnes
   CSS natives ÉQUILIBRENT la hauteur totale entre colonnes, ce qui laisse un
   grand vide sous les colonnes courtes dès qu'un item est beaucoup plus haut
   que les autres — un masonry "empilé" (chaque colonne se remplit
   indépendamment, comme Pinterest) n'a pas ce défaut. max-width comme les
   autres pages (panier, contact...) : au-delà, les images afficheraient plus
   grand que leur résolution générée (1600px max, voir SIZES dans
   js/images.js) et deviendraient floues. */
.grid {
    position: relative;
    max-width: 1400px;
    margin: 0 auto;
}

/* Largeur de colonne fixe (auto-fill + largeur en px, pas de 1fr) : les
   cartes gardent une taille constante et n'étirent plus pour remplir la
   largeur de leur section. La largeur exacte dépend de la catégorie (carré
   comme référence : un paysage a une colonne plus large pour garder la même
   hauteur qu'un carré, voir PRINT_CATEGORIES/PRINT_REFERENCE dans
   js/pages/prints.js) — posée en style inline par section plutôt qu'ici. Le
   ratio de chaque image est aussi posé en style inline par catégorie ;
   object-fit:cover fait le recadrage. row-gap plus grand que le column-gap :
   l'écart vertical vers la carte suivante doit se voir plus que l'écart
   interne titre/sous-texte (4px). */
.prints-grid {
    display: grid;
    gap: 32px 16px
}

.print-card {
    position: relative
}

.card {
    position: relative;
    background: #fff;
}

.card .thumb {
    position: relative;
    overflow: hidden;
    background: var(--placeholder-bg)
}

/* Pas de aspect-ratio fixe ici : chaque item pose son propre ratio en style
   inline, calculé depuis ses dimensions réelles (height/width en cm, voir
   renderOriginalGrid, js/pages/originals.js) — une photo de tableau cadrée
   serré suit d'assez près le ratio physique de la toile, donc ça réserve un
   espace de chargement proche du rendu final (pas de saut de mise en page)
   tout en gardant un ratio propre à chaque pièce plutôt qu'un recadrage
   uniforme. */
.card img {
    display: block;
    width: 100%;
    height: auto;
    object-fit: cover;
    background: var(--placeholder-bg);
    transition: opacity .25s ease, transform .25s ease
}

.disabled-img {
    filter: grayscale(80%);
    opacity: 0.5;
}

.meta {
    padding-top: 10px
}

.title {
    font-family: "dazzle-unicase", sans-serif;
    font-weight: 300
}

/* Titre en gras uniquement dans la grille originals (pas .product .title,
   qui reste à la graisse par défaut ailleurs). */
.card .title {
    font-weight: 700;
}

/* Sous-texte sous le titre d'une carte originals — "date, hauteur x largeur,
   nature" (voir renderOriginalGrid, js/pages/originals.js). Les cartes
   prints n'ont pas cette ligne (le stock n'est pas affiché publiquement). */
.card .details {
    color: var(--muted);
    font-size: 16px;
    line-height: 1.2;
    margin-top: 4px;
}

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

/* Mention livraison UE (page panier + fiche print) : lue comme une note de
   bas de page (italique, préfixée "* " en JS) plutôt qu'un composant d'UI,
   en écho à un "*" posé sur "Add to cart"/le mot "shipping" à l'endroit
   précis qu'elle concerne. Pas de fond ni de couleur d'alerte (--danger) :
   un fond plein donnait un faux-affordance de bouton cliquable à côté des
   vraies actions ("Add to cart", "View cart"), et c'est une info, pas un
   avertissement. `display:block` + `margin:auto` (pas `inline-block`) : se
   centre tout seul quel que soit l'alignement du parent (la fiche produit
   print, .meta, n'est pas centrée). */
.shipping-notice {
    display: block;
    width: fit-content;
    color: var(--muted);
    font-size: 13px;
    font-weight: 400;
    font-style: italic;
    margin: 10px auto;
}

/* Badge — porte le prix en permanence, et devient "prix barré + SOLD OUT"
   une fois le tableau vendu (voir .badge-price). Utilisé aussi tel quel par
   la grille prints ("Out of stock", sans prix dedans). */
.badge {
    position: absolute;
    left: 12px;
    top: 12px;
    background: #fff;
    padding: 10px 14px;
    font-size: 12px;
    font-family: "dazzle-unicase", sans-serif;
    font-weight: 500;
    letter-spacing: .03em;
}

/* Rayure dessinée à la main plutôt que `text-decoration: line-through` : son
   offset dépend des métriques du webfont et ne tombe pas au milieu visuel du
   texte — un trait positionné à 50% de la hauteur de ligne via ::after est
   indépendant de la police, donc toujours centré. */
.badge .badge-price {
    position: relative;
    color: var(--muted);
    margin-right: 6px;
}

.badge .badge-price::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    top: 50%;
    height: 1px;
    background: var(--muted);
    transform: translateY(-50%);
}

/* Sections prints par format (carré / portrait / paysage / tall / wide), au
   lieu de la mosaïque des originals. Une section masquée entièrement si vide
   (voir renderPrints, js/pages/prints.js). Même max-width que .grid/.product,
   portée par le wrapper plutôt que .prints-grid directement, pour ne pas la
   répéter sur chaque section. */
.prints-category {
    max-width: 1400px;
    margin: 0 auto 56px;
}

.prints-category:last-child {
    margin-bottom: 0;
}

.prints-category h2 {
    font-family: "dazzle-unicase", sans-serif;
    font-weight: 500;
    font-size: 22px;
    margin: 0 0 20px;
}

/* Carousel / Thumbnails ------------------------------------------------- */
.carousel {
    display: flex;
    flex-direction: column;
    gap: 12px
}

.carousel-main,
.product-main {
    position: relative;
}

/* Fond blanc, pas le gris clair utilisé comme placeholder de chargement
   ailleurs (grilles, panier) : les photos ici sont en object-fit:contain
   dans un cadre 1:1, donc un éventuel "letterboxing" (photo pas exactement
   carrée) reste visible en permanence après le chargement, pas juste pendant
   — en gris ça ressemblait à une bordure sale autour de l'image, en blanc ça
   se fond dans le fond de page. */
.carousel-main .viewer,
.product-main .viewer {
    width: 100%;
    aspect-ratio: 1/1;
    overflow: hidden;
    position: relative;
    background: #fff;
    cursor: zoom-in; /* clic -> overlay zoom, voir overlays.css / js/lightbox.js */
}

.carousel-main img,
.product-main img {
    width: 100%;
    height: 100%;
    object-fit: contain
}

.carousel-thumbs {
    display: flex;
    gap: 8px;
    justify-content: center
}

.carousel-thumbs img {
    width: 80px;
    height: 80px;
    object-fit: cover;
    background: var(--placeholder-bg);
    cursor: pointer;
    border: 2px solid transparent
}

.carousel-thumbs img.active {
    border-color: #000
}

.carousel .carousel-nav {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: space-between;
    pointer-events: none
}

.carousel .carousel-nav button {
    pointer-events: auto;
    background: #000;
    color: #fff;
    border: 0;
    font-family: "dazzle-unicase", sans-serif;
    font-size: 32px;
    font-weight: 300;
    padding: 12px 18px;
    cursor: pointer
}

.carousel .carousel-nav button:hover {
    background: #333;
}

/* Product page ---------------------------------------------------------- */
/* max-width : sans ça, l'image principale (.viewer) s'étire à la largeur de
   #product-left sur un grand écran, au-delà de la résolution générée (1600px
   max, voir SIZES dans js/images.js) — le navigateur agrandit alors l'image
   au-delà de ses pixels réels, visiblement flou. */
.product {
    max-width: 1400px;
    margin: 0 auto;
    display: flex;
    gap: 32px;
    align-items: flex-start;
    padding: 0 16px
}

.product-left {
    flex: 4
}

.product-right {
    flex: 3
}

.product .product-link {
    display: block;
    margin: 14px auto;
    text-align: center;
    background: #000;
    color: #fff;
    padding: 10px 20px;
    text-decoration: none;
    font-size: 16px;
    font-weight: 300;
    letter-spacing: .08em
}

.product .product-link:hover,
.product .product-link:focus {
    background: #333;
    outline: none
}

.product .product-link.disabled,
.product .product-link:disabled {
    pointer-events: none;
    background: var(--disabled-bg);
    cursor: not-allowed;
}

/* "Add to cart", posé à côté du stepper de quantité plutôt qu'en pleine
   largeur comme les autres .product-link (Contact me to buy, SOLD...) —
   hauteur alignée sur --control-h pour matcher exactement le stepper juste à
   côté, centrage par flex plutôt que padding/line-height pour rester fiable
   quel que soit le texte affiché ("Add to cart" / "Added ✓" / "Out of
   stock"). `flex:1` : prend toute la largeur restante de sa ligne à côté du
   stepper (qui garde sa taille fixe). */
#add-to-cart-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    height: var(--control-h);
    margin: 0;
    flex: 1;
}

.product-price {
    font-size: 28px;
    font-weight: 700;
    color: var(--text)
}

.product-divider {
    border: none;
    border-top: 1px solid var(--border);
    margin: 12px 0
}

.product-description {
    color: var(--muted);
    font-size: 15px;
    line-height: 1.6;
    margin: 0;
}

/* "Size:" à côté des boutons plutôt qu'au-dessus : un seul flex-wrap partagé
   entre le label et le groupe de boutons — tant qu'il y a la place, les deux
   tiennent sur une ligne (centrée) ; dès que ça manque de largeur,
   `.size-buttons` (2e enfant flex) repasse tout seul à la ligne suivante,
   sous le label, sans media query dédiée. */
.size-selector {
    margin-top: 14px;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 10px;
    flex-wrap: wrap;
}

.size-buttons {
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
    justify-content: center;
}

/* Size buttons for prints — délibérément distinct des boutons carrés noirs
   (add to cart, qty-stepper, carousel) : un bouton de taille rempli de noir
   se lisait comme une action ("acheter"), pas comme une simple sélection de
   format. Non-sélectionné = gris clair discret, sélectionné = fond blanc +
   bordure noire épaisse (accent, pas une action). `border` transparent par
   défaut (même épaisseur des deux côtés) pour éviter un micro-décalage de
   layout au moment de la sélection. */
.size-btn {
    background: var(--secondary-bg);
    color: #666;
    border: 2px solid transparent;
    padding: 8px 12px;
    cursor: pointer;
}

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

.size-btn.selected {
    background: #fff;
    color: #000;
    border-color: #000;
}

/* "View cart →" sur la fiche produit print, "Browse prints →" sur le panier
   vide : même famille visuelle que .size-btn (boîte grise discrète, action
   secondaire) plutôt que le noir plein de "Add to cart"/.product-link, pour
   ne pas rivaliser avec l'action principale juste au-dessus. */
.secondary-action {
    display: inline-block;
    background: var(--secondary-bg);
    color: var(--text);
    text-decoration: none;
    padding: 8px 16px;
    font-size: 14px;
    font-weight: 500;
}

.secondary-action:hover {
    background: var(--secondary-bg-hover);
}

.desc,
body,
p,
input,
textarea,
.meta {
    font-weight: 200
}

/* Cart nav badge ----------------------------------------------------------- */
.cart-link {
    position: relative;
}

.cart-icon {
    width: 20px;
    height: 20px;
    display: block;
}

.cart-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 16px;
    height: 16px;
    padding: 0 4px;
    margin-left: 4px;
    border-radius: 999px;
    background: #000;
    color: #fff;
    font-size: 10px;
    font-family: sans-serif;
    vertical-align: top;
}

/* [hidden] perd contre n'importe quelle règle d'auteur qui pose un display
   (ici display:flex juste au-dessus), quelle que soit la spécificité
   relative habituelle, parce que la feuille de l'agent utilisateur (où vit
   la règle par défaut [hidden]{display:none}) passe toujours après les
   règles d'auteur dans la cascade — sans cette règle, un panier vide
   affiche "0" en permanence. */
.cart-badge[hidden] {
    display: none;
}

/* Related products (original <-> print cross-link) ------------------------ */
.related-products h3 {
    font-family: "dazzle-unicase", sans-serif;
    font-weight: 400;
    font-size: 16px;
    margin-bottom: 10px;
}

.related-card {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    text-decoration: none;
    color: var(--text);
}

.related-card img {
    width: 64px;
    height: 64px;
    object-fit: cover;
    background: var(--placeholder-bg);
}

.related-card .related-title {
    font-family: "dazzle-unicase", sans-serif;
    font-weight: 300;
}

/* Quantity stepper "[-] qty [+]" (product page + cart lines), même esprit
   carré noir que .carousel-nav button. Hauteur alignée sur --control-h pour
   matcher le bouton "Add to cart" juste à côté et .cart-line-remove (rouge,
   voir plus bas). Les symboles "-"/"+" ne sont PAS des caractères de police :
   même en ASCII, le glyphe "-" et le glyphe "+" ne sont ni de la même taille
   visuelle ni centrés pareil dans la boîte du bouton (métriques de police
   hors de notre contrôle). Dessinés en CSS via ::before/::after à la place :
   deux barres `--icon-size` identiques, centrées avec
   `transform: translate(-50%,-50%)` — garanti pixel-parfait et strictement
   identique entre les deux boutons, quelle que soit la police chargée. */
.qty-stepper {
    display: inline-flex;
    align-items: stretch;
    height: var(--control-h);
    flex-shrink: 0;
}

.qty-btn {
    position: relative;
    width: var(--control-h);
    height: var(--control-h);
    background: #000;
    color: #fff;
    border: 0;
    padding: 0;
    cursor: pointer;
}

/* Grisé au plancher (qté 1, "-") ou au plafond (stock atteint, "+") — voir
   wireQtySteppers dans js/cart-store.js, qui bascule l'attribut natif
   `disabled` plutôt qu'une classe. Même gris que les autres contrôles
   désactivés (--disabled-bg), pas une nuance différente par contrôle. */
.qty-btn:disabled {
    background: var(--disabled-bg);
    cursor: not-allowed;
    pointer-events: none;
}

/* Un cran plus foncé que le fond actif (--secondary-bg, juste en dessous)
   pour rester distinguable au premier coup d'œil une fois grisé. */
.qty-stepper .qty-input:disabled {
    background: var(--secondary-bg-hover);
    color: var(--muted);
}

.qty-btn:hover {
    background: #333;
}

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

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

.qty-increment::after {
    width: 2px;
    height: var(--icon-size);
    transform: translate(-50%, -50%);
}

/* Fond gris "secondaire" (--secondary-bg, même famille que
   .secondary-action/.size-btn), pas celui des placeholders de chargement :
   sémantique différente (boîte d'UI discrète, pas un état de chargement).
   Reste plus clair que les boutons -/+ désactivés (--disabled-bg) et que
   l'input lui-même une fois désactivé (--secondary-bg-hover, juste
   au-dessus) : l'input actif doit rester visuellement le plus "vivant" des
   trois. */
.qty-stepper .qty-input {
    width: 48px;
    height: var(--control-h);
    text-align: center;
    background: var(--secondary-bg);
    border: 0;
    margin: 0;
    padding: 0;
    -moz-appearance: textfield;
}

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

/* Cart page ----------------------------------------------------------------- */
/* #app n'a pas de max-width (les grilles s'étirent volontairement sur toute
   la largeur) : sans ça, une liste de lignes de panier s'étire aussi sur un
   écran ultrawide, ce qui n'a pas de sens pour une mise en page en une
   colonne. */
.cart-page {
    max-width: 720px;
    margin: 0 auto;
}

.cart-lines {
    display: flex;
    flex-direction: column;
    gap: 16px;
    margin-top: 20px;
}

.cart-line {
    display: flex;
    align-items: center;
    gap: 14px;
    padding-bottom: 16px;
    border-bottom: 1px solid var(--border);
}

.cart-line-thumb img {
    width: 72px;
    height: 72px;
    object-fit: cover;
    display: block;
    background: var(--placeholder-bg);
}

.cart-line-info {
    flex: 1;
}

.cart-line-subtotal {
    min-width: 80px;
    text-align: right;
    font-weight: 500;
}

/* Croix en SVG (`background-image`, `stroke-linecap: round`) plutôt qu'un
   caractère ou des barres CSS tournées à ±45° : une ligne fine sous rotation
   CSS s'anti-aliase sur des pixels non-entiers et rend flou, contrairement à
   `.qty-btn` dont les barres +/- restent horizontales/verticales. Fond rouge
   (--danger) pour signaler une action destructive, à la place du noir
   partagé avec les autres contrôles. */
.cart-line-remove {
    width: var(--control-h);
    height: var(--control-h);
    min-width: var(--control-h);
    background-color: var(--danger);
    background-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='white'%20stroke-width='3'%20stroke-linecap='round'%3E%3Cline%20x1='6'%20y1='6'%20x2='18'%20y2='18'/%3E%3Cline%20x1='18'%20y1='6'%20x2='6'%20y2='18'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: center;
    background-size: 16px 16px;
    padding: 0;
    border: 0;
    flex-shrink: 0;
    cursor: pointer;
}

.cart-line-remove:hover {
    background-color: var(--danger-hover);
}

.cart-total {
    display: flex;
    justify-content: space-between;
    max-width: 320px;
    margin-left: auto;
    margin-top: 20px;
    font-size: 20px;
    font-weight: 700;
    padding-top: 12px;
    border-top: 1px solid var(--border);
}

@media (max-width:600px) {
    .cart-line {
        flex-wrap: wrap;
    }

    .cart-line-subtotal {
        text-align: left;
    }
}
