/* ==========================================================
   card-slab.css — Boîtier « Ultra collector » (slab type PSA)
   Composant autonome (partial shared/card-slab.php).

   Toutes les dimensions internes sont en CQW (container query
   width, container = .card-visual--slab, base 424px = 100cqw) :
   le boîtier scale de façon parfaitement cohérente à toute
   largeur, comme les cartes elles-mêmes.

   NB 3D : le container-type est porté par le WRAPPER (ancêtre de
   la scène 3D) — jamais par un élément de la chaîne scène →
   flipper → faces, sinon le contexte 3D serait aplati.
   ========================================================== */

/* ── Wrapper racine (vue interactive) : frontière entre l'OBJET 3D (carte
   ou boîtier, qui bouge) et l'UI fixe (bouton info, positionné en absolute
   par rapport à ce wrapper). Posé par card-visual.php. ── */
.card-visual {
    position: relative;
    width: fit-content;
    max-width: 100%;
    margin: 0 auto;
}

.card-visual--slab {
    /* Largeur EXPLICITE (pas 100%) : le containment (container-type) empêche
       la largeur de venir du contenu, et le parent public est un flex item
       dimensionné au contenu — un % créerait une boucle résolue trop étroite.
       La largeur est calibrée PAR TEMPLATE pour que le boîtier soit fit avec
       la carte : largeur carte native ÷ (1 − chrome cqw du boîtier ~10.4%). */
    width: min(var(--slab-width, 384px), calc(100vw - 20px));
    container-type: inline-size;
    container-name: slab;
}

/* Les deux templates actuels (default ET padel) ont des cartes de 340px →
   boîtier 384px pour tous. Un futur template avec une carte plus large
   surcharge --slab-width sur sa classe .card-visual--tpl-<template>. */

/* Contextes à largeur définie (colonne de grille, preview d'édition, aperçu
   consentement) : LA CARTE GARDE LA TAILLE DE LA COLONNE — même taille que
   ses voisines sans boîtier — et c'est la coque qui DÉBORDE en marges
   négatives, par-dessus les gouttières. Le facteur vient du chrome du
   boîtier : carte = boîtier × 0.896 − 4px (paddings 2.8cqw + 2.4cqw +
   bordures) → boîtier = colonne × 1.116 + 4.5px. */
.app-card-edit-layout__preview .card-visual--slab,
.app-consent-card-preview .card-visual--slab {
    width: calc(111.6% + 4.5px);
    max-width: none; /* le max-width:100% de .card-visual annulerait le débord */
    margin-left: calc(-5.8% - 2.25px);
    margin-right: calc(-5.8% - 2.25px);
}

/* Quand le layout d'édition passe en 1 colonne (≤992px, cf. cards.css), le
   preview devient pleine largeur et le débord -5.8% du slab le fait dépasser le
   viewport (ex : 826px à 768px → scroll horizontal). On cape alors le boîtier à
   une largeur de carte et on le centre. (Placé AVANT le bloc @430 pour que les
   téléphones gardent leur réglage dédié.) */
@media (max-width: 992px) {
    .app-card-edit-layout__preview .card-visual--slab {
        width: min(var(--slab-width, 384px), calc(100vw - 2 * var(--app-spacer)));
        margin-left: auto;
        margin-right: auto;
    }
}

/* En GRILLE, le débord doit rester sous le demi-gap (.app-ball-grid :
   gap = 2 x --app-spacer = 32px → 16px max par côté) pour que deux boîtiers
   adjacents ne se chevauchent jamais. La coque s'affine (chrome 1.8 + 1.6cqw
   au lieu de 2.8 + 2.4) : la carte garde 100 % de la colonne et le débord
   tombe à ~12px par côté (≤ 16px jusqu'à des colonnes de 380px). */
.app-trading-card-link .card-visual--slab {
    width: calc(107.3% + 4.3px);
    max-width: none;
    margin-left: calc(-3.65% - 2.15px);
    margin-right: calc(-3.65% - 2.15px);
}

.app-trading-card-link .as-slab {
    padding: 1.8cqw;
    border-radius: 4.2cqw;
}

