/* =====================================================================
   Tofus v5 — feuille de style de base
   Direction « Les Dofus » (voir DESIGN.md).

   Le thème Nuit, sombre, qui a tenu la production jusqu'au 15 août 2026,
   est archivé tel quel dans `docs/themes/nuit.css`. Aucun nom de classe
   n'a changé entre les deux : le revenir en arrière est une copie de
   fichier.

   Le principe, relevé sur 520 images du jeu : 71 à 78 % des pixels colorés
   de Dofus tombent dans la bande orange-ambre-or, et leur luminosité
   médiane est de 35 %. Un fond sombre ne pouvait pas répondre à ça. La
   lecture se fait donc sur une **feuille de sable clair**, qui flotte sur
   une terre ambrée éclairée par le haut.

   Un seul jeu de jetons : changer d'ambiance ne demande que de redéfinir
   ce bloc, jamais de toucher aux composants.
   ===================================================================== */

:root {
    color-scheme: light;

    /* Le sol, sous la feuille. Il ne porte que la barre et le pied. */
    --ground:     #241608;
    --ground-top: #4A2E15;

    /* La feuille. `--bg` est son creux — champs de saisie, vignettes — et
       `--surface` ce qui se pose dessus. La convention du thème sombre est
       conservée : plus clair vaut plus haut. */
    --bg:        #EADCC2;
    --surface:   #F6EBD7;
    --surface-2: #FDF5E4;
    --border:    #DCC9A8;
    --border-2:  #A48A5C;

    --text:   #33210F;
    --text-2: #5C4830;
    /* Le tertiaire tire vers l'ocre : un gris pur trahirait un choix non fait. */
    --text-3: #745D3E;

    /* L'or du thème Nuit ne pouvait pas rester : sur du sable il tombe à
       1,9:1. L'accent devient l'ambre profond des terres d'Amakna, lisible
       en texte comme en fond de bouton. */
    --accent:      #A8571A;
    --accent-2:    #8A4614;
    --accent-tint: #F4E2C4;
    --on-accent:   #FFF6E8;

    /* Les cinq éléments de Dofus : Force est Terre, Intelligence est Feu,
       Chance est Eau, Agilité est Air. Code de lecture, pas décoration.
       Assombris pour le fond clair, leurs teintes éclaircies d'autant. */
    --earth:   #8A5218;
    --fire:    #B3352C;
    --water:   #1D6A9E;
    --air:     #3A7233;
    --neutral: #5A696B;

    --earth-tint:   #F3E3CB;
    --fire-tint:    #F8E0DC;
    --water-tint:   #DCEAF5;
    --air-tint:     #E1EFDD;
    --neutral-tint: #E6ECEC;

    /* La barre ne porte plus de fond : elle est posée sur le sol. */
    --bar:        transparent;
    --bar-text:   #F3E7D2;
    --bar-text-2: #D8C4A4;

    /* Décalage et flou : un halo sans décalage serait un ornement, pas une
       profondeur. */
    --shadow: 0 2px 6px -3px rgb(58 32 10 / 30%), 0 18px 40px -24px rgb(58 32 10 / 45%);
    --shadow-sheet:
        0 1px 0 rgb(255 246 232 / 60%) inset,
        0 18px 48px -24px rgb(0 0 0 / 62%),
        0 4px 12px -8px rgb(0 0 0 / 45%);

    --font-display: "Segoe UI Variable Display", "Segoe UI", -apple-system, BlinkMacSystemFont, "SF Pro Display", system-ui, sans-serif;
    --font-body:    "Segoe UI Variable Text", "Segoe UI", -apple-system, BlinkMacSystemFont, system-ui, sans-serif;
    --font-mono:    ui-monospace, "Cascadia Mono", "SF Mono", Consolas, "Liberation Mono", monospace;

    --radius: 4px;
    --width: 78rem;
    /* La marge de sol laissée autour de la feuille. Sans elle, dès que la
       fenêtre descend sous `--width`, la feuille touche les bords : l'ombre
       ne se voit plus et les angles arrondis sont rognés. */
    --gutter: 1.25rem;
}

/* ---------------------------------------------------------------- socle */

*,
*::before,
*::after { box-sizing: border-box; }

/* L'attribut `hidden` doit toujours masquer.
   Le navigateur applique bien `[hidden] { display: none }`, mais depuis sa
   feuille par défaut : le moindre `display: flex` écrit ici l'emporte, et
   l'élément reste visible alors que l'attribut est posé. C'est ce qui a
   silencieusement neutralisé le filtrage des archimonstres. La règle est
   déclarée une fois pour toutes, avant les composants. */
[hidden] { display: none !important; }

/* Le sol : une terre ambrée éclairée par le haut, où le damier de combat court
   à 2 %. C'est la seule géométrie qu'un joueur de Dofus regarde des heures
   durant — ici sentie plutôt que vue. Elle est attachée à la fenêtre : la
   lumière reste en haut quand la page défile. */
body {
    margin: 0;
    background:
        repeating-linear-gradient(63deg,  rgb(255 240 214 / 2.2%) 0 1px, transparent 1px 38px),
        repeating-linear-gradient(-63deg, rgb(255 240 214 / 2.2%) 0 1px, transparent 1px 38px),
        radial-gradient(120% 70% at 50% 0%, var(--ground-top), transparent 62%),
        var(--ground);
    background-attachment: fixed;
    color: var(--text);
    font-family: var(--font-body);
    font-size: 16px;
    line-height: 1.65;
    -webkit-font-smoothing: antialiased;
}

img { max-width: 100%; height: auto; }

a { color: var(--accent); }
a:hover { color: var(--accent-2); }

:where(a, button, input, select, textarea):focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}

/* Le contenu principal doit être atteignable au clavier sans traverser
   les 5 rubriques du rail à chaque page. */
.skip {
    position: absolute;
    left: -9999px;
}
.skip:focus {
    left: 1rem;
    top: 1rem;
    z-index: 100;
    padding: .5rem 1rem;
    background: var(--surface);
    border: 1px solid var(--accent);
    border-radius: var(--radius);
}

/* ------------------------------------------------------- typographie */

.num {
    font-family: var(--font-mono);
    font-variant-numeric: tabular-nums;
}

/* Le losange : la tuile du damier de combat, seul emprunt graphique au jeu. */
.rhombus {
    display: inline-block;
    width: .5rem;
    height: .5rem;
    background: currentColor;
    transform: rotate(45deg);
    flex: none;
}

/* -------------------------------------------------------------- barre */

/* La barre appartient au sol, pas à la feuille : elle n'est pas du contenu, et
   la lecture commence d'autant plus vite. Elle s'aligne sur la feuille par la
   même largeur maximale. */
.bar {
    display: flex;
    align-items: center;
    gap: 1.5rem;
    max-width: min(var(--width), 100% - 2 * var(--gutter));
    margin-inline: auto;
    /* Rembourrage latéral réduit : la marque s'aligne sur le bord de la
       feuille, qui n'en a pas. */
    padding: 1.25rem .75rem .875rem;
    background: var(--bar);
    color: var(--bar-text);
}

/* Le mot-symbole, composé. Le « f » prend l'or vif : c'est la lettre qui
   distingue Tofus de Tofu, et le seul endroit de la barre où la couleur monte
   aussi haut. */
.bar__brand {
    flex: none;
    font-family: var(--font-display);
    font-size: 1.5rem;
    font-weight: 800;
    letter-spacing: -.04em;
    line-height: 1;
    color: var(--bar-text);
    text-decoration: none;
}

