/* ---------------------------------------------------------------------------
   Motchi : le socle de composants (lot 3).

   Une règle par composant du socle, et rien d'autre : pas d'écran, pas de
   variante propre à une page. Toute teinte vient de `tokens.css` ; une couleur
   écrite en dur ici est un jeton qui manque. Les voiles font exception : un
   blanc ou un noir translucide n'est pas une teinte, c'est une transparence
   posée sur la surface d'en dessous, quelle qu'elle soit.

   Les valeurs sont relevées sur le proto rendu, composant par composant, en
   styles calculés : c'est la seule lecture fiable d'un bundle où la feuille
   déclare bien plus que ce que les écrans emploient.

   Le préfixe `ui-` sépare ce socle de l'habillage d'avant la refonte
   (`app.css`), qui garde ses noms courts jusqu'à ce que le lot de son écran le
   remplace. Les deux cohabitent sans se marcher dessus : aucun sélecteur d'ici
   ne vise une classe de là-bas.

   Les gabarits sont dans `templates/components/`, et la page `/styleguide` les
   montre tous, dans les trois modes.
--------------------------------------------------------------------------- */

/* ── Surfaces ──
   Le feutre est le fond de la page. Il est nommé ici plutôt que sur `body`
   parce que la page n'est pas la seule à le porter : le styleguide en pose
   trois côte à côte, un par mode. Les `var()` se résolvent sur l'élément qui
   porte la classe, donc chaque bloc prend le feutre de son propre mode. */
body,
.ui-felt { background: var(--felt-bg); }

body { background-attachment: fixed; }

/* La carte de mode : le grand bloc coloré qui porte une entrée de l'accueil.
   C'est le dégradé du feutre, resserré et incliné autrement, sans son tissage :
   le fond de la page est hachuré, une carte posée dessus ne l'est pas, sans quoi
   les deux trames se superposent. */
.ui-mode-card {
    background: var(--mode-card-bg);
    border: 1px solid rgba(255, 255, 255, .19);
    border-radius: var(--radius-3xl);
    padding: var(--space-6);
    color: var(--light);
    box-shadow: var(--shadow-mode-card);
    overflow: hidden;
    isolation: isolate;
}

/* Le papier : la carte crème posée sur le feutre. `lg` est la grande carte qui
   porte un écran entier, celle du jeu ou du résultat. */
.ui-paper {
    background: linear-gradient(180deg, var(--cream), var(--cream-2));
    border-radius: var(--radius-xl);
    padding: var(--space-6);
    color: var(--ink-soft);
    box-shadow: var(--hairline), var(--shadow-felt-lg);
}

.ui-paper-lg { border-radius: var(--radius-2xl); padding: var(--space-6) var(--space-7); }

/* La tuile : le petit bloc blanc posé sur le papier, qui porte un chiffre, une
   ligne, un choix. Son blanc est légèrement dégradé et son liseré froid : posée
   sur le crème, une tuile d'un blanc plat se voit comme un trou. */
.ui-tile {
    background: linear-gradient(145deg, var(--tile), var(--tile-2));
    border: 1px solid var(--tile-border);
    border-radius: var(--radius-lg);
    padding: var(--space-4) var(--space-3);
    color: var(--ink-soft);
}

/* Une tuile qui a de l'épaisseur : le proto lui donne une ombre pleine de la
   couleur du bord du papier, jamais un flou. C'est ce qui fait « carte posée »
   plutôt que « zone détourée ». */
.ui-tile-raised {
    background: var(--tile);
    border: 2px solid var(--paper-border);
    box-shadow: 0 5px 0 var(--paper-edge);
}

.ui-tile-success { background: var(--success-bg); border-color: color-mix(in srgb, var(--success) 30%, transparent); }
.ui-tile-danger { background: var(--danger-bg); border-color: color-mix(in srgb, var(--danger) 30%, transparent); }
.ui-tile-mode { background: var(--mode-light); border-color: color-mix(in srgb, var(--mode) 25%, transparent); }

/* Le verre : la carte translucide posée sur le feutre, pour ce qui accompagne
   l'écran sans être son contenu (un rappel de score, une progression). Elle ne
   porte que des encres claires. */
