/* ══════════════════════════════════════════════════════════════════════
   components.css — les primitives partagées.
   ─────────────────────────────────────────────────────────────────────
   POURQUOI LE PRÉFIXE `lbs-` : les noms nus (.card, .btn, .chip, .badge,
   .pill) sont déjà définis à la main dans une trentaine de templates,
   chacun à sa sauce. Publier un `.card` global ici repeindrait au hasard
   des pages qui n'ont rien demandé. Le préfixe garantit qu'aucune page
   existante ne bouge tant qu'on ne l'a pas migrée exprès.

   MIGRATION : quand tu reprends un template, remplace ses classes
   locales par les `lbs-*` correspondantes ET supprime les règles
   devenues mortes de son <style>. Le but est que chaque page migrée
   RETIRE des lignes, pas qu'elle en ajoute.

   Le rendu de tout ce fichier est visible sur /styleguide, dans les
   deux thèmes.
   ══════════════════════════════════════════════════════════════════════ */

/* ══ Mise en page ═════════════════════════════════════════════════════ */

.lbs-container {
    max-width: 1180px;
    margin: 0 auto;
    padding: var(--sp-6) var(--sp-5) var(--sp-10);
}
@media (max-width: 640px) {
    .lbs-container { padding: var(--sp-4) var(--sp-3) var(--sp-8); }
}

/* Empilement vertical régulier : évite les `margin-bottom` semés à la
   main sur chaque enfant. */
.lbs-stack { display: flex; flex-direction: column; gap: var(--sp-4); }
.lbs-stack-sm { display: flex; flex-direction: column; gap: var(--sp-2); }

/* Alignement horizontal qui passe à la ligne proprement. */
.lbs-cluster { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2); }

/* Titre de section : petites capitales espacées, ton secondaire. Sert à
   annoncer un groupe sans consommer un niveau de titre. */
.lbs-eyebrow {
    font-size: var(--fs-xs);
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: .09em;
    color: var(--faint);
}

.lbs-title {
    font-family: var(--font-display);
    font-size: var(--fs-2xl);
    color: var(--accent);
    font-weight: 400;
}

/* ══ Cartes ═══════════════════════════════════════════════════════════ */

/* La carte du nouveau thème : pas de bordure, une ombre de contact, un
   rayon large. Ce qui la détache du fond, c'est l'élévation.
   La bordure ne revient qu'en mode sombre, où l'ombre ne se voit plus. */
.lbs-card {
    background: var(--surface);
    border: 1px solid var(--card-border);
    border-radius: var(--r-lg);
    box-shadow: var(--sh-2);
    padding: var(--sp-5);
}

/* Variante cliquable : réagit au survol en montant d'un cran. */
.lbs-card-link {
    display: block;
    text-decoration: none;
    color: inherit;
    transition: box-shadow var(--dur-2) var(--ease), transform var(--dur-2) var(--ease);
}
.lbs-card-link:hover { box-shadow: var(--sh-3); transform: translateY(-2px); }
.lbs-card-link:active { transform: translateY(0); }

/* Zone en creux À L'INTÉRIEUR d'une carte (sous-liste, encart, résumé).
   Surtout pas une carte dans une carte : deux ombres empilées, ça fait
   du relief pour rien. */
.lbs-well {
    background: var(--surface-2);
    border: 1px solid var(--card-border);
    border-radius: var(--r-md);
    padding: var(--sp-4);
}

.lbs-card-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-3);
    margin-bottom: var(--sp-4);
}
.lbs-card-title { font-size: var(--fs-lg); font-weight: 700; color: var(--text); }

/* Séparateur interne. Un seul trait, à la bonne opacité. */
.lbs-sep { height: 1px; background: var(--border); border: 0; margin: var(--sp-4) 0; }

/* ══ Boutons ══════════════════════════════════════════════════════════ */

/* Un seul socle, trois variantes, trois tailles. Tous les boutons de
   l'app devraient finir ici — aujourd'hui il en existe des dizaines de
   déclinaisons locales quasi identiques. */
.lbs-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--sp-2);
    font: inherit;
    font-size: var(--fs-sm);
    font-weight: 600;
    line-height: 1;
    padding: .62rem 1rem;
    border-radius: var(--r-sm);
    border: 1px solid transparent;
    cursor: pointer;
    text-decoration: none;
    white-space: nowrap;
    transition: background var(--dur-1) var(--ease),
                border-color var(--dur-1) var(--ease),
                box-shadow var(--dur-2) var(--ease),
                transform var(--dur-1) var(--ease);
}
/* Le petit enfoncement au clic : c'est ce qui fait qu'un bouton paraît
   physique plutôt que peint. */