.bar__brand i,
.auth__wordmark i { font-style: normal; color: #EFC468; }

.bar__brand:hover { color: var(--bar-text); }

/* Le champ s'éclaircit au lieu de se creuser : sur un sol déjà sombre, creuser
   ne se voit pas. */
.bar__search {
    display: flex;
    flex: 1;
    align-items: center;
    gap: .625rem;
    max-width: 30rem;
    padding: .5rem .875rem;
    border: 1px solid rgb(255 240 214 / 14%);
    border-radius: 2rem;
    background: rgb(255 240 214 / 7%);
    color: var(--bar-text-2);
    font-size: .875rem;
    transition: border-color .18s ease, background-color .18s ease;
}

.bar__search:focus-within {
    border-color: rgb(239 196 104 / 55%);
    background: rgb(255 240 214 / 11%);
}

.bar__search input {
    flex: 1;
    min-width: 0;
    border: 0;
    background: transparent;
    color: var(--bar-text);
    caret-color: #EFC468;
    font: inherit;
    outline: none;
}

/* `opacity: 1` : sans lui, le navigateur éclaircit encore le placeholder et le
   fait passer sous le seuil de contraste. */
.bar__search input::placeholder { color: #C8AC86; opacity: 1; }

.bar__search kbd {
    padding: .0625rem .375rem;
    border: 1px solid rgb(255 240 214 / 18%);
    border-radius: 3px;
    font-family: var(--font-mono);
    font-size: .6875rem;
    color: var(--bar-text-2);
}

.bar__links {
    display: flex;
    /* Sans `align-items`, les enfants s'étirent sur toute la hauteur : le texte
       des liens se cale en haut de leur boîte, tandis que celui de « Mon
       compte » descend du rembourrage de son `summary`. Les centrer les remet
       sur la même ligne, quel que soit leur rembourrage. */
    align-items: center;
    gap: 1.125rem;
    font-size: .875rem;
}

/* Sur le sol, l'opacité fait tomber le contraste sous le seuil : la nuance
   passe par la teinte, pleine. */
.bar__links a { color: var(--bar-text-2); text-decoration: none; }
.bar__links a:hover { color: var(--bar-text); }

/* ------------------------------------------------- le menu compact

   Sous 62 rem, le rail de gauche et les liens de la barre disparaissent tous
   les deux. Sans ce menu, un visiteur sur téléphone n'avait plus aucune
   navigation — il ne pouvait plus quitter la page où Google l'avait déposé
   autrement qu'en revenant en arrière.

   Il est masqué au-dessus de 62 rem, et non simplement caché à l'œil : un
   `display: none` le retire aussi de l'arbre d'accessibilité, sans quoi un
   lecteur d'écran annoncerait deux fois les mêmes rubriques. */

.burger { display: none; position: relative; }

.burger > summary {
    display: grid;
    place-items: center;
    width: 2.25rem;
    height: 2.25rem;
    flex: none;
    border-radius: var(--radius);
    list-style: none;
    cursor: pointer;
}

.burger > summary::-webkit-details-marker { display: none; }
.burger[open] > summary { background: rgb(255 240 214 / 14%); }

/* Les trois barres sont dessinées : une icône importée pour six trames de
   deux pixels serait une requête de plus pour rien. */
.burger__bars,
.burger__bars::before,
.burger__bars::after {
    display: block;
    width: 1.125rem;
    height: 2px;
    border-radius: 2px;
    background: var(--bar-text);
}

.burger__bars { position: relative; }

.burger__bars::before,
.burger__bars::after {
    content: "";
    position: absolute;
    left: 0;
}

.burger__bars::before { top: -6px; }
.burger__bars::after  { top: 6px; }

/* Le panneau descend de la barre et occupe la largeur utile, sans jamais
   déborder de la fenêtre. */
.burger__panel {
    position: absolute;
    left: 0;
    z-index: 50;
    width: max-content;
    min-width: 15rem;
    max-width: calc(100vw - 2.5rem);
    max-height: min(70vh, 34rem);
    overflow-y: auto;
    margin-top: .5rem;
    padding: .625rem .5rem;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--surface);
    box-shadow: var(--shadow);
}

/* Le panneau réemploie la grammaire du rail : mêmes classes, même rendu, une
   seule feuille de style à tenir. */
.burger__panel .rail__group:last-child { margin-bottom: 0; }

@media (width <= 62rem) {
    .burger { display: block; }
}

/* ---------------------------------------------------------- structure */

/* La feuille. Elle flotte sur le sol, tenue par une ombre portée et non par
   une bordure : rien de dur ne borde la lecture. */
.shell {
    display: grid;
    grid-template-columns: 13.5rem minmax(0, 1fr);
    max-width: min(var(--width), 100% - 2 * var(--gutter));
    margin-inline: auto;
    background: var(--bg);
    border-radius: 10px;
    overflow: hidden;
    box-shadow: var(--shadow-sheet);
}

.rail {
    padding: 1.25rem 0;
    border-right: 1px solid var(--border);
    background: var(--surface);
}

.rail__group { padding: 0 1rem; margin-bottom: 1.25rem; }
.burger__panel .rail__group { padding: 0; }

.rail__group > p {
    margin: 0 0 .5rem;
    padding-left: .5rem;
    font-family: var(--font-mono);
    font-size: .625rem;
    letter-spacing: .16em;
    text-transform: uppercase;
    color: var(--text-3);
}

/* Le style porte sur le **groupe de rubriques**, pas sur le rail.
   C'est ce qui permet au menu compact de la barre de réemployer exactement le
   même rendu : il inclut le même gabarit, sans ancêtre `.rail`. Accroché au
   conteneur, ce style laissait ses liens nus dans le panneau. */
.rail__group a {
    display: flex;
    align-items: center;
    gap: .5rem;
    padding: .375rem .5rem;
    border-radius: var(--radius);
    font-size: .875rem;
    color: var(--text-2);
    text-decoration: none;
}

.rail__group a .rhombus { width: .375rem; height: .375rem; color: var(--border-2); }
.rail__group a:hover { background: var(--surface-2); color: var(--text); }

/* ------------------------------------ le rail suit la rubrique courante

   La rubrique active ne porte pas l'ambre générique mais la teinte de sa
   propre rubrique, celle-là même qui tient le bandeau de tête juste à côté.
   Sur une fiche de Frigost, « Donjons » passe au bleu glacé.

   Le voile est tiré de la teinte, à 9 % : au-delà, « Donjons » tombait à
   4,18:1. Le texte, lui, est assombri de 12 % par rapport au bandeau — l'ambre
   d'Amakna est la plus claire du jeu et n'avait pas de marge autrement.

   Repli sur l'accent si `--section` n'est pas défini : retirer le bloc des
   couleurs de rubrique ne casse rien. */

.rail__group a[aria-current="page"] {
    background: color-mix(in srgb, var(--section, var(--accent)) 9%, var(--surface));
    color: color-mix(in srgb, var(--section, var(--accent-2)) 88%, #000);
    font-weight: 600;
}

.rail__group a[aria-current="page"] .rhombus {
    color: color-mix(in srgb, var(--section, var(--accent-2)) 88%, #000);
}

.rail__count {
    margin-left: auto;
    font-family: var(--font-mono);
    font-size: .6875rem;
    color: var(--text-3);
}

.content { padding: 1.75rem 2rem 4rem; min-width: 0; }

/* =====================================================================
   L'en-tête de zone

   La couleur de la zone tient un bandeau plein largeur : elle dit **où l'on
   est** avant qu'on ait lu le titre. C'est la seule surface dense de la
   feuille, et elle sert de respiration entre la barre et la lecture.

   La teinte est choisie par `data-area`, donc en CSS et non dans le gabarit :
   une couleur n'a rien à faire dans un template. Une zone inconnue retombe sur
   l'ambre d'Amakna, qui est la valeur par défaut du bloc.
   ===================================================================== */

/* ---------------------------------------------- la couleur de rubrique

   `--section` est portée par `<body>` : le bandeau de tête et la rubrique
   active du rail la lisent tous les deux, et se répondent donc toujours.

   Elle est déclarée ici et nulle part ailleurs. Retirer ce bloc rend au site
   son ambre uniforme, sans rien casser : tout ce qui la consomme prévoit un
   repli sur l'accent. */

body {
    /* L'ambre d'Amakna, par défaut et pour l'accueil. */
    --section:     #9E5116;
    --section-vif: #E08A28;
    --egg-1:       #F7C56A;
    --egg-2:       #D98A2B;
    --egg-3:       #7A3D0C;
    --egg-shade:   #5C2C08;
    --egg-sheen:   #FFD79A;
}

/* Les couleurs sont déclarées une fois pour deux usages : la page entière, par
   `data-section` sur `<body>`, et la ligne d'une rubrique dans la liste de
   l'accueil, par `data-for`. Les redéclarer ailleurs les ferait diverger le
   jour où l'une bougerait. */
body[data-section="items"],      .sections__row[data-for="items"]      { --section: #8A4614; --section-vif: #C97A2A; }
body[data-section="donjons"],    .sections__row[data-for="donjons"]    { --section: #9E5116; --section-vif: #E08A28; }
body[data-section="chemins"],    .sections__row[data-for="chemins"]    { --section: #7C5A14; --section-vif: #C79A2C; }
body[data-section="challenges"], .sections__row[data-for="challenges"] { --section: #A33328; --section-vif: #DE6A4A; }
body[data-section="quete"],      .sections__row[data-for="quete"]      { --section: #8C2F5E; --section-vif: #C85B95; }
body[data-section="metiers"],    .sections__row[data-for="metiers"]    { --section: #155E5E; --section-vif: #3FA0A0; }
body[data-section="fiches"],     .sections__row[data-for="fiches"]     { --section: #5E4632; --section-vif: #9C7A56; }
body[data-section="guide"],      .sections__row[data-for="guide"]      { --section: #4A4E86; --section-vif: #8186C4; }

/* La zone d'une fiche de donjon prend la main sur la rubrique : le froid de
   Frigost est une exception du jeu, et il doit se voir. */
body[data-area="Frigost"] {
    --section: #1D5F86; --section-vif: #4BA8D8;
    --egg-1: #CDEBF8; --egg-2: #6FB4DC; --egg-3: #14496B;
    --egg-shade: #0E3450; --egg-sheen: #DFF3FD;
}

body[data-area="Nouveaux donjons"] {
    --section: #9A4520; --section-vif: #D9702E;
    --egg-1: #F9D08A; --egg-2: #DE7B33; --egg-3: #71300B;
    --egg-shade: #4C1F08; --egg-sheen: #FFDCA8;
}

/* Les dimensions divines ne sont pas du Monde des Douze : le pourpre le dit. */
body[data-area="Dimensions divines"] {
    --section: #7A2A5C; --section-vif: #B84A8C;
    --egg-1: #F2C2E0; --egg-2: #C05E9B; --egg-3: #5A1B42;
    --egg-shade: #3E0E2C; --egg-sheen: #F8D8EC;
}

.zone-head {
    padding: 2.25rem 2rem 2rem;
    /* Le halo est confiné à droite, sous l'œuf : étalé, il éclaircissait assez
       le bandeau pour faire tomber le titre à 3,5:1. */
    background:
        radial-gradient(34% 105% at 88% 55%,
            color-mix(in srgb, var(--section-vif) 34%, transparent), transparent 72%),
        var(--section);
    color: #FFF6E8;
}

/* Le bandeau déborde le rembourrage du contenu : il occupe toute la largeur de
   la feuille, sinon il ne serait qu'une carte de plus. */
.content > .zone-head:first-child { margin: -1.75rem -2rem 2rem; }

.zone-head__grid {
    display: grid;
    gap: 2.5rem;
    align-items: center;
}

/* La colonne de l'œuf n'existe que s'il y a un œuf : un donjon sans niveau
   connu ne doit pas laisser un vide de 9 rem. */
.zone-head__grid:has(.egg) { grid-template-columns: minmax(0, 1fr) 9rem; }

/* Aucun voile sur ce libellé : sur l'ambre d'Amakna, le crème ne donne que
   5,38:1 — le moindre affaiblissement le fait passer sous le seuil. La
   hiérarchie passe donc par le corps et l'interlettrage, pas par l'opacité. */
.zone-head__where {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: .5rem;
    margin: 0;
    font-family: var(--font-mono);
    font-size: .6875rem;
    font-weight: 500;
    letter-spacing: .18em;
    text-transform: uppercase;
}

.zone-head__where a { color: inherit; text-decoration: none; }
.zone-head__where a:hover { color: inherit; text-decoration: underline; }
.zone-head__where b { font-variant-numeric: tabular-nums; letter-spacing: .06em; }

.zone-head__name {
    margin: .625rem 0 0;
    font-family: var(--font-display);
    font-size: clamp(2rem, 5vw, 3.25rem);
    font-weight: 800;
    line-height: 1;
    letter-spacing: -.04em;
    text-wrap: balance;
}

.zone-head__boss { margin: .5rem 0 0; font-size: 1rem; }
.zone-head__boss b { font-weight: 600; }

/* L'œuf porte le niveau : c'est la première question posée à un donjon, et la
   seule qui mérite d'être lisible à trois mètres. Il prend la teinte de sa
   zone — un œuf ambré sur un bandeau glacé jurerait. */
.egg { position: relative; width: 9rem; height: 11rem; justify-self: center; }
.egg svg { position: absolute; inset: 0; width: 100%; height: 100%; }

/* Les teintes de la coquille, appliquées depuis la feuille de style : posées
   dans les attributs SVG, elles auraient dépendu de la prise en charge de
   `var()` dans un attribut de présentation. */
.egg__stops stop:nth-child(1) { stop-color: var(--egg-1); }
.egg__stops stop:nth-child(2) { stop-color: var(--egg-2); }
.egg__stops stop:nth-child(3) { stop-color: var(--egg-3); }
.egg__shade { fill: var(--egg-shade); }
.egg__sheen { stroke: var(--egg-sheen); }

.egg__text {
    position: absolute;
    inset: 0;
    display: grid;
    place-content: center;
    text-align: center;
    color: #FFF6E8;
}

.egg__text span {
    display: block;
    font-family: var(--font-mono);
    font-size: .5rem;
    letter-spacing: .2em;
    text-transform: uppercase;
}

.egg__text b {
    display: block;
    font-family: var(--font-display);
    font-size: 2.75rem;
    font-weight: 800;
    line-height: 1;
    letter-spacing: -.05em;
    font-variant-numeric: tabular-nums;
}

/* Un seul moment, orchestré : le bandeau se déploie, puis l'œuf paraît. Rien
   d'autre ne bouge sur la page. */
@media (prefers-reduced-motion: no-preference) {
    .zone-head { animation: zone-unfold .55s cubic-bezier(.16, .84, .28, 1) both; }
    .egg { animation: egg-appear .7s cubic-bezier(.2, .9, .3, 1) .25s both; }

    @keyframes zone-unfold {
        from { opacity: 0; transform: translateY(-8px); }
        to   { opacity: 1; transform: none; }
    }

    @keyframes egg-appear {
        from { opacity: 0; transform: translateY(14px) scale(.94); }
        to   { opacity: 1; transform: none; }
    }
}

@media (width <= 62rem) {
    .content > .zone-head:first-child { margin: -1.25rem -1.25rem 1.5rem; }
}

@media (width <= 48rem) {
    .zone-head { padding: 1.75rem 1.25rem 1.5rem; }
    .zone-head__grid:has(.egg) { grid-template-columns: 1fr; gap: 1.5rem; }
    .egg { justify-self: start; width: 7rem; height: 8.5rem; }
    .egg__text b { font-size: 2.25rem; }
}

/* =====================================================================
   Le bandeau de rubrique

   Le même bandeau que sur une fiche de donjon, en plus bas : pas d'œuf, pas de
   gardien, juste la rubrique et son chapô. Il tient le principe emprunté au
   Plakatstil — le fond dit où l'on est avant qu'on ait lu le titre — sur les
   huit rubriques et non sur les seuls donjons.

   Il est posé par `templates/pages/section.html.twig` et, pour la recherche
   d'items qui a son propre gabarit, par `templates/pages/items.html.twig`.
   ===================================================================== */

.section-head {
    padding: 1.75rem 2rem 1.5rem;
    background:
        radial-gradient(34% 105% at 88% 55%,
            color-mix(in srgb, var(--section-vif, var(--accent)) 34%, transparent), transparent 72%),
        var(--section, var(--accent));
    color: #FFF6E8;
}

.content > .section-head:first-child { margin: -1.75rem -2rem 2rem; }

.section-head__name {
    margin: 0;
    font-family: var(--font-display);
    font-size: clamp(1.75rem, 4vw, 2.75rem);
    font-weight: 800;
    line-height: 1;
    letter-spacing: -.04em;
    text-wrap: balance;
}

/* Le chapô reste en crème plein : sur l'ambre d'Amakna, le voile le ferait
   passer sous le seuil, comme la ligne de situation de la fiche. */
.section-head__lead {
    max-width: 44rem;
    margin: .75rem 0 0;
    font-size: .9375rem;
    line-height: 1.6;
}

.section-head__count {
    margin: 0 0 .5rem;
    font-family: var(--font-mono);
    font-size: .6875rem;
    font-weight: 500;
    letter-spacing: .18em;
    text-transform: uppercase;
}

@media (width <= 62rem) {
    .content > .section-head:first-child { margin: -1.25rem -1.25rem 1.5rem; }
    .section-head { padding: 1.5rem 1.25rem 1.25rem; }
}

/* ------------------------------------------------------------- entête */

.breadcrumb {
    margin: 0 0 .75rem;
    font-family: var(--font-mono);
    font-size: .6875rem;
    letter-spacing: .14em;
    text-transform: uppercase;
    color: var(--text-3);
}
.breadcrumb a { color: var(--text-2); text-decoration: none; }
.breadcrumb a:hover { color: var(--text); }

.title {
    margin: 0 0 1.25rem;
    font-family: var(--font-display);
    font-weight: 800;
    font-size: clamp(1.75rem, 3.6vw, 2.5rem);
    letter-spacing: -.035em;
    line-height: 1.05;
    text-wrap: balance;
}

/* Ce qu'un joueur vérifie avant d'entrer : niveau, salles, clé requise. */
.facts { display: flex; flex-wrap: wrap; gap: .5rem; margin: 0 0 2rem; padding: 0; list-style: none; }

.fact {
    display: flex;
    align-items: baseline;
    gap: .5rem;
    padding: .4375rem .75rem;
    border: 1px solid var(--border);
    border-radius: 2rem;
    background: var(--surface);
}

.fact__label {
    font-family: var(--font-mono);
    font-size: .625rem;
    letter-spacing: .12em;
    text-transform: uppercase;
    color: var(--text-3);
}

.fact__value {
    font-family: var(--font-mono);
    font-variant-numeric: tabular-nums;
    font-size: .9375rem;
    font-weight: 600;
}

.fact--key { background: var(--accent-tint); border-color: transparent; }
.fact--key .fact__value { color: var(--accent-2); }
/* Sans opacité : voilée, l'étiquette repassait sous le seuil de contraste. */
.fact--key .fact__label { color: var(--accent-2); }

.section-title {
    display: flex;
    align-items: center;
    gap: .75rem;
    margin: 2.25rem 0 1rem;
    font-family: var(--font-mono);
    font-size: .6875rem;
    font-weight: 500;
    letter-spacing: .18em;
    text-transform: uppercase;
    color: var(--text-3);
}
.section-title::after { content: ""; flex: 1; height: 1px; background: var(--border); }

/* ------------------------------------------------------------ cartes */

.grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(17.5rem, 1fr)); gap: .75rem; }

.card {
    display: flex;
    gap: .875rem;
    padding: .875rem;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--surface);
    transition: border-color .18s ease, transform .18s ease;
}
.card:hover { border-color: var(--border-2); transform: translateY(-1px); }

.card--link { text-decoration: none; color: inherit; }

/* Le lien étiré : le titre est le seul `<a>`, mais son `::after` couvre toute
   la carte. On garde le « clic n'importe où » sans imbriquer deux éléments
   cliquables l'un dans l'autre — ce que le HTML interdit et qui casse la
   navigation au clavier. */
.card { position: relative; }
.card__body { flex: 1; min-width: 0; }

.card__link { text-decoration: none; color: inherit; }

.card__link::after {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: inherit;
}

/* Le crayon repasse au-dessus de la zone étirée : sans `position`, il serait
   recouvert et le clic partirait sur la fiche. */
.card__edit {
    position: relative;
    align-self: flex-start;
    flex: none;
    padding: .125rem .375rem;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    color: var(--text-3);
    text-decoration: none;
    font-size: .875rem;
    line-height: 1.3;
}

.card__edit:hover { border-color: var(--accent); color: var(--accent); }

/* Le compteur de la recherche instantanée : discret, mais il doit bouger sous
   les doigts pour qu'on comprenne que la frappe agit. */
.section-count {
    margin: 0 0 .75rem;
    font-family: var(--font-mono);
    font-size: .75rem;
    color: var(--text-3);
}

.section-count .num { color: var(--text); font-weight: 600; }

.section-empty { margin: 1.5rem 0; color: var(--text-3); }

/* ----------------------------------------------------------------- l'accueil

   Deux composants qui ne servent que là, et qui n'ont donc pas à peser sur le
   reste : le champ de recherche et la liste des rubriques.

   L'accueil n'est pas une porte d'entrée — le visiteur arrive d'un moteur, sur
   une page profonde. Celui qui atterrit ici a plutôt échoué à trouver : d'où un
   champ de recherche large, avant toute chose. */

.home-search { margin: 0 0 1.5rem; }

.home-search label {
    display: block;
    margin-bottom: .375rem;
    font-family: var(--font-mono);
    font-size: .6875rem;
    letter-spacing: .12em;
    text-transform: uppercase;
    color: var(--text-3);
}

.home-search__row { display: flex; gap: .5rem; }

.home-search input {
    flex: 1;
    min-width: 0;
    padding: .625rem .875rem;
    border: 1px solid var(--border-2);
    border-radius: var(--radius);
    background: var(--surface-2);
    color: var(--text);
    font: inherit;
    font-size: 1rem;
}

.home-search input:focus { border-color: var(--accent); outline: none; }

/* Les rubriques en **réglure continue**, et non en grille de cartes : la
   direction refuse « la grille de cartes indifférenciées du wiki de jeu ».
   Un seul filet court d'une ligne à l'autre, et chaque rubrique se distingue
   par sa couleur portée sur la tranche gauche — pas par une boîte de plus. */
.sections {
    margin: 0 0 2rem;
    padding: 0;
    list-style: none;
    border-top: 1px solid var(--border);
}

.sections__row { border-bottom: 1px solid var(--border); }

.sections__link {
    display: grid;
    grid-template-columns: minmax(7rem, auto) 1fr auto;
    align-items: baseline;
    gap: .25rem 1rem;
    /* Le filet de couleur est un fond, pas une bordure : une bordure
       s'additionnerait au filet horizontal et ferait un angle disgracieux. */
    padding: .8125rem .875rem .8125rem 1.125rem;
    background: linear-gradient(var(--section), var(--section)) left / 3px 100% no-repeat;
    color: inherit;
    text-decoration: none;
    transition: background-size .18s ease, padding-left .18s ease;
}

/* Au survol, le filet s'épaissit au lieu que la ligne se colore : l'état est
   encodé par la forme du trait, jamais par la seule teinte. */
.sections__link:hover,
.sections__link:focus-visible {
    background-size: 6px 100%;
    padding-left: 1.375rem;
    outline: none;
}

.sections__name { font-weight: 600; font-size: 1.0625rem; }
.sections__what { color: var(--text-2); font-size: .875rem; }

.sections__count {
    justify-self: end;
    font-family: var(--font-mono);
    font-size: .8125rem;
    color: var(--text-3);
}

/* Sous 34 rem, la colonne du milieu n'a plus la place de vivre à côté du nom :
   la description passe dessous, et le compte reste aligné à droite du nom. */
@media (width <= 34rem) {
    .sections__link { grid-template-columns: 1fr auto; }
    .sections__what { grid-column: 1 / -1; }
}

/* Un renvoi mis en avant : sobre, mais assez présent pour ne pas se confondre
   avec le texte d'introduction juste au-dessus.

   La couleur est **engagée à l'échelle du bloc** — une surface teintée bordée
   d'un filet d'un pixel — et non posée en onglet latéral épais. C'est ce que
   la direction emprunte au Plakatstil, et cela évite au passage le liseré de
   trois pixels qui jure avec les angles arrondis. */
.callout {
    margin: 0 0 1.25rem;
    padding: .625rem .875rem;
    border: 1px solid var(--accent);
    border-radius: var(--radius);
    background: var(--accent-tint);
    font-size: .9375rem;
}

/* Sur sa propre teinte, l'ambre plein tombe à 4,09:1 : les liens y prennent
   l'ambre profond, qui donne 5,57:1. */
.callout a,
.notice a { color: var(--accent-2); text-decoration: none; }
.callout a:hover,
.notice a:hover { text-decoration: underline; }

/* Les étoiles vides sont dessinées : « ★★ » seul ne dit pas sur combien. */
.star { color: var(--border-2); }
.star--on { color: var(--accent); }

.legend {
    margin: -1.25rem 0 1.75rem;
    font-size: .875rem;
    color: var(--text-2);
}

.legend__stars { color: var(--accent); margin-right: .375rem; }

/* =====================================================================
   Administration

   Délibérément distincte du site : on doit voir qu'on modifie, pas qu'on
   consulte. Le liseré n'est pas un ornement, c'est le repère.
   ===================================================================== */

/* L'entree vers l'administration, dans la barre membre : elle doit se
   distinguer des outils de jeu qui l'entourent. */
.member__admin { color: var(--fire) !important; }

.admin { --admin: #B3352C; }

.admin__bar {
    display: flex;
    align-items: center;
    gap: 1rem;
    flex-wrap: wrap;
    margin-bottom: 1.5rem;
    padding: .625rem .875rem;
    /* La barre entière prend la teinte au lieu de porter un liseré de trois
       pixels sur un bloc arrondi. Le repère est plus fort — on voit d'un coup
       d'œil qu'on modifie — et il tient sur toute la largeur. */
    border: 1px solid var(--admin);
    border-radius: var(--radius);
    background: var(--fire-tint);
}

/* Sur la teinte rouge, l'ambre plein tombe à 4,13:1. */
.admin__links a { color: var(--accent-2); }

.admin__badge {
    font-family: var(--font-mono);
    font-size: .625rem;
    letter-spacing: .14em;
    text-transform: uppercase;
    color: var(--admin);
}

.admin__links { display: flex; gap: 1rem; flex: 1; font-size: .875rem; }
.admin__links a { text-decoration: none; }
.admin__links a[aria-current="page"] { color: var(--text); font-weight: 600; }

.admin__who { font-family: var(--font-mono); font-size: .75rem; color: var(--text-3); }

.admin__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    flex-wrap: wrap;
}

.admin__head .title { margin-bottom: 0; }

.tag {
    display: inline-block;
    padding: .0625rem .4375rem;
    border: 1px solid var(--border-2);
    border-radius: 1rem;
    font-family: var(--font-mono);
    font-size: .625rem;
    color: var(--text-3);
    white-space: nowrap;
}

.tag--live { border-color: var(--air); color: var(--air); }
.tag--draft { border-color: var(--accent); color: var(--accent); }
.tag--pending { border-color: var(--admin); color: var(--admin); }

.admin-form { margin-bottom: 2rem; }

.admin-group {
    margin: 0 0 1.25rem;
    padding: 1rem 1.25rem 1.25rem;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--surface);
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
    gap: .875rem;
}

.admin-group legend {
    grid-column: 1 / -1;
    padding: 0 .375rem;
    font-family: var(--font-mono);
    font-size: .625rem;
    letter-spacing: .14em;
    text-transform: uppercase;
    color: var(--text-3);
}

/* Le bloc qui retire du site se distingue : on n'y arrive pas par mégarde. */
.admin-group--danger { border-color: var(--fire); }
.admin-group--danger legend { color: var(--fire); }

.admin-field { display: flex; flex-direction: column; gap: .25rem; }
.admin-field--wide { grid-column: 1 / -1; }

.admin-field__label {
    font-size: .8125rem;
    font-weight: 600;
    color: var(--text-2);
}

.admin-field__label em {
    font-weight: 400;
    font-style: normal;
    color: var(--text-3);
}

.admin-field input,
.admin-field select,
.admin-field textarea {
    padding: .4375rem .625rem;
    border: 1px solid var(--border-2);
    border-radius: var(--radius);
    background: var(--bg);
    color: var(--text);
    font: inherit;
    font-size: .875rem;
}

.admin-field textarea { font-family: var(--font-mono); font-size: .8125rem; line-height: 1.6; resize: vertical; }

.admin-field__error { font-size: .8125rem; color: var(--fire); }

.admin-actions { display: flex; align-items: center; gap: .75rem; flex-wrap: wrap; }

.admin-state { grid-column: 1 / -1; margin: 0; font-size: .9375rem; }
.admin-remove { grid-column: 1 / -1; display: flex; flex-direction: column; gap: .625rem; }

/* Le renvoi vers l'edition, sur les fiches publiques. */
.edit-bar {
    margin: 0 0 1rem;
    padding: .4375rem .75rem;
    border: 1px dashed var(--border-2);
    border-radius: var(--radius);
    font-size: .875rem;
}

.edit-bar a { text-decoration: none; }
.edit-bar a:hover { text-decoration: underline; }

/* ------------------------------------------- éditeur source + aperçu */

.editor {
    grid-column: 1 / -1;
    border: 1px solid var(--border-2);
    border-radius: var(--radius);
    overflow: hidden;
}

.editor__bar {
    display: flex;
    flex-wrap: wrap;
    gap: .25rem;
    padding: .375rem;
    border-bottom: 1px solid var(--border);
    background: var(--surface-2);
}

.editor__tool {
    padding: .1875rem .5rem;
    border: 1px solid var(--border);
    border-radius: 3px;
    background: var(--surface);
    color: var(--text-2);
    font-family: var(--font-mono);
    font-size: .75rem;
    cursor: pointer;
}

.editor__tool:hover { border-color: var(--accent); color: var(--accent); }
.editor__toggle { margin-left: auto; }

/* Deux colonnes de largeur égale, empilées dès que l'écran ne suit plus :
   côte à côte sous 60 caractères de large, ni la source ni l'aperçu ne sont
   lisibles. */
.editor__panes { display: grid; grid-template-columns: 1fr 1fr; min-height: 24rem; }

@media (max-width: 60rem) {
    .editor__panes { grid-template-columns: 1fr; }
}

.editor--solo .editor__panes { grid-template-columns: 1fr; }
.editor--solo .editor__preview { display: none; }

.editor__panes textarea {
    border: 0;
    border-right: 1px solid var(--border);
    border-radius: 0;
    resize: vertical;
}

.editor__preview {
    padding: 1rem 1.25rem;
    overflow: auto;
    max-height: 40rem;
    background: var(--bg);
}

/* L'aperçu montre le rendu réel, images comprises : une capture manquante s'y
   voit tout de suite, plutôt qu'après publication. */
.editor__preview img { max-width: 100%; height: auto; }
.editor__preview table { width: 100%; border-collapse: collapse; }
.editor__preview td,
.editor__preview th { border: 1px solid var(--border); padding: .25rem .5rem; }

/* Le champ portrait : le numero, et l'image a cote. */
.portrait { display: flex; align-items: center; gap: .5rem; }
.portrait input { flex: 1; min-width: 0; }

.portrait__preview {
    width: 2.75rem;
    height: 2.75rem;
    flex: none;
    object-fit: contain;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--bg);
}

/* Les droits : une case par rubrique du site, y compris celles qui n'ont pas
   encore d'ecran d'edition — elles sont grisees et marquees. */
.member-card {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    justify-content: space-between;
    gap: 1rem;
    margin-bottom: .625rem;
    padding: .875rem 1rem;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--surface);
}

.member-card__who { display: flex; flex-direction: column; min-width: 10rem; }
.member-card__meta { font-size: .8125rem; color: var(--text-3); }

.rights { display: flex; align-items: flex-start; gap: .75rem; flex-wrap: wrap; flex: 1; }

.rights__grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr));
    gap: .25rem .75rem;
    flex: 1;
    min-width: 0;
}

.rights__item {
    display: flex;
    align-items: center;
    gap: .375rem;
    font-size: .8125rem;
    cursor: pointer;
}

.rights__item input { accent-color: var(--accent); }
.rights__name { flex: 1; }

.rights__count {
    font-size: .6875rem;
    color: var(--text-3);
}

/* Une rubrique sans ecran d'edition reste visible : c'est ce qui montre le
   chemin restant. Mais elle ne se coche pas. */
.rights__item--soon { color: var(--text-3); cursor: not-allowed; }

.rights__soon {
    padding: 0 .3125rem;
    border: 1px solid var(--border);
    border-radius: 1rem;
    font-family: var(--font-mono);
    font-size: .5625rem;
    text-transform: uppercase;
    letter-spacing: .08em;
}

.button--small { padding: .3125rem .75rem; font-size: .8125rem; }

/* Le differentiel : l'avant en retrait, l'apres mis en avant. */
.diff td { vertical-align: top; font-size: .8125rem; }
.diff__field { font-family: var(--font-mono); font-size: .75rem; color: var(--text-3); white-space: nowrap; }
.diff__before { color: var(--text-3); text-decoration: line-through; text-decoration-color: var(--fire); }
.diff__after { color: var(--text); }

.button--danger { background: var(--fire); color: #fff; border-color: var(--fire); }
.button--danger:hover { background: #8F2A22; }

.thumb {
    display: grid;
    place-items: center;
    width: 3.25rem;
    height: 3.25rem;
    flex: none;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--surface-2);
    font-family: var(--font-mono);
    font-size: .625rem;
    color: var(--text-3);
    overflow: hidden;
}

/* Les portraits du jeu sont détourés sur fond transparent et de proportions
   très variables : `contain` les laisse entiers plutôt que de les rogner, et
   la case garde partout la même taille. */
.thumb--portrait { background: var(--bg); }

.thumb img {
    width: 100%;
    height: 100%;
    object-fit: contain;
    /* Les vignettes du site actuel sont de petites captures : un léger
       agrandissement leur évite de flotter au milieu de la case. */
    transform: scale(1.08);
}

.card__name { margin: 0 0 .0625rem; font-size: .9375rem; font-weight: 600; }

.card__meta {
    margin: 0 0 .5rem;
    font-family: var(--font-mono);
    font-variant-numeric: tabular-nums;
    font-size: .75rem;
    color: var(--text-3);
}

/* ------------------------------------------------- résistances / jets */

.resistances { display: flex; flex-wrap: wrap; gap: .375rem; }

.resistance {
    display: flex;
    align-items: center;
    gap: .3125rem;
    padding: .0625rem .375rem;
    border-radius: 3px;
    font-family: var(--font-mono);
    font-variant-numeric: tabular-nums;
    font-size: .75rem;
}
.resistance .rhombus { width: .375rem; height: .375rem; }

/* Chaque élément porte sa couleur pleine sur sa teinte voilée. */
.el-earth   { color: var(--earth);   background: var(--earth-tint); }
.el-fire    { color: var(--fire);    background: var(--fire-tint); }
.el-water   { color: var(--water);   background: var(--water-tint); }
.el-air     { color: var(--air);     background: var(--air-tint); }
.el-neutral { color: var(--neutral); background: var(--neutral-tint); }

/* La fiche de jets : l'élément signature. Un joueur ne demande pas
   « combien de Force ? » mais « est-ce que ce jet est bon ? ». */
.roll { padding: .5rem 0; }
.roll + .roll { border-top: 1px solid var(--border); }

.roll__head { display: flex; align-items: center; gap: .5rem; margin-bottom: .375rem; }
.roll__head .rhombus { width: .4375rem; height: .4375rem; }
.roll__stat { font-size: .875rem; }

.roll__range {
    margin-left: auto;
    font-family: var(--font-mono);
    font-size: .6875rem;
    color: var(--text-3);
}

.roll__value {
    min-width: 2.5rem;
    text-align: right;
    font-family: var(--font-mono);
    font-variant-numeric: tabular-nums;
    font-size: .9375rem;
    font-weight: 700;
}

.track { height: 5px; border-radius: 3px; overflow: hidden; }
.track__fill { height: 100%; border-radius: 3px; }

/* ------------------------------------------------------------ prose */

.prose { max-width: 44rem; color: var(--text-2); }
.prose p { margin: 0 0 .75rem; }
.prose p:last-child { margin-bottom: 0; }
.prose--lead { margin-bottom: 2rem; }

/* ------------------------------------------------------------- pied */

/* Le pied appartient au sol, comme la barre : la feuille se termine où le
   contenu se termine. */
.footer {
    padding: 1.75rem 1.75rem 2.5rem;
    color: var(--bar-text-2);
    font-size: .875rem;
}
.footer__inner { max-width: min(var(--width), 100% - 2 * var(--gutter)); margin-inline: auto; }
.footer a { color: var(--bar-text); }

/* Les liens utiles au-dessus de la mention légale, séparés par des points
   médians dessinés en CSS : un séparateur écrit dans le gabarit serait lu par
   les lecteurs d'écran comme un mot. */
.footer__links { display: flex; flex-wrap: wrap; gap: .5rem 1rem; margin-bottom: .875rem; }

.footer__links a + a::before {
    content: "·";
    margin-right: .5rem;
    color: var(--bar-text-2);
}

.footer__legal { margin: 0; }

/* ------------------------------------------------------------ erreur */

.error { max-width: 34rem; margin: 6rem auto; padding: 0 1.5rem; text-align: center; }
.error__code {
    font-family: var(--font-mono);
    font-size: 4rem;
    font-weight: 700;
    line-height: 1;
    color: var(--accent);
}
.error h1 { margin: 1rem 0 .5rem; font-family: var(--font-display); font-size: 1.5rem; letter-spacing: -.02em; }
.error p { color: var(--text-2); }
.error__back { margin-top: 1.5rem; }

/* ------------------------------------------------------- adaptation */

@media (width <= 62rem) {
    .shell { grid-template-columns: 1fr; }
    .rail { display: none; }
    .bar__links { display: none; }
    .content { padding: 1.25rem 1.25rem 3rem; }
    .bar { padding: 1rem 1.25rem .875rem; }
}

/* Sous 48 rem, la feuille prend toute la largeur : garder une marge de sol sur
   un écran de téléphone, c'est perdre de la lecture pour montrer un fond. */
@media (width <= 48rem) {
    :root { --gutter: 0px; }
    .shell { border-radius: 0; box-shadow: none; }
    .bar, .footer__inner { padding-inline: 1.25rem; }
}

@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        animation-duration: .01ms !important;
        transition-duration: .01ms !important;
    }
}

/* ---------------------------------------------------- fiche d'item */

.card--panel { display: block; padding: .25rem 1rem; }

.ingredients { display: flex; flex-wrap: wrap; gap: .5rem; margin: 0; padding: 0; list-style: none; }

.ingredient {
    display: flex;
    align-items: baseline;
    gap: .5rem;
    padding: .375rem .75rem;
    border: 1px solid var(--border);
    border-radius: 2rem;
    background: var(--surface);
    font-size: .875rem;
}
.ingredient a { text-decoration: none; }
.ingredient a:hover { text-decoration: underline; }

.ingredient__qty {
    font-family: var(--font-mono);
    font-variant-numeric: tabular-nums;
    font-size: .75rem;
    color: var(--text-3);
}

/* ------------------------------------------------------ recherche */

.filters {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: .75rem;
    margin-bottom: 1rem;
    padding: 1rem;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--surface);
}