.ui-glass {
    background: rgba(255, 255, 255, .08);
    border: 1px solid rgba(255, 255, 255, .16);
    border-radius: var(--radius-lg);
    padding: var(--space-4);
    color: var(--light);
}

/* Le verre habille ce qu'il porte, comme le papier : un chiffre posé dedans
   prendrait sinon les encres du papier, donc du bleu nuit sur le feutre, et
   l'appelant devrait le corriger à chaque fois sans que rien le lui dise. */
.ui-glass .ui-stat-value { color: var(--light); }
.ui-glass .ui-stat-value small,
.ui-glass .ui-stat-label { color: var(--light-sub); }

/* ── Titres ──
   Six tailles, nommées par ce qu'elles titrent. La hauteur de ligne se resserre
   à mesure que la taille monte : un grand titre sur deux lignes se lit mieux
   serré. */
.ui-title { font-family: var(--font-title); font-weight: 700; margin: 0; color: inherit; }
.ui-title-display { font-size: var(--type-display); line-height: 1.02; }
.ui-title-page { font-size: var(--type-page); line-height: 1.05; }
.ui-title-metric { font-size: var(--type-metric); line-height: 1; }
.ui-title-compact { font-size: var(--type-compact); line-height: 1.08; }
.ui-title-section { font-size: var(--type-section); line-height: 1.12; }
.ui-title-card { font-size: var(--type-card); line-height: 1.15; }

/* La seconde ligne en or : le proto coupe ses grands titres en deux et dore la
   moitié qui porte la promesse. C'est une figure de style du dessin, pas une
   emphase de texte, donc une classe et pas un `<strong>`. */
.ui-title-accent { display: block; color: var(--gold); }
.ui-paper .ui-title { color: var(--ink); }

/* ── Textes secondaires ──
   Le surtitre nomme un bloc, l'indication l'accompagne. Chacun prend l'encre de
   la surface où il est posé : c'est la seule chose qu'un composant a besoin de
   savoir. */
.ui-eyebrow {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    font-family: var(--font-code);
    font-size: var(--type-label);
    font-weight: 900;
    letter-spacing: .9px;
    text-transform: uppercase;
    color: var(--light-sub);
}

/* La pastille qui ouvre un surtitre : le proto la pose devant les siens sur le
   feutre, où elle sert de puce. */
.ui-eyebrow-dot::before {
    content: "";
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: currentColor;
    opacity: .7;
    flex: 0 0 7px;
}

.ui-hint {
    margin: 0;
    font-size: var(--type-body);
    line-height: 1.5;
    color: var(--light-sub);
}

.ui-hint-sm { font-size: var(--type-sm); }
.ui-paper .ui-eyebrow, .ui-tile .ui-eyebrow { color: var(--cream-sub); }
.ui-paper .ui-hint, .ui-tile .ui-hint { color: var(--cream-sub); }

/* ── En-tête d'écran ──
   Le surtitre, le titre coupé en deux et la phrase qui explique : le proto
   ouvre chacun de ses écrans par cette même composition. */
.ui-page-header { display: flex; flex-direction: column; gap: var(--space-2); color: var(--light); }
.ui-page-header .ui-hint { max-width: 62ch; }

/* ── Boutons ──
   Une variante dit de quoi le bouton est fait, une taille dit combien il est
   épais, et le composant expose les deux séparément : elles doivent donc se
   combiner. C'est pourquoi ni les unes ni les autres ne peignent quoi que ce
   soit. Elles ne posent que des variables, et les quatre états (repos, survol,
   appui, focus) sont écrits une fois pour toutes sur `.ui-btn`.

   Écrit autrement, `.ui-btn-sm`, qui vient forcément après les variantes et a
   la même spécificité, réécrivait leur ombre : un petit bouton `outline` ou
   `link` reprenait une épaisseur colorée, un `danger` prenait l'ombre du mode,
   et un `gold` perdait son halo de focus, la règle tardive écrasant le
   `box-shadow` qui portait `--ring`.

   L'ombre pleine sous le bouton est son épaisseur : le survol la creuse et le
   bouton monte, l'appui l'écrase et le bouton descend. Les profondeurs
   (6, 8, 2) sont la géométrie du composant, pas un jeton : rien d'autre ne s'en
   sert. Une variante plate n'a pas de profondeur à régler à zéro, elle a une
   tranche transparente, ce qui la rend indifférente à la taille posée à côté
   d'elle. */