.lbs-btn:active { transform: translateY(1px); }
.lbs-btn:disabled, .lbs-btn[aria-disabled="true"] {
    opacity: .5;
    cursor: not-allowed;
    transform: none;
}

/* Primaire — l'action principale. UNE SEULE par écran. */
.lbs-btn-primary {
    background: var(--action);
    color: var(--action-fg);
    box-shadow: var(--sh-1);
}
.lbs-btn-primary:hover:not(:disabled) { background: var(--action-hover); box-shadow: var(--sh-2); }

/* Secondaire — l'action courante, posée sur une surface. */
.lbs-btn-secondary {
    background: var(--surface);
    color: var(--text);
    border-color: var(--border-strong);
}
.lbs-btn-secondary:hover:not(:disabled) { background: var(--surface-2); border-color: var(--faint); }

/* Discret — les actions de service (fermer, filtrer, replier). */
.lbs-btn-ghost {
    background: transparent;
    color: var(--muted);
}
.lbs-btn-ghost:hover:not(:disabled) { background: var(--surface-2); color: var(--text); }

/* Destructif — supprimer, annuler une résa. Texte rouge sur fond teinté
   plutôt que bouton rouge plein : ça reste lisible sans hurler. */
.lbs-btn-danger {
    background: var(--danger-bg);
    color: var(--danger-fg);
    border-color: var(--danger-border);
}
.lbs-btn-danger:hover:not(:disabled) { background: var(--danger); color: #fff; border-color: transparent; }
.lbs-btn-danger:focus-visible { box-shadow: var(--ring-danger); }

/* Or — réservé aux actions de marque (parier, offrir un terrain). */
.lbs-btn-gold {
    background: var(--gold);
    color: #3d2f08;
    box-shadow: var(--sh-1);
}
.lbs-btn-gold:hover:not(:disabled) { background: var(--gold-lt); box-shadow: var(--sh-2); }

.lbs-btn-sm { font-size: var(--fs-xs); padding: .42rem .7rem; border-radius: var(--r-xs); }
.lbs-btn-lg { font-size: var(--fs-base); padding: .8rem 1.4rem; border-radius: var(--r-md); }
.lbs-btn-block { display: flex; width: 100%; }

/* Bouton purement iconographique : carré, sans texte. */
.lbs-btn-icon { padding: .5rem; aspect-ratio: 1; border-radius: var(--r-sm); }

/* ══ Champs de saisie ═════════════════════════════════════════════════ */

.lbs-field { display: flex; flex-direction: column; gap: var(--sp-1); }

.lbs-label {
    font-size: var(--fs-sm);
    font-weight: 600;
    color: var(--muted);
}

.lbs-input,
.lbs-select,
.lbs-textarea {
    font: inherit;
    font-size: var(--fs-base);
    color: var(--text);
    background: var(--surface);
    border: 1px solid var(--border-strong);
    border-radius: var(--r-sm);
    padding: .58rem .75rem;
    width: 100%;
    transition: border-color var(--dur-1) var(--ease), box-shadow var(--dur-2) var(--ease);
}
.lbs-input::placeholder, .lbs-textarea::placeholder { color: var(--faint); }
.lbs-input:focus, .lbs-select:focus, .lbs-textarea:focus {
    outline: none;
    border-color: var(--accent-mid);
    box-shadow: var(--ring);
}
.lbs-input:disabled, .lbs-select:disabled, .lbs-textarea:disabled {
    background: var(--surface-2);
    color: var(--faint);
    cursor: not-allowed;
}
.lbs-textarea { min-height: 6rem; resize: vertical; }

/* Le chevron du select est dessiné en CSS : pas de fichier à charger, et
   il suit la couleur du texte dans les deux thèmes. */
.lbs-select {
    appearance: none;
    padding-right: 2.2rem;
    background-image:
        linear-gradient(45deg, transparent 50%, currentColor 50%),
        linear-gradient(135deg, currentColor 50%, transparent 50%);
    background-position: right 1.1rem center, right .85rem center;
    background-size: 5px 5px, 5px 5px;
    background-repeat: no-repeat;
}

.lbs-hint { font-size: var(--fs-xs); color: var(--faint); }
.lbs-error { font-size: var(--fs-xs); color: var(--danger-fg); font-weight: 600; }

/* ══ Pastilles & étiquettes ═══════════════════════════════════════════ */

/* Étiquette d'état, non cliquable. */
.lbs-badge {
    display: inline-flex;
    align-items: center;
    gap: .3rem;
    font-size: var(--fs-xs);
    font-weight: 700;
    line-height: 1.6;
    padding: .1rem .5rem;
    border-radius: var(--r-full);
    border: 1px solid transparent;
    white-space: nowrap;
}
.lbs-badge-neutral { background: var(--surface-2); color: var(--muted); border-color: var(--border); }
.lbs-badge-success { background: var(--success-bg); color: var(--success-fg); border-color: var(--success-border); }
.lbs-badge-danger  { background: var(--danger-bg);  color: var(--danger-fg);  border-color: var(--danger-border); }
.lbs-badge-warn    { background: var(--warn-bg);    color: var(--warn-fg);    border-color: var(--warn-border); }
.lbs-badge-info    { background: var(--info-bg);    color: var(--info-fg);    border-color: var(--info-border); }
.lbs-badge-gold    { background: var(--gold-bg);    color: var(--gold-fg);    border-color: var(--gold-border); }
.lbs-badge-special { background: var(--special-bg); color: var(--special-fg); border-color: var(--special-border); }

/* Pastille CLIQUABLE (filtre, sélection). Distincte du badge : elle a un
   état actif et réagit au survol. */
.lbs-chip {
    display: inline-flex;
    align-items: center;
    gap: .35rem;
    font: inherit;
    font-size: var(--fs-sm);
    font-weight: 600;
    color: var(--muted);
    background: var(--surface);
    border: 1px solid var(--border-strong);
    border-radius: var(--r-full);
    padding: .34rem .8rem;
    cursor: pointer;
    white-space: nowrap;
    transition: background var(--dur-1) var(--ease), color var(--dur-1) var(--ease),
                border-color var(--dur-1) var(--ease);
}
.lbs-chip:hover { background: var(--surface-2); color: var(--text); }
.lbs-chip[aria-pressed="true"], .lbs-chip.is-active {
    background: var(--action);
    color: var(--action-fg);
    border-color: transparent;
}

/* ══ Onglets ══════════════════════════════════════════════════════════ */

/* Onglets soulignés plutôt qu'en boutons : plus léger, et le trait actif
   glisse sous le libellé sans faire bouger la mise en page. */
.lbs-tabs {
    display: flex;
    gap: var(--sp-1);
    border-bottom: 1px solid var(--border);
    overflow-x: auto;
    scrollbar-width: none;
}
.lbs-tabs::-webkit-scrollbar { display: none; }
.lbs-tab {
    font: inherit;
    font-size: var(--fs-sm);
    font-weight: 600;
    color: var(--muted);
    background: none;
    border: none;
    border-bottom: 2px solid transparent;
    padding: .6rem .9rem;
    margin-bottom: -1px;
    cursor: pointer;
    white-space: nowrap;
    text-decoration: none;
    transition: color var(--dur-1) var(--ease), border-color var(--dur-1) var(--ease);
}
.lbs-tab:hover { color: var(--text); }
.lbs-tab.is-active { color: var(--accent); border-bottom-color: var(--gold); }

/* ══ Tableaux ═════════════════════════════════════════════════════════ */

/* À envelopper dans un conteneur qui défile (voir .lbs-table-wrap) :
   sur mobile, un tableau large ne doit JAMAIS pousser la page en
   débordement horizontal. */
.lbs-table-wrap { overflow-x: auto; border-radius: var(--r-md); }
.lbs-table {
    width: 100%;
    border-collapse: collapse;
    font-size: var(--fs-sm);
}
.lbs-table th {
    text-align: left;
    font-size: var(--fs-xs);
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: .06em;
    color: var(--faint);
    padding: .55rem .7rem;
    border-bottom: 1px solid var(--border);
    white-space: nowrap;
}
.lbs-table td {
    padding: .6rem .7rem;
    border-bottom: 1px solid var(--border);
}
.lbs-table tbody tr:last-child td { border-bottom: none; }
.lbs-table tbody tr:hover td { background: var(--surface-2); }
/* Colonnes de chiffres : alignées à droite et en chasse fixe, sinon les
   scores ne se comparent pas d'une ligne à l'autre. */
.lbs-table .num { text-align: right; font-variant-numeric: tabular-nums; }

/* ══ Modales ══════════════════════════════════════════════════════════ */

.lbs-overlay {
    position: fixed;
    inset: 0;
    z-index: 400;
    background: rgba(10, 20, 36, .55);
    /* Pas de backdrop-filter : flouter toute la page derrière un voile plein
       écran se recalcule à chaque image du fondu. Le tiroir de navigation en
       souffrait au point d'être signalé comme lent ; un voile à 55 % détache
       la modale sans ce coût. */
    display: flex;
    align-items: center;
    justify-content: center;
    padding: var(--sp-4);
    opacity: 0;
    pointer-events: none;
    transition: opacity var(--dur-2) var(--ease);
}
.lbs-overlay.is-open { opacity: 1; pointer-events: auto; }

.lbs-modal {
    background: var(--elevated);
    border-radius: var(--r-xl);
    box-shadow: var(--sh-4);
    padding: var(--sp-6);
    width: min(520px, 100%);
    max-height: 88vh;
    overflow-y: auto;
    transform: translateY(10px) scale(.98);
    transition: transform var(--dur-3) var(--ease);
}
.lbs-overlay.is-open .lbs-modal { transform: none; }
[data-theme="dark"] .lbs-modal { border: 1px solid var(--border); }

.lbs-modal-title { font-size: var(--fs-xl); font-weight: 700; margin-bottom: var(--sp-2); }
.lbs-modal-actions {
    display: flex;
    justify-content: flex-end;
    gap: var(--sp-2);
    margin-top: var(--sp-5);
}
/* Sur téléphone la modale se colle en bas et prend toute la largeur :
   c'est là que le pouce se trouve. */
@media (max-width: 560px) {
    .lbs-overlay { align-items: flex-end; padding: 0; }
    .lbs-modal {
        width: 100%;
        border-radius: var(--r-xl) var(--r-xl) 0 0;
        max-height: 92vh;
        padding-bottom: calc(var(--sp-6) + env(safe-area-inset-bottom));
    }
}

/* ══ Primitives historiques, consolidées ══════════════════════════════
   Ces noms nus (.container, h1, .card, .btn…) étaient redéfinis dans une
   quinzaine de templates, chacun à sa sauce : `.container` avait 12
   variantes, `h1` 10, `.card` 9, `.btn` 9. Même nom, comportements
   différents — c'est ce qui a produit un survol de carte corrigé dans un
   fichier et pas dans deux autres.

   Ils vivent ici désormais. Une page qui a besoin d'un écart garde une
   règle locale ne portant QUE la déclaration qui diffère (typiquement la
   `max-width` d'un conteneur) : le <style> de page passe après ce fichier,
   donc il l'emporte. Les nouveaux composants, eux, prennent le préfixe
   `lbs-` — ceux-ci sont là par héritage, pas par choix.
   ══════════════════════════════════════════════════════════════════════ */

.container {
    max-width: 1180px;
    margin: 2rem auto;
    padding: 0 1.5rem;
}

h1 {
    font-family: var(--font-display);
    font-size: var(--fs-2xl);
    font-weight: 400;
    color: var(--accent);
    margin-bottom: 1.2rem;
}

.card {
    background: var(--surface);
    border: 1px solid var(--card-border);
    border-radius: var(--r-lg);
    box-shadow: var(--sh-2);
    padding: 1.15rem 1.25rem;
}

.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: .35rem;
    font: inherit;
    font-size: .88rem;
    font-weight: 600;
    line-height: 1.2;
    padding: .55rem 1.1rem;
    border: 1px solid transparent;
    border-radius: var(--r-sm);
    cursor: pointer;
    text-decoration: none;
    white-space: nowrap;
    transition: background var(--dur-1) var(--ease), color var(--dur-1) var(--ease),
                border-color var(--dur-1) var(--ease), box-shadow var(--dur-2) var(--ease);
}
.btn:disabled, .btn[aria-disabled="true"] { opacity: .5; cursor: not-allowed; }
.btn-primary { background: var(--action); color: var(--action-fg); }
.btn-primary:hover:not(:disabled) { background: var(--action-hover); }