.app-trading-card-link .as-slab__case {
    padding: 1.6cqw;
    border-radius: 3.2cqw;
}

.app-trading-card-link .as-slab__label {
    margin-bottom: 1.8cqw;
}

/* Dans une grille cliquable, le boîtier ne capte pas les interactions
   carte (toute la tuile est un lien). */
.app-trading-card-link .as-slab-backcard,
.app-trading-card-link .card-visual--slab {
    pointer-events: none;
}
.app-trading-card-link {
    pointer-events: auto;
}

/* La scène porte la perspective : c'est la BOÎTE entière qui s'incline
   et se retourne (trading-card.js anime .as-slab-flipper). */
.as-slab-scene {
    perspective: 1000px;
    width: 100%;
}

/* Flipper de boîtier : deux faces physiques (avant / arrière), comme un
   vrai slab qu'on retourne. */
.as-slab-flipper {
    position: relative;
    width: 100%;
    transform-style: preserve-3d;
    will-change: transform;
}

/* Une FACE du boîtier (la coque plexiglas). */
.as-slab {
    width: 100%;
    position: relative;
    border-radius: 5.2cqw;
    padding: 2.8cqw;
    /* PAS de backface-visibility ici : la face visible est entièrement
       pilotée par .is-flipped (ci-dessous). Sur certaines machines le cull
       backface est faux et masquerait aussi la face arrière légitime. */
    /* Plexiglas : translucide, le fond de page transparaît. */
    background: linear-gradient(
        160deg,
        rgba(255, 255, 255, 0.30) 0%,
        rgba(255, 255, 255, 0.08) 40%,
        rgba(255, 255, 255, 0.05) 65%,
        rgba(255, 255, 255, 0.22) 100%
    );
    border: 1px solid rgba(255, 255, 255, 0.35);
    /* NB : pas de backdrop-filter ici — il aplatirait le contexte 3D. */
    /* Ombre du boîtier « ultra collector » : multi-couches (smooth), plus
       marquée que la carte simple (le boîtier est plus épais). */
    box-shadow:
        0 2px 4px rgba(0, 0, 0, 0.08),
        0 6px 12px rgba(0, 0, 0, 0.12),
        0 14px 28px rgba(0, 0, 0, 0.16),
        0 28px 56px rgba(0, 0, 0, 0.22),
        inset 0 1px 0 rgba(255, 255, 255, 0.45);
}

/* Face ARRIÈRE : superposée, pré-tournée — montre l'étiquette dos et la
   réplique du dos de carte quand le boîtier est retourné. */
.as-slab--back {
    position: absolute;
    inset: 0;
    transform: rotateY(180deg);
    display: flex;
    flex-direction: column;
}

/* La face visible est pilotée EXPLICITEMENT par .is-flipped — posée par
   trading-card.js à L'ANGLE RÉEL de la rotation (lecture de la matrice de
   transform à chaque frame) : la bascule tombe pile quand la boîte est de
   profil, donc invisible. Pas de backface-visibility, pas de délai fixe. */
.as-slab--back {
    visibility: hidden;
}

[data-as-slab].is-flipped .as-slab--back {
    visibility: visible;
}

[data-as-slab].is-flipped .as-slab--front {
    visibility: hidden;
}

/* Le VRAI dos de la carte enchâssée ne sert jamais en mode boîtier (le
   verso montre la réplique) : on l'occulte pour qu'il ne transparaisse
   pas sur les navigateurs au backface fragile. */
.as-slab .tc-card__face--back,
.as-slab .trading-card__face--back {
    visibility: hidden;
}

.as-slab--back .as-slab__case {
    flex: 1;
    align-items: center;
}

/* Grain de la coque : texture pleine boîte en blend overlay — au-dessus de
   la carte enchâssée (c'est la surface du plexi), sous le glare (z3). */
.as-slab::before {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: inherit;
    z-index: 2;
    /* Site vitrine (08/10) : tuile de 300 px répétée (67 Ko), comme le grain de la carte. */
    background: url('../img/img-box-grain-tuile.webp') 0 0 / 25% auto repeat;
    mix-blend-mode: overlay;
    pointer-events: none;
}