.ui-btn {
    /* Ce qu'une variante change : la couleur, jamais l'épaisseur. La bordure en
       fait partie, et c'est pour cela qu'elle est posée ici, transparente, sur
       tous les boutons : une variante qui l'ajoute ajoute aussi sa hauteur, et
       un contour posé à côté d'un plein ne mesurait plus pareil. Le contour
       retranchait bien son trait de son remplissage, mais en écrivant une
       mesure à lui, donc à une seule taille : `sm` la réécrivait ensuite et
       l'écart revenait, deux pixels plus loin. */
    --btn-border: 2px;
    --btn-bg: var(--mode);
    --btn-bg-hover: var(--btn-bg);
    --btn-ink: var(--on-accent);
    --btn-edge: var(--mode-dark);
    /* Ce qu'une taille change : l'épaisseur, jamais la couleur. `--btn-depth`
       est aussi ce que le bouton déborde vers le bas : un écran qui en empile
       deux le lit pour dégager le second de l'ombre du premier, la façon dont
       ils s'empilent appartenant à l'écran et l'épaisseur au composant. */
    --btn-depth: 6px;
    --btn-depth-hover: 8px;
    --btn-depth-active: 2px;
    --btn-lift: -2px;
    --btn-press: 4px;

    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    width: 100%;
    /* Le remplissage retranche la bordure, donc la hauteur écrite est celle du
       bouton fini : `--space-4` de haut en bas, trait compris. */
    padding: calc(var(--space-4) - var(--btn-border));
    border: var(--btn-border) solid transparent;
    border-radius: var(--radius-lg);
    font-family: var(--font-title);
    font-weight: 600;
    font-size: var(--type-card);
    text-align: center;
    text-decoration: none;
    cursor: pointer;
    background: var(--btn-bg);
    color: var(--btn-ink);
    box-shadow: 0 var(--btn-depth) 0 var(--btn-edge);
    transition:
        transform var(--dur-fast) var(--ease-pop),
        box-shadow var(--dur-fast),
        background var(--dur-fast),
        border-color var(--dur-fast),
        opacity var(--dur-fast);
    -webkit-tap-highlight-color: transparent;
}

.ui-btn:hover:not(:disabled) { background: var(--btn-bg-hover); transform: translateY(var(--btn-lift)); box-shadow: 0 var(--btn-depth-hover) 0 var(--btn-edge); }
.ui-btn:active:not(:disabled) { transform: translateY(var(--btn-press)); box-shadow: 0 var(--btn-depth-active) 0 var(--btn-edge); }
.ui-btn:focus-visible { outline: none; box-shadow: 0 var(--btn-depth) 0 var(--btn-edge), var(--ring); }
.ui-btn:disabled, .ui-btn[aria-disabled="true"] { opacity: var(--disabled-opacity); cursor: default; }
.ui-btn-arrow { font-size: .9em; }


/* L'or est l'action principale d'un écran, et il n'y en a qu'une. */
.ui-btn-gold {
    --btn-bg: var(--gold);
    --btn-ink: var(--on-gold);
    --btn-edge: var(--gold-dark);
}