.field { margin-bottom: 1rem; }
/* ⚠️ `>` et non un descendant quelconque : le LIBELLÉ du champ, rien d'autre.
   En `.field label`, la règle attrapait tous les <label> imbriqués — dont les
   lignes de joueurs du sélecteur de réservation, qui sont des <label> dans un
   `.field`. Avec une spécificité de 0,1,1 elle écrasait leur propre `display:
   flex` et leur imposait ses capitales : les noms sortaient en majuscules,
   empilés, la case à cocher rejetée dans un coin. */
.field > label {
    display: block;
    font-size: .72rem;
    font-weight: 700;
    color: var(--muted);
    text-transform: uppercase;
    letter-spacing: .05em;
    margin-bottom: .3rem;
}

.empty {
    text-align: center;
    color: var(--muted);
    font-size: .92rem;
    padding: 2rem 0;
}

.section-title {
    font-size: .72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .08em;
    color: var(--muted);
}

/* ══ Messages flash ═══════════════════════════════════════════════════ */

/* Le message de confirmation ou d'erreur après un POST. Il était redéfini
   dans 14 templates, avec quatre paddings et quatre rayons différents —
   d'où quatre allures pour la même chose selon la page.

   Exception au préfixe `lbs-` : `.flash` est posé par les handlers Flask via
   `session["flash_success"]`, donc le nom est figé côté serveur et déjà
   partagé par toutes les pages. Le renommer imposerait de toucher chaque
   handler pour zéro gain. */