.filters__field { display: flex; flex-direction: column; gap: .25rem; flex: 1 1 10rem; }
.filters__field--narrow { flex: 0 0 7rem; }

.filters__field > span {
    font-family: var(--font-mono);
    font-size: .625rem;
    letter-spacing: .12em;
    text-transform: uppercase;
    color: var(--text-3);
}

/* Accroché au champ et non au conteneur : le bloc des listes d'archimonstres
   réemploie `filters__field` sans être un `.filters`, et ses champs seraient
   sortis sans mise en forme. */
.filters__field input,
.filters__field select {
    padding: .4375rem .625rem;
    border: 1px solid var(--border-2);
    border-radius: var(--radius);
    background: var(--bg);
    color: var(--text);
    font: inherit;
    font-size: .875rem;
}

.filters button {
    padding: .5rem 1.125rem;
    border: 0;
    border-radius: var(--radius);
    background: var(--accent);
    color: var(--on-accent);
    font: inherit;
    font-weight: 600;
    font-size: .875rem;
    cursor: pointer;
}
.filters button:hover { background: var(--accent-2); }

/* ------------------------------------------------------- tableaux */

.results { width: 100%; border-collapse: collapse; font-size: .875rem; }

.results th {
    padding: .5rem .625rem;
    border-bottom: 1px solid var(--border-2);
    text-align: left;
    font-family: var(--font-mono);
    font-size: .625rem;
    font-weight: 500;
    letter-spacing: .14em;
    text-transform: uppercase;
    color: var(--text-3);
}