/* Ce qui refuse ou détruit. */
.ui-btn-danger {
    --btn-bg: var(--danger);
    --btn-edge: color-mix(in srgb, var(--danger) 70%, #000);
}

/* Le contour n'a pas d'épaisseur : c'est une action secondaire, et elle ne vit
   que sur le feutre, où son voile et sa bordure claire se voient. */
.ui-btn-outline {
    --btn-bg: rgba(255, 255, 255, .08);
    --btn-bg-hover: rgba(255, 255, 255, .16);
    --btn-ink: var(--light);
    --btn-edge: transparent;
    --btn-lift: 0;
    --btn-press: 0;
    border-color: color-mix(in srgb, var(--light) 48%, transparent);
}

/* Sur le papier, le contour prend l'encre du mode et un fond de tuile : son
   voile blanc et sa bordure claire ne se voient que sur le feutre. L'adaptation
   est ici, comme celle du lien juste en dessous, et non dans la feuille de
   l'écran qui s'en sert : un composant corrigé sur place devient un composant
   différent d'une page à l'autre, ce que le socle existe pour empêcher. */
.ui-paper .ui-btn-outline,
.ui-tile .ui-btn-outline {
    --btn-bg: var(--tile);
    --btn-bg-hover: var(--mode-light);
    --btn-ink: var(--mode-dark);

    border-color: color-mix(in srgb, var(--mode) 55%, transparent);
}

/* Le lien : ni fond, ni épaisseur, un simple trait sous le texte. Le proto s'en
   sert pour les sorties d'un écran (« Retour à l'accueil »), sous l'action
   principale. Ses mesures sont écrites en doublant la classe, donc au-dessus de
   n'importe quelle taille : un lien est déjà petit, et `sm` ne doit pas
   l'agrandir en lui posant les mesures d'un vrai bouton. */
.ui-btn.ui-btn-link {
    --btn-bg: transparent;
    --btn-bg-hover: transparent;
    --btn-ink: var(--light);
    --btn-edge: transparent;
    --btn-lift: 0;
    --btn-press: 0;
    width: auto;
    border: none;
    border-bottom: 1px solid color-mix(in srgb, currentColor 40%, transparent);
    border-radius: 0;
    font-size: var(--type-sm);
    padding: var(--space-2) var(--space-1);
}

.ui-btn-link:hover:not(:disabled) { border-bottom-color: currentColor; }
.ui-paper .ui-btn-link, .ui-tile .ui-btn-link { --btn-ink: var(--mode-dark); }

/* Le retour, en tête d'écran : il nomme ce que l'on quitte et n'est pas une
   action, donc ni fond, ni épaisseur, ni souligné. C'est le seul lien que le
   proto laisse sans trait, et cela le distingue des secondes lectures d'une
   carte, qui en portent un. Sous le seuil, il prend la hauteur d'une cible au
   doigt, que le proto lui donne aussi : seul en haut de page, il est sinon la
   plus petite cible de l'écran. */
.ui-btn.ui-btn-back {
    --btn-bg: transparent;
    --btn-bg-hover: transparent;
    --btn-ink: var(--light-sub);
    --btn-edge: transparent;
    --btn-lift: 0;
    --btn-press: 0;

    width: auto;
    border: none;
    border-radius: var(--radius-xs);
    padding: var(--space-2) 0;
    font-size: var(--type-sm);
    font-weight: 900;
}
.ui-btn-back:hover:not(:disabled) { --btn-ink: var(--light); }

@media (max-width: 759px) {
    .ui-btn.ui-btn-back { min-height: 44px; padding-inline: var(--space-1); }
}

/* Un bouton qui n'occupe que sa place, et un bouton plus petit. */
.ui-btn-auto { width: auto; }
.ui-btn-sm {
    --btn-depth: 4px;
    --btn-depth-hover: 5px;
    font-size: var(--type-body);
    padding: calc(var(--space-2) - var(--btn-border)) calc(var(--space-4) - var(--btn-border));
    border-radius: var(--radius-md);
}

/* ── Champs ── */
.ui-field-group { display: block; margin-bottom: var(--space-4); }

.ui-field {
    width: 100%;
    padding: var(--space-3) var(--space-4);
    border: 3px solid var(--paper-border);
    border-radius: var(--radius-md);
    background: var(--tile);
    color: var(--ink);
    font-family: var(--font-title);
    font-weight: 600;
    font-size: var(--type-card);
    outline: none;
    transition: border-color var(--dur), box-shadow var(--dur);
}

.ui-field::placeholder { color: var(--ink-placeholder); }
.ui-field:focus-visible, .ui-field:focus { border-color: var(--mode); box-shadow: var(--ring); }
.ui-field:disabled { opacity: var(--disabled-opacity); cursor: default; }
.ui-field[aria-invalid="true"] { border-color: var(--danger); }
/* Le code d'une partie se lit lettre à lettre, jamais comme un mot. */
.ui-field-code { text-align: center; letter-spacing: 8px; text-transform: uppercase; font-weight: 700; }

.ui-field-label {
    display: block;
    margin-bottom: var(--space-2);
    font-family: var(--font-code);
    font-size: var(--type-label);
    font-weight: 900;
    letter-spacing: .9px;
    text-transform: uppercase;
    color: var(--light-sub);
}

.ui-paper .ui-field-label { color: var(--cream-sub); }
.ui-field-error { margin: var(--space-1) 0 0; font-size: var(--type-sm); font-weight: 900; color: var(--danger); }
.ui-field-group .ui-hint { margin-top: var(--space-2); }

/* ── Pastilles ──
   Une pastille est une étiquette, pas un bouton : elle nomme un état, et sa
   couleur dit lequel. */
.ui-chip {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    padding: var(--space-2) var(--space-3);
    border-radius: var(--radius-sm);
    font-family: var(--font-text);
    font-size: var(--type-label);
    font-weight: 900;
    line-height: 1.2;
    white-space: nowrap;
}

.ui-chip-neutral { background: rgba(0, 0, 0, .06); color: var(--ink-soft); }
.ui-chip-mode { background: var(--mode-light); color: var(--mode-dark); }
.ui-chip-gold { background: var(--gold); color: var(--on-gold); }
.ui-chip-success { background: var(--success-bg); color: var(--success); }
.ui-chip-danger { background: var(--danger-bg); color: var(--danger); }
.ui-chip-warning { background: var(--warning-bg); color: var(--warning); }
/* Sur le feutre : le fond translucide est la seule pastille lisible, les fonds
   pastel du papier y perdent leur contraste. */
.ui-chip-felt { background: rgba(255, 255, 255, .14); color: var(--light); }

/* ── Bandeaux ──
   Une phrase que l'écran ajoute à côté de son contenu : ce qui vient d'être
   gagné, ce qui reste verrouillé, ce qu'il faut savoir. Le fond est pâle, la
   première ligne porte le sens et la seconde l'explique. */
.ui-note {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-3) var(--space-4);
    border-radius: var(--radius-md);
    background: var(--mode-light);
    color: var(--mode-dark);
    font-size: var(--type-sm);
}