.flash {
    padding: .7rem 1rem;
    border-radius: var(--r-md);
    margin-bottom: 1rem;
    font-size: var(--fs-base);
    font-weight: 600;
    /* Le liseré à gauche donne au message un ancrage visuel et redit son
       état sans dépendre de la seule teinte de fond, très pâle. */
    border-left: 4px solid transparent;
}
.flash.success { background: var(--success-bg); color: var(--success-fg); border-left-color: var(--success); }
.flash.error   { background: var(--danger-bg);  color: var(--danger-fg);  border-left-color: var(--danger); }
.flash.warn    { background: var(--warn-bg);    color: var(--warn-fg);    border-left-color: var(--warn); }
.flash.info    { background: var(--info-bg);    color: var(--info-fg);    border-left-color: var(--info); }

/* ══ États vides & chargement ═════════════════════════════════════════ */

/* Un écran vide doit dire pourquoi il est vide et quoi faire ensuite —
   pas rester blanc. */
.lbs-empty {
    text-align: center;
    padding: var(--sp-10) var(--sp-5);
    color: var(--muted);
}
.lbs-empty-icon { font-size: 2.4rem; opacity: .55; margin-bottom: var(--sp-3); }
.lbs-empty-title { font-size: var(--fs-lg); font-weight: 700; color: var(--text); margin-bottom: var(--sp-1); }
.lbs-empty-text { font-size: var(--fs-sm); max-width: 34ch; margin: 0 auto var(--sp-4); }