.results td { padding: .5rem .625rem; border-bottom: 1px solid var(--border); }
.results tbody tr:hover { background: var(--surface); }
.results .n { text-align: right; }
.results a { text-decoration: none; }
.results a:hover { text-decoration: underline; }

.scroll-x { overflow-x: auto; }

/* ------------------------------------------------ contenu repris */

/* Le HTML vient du site actuel : il porte ses propres balises, sans
   classes. On l'habille par sélecteurs d'éléments, dans un conteneur
   isolé pour ne pas déborder sur le reste de l'interface. */
.article { max-width: 46rem; color: var(--text-2); }

.article h2,
.article h3 {
    margin: 2rem 0 .75rem;
    font-family: var(--font-display);
    font-weight: 700;
    letter-spacing: -.02em;
    color: var(--text);
    text-wrap: balance;
}
.article h2 { font-size: 1.375rem; }
.article h3 { font-size: 1.125rem; }

.article p { margin: 0 0 .875rem; }
.article ul, .article ol { margin: 0 0 1rem; padding-left: 1.5rem; }
.article li { margin-bottom: .3125rem; }
.article strong, .article b { color: var(--text); font-weight: 600; }

.article img {
    max-width: 100%;
    height: auto;
    border-radius: var(--radius);
    margin: .5rem 0;
}