.ui-note-gold { background: var(--gold-bg); color: var(--cream-sub); }
.ui-note-neutral { background: rgba(0, 0, 0, .04); color: var(--ink-soft); }
.ui-note b { display: block; font-weight: 900; }
.ui-note small { display: block; font-size: var(--type-sm); opacity: .82; }
.ui-note-icon { flex: 0 0 auto; display: grid; place-items: center; }

/* ── Chiffres ──
   Le chiffre et ce qu'il compte : le proto en aligne trois ou quatre par carte,
   et c'est ce qui donne le ton « tableau de bord » de ses écrans de résultat. */
.ui-stat { display: flex; flex-direction: column; align-items: center; gap: var(--space-1); text-align: center; }
.ui-stat-value { font-family: var(--font-title); font-weight: 700; font-size: var(--type-section); line-height: 1; color: var(--ink); }
.ui-stat-value small { font-size: .6em; color: var(--cream-sub); }
.ui-stat-label { font-family: var(--font-text); font-weight: 900; font-size: var(--type-label); color: var(--cream-sub); }

/* ── Messages ──
   Un flash annonce ce qui vient d'arriver. Il est posé sur le feutre, en haut
   de la page, donc il porte son propre fond de papier. */
.ui-flash {
    border-radius: var(--radius-md);
    padding: var(--space-3) var(--space-4);
    margin-bottom: var(--space-3);
    font-size: var(--type-sm);
    font-weight: 900;
    box-shadow: var(--shadow-felt-md);
}

.ui-flash-success { background: var(--success-bg); color: var(--success); }
.ui-flash-error, .ui-flash-danger { background: var(--danger-bg); color: var(--danger); }
.ui-flash-warning, .ui-flash-info { background: var(--warning-bg); color: var(--warning); }

/* ── Mascotte et bulle ──
   La mascotte de la refonte est une image, pas le SVG que `panda.js` dessine :
   le proto la rend en volume, ce qu'aucun tracé écrit à la main ne rattrape.
   L'ancien panda reste en place sur les écrans que leur lot n'a pas encore
   repris.

   Le panda parle : sa bulle pointe vers lui par son coin manquant, en bas à
   gauche. */