/* Reflet diagonal statique de la coque (verre). */
.as-slab::after {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: inherit;
    pointer-events: none;
    background: linear-gradient(
        115deg,
        transparent 32%,
        rgba(255, 255, 255, 0.16) 44%,
        rgba(255, 255, 255, 0.04) 52%,
        transparent 60%
    );
}

/* ── Étiquette de certification (les deux faces) ── */
.as-slab__label {
    display: flex;
    align-items: center;
    gap: 2.8cqw;
    background: #ffffff;
    border-radius: 2.4cqw;
    padding: 2.4cqw 3.3cqw;
    margin-bottom: 2.8cqw;
    box-shadow:
        inset 0 0 0 1px rgba(0, 0, 0, 0.08),
        0 2px 6px rgba(0, 0, 0, 0.18);
    position: relative;
    z-index: 2;
}

.as-slab__logo {
    height: 6.6cqw;
    flex-shrink: 0;
}

.as-slab__id {
    display: flex;
    flex-direction: column;
    gap: 0.3cqw;
    min-width: 0;
    overflow: hidden;
}

.as-slab__certified {
    font-size: 2.7cqw;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--app-dark);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.as-slab__hash {
    font-family: var(--app-font-mono);
    font-size: 2.2cqw;
    color: var(--app-gray-500);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Note seule, bien visible (le libellé « Ultra collector » est à gauche). */
.as-slab__grade {
    margin-left: auto;
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    padding-left: 3.6cqw;
    flex-shrink: 0;
    text-align: right;
    position: relative;
}

/* Séparateur « ligne de sécurité » : bande holographique verticale qui
   traverse l'étiquette de haut en bas (les offsets négatifs compensent le
   padding vertical de l'étiquette pour aller bord à bord). */
.as-slab__grade::before {
    content: '';
    position: absolute;
    left: 0;
    top: -2.4cqw;
    bottom: -2.4cqw;
    width: 1.8cqw;
    background: url('../img/img-card-holo-border.webp') center / cover;
}

.as-slab__grade-note {
    font-size: 9cqw;
    font-weight: 800;
    line-height: 1.05;
    color: var(--app-dark);
}

.as-slab__grade-note small {
    font-size: 4cqw;
    font-weight: 700;
    color: var(--app-gray-400);
}

/* ── Compartiment carte : alvéole translucide ── */
.as-slab__case {
    position: relative;
    display: flex;
    justify-content: center;
    border-radius: 3.8cqw;
    padding: 2.4cqw;
    background: rgba(255, 255, 255, 0.05);
    border: 1px solid rgba(255, 255, 255, 0.16);
    box-shadow:
        inset 0 2px 10px rgba(0, 0, 0, 0.28);
}

/* Réplique du dos de carte sur la face arrière : reprend les classes du
   template (cadre + surface + logo) en flux normal. PAS de width forcée :
   elle hérite de la largeur NATIVE de sa classe racine (.tc-card 340px /
   .trading-card 340px — les deux templates partagent la même largeur ;
   un futur template plus large devra surcharger --slab-width ET la largeur
   booster, cf. public-ball.css 97.4%) — exactement la taille de la vraie
   carte au recto, pour que recto et verso soient parfaitement alignés. */
.as-slab-backcard {
    perspective: none;
    cursor: default;
}

.as-slab-backcard .tc-card__back,
.as-slab-backcard .trading-card__back {
    width: 100%;
    /* Hauteur de la VRAIE carte, pas 2/3 strict : le recto = surface 2/3
       enchâssée dans le padding 1.2cqw du tilt → H = 1.5 × (100cqw − 2.4cqw)
       + 2.4cqw = 148.8cqw. Les cqw se résolvent contre la racine
       .tc-card/.trading-card de la réplique (container-type) — même base
       que la carte du recto : les deux faces sont flush au pixel près. */
    height: calc(150cqw - 1.2cqw);
}

/* ── Reflet lumineux du plexi : suit le pointeur (variables --slab-px/--slab-py
   posées par trading-card.js). Visible des deux faces du boîtier. ── */
.as-slab__glare {
    position: absolute;
    inset: 0;
    border-radius: inherit;
    pointer-events: none;
    z-index: 3;
    opacity: 0;
    transition: opacity 0.3s ease-out;
    background: radial-gradient(
        110cqw circle at var(--slab-px, 50%) var(--slab-py, 50%),
        rgba(255, 255, 255, 0.26) 0%,
        rgba(255, 255, 255, 0.08) 38%,
        transparent 62%
    );
}

.as-slab-flipper:hover .as-slab__glare {
    opacity: 1;
}

/* ── Mini-boîtier : enchâsse la vignette des tableaux (rappel du slab).
   Juste la coque grise, sobre — pas de micro-étiquette. ── */
.as-slab-mini {
    display: inline-flex;
    padding: 4px;
    border-radius: 5px;
    background: linear-gradient(160deg, #e3e6ea 0%, #b4b9c1 55%, #d3d6db 100%);
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, 0.7),
        inset 0 -1px 2px rgba(0, 0, 0, 0.18),
        0 1px 3px rgba(0, 0, 0, 0.15);
}

/* ── Petits écrans : LA CARTE EST LA RÉFÉRENCE. Son empreinte doit rester
   celle d'une carte nue ; c'est le chrome du boîtier (paddings structurels)
   qui se compresse en px fixes pour l'absorber. Carte default 340px : pleine
   taille préservée jusqu'à 386px de viewport (wrapper 366px = 340 + 26 de
   chrome) ; en dessous, carte nue et carte boxée rétrécissent quasi à
   l'identique. ── */
@media (max-width: 430px) {
    .app-trading-card-link .card-visual--slab,
    .app-card-edit-layout__preview .card-visual--slab,
    .app-consent-card-preview .card-visual--slab {
        width: calc(100% + 26px);
        max-width: none;
        margin-left: -13px;
        margin-right: -13px;
    }

    /* Vue publique : le wrapper colle au chrome px du boîtier (340px carte
       + 26px de chrome = 366px) — sans ce cap, le wrapper resterait à 384px
       et la coque flotterait à ~9px de la carte (flush rompu). Scopé
       __container pour ne pas écraser l'aperçu consentement. */
    .app-public-ball__container .card-visual--slab {
        width: min(366px, 100vw - 20px);
    }

    .as-slab {
        padding: 6px;
        border-radius: 14px;
    }

    .as-slab__case {
        padding: 5px;
        border-radius: 10px;
    }

    .as-slab__label {
        margin-bottom: 6px;
    }
}

/* ==========================================================
   VUE PUBLIQUE — animations d'entrée portées par le BOÎTIER
   ----------------------------------------------------------
   Comme pour le tilt et le flip (trading-card.js), c'est le
   boîtier ENTIER qui s'anime à l'arrivée — la carte interne
   reste solidaire de sa coque (ses propres animations sont
   neutralisées dans card-default.css / public-ball.css).
   Keyframes ballCardEntrance / ballCardSpin : définies dans
   les feuilles de carte, toujours chargées sur la vue publique.
   ========================================================== */
.app-public-ball .as-slab-scene {
    animation: ballCardEntrance 0.7s cubic-bezier(0.22, 1, 0.36, 1) 0.15s both;
}

@media (prefers-reduced-motion: reduce) {
    .app-public-ball .as-slab-scene {
        animation: none;
    }
}

/* ==========================================================
   Responsive grille : neutraliser le débord du boîtier slab
   ----------------------------------------------------------
   En GRILLE (.app-trading-card-link), les gaps se resserrent en
   mobile (.app-ball-grid : 8px @768 puis 4px @480 ; album 16px en
   2 col). Le débord négatif du boîtier (calibré sur le demi-gap
   desktop 16px) dépasse alors le gap → boîtiers voisins qui se
   chevauchent + carte de bord rognée / scroll horizontal. On le
   neutralise : la carte remplit exactement sa colonne. Placé après
   le bloc @430 pour le surcharger. NE touche PAS la vue publique
   (.app-public-ball__container) ni l'aperçu édition/consent — qui
   ne sont pas .app-trading-card-link et gardent leur débord voulu.
   ========================================================== */
@media (max-width: 768px) {
    .app-trading-card-link .card-visual--slab {
        width: 100%;
        margin-left: 0;
        margin-right: 0;
    }
}