.article table {
    width: 100%;
    border-collapse: collapse;
    margin: 1rem 0;
    font-size: .875rem;
}
.article th, .article td { padding: .4375rem .625rem; border: 1px solid var(--border); text-align: left; }
.article th { background: var(--surface); color: var(--text); font-weight: 600; }

/* Les pages du legacy portent des styles en dur hérités de 2010. */
.article [style*="color"] { color: inherit !important; }
.article [bgcolor] { background: var(--surface) !important; }

/* --------------------------------------------------- espace membre */

.panel {
    max-width: 26rem;
    margin: 2rem auto 4rem;
    padding: 1.75rem;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--surface);
    box-shadow: var(--shadow);
}

.form { display: flex; flex-direction: column; gap: 1rem; }
.form--inline { flex-direction: row; margin-top: 2.5rem; }

.form__field { display: flex; flex-direction: column; gap: .3125rem; }

.form__field > span {
    font-family: var(--font-mono);
    font-size: .625rem;
    letter-spacing: .12em;
    text-transform: uppercase;
    color: var(--text-3);
}

.form input,
.form textarea {
    padding: .625rem .75rem;
    border: 1px solid var(--border-2);
    border-radius: var(--radius);
    background: var(--bg);
    color: var(--text);
    font: inherit;
}

/* Le message de contact s'étire à la verticale, jamais à l'horizontale : une
   zone plus large que la colonne casserait la mise en page. */
.form textarea { resize: vertical; min-height: 9rem; line-height: 1.6; }

/* Le leurre anti-robot — voir `Service\FormGuard`.

   Il n'est pas en `type="hidden"` : les robots sérieux ignorent les champs
   cachés, alors qu'ils remplissent ce qui ressemble à un champ ordinaire. Il
   est donc masqué **par la feuille de style**, et sorti du parcours au clavier
   comme des lecteurs d'écran par le gabarit.

   `position: absolute` plutôt que `display: none` : quelques robots vérifient
   la seconde, et un champ franchement invisible les fait renoncer. Celui-ci
   existe pour le navigateur, il est seulement hors de l'écran. */
.trap {
    position: absolute;
    left: -9999px;
    width: 1px;
    height: 1px;
    overflow: hidden;
}

.form button {
    padding: .625rem 1.25rem;
    border: 0;
    border-radius: var(--radius);
    background: var(--accent);
    color: var(--on-accent);
    font: inherit;
    font-weight: 600;
    cursor: pointer;
}
.form button:hover { background: var(--accent-2); }

.form__aside { margin: 1.25rem 0 0; font-size: .875rem; }

.form__note {
    margin: 1rem 0 0;
    padding-top: 1rem;
    border-top: 1px solid var(--border);
    font-size: .8125rem;
    color: var(--text-3);
}

/* Les messages d'un affichage à l'autre : succès, erreur de saisie. */
.flashes { margin: 0 0 1.25rem; padding: 0; list-style: none; display: flex; flex-direction: column; gap: .5rem; }

.flash {
    padding: .625rem .875rem;
    border-radius: var(--radius);
    font-size: .875rem;
}

.flash--error   { color: var(--fire);    background: var(--fire-tint); }
.flash--success { color: var(--air);     background: var(--air-tint); }
.flash--info    { color: var(--neutral); background: var(--neutral-tint); }

/* =====================================================================
   Pages d'identification
   Aucun rail, aucune recherche : une page de connexion a une seule
   chose à faire.
   ===================================================================== */

.auth {
    display: grid;
    place-items: center;
    min-height: 100vh;
    padding: 2rem 1.25rem;
    /* Le même sol que partout ailleurs, mais la lumière descend un peu plus
       bas : la page n'a qu'un objet, et il est au centre. */
    background:
        repeating-linear-gradient(63deg,  rgb(255 240 214 / 2.2%) 0 1px, transparent 1px 38px),
        repeating-linear-gradient(-63deg, rgb(255 240 214 / 2.2%) 0 1px, transparent 1px 38px),
        radial-gradient(90% 60% at 50% 8%, var(--ground-top), transparent 68%),
        var(--ground);
}

.auth__stage { width: 100%; max-width: 25rem; }

.auth__brand {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: .875rem;
    margin-bottom: 1.75rem;
    text-decoration: none;
}

.auth__brand img:first-child { height: 4.5rem; width: auto; }

/* Plus grand que dans la barre : ici le mot-symbole n'accompagne pas la
   navigation, il tient la page à lui seul. */
.auth__wordmark {
    font-family: var(--font-display);
    font-size: 2rem;
    font-weight: 800;
    letter-spacing: -.04em;
    line-height: 1;
    color: var(--bar-text);
}

.auth__card {
    overflow: hidden;
    border: 1px solid var(--border);
    border-radius: 10px;
    background: var(--surface);
    box-shadow: var(--shadow);
}

/* Le filet élémentaire : les cinq couleurs de Dofus, rappel du code de
   lecture employé partout ailleurs. Seul ornement de la page. */
.auth__thread { display: flex; height: 3px; }
.auth__thread i { flex: 1; background: currentColor; }

.auth__body { padding: 1.75rem; }

.auth__title {
    margin: 0 0 1.25rem;
    font-family: var(--font-display);
    font-weight: 800;
    font-size: 1.5rem;
    letter-spacing: -.03em;
    text-wrap: balance;
}

.auth__lead {
    margin: -.5rem 0 1.5rem;
    color: var(--text-2);
    font-size: .9375rem;
}

.auth__footer {
    padding: 1.125rem 1.75rem;
    border-top: 1px solid var(--border);
    background: var(--surface-2);
    font-size: .875rem;
}

.auth__note {
    margin: .875rem 0 0;
    color: var(--text-3);
    font-size: .8125rem;
    line-height: 1.55;
}

.auth__back {
    margin: 1.5rem 0 0;
    text-align: center;
    font-size: .8125rem;
}
/* Ce lien est hors de la carte, donc sur le sol : il prend les teintes de la
   barre et non celles de la feuille. */
.auth__back a { color: var(--bar-text-2); text-decoration: none; }
.auth__back a:hover { color: var(--bar-text); }

/* ------------------------------------------------------- formulaires */

.form { display: flex; flex-direction: column; gap: 1.125rem; }

.form__field { display: flex; flex-direction: column; gap: .4375rem; }

.form__field > span {
    font-family: var(--font-mono);
    font-size: .625rem;
    letter-spacing: .14em;
    text-transform: uppercase;
    color: var(--text-3);
}

.form input {
    width: 100%;
    padding: .6875rem .8125rem;
    border: 1px solid var(--border-2);
    border-radius: var(--radius);
    background: var(--bg);
    color: var(--text);
    font: inherit;
    transition: border-color .15s ease, box-shadow .15s ease;
}

.form input::placeholder { color: var(--text-3); opacity: .6; }

.form input:focus {
    outline: none;
    border-color: var(--accent);
    box-shadow: 0 0 0 3px var(--accent-tint);
}

.button {
    display: inline-block;
    padding: .6875rem 1.25rem;
    border: 0;
    border-radius: var(--radius);
    background: var(--accent);
    color: var(--on-accent);
    font: inherit;
    font-weight: 600;
    text-align: center;
    text-decoration: none;
    cursor: pointer;
    transition: background .15s ease;
}
.button:hover { background: var(--accent-2); color: var(--on-accent); }
.button--full { width: 100%; margin-top: .375rem; }

/* Les messages d'un affichage à l'autre : succès, erreur de saisie. */
.flashes { margin: 0 0 1.25rem; padding: 0; list-style: none; display: flex; flex-direction: column; gap: .5rem; }

.flash {
    padding: .625rem .875rem;
    border-radius: var(--radius);
    font-size: .875rem;
    line-height: 1.45;
}

.flash--error   { color: var(--fire);    background: var(--fire-tint); }
.flash--success { color: var(--air);     background: var(--air-tint); }
.flash--info    { color: var(--neutral); background: var(--neutral-tint); }

/* =====================================================================
   Espace membre
   ===================================================================== */

.member {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 1rem;
    margin-bottom: 1.75rem;
    padding: .75rem 1rem;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--surface);
}

.member__identity { display: flex; align-items: baseline; gap: .5rem; }
.member__name { font-weight: 700; }

.member__role {
    padding: .0625rem .4375rem;
    border-radius: 2rem;
    background: var(--accent-tint);
    color: var(--accent-2);
    font-family: var(--font-mono);
    font-size: .625rem;
    letter-spacing: .1em;
    text-transform: uppercase;
}

.member__tools { display: flex; flex-wrap: wrap; gap: .25rem; flex: 1; }

.member__tools a {
    padding: .3125rem .6875rem;
    border-radius: 2rem;
    color: var(--text-2);
    font-size: .875rem;
    text-decoration: none;
}
.member__tools a:hover { background: var(--surface-2); color: var(--text); }
.member__tools a[aria-current="page"] { background: var(--accent-tint); color: var(--accent-2); font-weight: 600; }

.member__logout button {
    padding: .3125rem .875rem;
    border: 1px solid var(--border-2);
    border-radius: 2rem;
    background: transparent;
    color: var(--text-3);
    font: inherit;
    font-size: .8125rem;
    cursor: pointer;
}
.member__logout button:hover { border-color: var(--fire); color: var(--fire); }

/* ------------------------------------------------ grille d'archimonstres */

.archi-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(17rem, 1fr));
    gap: .5rem;
}

/*
   La carte, en grille : le nom occupe une ligne entière, le reste suit.

   Coincé entre le portrait et le compteur, le nom n'avait qu'une quinzaine
   de caractères — or **268 des 306 archimonstres Dofus 3 en portent plus de
   seize**, pour une moyenne de vingt et un maximum de vingt-neuf. La
   quasi-totalité arrivait tronquée.

   La carte n'y gagne pas en hauteur : le corps perd la ligne que le nom
   reprend au-dessus.
*/
.archi {
    display: grid;
    grid-template-columns: auto 1fr auto;
    align-items: center;
    column-gap: .75rem;
    row-gap: .1875rem;
    padding: .5rem .625rem;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--surface);
    /* Les non-capturés reculent : l'œil doit trouver ce qui manque. Pas
       plus bas que 72 % : en dessous, le nom passe sous le seuil de
       contraste sur le sable. */
    opacity: .72;
    transition: opacity .15s ease, border-color .15s ease;
}


.archi--owned { opacity: 1; border-color: var(--border-2); }
.archi--saving { border-color: var(--accent); }
.archi--failed { border-color: var(--fire); background: var(--fire-tint); }

/* Colonne `auto` de la grille : la largeur fixe suffit, plus besoin de
   `flex: none` depuis que la carte n'est plus une boîte flexible. */
.archi__portrait {
    display: grid;
    place-items: center;
    width: 3rem;
    height: 3rem;
    border-radius: var(--radius);
    background: var(--surface-2);
}
.archi__portrait img { max-width: 100%; height: auto; }

.archi__body { min-width: 0; }

/* Le nom traverse la carte : c'est ce qu'on lit en premier, et il n'a plus
   à se partager la ligne avec le portrait et le compteur. */
.archi__name {
    grid-column: 1 / -1;
    margin: 0;
    min-width: 0;
    font-size: .875rem;
    font-weight: 600;
}

/* Le nom ouvre le détail. Il garde l'apparence d'un titre : un bouton dessiné
   comme tel, sur 306 cartes, ferait une page de boutons. Le soulignement au
   survol suffit à dire qu'il se clique. */
.archi__open {
    display: flex;
    align-items: center;
    gap: .3125rem;
    font: inherit;
    color: inherit;
    background: none;
    border: 0;
    padding: 0;
    margin: 0;
    cursor: pointer;
    text-align: left;
    max-width: 100%;
    min-width: 0;
}