.ui-mascot { display: block; object-fit: contain; filter: drop-shadow(0 8px 9px rgba(0, 0, 0, .22)); }

/* Le halo des heroes appartient à la mascotte, pas à un mode. Ses dimensions
   restent celles de l'écran qui l'accueille, tandis que sa matière et son
   mouvement sont partagés entre Défi du jour et Entre amis. */
.ui-mascot-halo {
    position: absolute;
    z-index: 0;
    bottom: -2px;
    left: 50%;
    width: 255px;
    height: 225px;
    margin-left: -127px;
    background:
        radial-gradient(ellipse 22% 28% at 50% 46%, rgba(255, 224, 97, .34), transparent 78%),
        repeating-conic-gradient(from 4deg, rgba(255, 255, 255, .2) 0 5deg, transparent 5deg 16deg);
    mask-image: radial-gradient(ellipse 50% 72% at 50% 58%, #000 0 16%, rgba(0, 0, 0, .82) 38%, transparent 73%);
    opacity: .92;
    animation: ui-mascot-halo 48s linear infinite;
}

@keyframes ui-mascot-halo {
    to { transform: rotate(360deg); }
}

@media (prefers-reduced-motion: reduce) {
    .ui-mascot-halo { animation: none; }
}

.ui-bubble-row { display: flex; align-items: flex-start; gap: var(--space-3); }
.ui-bubble-row .ui-mascot { flex: 0 0 auto; }

.ui-bubble {
    flex: 1;
    align-self: center;
    background: linear-gradient(180deg, var(--cream), var(--cream-2));
    border-radius: var(--radius-lg) var(--radius-lg) var(--radius-lg) var(--radius-xs);
    padding: var(--space-3) var(--space-4);
    font-family: var(--font-title);
    font-weight: 500;
    font-size: var(--type-body);
    line-height: 1.42;
    color: var(--ink-soft);
    box-shadow: var(--shadow-felt-md);
}

.ui-bubble b, .ui-bubble strong { color: var(--panda); }

/* ── La scène des indices ──
   Le cadre porte le format du fichier, et la lueur de l'ampoule se place en
   pourcentage de lui : sur un cadre plus haut que l'image, les deux
   pourcentages tombent à côté de l'ampoule. Le placement du cadre lui-même
   appartient à l'écran qui l'accueille, qui le pose où sa mise en page le veut.

   La lueur est derrière l'image : l'ampoule y est dessinée, donc ce qui doit
   briller est son pourtour, et une lueur posée devant la repeindrait. */
.ui-scene { position: relative; display: block; width: 100%; aspect-ratio: 760 / 517; }
.ui-scene picture,
.ui-scene > img { position: relative; z-index: 2; display: block; width: 100%; height: 100%; }
.ui-scene img { display: block; width: 100%; height: 100%; object-fit: contain; }

.ui-scene-glow {
    position: absolute;
    z-index: 1;
    top: 10.5%;
    left: 50%;
    width: 18%;
    aspect-ratio: 1;
    border-radius: 50%;
    transform: translate(-50%, -50%);
    background: radial-gradient(
        circle,
        color-mix(in srgb, var(--gold) 75%, transparent) 0 17%,
        color-mix(in srgb, var(--gold) 30%, transparent) 35%,
        color-mix(in srgb, var(--gold) 8%, transparent) 58%,
        transparent 72%
    );
    animation: ui-scene-glow 2.6s ease-in-out infinite;
}

/* Le décalage fait partie de la transformation, donc chaque étape doit le
   reposer, sans quoi l'animation renvoie la lueur dans le coin. */
@keyframes ui-scene-glow {
    0%, 100% { opacity: .55; transform: translate(-50%, -50%) scale(.86); }
    50% { opacity: 1; transform: translate(-50%, -50%) scale(1.14); }
}

/* ── Mouvement ──
   Le rebond des boutons est un agrément : qui l'a refusé dans son système ne le
   reçoit pas. */
@media (prefers-reduced-motion: reduce) {
    .ui-btn, .ui-field { transition: none; }
    .ui-btn:hover:not(:disabled), .ui-btn:active:not(:disabled) { transform: none; }
    .ui-scene-glow { animation: none; }
}