/* Squelette de chargement : un balayage lent, pas un clignotement. */
.lbs-skel {
    background: linear-gradient(90deg, var(--surface-2) 25%, var(--border) 37%, var(--surface-2) 63%);
    background-size: 400% 100%;
    animation: lbs-shimmer 1.4s ease-in-out infinite;
    border-radius: var(--r-xs);
    min-height: .85rem;
}
@keyframes lbs-shimmer {
    from { background-position: 100% 50%; }
    to   { background-position: 0 50%; }
}

/* Le point rouge « en direct », avec son halo qui bat. */
.lbs-live-dot {
    width: 8px; height: 8px;
    border-radius: 50%;
    background: var(--red);
    box-shadow: 0 0 0 0 rgba(217, 48, 37, .6);
    animation: lbs-pulse 1.8s var(--ease) infinite;
    flex: none;
}
@keyframes lbs-pulse {
    to { box-shadow: 0 0 0 9px rgba(217, 48, 37, 0); }
}

/* ══ Utilitaires ══════════════════════════════════════════════════════ */

.lbs-muted { color: var(--muted); }
.lbs-faint { color: var(--faint); }
.lbs-num   { font-variant-numeric: tabular-nums; }
/* Coupe une ligne trop longue au lieu de la laisser casser la mise en page. */
.lbs-truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
/* Visible uniquement pour les lecteurs d'écran. */
.lbs-sr {
    position: absolute; width: 1px; height: 1px;
    padding: 0; margin: -1px; overflow: hidden;
    clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}