/* L'ellipse porte sur le nom, pas sur le bouton : sur le bouton, elle
   rognerait l'œil avant le texte. */
.archi__label {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.archi__open:hover { color: var(--accent-2); text-decoration: underline; }
.archi__open:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 2px; }

/*
   La carte du boss ouvre la grille.

   Elle se distingue par un liseré d'accent et une étiquette, pas par une
   taille ou une couleur de fond : c'est une carte comme les autres, et
   c'est son rang qu'on signale, pas sa nature.
*/
.card--boss {
    border-color: var(--accent);
    box-shadow: inset 3px 0 0 var(--accent);
}

.card__boss {
    margin: .0625rem 0 .1875rem;
    font-family: var(--font-mono);
    font-size: .625rem;
    letter-spacing: .12em;
    text-transform: uppercase;
    color: var(--accent-2);
}

/* Le même geste sur les cartes de monstre d'une fiche de donjon : le nom
   ouvre le détail, sans se dessiner comme un bouton. */
.card__open {
    display: inline-flex;
    align-items: center;
    gap: .3125rem;
    font: inherit;
    color: inherit;
    background: none;
    border: 0;
    padding: 0;
    margin: 0;
    cursor: pointer;
    text-align: left;
}
.card__open:hover { color: var(--accent-2); text-decoration: underline; }
.card__open:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 2px; }

/*
   L'œil dit qu'il y a quelque chose à voir.

   Un nom souligné au survol ne se découvre qu'en passant dessus — encore
   faut-il soupçonner qu'il s'y trouve quelque chose. L'œil se voit sans
   qu'on cherche, et reste assez discret pour ne pas concurrencer le nom.

   Une classe autonome et non `card__eye` : il sert aussi les cartes
   d'archimonstres, qui ne sont pas des `.card`. Le tracé vit dans un
   partiel, pour la même raison.

   `stroke` et non `fill` : le trait garde la même épaisseur quelle que
   soit la taille du texte, et suit sa couleur. Dimensionné en `em`, il
   suit aussi celle du nom qu'il accompagne — .875 rem sur une carte
   d'archimonstre, davantage sur une fiche de donjon.
*/
.eye {
    width: .875em;
    height: .875em;
    flex: none;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.9;
    stroke-linecap: round;
    stroke-linejoin: round;
    /* Plus effacé que sur une fiche de donjon : la grille en aligne trois
       cents, et à pleine opacité ils feraient une colonne de points. */
    opacity: .35;
    transition: opacity .15s ease;
}
.card__open .eye { opacity: .45; }

.card__open:hover .eye,
.card__open:focus-visible .eye,
.archi__open:hover .eye,
.archi__open:focus-visible .eye { opacity: 1; }

@media (prefers-reduced-motion: reduce) {
    .eye { transition: none; }
}

.archi__base, .archi__stage {
    margin: 0;
    font-size: .75rem;
    color: var(--text-3);
}

/* Le nom du monstre ordinaire et le niveau tiennent sur une ligne : ce sont
   deux façons de dire la même chose — de quelle créature il s'agit. */
.archi__base {
    display: flex;
    align-items: baseline;
    gap: .375rem;
    min-width: 0;
}
.archi__base > .archi__level {
    flex: none;
    font-size: .6875rem;
    color: var(--text-2);
}

/* La ligne de repérage : où le trouver, à quelle étape de la quête, avec
   quelle pierre. Elle s'efface d'un cran sous le nom, et laisse tomber ses
   éléments à la ligne plutôt que de déborder. */
.archi__meta {
    margin: .0625rem 0 0;
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: .1875rem .5rem;
    font-size: .6875rem;
    color: var(--text-3);
    min-width: 0;
}

.archi__area {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
/* La sous-zone précise la zone sans lui disputer la lecture : c'est la zone
   qu'on cherche d'abord des yeux, le lieu exact ne sert qu'une fois sur place. */
.archi__sub { color: var(--border-2); }

/* Le compteur des sous-zones tues : discret, mais il doit se distinguer du
   nom de zone pour qu'on ne le lise pas comme sa suite. */
.archi__more { color: var(--border-2); }

.archi__stage { font-size: .6875rem; }

/* La pierre est la seule information qui décide d'un achat avant de partir :
   elle porte donc la couleur, et rien d'autre sur cette ligne. */
.archi__stone {
    flex: none;
    padding: 0 .3125rem;
    border-radius: 999px;
    background: var(--accent-tint);
    color: var(--accent-2);
}

.archi__count { display: flex; align-items: center; gap: .125rem; }

.archi__button {
    width: 1.75rem;
    height: 1.75rem;
    border: 1px solid var(--border-2);
    border-radius: var(--radius);
    background: var(--bg);
    color: var(--text-2);
    font: inherit;
    font-size: 1rem;
    line-height: 1;
    cursor: pointer;
    transition: background .12s ease, color .12s ease;
}
.archi__button:hover { background: var(--accent-tint); color: var(--accent-2); border-color: var(--accent); }
.archi__button:active { transform: scale(.94); }

.archi__quantity {
    min-width: 1.75rem;
    text-align: center;
    font-size: .9375rem;
    font-weight: 700;
}

.archi--owned .archi__quantity { color: var(--accent); }

/* =====================================================================
   Le panneau de détail d'un archimonstre

   Un tiroir latéral, pas une fenêtre modale : avec trois cents lignes on
   compare en naviguant, et la grille doit rester lisible derrière. Il ne
   pose donc aucun voile et ne bloque rien.

   Sous 900 px il devient une feuille en bas d'écran : un tiroir de 22 rem
   sur un téléphone ne laisserait plus rien de la grille.
   ===================================================================== */

.archi-panel {
    position: fixed;
    top: 0;
    right: 0;
    z-index: 40;
    width: min(22rem, 100vw);
    height: 100dvh;
    overflow-y: auto;
    overscroll-behavior: contain;
    background: var(--surface-2);
    border-left: 1px solid var(--border-2);
    box-shadow: -8px 0 28px rgb(36 22 8 / .16);
}
.archi-panel[hidden] { display: none; }
.archi-panel:focus { outline: none; }

.archi-panel__bar {
    position: sticky;
    top: 0;
    z-index: 1;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: .5rem;
    padding: .625rem .875rem;
    background: var(--ground);
    color: var(--on-accent);
}
.archi-panel__heading {
    margin: 0;
    font-size: .9375rem;
    font-weight: 600;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.archi-panel__close {
    flex: none;
    width: 1.75rem;
    height: 1.75rem;
    display: grid;
    place-items: center;
    font: inherit;
    font-size: 1.25rem;
    line-height: 1;
    color: inherit;
    background: none;
    border: 1px solid transparent;
    border-radius: var(--radius);
    cursor: pointer;
}
.archi-panel__close:hover { background: rgb(255 255 255 / .12); }
.archi-panel__close:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

.archi-panel__body { padding: .875rem; }
.archi-panel__empty { margin: 0; color: var(--text-3); font-size: .8125rem; }

.archi-panel__head { display: flex; align-items: center; gap: .75rem; margin-bottom: .875rem; }
.archi-panel__portrait {
    flex: none;
    width: 4.5rem;
    height: 4.5rem;
    object-fit: contain;
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: var(--radius);
}
.archi-panel__name { margin: 0; font-size: 1.0625rem; line-height: 1.2; }
.archi-panel__base { margin: .1875rem 0 0; font-size: .8125rem; color: var(--text-3); }

/* Les chiffres en colonnes plutôt qu'en phrase : on les compare d'un
   archimonstre à l'autre, on ne les lit pas. */
.archi-panel__facts {
    margin: 0 0 1rem;
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(6rem, 1fr));
    gap: .5rem;
}
.archi-panel__facts > div {
    padding: .375rem .5rem;
    background: var(--bg);
    border-radius: var(--radius);
}
.archi-panel__facts dt {
    font-size: .625rem;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--text-3);
}
.archi-panel__facts dd { margin: .0625rem 0 0; font-size: .9375rem; font-weight: 600; }

.archi-panel__block { margin-bottom: 1rem; }
.archi-panel__block:last-child { margin-bottom: 0; }

.archi-panel__title {
    margin: 0 0 .375rem;
    font-size: .75rem;
    letter-spacing: .05em;
    text-transform: uppercase;
    color: var(--text-2);
    border-bottom: 1px solid var(--border);
    padding-bottom: .1875rem;
}
/* La zone accompagne le titre : elle situe la liste qui suit sans lui voler
   une ligne. */
.archi-panel__zone { text-transform: none; letter-spacing: 0; color: var(--text-3); font-weight: 400; }
.archi-panel__count { color: var(--text-3); font-weight: 400; }

.archi-panel__zones { margin: 0; padding: 0; list-style: none; font-size: .8125rem; }
.archi-panel__zones li { padding: .125rem 0; color: var(--text-2); }

.archi-panel__drops { margin: 0; padding: 0; list-style: none; font-size: .8125rem; }
.archi-panel__drops li {
    display: flex;
    align-items: center;
    gap: .5rem;
    padding: .25rem 0;
    border-bottom: 1px dotted var(--border);
}
/* Le nom prend la place qui reste, le taux se cale à droite. */
.archi-panel__drops .archi-panel__objet { flex: 1 1 auto; }
/* La vignette de la ressource. Un cadre de taille fixe pour toutes, y
   compris quand l'image manque : sans lui, les noms ne s'aligneraient plus
   d'une ligne à l'autre. */
.archi-panel__icon {
    flex: none;
    width: 2rem;
    height: 2rem;
    object-fit: contain;
    border-radius: var(--radius);
    background: var(--bg);
}
.archi-panel__icon--vide { border: 1px dashed var(--border); background: none; }

/* Le nom cède avant le taux : « Sachet de Feuilles de salace » ne doit pas
   pousser son pourcentage hors de la feuille sur un téléphone. */
.archi-panel__objet { min-width: 0; overflow-wrap: anywhere; }
.archi-panel__drops li:last-child { border-bottom: 0; }
.archi-panel__drops a { color: var(--accent-2); }
.archi-panel__rate { flex: none; color: var(--text-3); }

/*
   Sous 62 rem, le tiroir devient une feuille en bas d'écran.

   Même seuil que le reste de la page — c'est là que `.content` resserre ses
   marges et que le bandeau passe sur une colonne. Un tiroir de 22 rem y
   couvrirait déjà la moitié de la grille, sans la faire refluer puisqu'il
   est en `fixed` : on masquerait des cartes sans que rien ne le dise.

   Une feuille laisse au contraire la grille entière au-dessus d'elle.
*/
@media (width <= 62rem) {
    .archi-panel {
        top: auto;
        bottom: 0;
        left: 0;
        width: 100%;
        height: min(70dvh, 34rem);
        border-left: 0;
        border-top: 1px solid var(--border-2);
        border-radius: var(--radius) var(--radius) 0 0;
        box-shadow: 0 -8px 28px rgb(36 22 8 / .2);
    }

    /* La feuille recouvre le bas de la page tant qu'elle est ouverte. Sans
       cette réserve, les dernières cartes resteraient inatteignables : on
       défile jusqu'en bas et elles sont dessous. */
    .has-panel .archi-grid { padding-bottom: min(70dvh, 34rem); }
}

.button--ghost {
    background: transparent;
    border: 1px solid var(--border-2);
    color: var(--text-2);
    font-weight: 500;
}
.button--ghost:hover { background: var(--surface-2); color: var(--text); border-color: var(--accent); }

@media (max-width: 40rem) {
    .member { flex-direction: column; align-items: flex-start; }
    .member__tools { width: 100%; }
}

/* ------------------------------------------- menu déroulant du compte */

/* En `details` natif : clavier, sans script, et statique — la page reste
   cachable, ce qu'un menu rendu selon l'état de connexion interdirait. */
.menu { position: relative; }

.menu > summary {
    padding: .1875rem .5rem;
    border-radius: var(--radius);
    color: var(--bar-text);
    font-size: .875rem;
    list-style: none;
    cursor: pointer;
    opacity: .75;
    user-select: none;
}
.menu > summary::-webkit-details-marker { display: none; }
.menu > summary::after { content: " ▾"; font-size: .75rem; }
.menu > summary:hover { opacity: 1; }
.menu[open] > summary { background: rgb(255 240 214 / 14%); opacity: 1; }

.menu__panel {
    position: absolute;
    right: 0;
    z-index: 40;
    display: flex;
    flex-direction: column;
    min-width: 13rem;
    margin-top: .5rem;
    padding: .375rem;
    border: 1px solid var(--border-2);
    border-radius: var(--radius);
    background: var(--surface);
    box-shadow: var(--shadow);
}

.menu__panel a {
    padding: .4375rem .625rem;
    border-radius: var(--radius);
    color: var(--text-2);
    font-size: .875rem;
    text-decoration: none;
    white-space: nowrap;
    opacity: 1;
}
.menu__panel a:hover { background: var(--surface-2); color: var(--text); }

/* ------------------------------------------------- Dofus Ocre, progression */

/* Le dofus se colore à mesure que la collection se remplit : deux exemplaires
   de la même image superposés, celui du dessus en couleur et découpé par le
   bas à hauteur de `--fill`. Aucune image supplémentaire à produire. */
/* =====================================================================
   Le bandeau de l'outil d'archimonstres

   Même principe que le bandeau de rubrique des donjons : la couleur situe
   avant qu'on ait lu. Sur le sol ambré plutôt que sur une couleur de
   section — un espace membre n'appartient à aucune rubrique.

   Il rassemble ce qui situe : titre, avancement, liste suivie. Ce qui agit
   descend sous le dépliant. Sept blocs se succédaient avant la grille ;
   il en reste trois.
   ===================================================================== */

.archi-head {
    /* Exactement le traitement du bandeau de rubrique, avec l'ocre des
       donjons : c'est la couleur du Dofus Ocre, et un espace membre n'a pas
       de `data-section` d'où tirer la sienne. */
    --section:     #9E5116;
    --section-vif: #E08A28;

    display: grid;
    grid-template-columns: auto 1fr;
    align-items: center;
    gap: .75rem 1.75rem;
    padding: 1.25rem 1.5rem;
    background:
        radial-gradient(34% 105% at 88% 55%,
            color-mix(in srgb, var(--section-vif) 34%, transparent), transparent 72%),
        var(--section);
    color: #FFF6E8;
}

/* Le bandeau déborde jusqu'aux bords de la page. Pas de `:first-child` : la
   barre du compte le précède toujours, il n'est donc jamais premier. */
.content > .archi-head { margin: 0 -2rem 1.5rem; }

/*
   Placement explicite : le sélecteur de liste remonte à hauteur du titre.

   Il occupait une ligne à lui seul, séparée par un filet, pour un menu qui
   n'a qu'un nom de personnage à montrer. Or c'est le même propos que le
   titre — de quelle collection on parle — et l'espace à droite du titre
   était vide.
*/
.archi-head__intro { grid-column: 1; grid-row: 1; }

.archi-head__kicker {
    margin: 0 0 .1875rem;
    font-family: var(--font-mono);
    font-size: .625rem;
    letter-spacing: .18em;
    text-transform: uppercase;
    color: rgb(255 246 232 / .78);
}

.archi-head__title {
    margin: 0;
    font-family: var(--font-display);
    font-size: clamp(1.375rem, 3vw, 1.875rem);
    font-weight: 800;
    line-height: 1.05;
    letter-spacing: -.03em;
}

/*
   L'œuf et son pourcentage : la première chose qu'on regarde en arrivant.

   Sélecteur en deux classes, et non `.archi-head__gauge` seul : la règle
   `.ocre` est déclarée plus bas dans ce fichier, et à spécificité égale
   c'est la dernière qui gagne. Une première version posait donc un
   rectangle de sable clair, bordé, au milieu du bandeau — l'image, elle,
   est bien détourée.
*/
.archi-head .ocre { margin: 0; padding: 0; border: 0; background: none; }
.archi-head .ocre__percent { color: #FFF6E8; }
.archi-head .ocre__caption { color: rgb(255 246 232 / .78); }
/* La part non acquise s'efface sans disparaître : sur l'ocre, un simple
   `opacity(.3)` la noierait dans le fond. */
.archi-head .ocre__grey { filter: grayscale(1) brightness(1.9) opacity(.3); }

/* Les compteurs secondaires, en ligne : ils accompagnent le pourcentage,
   ils ne le concurrencent pas. */
.archi-head__facts {
    display: flex;
    flex-wrap: wrap;
    gap: .25rem 1.25rem;
    margin: 0;
    padding: 0;
    list-style: none;
}
.archi-head__facts li { display: flex; align-items: baseline; gap: .375rem; }
.archi-head__facts span {
    font-size: .6875rem;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: rgb(255 246 232 / .78);
}
.archi-head__facts strong { font-size: 1.0625rem; font-weight: 700; }

/* La liste suivie sur une ligne : c'est le geste de chaque visite. */
.archi-head__list {
    grid-column: 2;
    grid-row: 1;
    justify-self: end;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .5rem;
}
.archi-head__list label {
    font-size: .6875rem;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: rgb(255 246 232 / .78);
}
/* Le menu se règle sur son contenu. Il s'étirait jusqu'à 26 rem pour
   afficher un nom de personnage, et le vide se voyait. */
.archi-head__list select {
    flex: 0 1 auto;
    min-width: 0;
    max-width: 16rem;
    font: inherit;
    font-size: .875rem;
    padding: .3125rem .5rem;
    color: var(--text);
    background: var(--surface-2);
    border: 1px solid var(--border-2);
    border-radius: var(--radius);
}

.archi-head__gauge { grid-column: 1; grid-row: 2; }
.archi-head__facts { grid-column: 2; grid-row: 2; }

/* Les filtres, dans le bandeau : filtrer est le geste le plus fréquent de
   l'outil — on l'ouvre pour savoir ce qu'il reste à capturer. */
.archi-filters {
    grid-column: 1 / -1;
    grid-row: 3;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .5rem;
    padding-top: .875rem;
    border-top: 1px solid rgb(255 246 232 / .22);
}

.archi-filters__search {
    flex: 1 1 12rem;
    min-width: 0;
    font: inherit;
    font-size: .875rem;
    padding: .3125rem .5rem;
    color: var(--text);
    background: var(--surface-2);
    border: 1px solid var(--border-2);
    border-radius: var(--radius);
}

.archi-filters__stage { display: flex; align-items: center; gap: .375rem; }
.archi-filters__stage > span {
    font-size: .6875rem;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: rgb(255 246 232 / .78);
}
.archi-filters__stage select {
    font: inherit;
    font-size: .875rem;
    padding: .3125rem .5rem;
    color: var(--text);
    background: var(--surface-2);
    border: 1px solid var(--border-2);
    border-radius: var(--radius);
}

/* Le bouton reste pour ceux qui n'ont pas de script ; le script le masque. */
.archi-filters .filters__submit { flex: none; }

/*
   Trois choix exclusifs, côte à côte.

   Des boutons radio habillés, et non des boutons : le choix se garde au
   rechargement, le formulaire le transmet sans script, et le clavier les
   parcourt aux flèches comme il s'y attend.
*/
.segmented {
    display: flex;
    flex: none;
    border: 1px solid var(--border-2);
    border-radius: var(--radius);
    overflow: hidden;
    background: var(--surface-2);
}

.segmented__choice { display: flex; }

/* Le bouton radio disparaît mais reste focalisable : `display: none` le
   retirerait de l'ordre de tabulation. */
.segmented__choice input {
    position: absolute;
    width: 1px;
    height: 1px;
    opacity: 0;
    pointer-events: none;
}

.segmented__choice span {
    display: block;
    padding: .3125rem .625rem;
    font-size: .8125rem;
    color: var(--text-2);
    cursor: pointer;
    border-left: 1px solid var(--border);
}
.segmented__choice:first-child span { border-left: 0; }
.segmented__choice span:hover { background: var(--accent-tint); color: var(--accent-2); }
.segmented__choice input:checked + span {
    background: var(--accent);
    color: var(--on-accent);
    font-weight: 600;
}
.segmented__choice input:focus-visible + span { outline: 2px solid #FFF6E8; outline-offset: -2px; }

@media (width <= 62rem) {
    .content > .archi-head { margin: 0 -1.25rem 1.25rem; }
    .archi-head { grid-template-columns: 1fr; padding: 1.125rem 1.25rem; }
    .archi-filters__search { flex-basis: 100%; }

    /* Une seule colonne : les blocs reprennent l'ordre du document, et le
       placement explicite les y empêcherait. */
    .archi-head__intro,
    .archi-head__list,
    .archi-head__gauge,
    .archi-head__facts,
    .archi-filters { grid-column: auto; grid-row: auto; justify-self: stretch; }

    .archi-head__list select { max-width: none; flex: 1 1 10rem; }
}

/*
   Les très petits écrans — sous 30 rem, soit la largeur d'un téléphone tenu
   à la verticale.

   Les trois choix d'affichage refusaient de rétrécir : à 320 px, une fois
   les marges retirées, ils touchaient le bord. Ils s'étalent désormais sur
   toute la largeur et se partagent la place à parts égales.
*/
@media (width <= 30rem) {
    .archi-filters__stage { flex: 1 1 100%; }
    .archi-filters__stage select { flex: 1 1 auto; min-width: 0; }

    .segmented { flex: 1 1 100%; }
    .segmented__choice { flex: 1 1 0; }
    .segmented__choice span { text-align: center; padding-inline: .375rem; }

    /* Le pourcentage garde son rang, mais cesse d'écraser la légende. */
    .archi-head .ocre { gap: .875rem; }
    .archi-head .ocre__percent { font-size: 1.5rem; }
    .archi-head__facts { gap: .25rem .875rem; }
}

.ocre {
    --fill: 0%;

    display: flex;
    align-items: center;
    gap: 1.25rem;
    margin-bottom: 1.75rem;
    padding: 1rem 1.25rem;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--surface);
}

.ocre__art { position: relative; width: 5rem; height: 5rem; flex: none; }

.ocre__art img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: contain;
}

/* La part non acquise s'efface. Sur le thème sombre elle était assombrie ;
   sur du sable, assombrir la ferait au contraire avancer — c'est l'inverse de
   ce qu'elle doit dire. */
.ocre__grey { filter: grayscale(1) opacity(.3); }

.ocre__color {
    clip-path: inset(calc(100% - var(--fill)) 0 0 0);
    transition: clip-path .45s cubic-bezier(.2, .8, .2, 1);
}

@media (prefers-reduced-motion: reduce) {
    .ocre__color { transition: none; }
}

.ocre__percent {
    margin: 0;
    font-size: 1.75rem;
    font-weight: 700;
    line-height: 1.1;
    color: var(--accent);
    letter-spacing: -.02em;
}

.ocre__caption { margin: .1875rem 0 0; font-size: .875rem; color: var(--text-2); }

.archi-empty { margin: 1.5rem 0; color: var(--text-3); }

/* ------------------------------------------------- outils du compte */

.tools {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
    gap: .75rem;
    margin-bottom: 2rem;
}

/* La carte entière est le lien : viser un « ouvrir » de trois mots au clavier
   ou au doigt est plus difficile qu'il n'y paraît. */
.tool {
    --fill: 0%;

    display: flex;
    flex-direction: column;
    gap: .25rem;
    padding: .875rem 1rem 1rem;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--surface);
    color: var(--text);
    text-decoration: none;
    transition: border-color .15s ease, background .15s ease;
}

.tool:hover {
    border-color: var(--border-2);
    background: var(--surface-2);
    color: var(--text);
}

.tool__title { font-weight: 600; }

.tool__note {
    font-size: .8125rem;
    color: var(--text-3);
    min-height: 2.4em;
}

.tool__figures {
    display: flex;
    align-items: baseline;
    gap: .375rem;
    margin: .375rem 0 .5rem;
}

.tool__figures strong { font-size: 1.375rem; }
.tool__total { flex: 1; font-size: .8125rem; color: var(--text-3); }
.tool__percent { font-size: .875rem; font-weight: 600; color: var(--accent); }

/* ------------------------------------------- les listes d'archimonstres

   Un joueur a rarement un seul personnage, et chacun a sa collection.

   **Deux étages, parce que les gestes n'ont pas le même rang.** Choisir le
   personnage qu'on regarde est le sujet de la page — on le fait à chaque
   visite. Renommer, ajouter et supprimer sont occasionnels. Une première
   version leur donnait à tous la même largeur et le même poids : quatre blocs
   alignés qui ne disaient pas par où commencer.

   Le rythme dit la même chose que la hiérarchie : l'étage du haut respire,
   celui du bas est serré. */

/* Les gestes rares — renommer, ajouter, supprimer, valider la quête — sous
   un dépliant. `<details>` plutôt qu'un script : il s'ouvre sans JavaScript,
   se referme au rechargement, et le clavier le connaît déjà. */
.lists {
    margin-bottom: 1.25rem;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--surface);
}

.lists__summary {
    padding: .5rem .875rem;
    font-size: .8125rem;
    font-weight: 600;
    color: var(--text-2);
    cursor: pointer;
    list-style-position: inside;
}
.lists__summary:hover { color: var(--accent-2); }
.lists__summary:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; border-radius: var(--radius); }
.lists[open] .lists__summary { border-bottom: 1px solid var(--border); }
.lists .lists__manage { padding: .875rem; }

/* -------- l'étage du haut : quelle liste je regarde */

.lists__label {
    display: block;
    margin-bottom: .375rem;
    font-family: var(--font-mono);
    font-size: .625rem;
    letter-spacing: .14em;
    text-transform: uppercase;
    color: var(--text-3);
}

.lists__pick { display: flex; align-items: center; gap: .5rem; }

/* Le sélecteur porte le sujet de la page : il est plus grand que les champs
   ordinaires, et sa flèche est dessinée plutôt que laissée au navigateur —
   celle du système appartient à aucune direction artistique.

   `appearance: none` retire aussi la flèche native : sans le fond dessiné
   ci-dessous, il ne resterait rien pour dire que le champ se déroule. */
.lists__pick select {
    flex: 1 1 auto;
    max-width: 26rem;
    padding: .5rem 2.25rem .5rem .75rem;
    appearance: none;
    border: 1px solid var(--border-2);
    border-radius: var(--radius);
    background:
        linear-gradient(45deg, transparent 50%, currentColor 50%) calc(100% - 1.0625rem) 55% / 5px 5px no-repeat,
        linear-gradient(135deg, currentColor 50%, transparent 50%) calc(100% - .6875rem) 55% / 5px 5px no-repeat,
        var(--bg);
    color: var(--text);
    font: inherit;
    font-size: 1rem;
    font-weight: 600;
    cursor: pointer;
}

.lists__pick select:hover { border-color: var(--accent); }

/* -------- l'étage du bas : les gestes sur les listes

   Séparé par un filet et non par un simple écart : les deux étages ne sont pas
   deux groupes voisins, c'est un sujet et ce qu'on peut en faire. */

.lists__manage {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .5rem 1.25rem;
    margin-top: 1rem;
    padding-top: .875rem;
    border-top: 1px solid var(--border);
}

.lists__action { display: flex; align-items: center; gap: .375rem; }

/* Le retrait se détache du reste : c'est le seul geste irréversible. */
.lists__action--end { margin-left: auto; }

.lists__action input[type="text"] {
    width: 11rem;
    padding: .3125rem .5rem;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--bg);
    color: var(--text);
    font: inherit;
    font-size: .8125rem;
}

.lists__action input[type="text"]:focus { border-color: var(--accent); }
.lists__full { margin: 0; font-size: .8125rem; color: var(--text-3); }

/* Le bouton « Ouvrir » ne sert que sans script : avec, le choix agit à la
   sélection. Il est donc masqué par le script, jamais par le CSS — sans quoi
   il disparaîtrait aussi pour qui n'a pas de script. */
.lists__pick button[hidden] { display: none; }

@media (width <= 40rem) {
    /* Sur un téléphone, les champs prennent la largeur plutôt que de se
       tasser à onze caractères. */
    .lists__action { flex: 1 1 100%; }
    .lists__action input[type="text"] { flex: 1; width: auto; }
    .lists__action--end { margin-left: 0; }
}

/* ------------------------------------- la carte à listes du tableau de bord

   Une carte par outil, que des flèches font parcourir : le tableau de bord
   garde sa taille qu'on suive un personnage ou dix. */

.tool--lists { display: flex; flex-direction: column; gap: .25rem; padding-bottom: .75rem; }

.tool__nav {
    display: flex;
    align-items: center;
    gap: .5rem;
    margin: .125rem 0 .25rem;
}

.tool__arrow {
    display: grid;
    place-items: center;
    width: 1.5rem;
    height: 1.5rem;
    flex: none;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    color: var(--text-2);
    font-size: 1rem;
    line-height: 1;
    text-decoration: none;
}

.tool__arrow:hover { border-color: var(--accent); color: var(--accent); }
.tool__which { font-size: .75rem; color: var(--text-3); }

/* Défilement horizontal à aimant : sur un écran tactile on fait glisser, sans
   qu'aucun script n'ait besoin de fonctionner. */
.tool__track {
    display: flex;
    gap: .75rem;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    scrollbar-width: none;
}

.tool__track::-webkit-scrollbar { display: none; }

.tool__panel {
    display: flex;
    flex-direction: column;
    gap: .25rem;
    flex: 0 0 100%;
    scroll-snap-align: start;
    color: inherit;
    text-decoration: none;
}

.tool__who { font-weight: 600; }

.tool__start {
    margin-top: .375rem;
    font-size: .875rem;
}

/* ------------------------------------------- l'effacement de son compte

   Replié par défaut, mais présent et nommé : un droit qu'il faut chercher n'en
   est pas tout à fait un. Le liseré rouge dit ce que le bloc fait avant qu'on
   l'ouvre. */

/* Le rouge est dans la bordure entière et dans le libellé, pas dans un onglet
   latéral épais : celui-ci jure avec les angles arrondis, et il ne dit rien
   que la couleur du texte ne dise déjà. */
.danger-zone {
    margin-bottom: 2rem;
    border: 1px solid color-mix(in srgb, var(--fire) 35%, var(--border));
    border-radius: var(--radius);
    background: var(--surface);
}

.danger-zone__summary {
    padding: .75rem 1rem;
    color: var(--fire);
    font-weight: 600;
    cursor: pointer;
}

.danger-zone__body {
    padding: 0 1rem 1.25rem;
    border-top: 1px solid var(--border);
    max-width: 34rem;
}

.danger-zone__body p { font-size: .9375rem; }
.danger-zone__note { color: var(--text-3); font-size: .875rem; }
.danger-zone .form { margin-top: 1rem; }

/* ------------------------------------------------------------- quêtes */

.title__owner { font-weight: 400; color: var(--text-2); }

/* Même pilotage que le Dofus Ocre : une seule variable, `--fill`, que le
   script met à jour après chaque clic. */
.progress {
    --fill: 0%;

    margin-bottom: 1.5rem;
    padding: 1rem 1.25rem;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--surface);
}

/* `display: block` explicite sur les deux.
   La page des quêtes les écrit en `<div>`, le tableau de bord en `<span>` — et
   sur une boîte en ligne, `width` et `height` n'ont aucun effet. Les barres du
   tableau de bord restaient donc vides quelle que soit la progression. */
.progress__bar {
    display: block;
    height: .5rem;
    border-radius: 1rem;
    background: var(--accent-tint);
    overflow: hidden;
}

/* La barre se remplit par `scale` et non par `width`.

   Animer une largeur oblige le navigateur à recalculer la mise en page à
   chaque image ; une mise à l'échelle se fait sur le compositeur. La propriété
   `scale` accepte un pourcentage, ce que la fonction `scaleX()` ne fait pas —
   c'est ce qui permet de garder `--fill` en pourcentage, tel que le script et
   les gabarits l'écrivent, et tel que le Dofus Ocre s'en sert de son côté. */
.progress__fill {
    display: block;
    width: 100%;
    height: 100%;
    border-radius: inherit;
    background: linear-gradient(90deg, var(--accent-2), var(--accent));
    transform-origin: left center;
    scale: var(--fill) 1;
    transition: scale .45s cubic-bezier(.2, .8, .2, 1);
}

@media (prefers-reduced-motion: reduce) {
    .progress__fill { transition: none; }
}

.progress__legend {
    display: flex;
    align-items: baseline;
    gap: .5rem;
    margin: .75rem 0 0;
    font-size: .875rem;
    color: var(--text-2);
}

.progress__legend strong { font-size: 1.25rem; color: var(--text); }
.progress__total { flex: 1; }

.progress__percent {
    font-size: 1.25rem;
    font-weight: 700;
    color: var(--accent);
}

/* Le lien de partage : le champ est en lecture seule et se sélectionne au
   clic — c'est ce qu'on en fait dans neuf cas sur dix. */
.share {
    display: flex;
    align-items: center;
    gap: .75rem;
    flex-wrap: wrap;
    margin-bottom: 1.25rem;
}

.share__label {
    font-family: var(--font-mono);
    font-size: .625rem;
    letter-spacing: .12em;
    text-transform: uppercase;
    color: var(--text-3);
}

.share__url {
    flex: 1;
    min-width: 18rem;
    padding: .4375rem .75rem;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--bg);
    color: var(--text-2);
    font-family: var(--font-mono);
    font-size: .8125rem;
}

/* Même traitement que `.callout` : la teinte porte le signal, pas un liseré. */
.notice {
    margin-bottom: 1.25rem;
    padding: .75rem 1rem;
    border: 1px solid var(--accent);
    border-radius: var(--radius);
    background: var(--accent-tint);
    font-size: .9375rem;
}

.quest-group {
    margin-bottom: .5rem;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--surface);
}

.quest-group__head {
    display: flex;
    align-items: center;
    gap: .75rem;
    padding: .625rem .875rem;
    cursor: pointer;
    list-style: none;
    font-weight: 600;
}

.quest-group__head::-webkit-details-marker { display: none; }

/* Le chevron est dessiné plutôt qu'importé : une image de plus à charger pour
   un triangle serait excessif. */
.quest-group__head::before {
    content: "";
    width: .375rem;
    height: .375rem;
    flex: none;
    border-right: 2px solid var(--text-3);
    border-bottom: 2px solid var(--text-3);
    transform: rotate(-45deg);
    transition: transform .15s ease;
}

.quest-group[open] > .quest-group__head::before { transform: rotate(45deg); }

.quest-group__title { flex: 1; }

.quest-group__count {
    font-size: .8125rem;
    color: var(--text-3);
}

.quest-list {
    margin: 0;
    padding: 0 .875rem .625rem;
    list-style: none;
    border-top: 1px solid var(--border);
}

.quest {
    display: flex;
    align-items: center;
    gap: .5rem;
    padding: .3125rem 0;
    border-bottom: 1px solid var(--border);
}

.quest:last-child { border-bottom: 0; }

/* La sous-quête se décale sous sa mère, et un filet la rattache à elle.
   Le décalage seul suffirait à l'œil, mais le filet dit **jusqu'où** va la
   grappe : sur les onze étapes de « Frigost, une île pas comme les autres »,
   c'est ce qui distingue la fin d'un groupe du début du suivant. */
.quest--child {
    position: relative;
    padding-left: 1.5rem;
}

.quest--child::before {
    content: "";
    position: absolute;
    left: .5rem;
    top: 0;
    bottom: 0;
    width: 1px;
    background: var(--border);
}

/* Le dernier maillon ferme la grappe par un coude plutôt qu'un trait qui
   file dans le vide. */
.quest--child:not(:has(+ .quest--child))::before { bottom: 50%; }

.quest--child:not(:has(+ .quest--child))::after {
    content: "";
    position: absolute;
    left: .5rem;
    top: 50%;
    width: .5rem;
    height: 1px;
    background: var(--border);
}

.quest__toggle {
    display: flex;
    align-items: center;
    gap: .625rem;
    flex: 1;
    cursor: pointer;
}

.quest__toggle--locked { cursor: default; }

.quest__toggle input {
    width: 1rem;
    height: 1rem;
    flex: none;
    accent-color: var(--accent);
}

.quest__name { color: var(--text-2); }
.quest--done .quest__name { color: var(--accent); font-weight: 600; }

.quest--saving { opacity: .6; }
.quest--failed { background: var(--fire-tint); }

/* Le nombre de quêtes que ce clic entraîne. Le site actuel ne le disait pas :
   on cochait une case et six autres s'allumaient sans explication. */
.quest__cascade {
    padding: .0625rem .375rem;
    border: 1px solid var(--border-2);
    border-radius: 1rem;
    font-family: var(--font-mono);
    font-size: .6875rem;
    color: var(--text-3);
}

/* Le bouton de filtre est masqué par le script : le tri suit la frappe. */
