/* ---------------------------------------------------------------------------
   Drangit — feuille de style unique.
   Pas de framework : la surface est petite, et une dépendance CSS externe
   coûterait plus en poids et en maintenance qu'elle ne rapporterait ici.
   --------------------------------------------------------------------------- */

/* Palette « Console phosphore » (ADR 0008) : un écran à phosphore vert. L'accent n'y est pas
   un ornement posé sur du gris, c'est la couleur du texte vif — d'où un fond presque noir et
   des bordures qui sont du vert éteint, jamais du gris. */
:root {
    color-scheme: dark;

    --bg: #04070a;
    --bg-elevated: #0a1015;
    --bg-input: #081119;
    --border: #123526;
    --border-strong: #1e5039;
    --text: #d7ffe9;
    --text-muted: #4c8a6d;
    --accent: #3ef08c;
    --accent-hover: #7cf5b3;
    --accent-contrast: #04070a;
    --success: #3ef08c;
    --warning: #ffb454;

    /* Un terminal n'arrondit rien. Le rayon reste nommé pour ne pas avoir à le traquer
       dans chaque règle le jour où l'on en voudrait. */
    --radius: 2px;
    --radius-sm: 2px;
    --shell: 72rem;
    --transition: 140ms ease;

    /* La trame de balayage, partagée par l'écran et la ligne de commande : ils ne font
       qu'une surface. */
    --scanlines: repeating-linear-gradient(
        to bottom,
        color-mix(in srgb, #3ef08c 4%, transparent) 0 1px,
        transparent 1px 3px
    );

    --mono: ui-monospace, "Cascadia Mono", "SFMono-Regular", Consolas, "Liberation Mono", monospace;
}

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

body {
    margin: 0;
    min-height: 100vh;
    display: flex;
    flex-direction: column;
    background: var(--bg);
    color: var(--text);
    font-family: var(--mono);
    font-size: 15px;
    line-height: 1.6;
    -webkit-font-smoothing: antialiased;
}

a {
    color: var(--accent);
    text-decoration: none;
}

a:hover,
a:focus-visible {
    color: var(--accent-hover);
    text-decoration: underline;
}

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

h1, h2, h3 {
    line-height: 1.25;
    margin: 0 0 0.5em;
}

code {
    font-family: var(--mono);
    font-size: 0.9em;
}

:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
    border-radius: var(--radius-sm);
}

.shell {
    width: 100%;
    max-width: var(--shell);
    margin-inline: auto;
    padding-inline: 1.25rem;
}

.visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
}

.skip-link {
    position: absolute;
    left: -9999px;
    top: 0;
    z-index: 10;
    padding: 0.75rem 1rem;
    background: var(--accent);
    color: var(--accent-contrast);
    font-weight: 600;
}

.skip-link:focus {
    left: 0;
}

.muted {
    color: var(--text-muted);
}

/* --- En-tête ------------------------------------------------------------- */

.site-header {
    border-bottom: 1px solid var(--border);
    background: color-mix(in srgb, var(--bg) 88%, transparent);
    backdrop-filter: blur(8px);
    position: sticky;
    top: 0;
    z-index: 5;
}

.site-header__inner {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 1rem 1.5rem;
    padding-block: 0.9rem;
}

.brand {
    display: inline-flex;
    align-items: center;
    gap: 0.55rem;
    color: var(--text);
    font-weight: 700;
    font-size: 1.05rem;
    letter-spacing: 0.01em;
}

.brand:hover {
    color: var(--text);
    text-decoration: none;
}

.brand__mark {
    color: var(--accent);
    font-family: var(--mono);
    font-size: 0.95rem;
}

.site-nav {
    display: flex;
    gap: 1.25rem;
    margin-right: auto;
}

.site-nav__link {
    color: var(--text-muted);
    font-weight: 500;
    padding-block: 0.25rem;
    border-bottom: 2px solid transparent;
}

.site-nav__link:hover {
    color: var(--text);
    text-decoration: none;
}

.site-nav__link.active {
    color: var(--text);
    border-bottom-color: var(--accent);
}

/* --- Sélecteur de langue -------------------------------------------------- */

.culture {
    display: inline-flex;
    gap: 0.25rem;
    padding: 0.2rem;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
}

.culture__button {
    border: 0;
    background: none;
    color: var(--text-muted);
    font: inherit;
    font-size: 0.85rem;
    padding: 0.25rem 0.6rem;
    border-radius: 4px;
    cursor: pointer;
    transition: background var(--transition), color var(--transition);
}

.culture__button:hover,
.culture__button:focus-visible {
    color: var(--text);
    background: var(--bg-input);
    /* Ce sont des liens (ADR 0006) : sans cela, ils se soulignent au survol alors qu'ils
       ont l'apparence de boutons. */
    text-decoration: none;
}

.culture__button--current {
    background: var(--accent);
    color: var(--accent-contrast);
    font-weight: 600;
}

/* --- Corps ---------------------------------------------------------------- */

.site-main {
    flex: 1;
    padding-block: 2.5rem 4rem;
}

.page-title {
    font-size: clamp(1.75rem, 1.2rem + 2vw, 2.5rem);
    letter-spacing: -0.02em;
}

.page-intro {
    color: var(--text-muted);
    max-width: 60ch;
    margin-top: -0.25rem;
}

.notice {
    padding: 1rem 1.25rem;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--bg-elevated);
    color: var(--text-muted);
}

.notice--warning {
    border-color: color-mix(in srgb, var(--warning) 45%, var(--border));
    color: var(--warning);
}

.results-count {
    color: var(--text-muted);
    font-size: 0.9rem;
    margin-block: 1.5rem 1rem;
}

/* --- Boutons -------------------------------------------------------------- */

.button {
    display: inline-block;
    padding: 0.55rem 1.1rem;
    border: 1px solid transparent;
    border-radius: var(--radius-sm);
    font-weight: 600;
    font-size: 0.95rem;
    cursor: pointer;
    transition: background var(--transition), color var(--transition);
}

.button--primary {
    background: var(--accent);
    color: var(--accent-contrast);
}

.button--primary:hover {
    background: var(--accent-hover);
    color: var(--accent-contrast);
    text-decoration: none;
}

.button--ghost {
    border-color: var(--border-strong);
    color: var(--text-muted);
    background: none;
}

.button--ghost:hover {
    color: var(--text);
    text-decoration: none;
}

/* --- Fenêtre de terminal -------------------------------------------------- */

/* Toute la page tient dans ce cadre (ADR 0010). La barre de titre n'est pas un ornement :
   elle dit le nom du site et ce que la fenêtre contient, comme le ferait un émulateur. */
.window {
    margin-top: 0.5rem;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--bg);
    overflow: hidden;
    /* La lueur que laisse un écran allumé dans une pièce sombre. */
    box-shadow: 0 24px 60px -30px color-mix(in srgb, var(--accent) 35%, transparent);
}

.window__bar {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.5rem 0.85rem;
    border-bottom: 1px solid var(--border);
    background: var(--bg-elevated);
    color: var(--text-muted);
    font-size: 0.78rem;
}

/* Les trois pastilles, dessinées en ombres plutôt qu'en trois éléments vides : elles ne
   disent rien, elles situent. */
.window__dots {
    width: 9px;
    height: 9px;
    border-radius: 50%;
    background: var(--border-strong);
    box-shadow: 14px 0 0 var(--border-strong), 28px 0 0 var(--border-strong);
    margin-right: 28px;
    flex: none;
}

.window__meta {
    margin-left: auto;
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
}

/* Dans la barre de titre, le sélecteur de langue se fait tout petit : c'est une mention de
   fenêtre, pas un élément de page. */
.window__bar .culture {
    border: 0;
    padding: 0;
    gap: 0;
}

.window__bar .culture__button {
    padding: 0 0.4rem;
    font-size: inherit;
    border-radius: 0;
}

.window__bar .culture__button--current {
    background: none;
    color: var(--accent);
    font-weight: 400;
}

/* L'écran défile dans la fenêtre plutôt que d'allonger la page : le prompt reste visible au
   bas du cadre, comme dans un terminal, et la sortie s'empile au-dessus de lui. La trame de
   balayage donne le grain d'un écran ; elle est en fond, donc sous le texte. */
.window__screen {
    height: min(72vh, 640px);
    overflow-y: auto;
    padding: 1.1rem 1.15rem 0.5rem;
    background: var(--scanlines);
}

/* Sur un écran bas ou un téléphone, une hauteur fixe enfermerait la liste dans une fente :
   la fenêtre reprend alors la hauteur de son contenu. */
@media (max-height: 40rem), (max-width: 34rem) {
    .window__screen {
        height: auto;
        max-height: none;
    }
}

/* --- Sortie de terminal --------------------------------------------------- */

/* Le nom du site dessiné en caractères : la peau n'a pas de fonte d'affichage, et c'est ce
   dessin qui en tient lieu. Il déborde sur les écrans étroits, d'où le défilement propre à
   ce bloc — le réduire davantage le rendrait illisible. */
.cli__banner {
    margin: 0 0 1.25rem;
    overflow-x: auto;
    color: var(--accent);
    text-shadow: 0 0 10px color-mix(in srgb, var(--accent) 45%, transparent);
    font-size: clamp(5.5px, 1.5vw, 10px);
    line-height: 1.15;
}

/* Les lignes de commande décoratives qui annoncent chaque section. Elles ne sont pas
   cliquables et ne sont pas lues : ce qu'elles disent, la section le montre juste après. */
.cli__line {
    margin: 2rem 0 0.75rem;
    color: var(--text-muted);
    font-size: 0.9rem;
    overflow-wrap: anywhere;
}

.cli__prompt {
    color: var(--accent);
}

/* Ce qu'un programme écrit après sa bannière : ce qu'on peut lui demander. */
.cli__boot {
    margin: 0.9rem 0 0;
    color: var(--warning);
    font-size: 0.9rem;
}

/* Les raccourcis et les exemples, hors du cadre : ce sont des indications sur la fenêtre,
   pas une sortie de la fenêtre. */
.cli__hints {
    margin: 0.9rem 0 0;
    color: var(--text-muted);
    font-size: 0.8rem;
}

.cli__examples {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
    margin-top: 0.75rem;
}

.cli__example {
    padding: 0.2rem 0.6rem;
    border: 1px solid var(--border);
    color: var(--text-muted);
    font-size: 0.8rem;
}

.cli__example:hover,
.cli__example:focus-visible {
    border-color: var(--accent);
    color: var(--accent);
    text-decoration: none;
}

/* Les en-têtes de colonnes de la liste, calés sur la grille des lignes. */
.listing__head {
    display: grid;
    grid-template-columns: 7rem 6rem 3.5rem minmax(0, 1fr);
    gap: 1rem;
    margin: 1.25rem 0 0.35rem;
    padding: 0 0.4rem;
    color: var(--text-muted);
    font-size: 0.7rem;
    letter-spacing: 0.1em;
    text-transform: uppercase;
}

/* La colonne des étoiles se lit alignée à droite dans les lignes : son en-tête suit. */
.listing__head span:nth-child(3) {
    text-align: right;
}

@media (max-width: 52rem) {
    .listing__head {
        display: none;
    }
}

/* Le titre et l'intro, écrits comme des lignes de commentaire : ils gardent leur rôle —
   un h1 indexable, une phrase qui situe — sans rompre la sortie. */
.cli__note {
    margin: 0 0 0.35rem;
    color: var(--text-muted);
    font-size: 0.9rem;
    font-weight: 400;
    line-height: 1.6;
    max-width: 80ch;
}

h1.cli__note {
    color: var(--text);
    letter-spacing: 0;
}

.cli__line--last {
    margin-top: 2.5rem;
}

/* La sortie empilée par le prompt, quand le script est là pour la produire. Sans lui, ce
   bloc reste vide et la page se comporte comme avant (ADR 0008). */
.cli__log {
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
    margin-top: 2.5rem;
}

.cli__log:empty {
    display: none;
}

.cli__log pre {
    margin: 0;
    overflow-x: auto;
    font: inherit;
    font-size: 0.88rem;
    line-height: 1.6;
    color: var(--text-muted);
}

/* Quand c'est le serveur qui répond — sans JavaScript —, le bloc demandé est le seul que le
   conteneur laisse voir, et il se lit comme la sortie qu'il aurait été côté client. */
.cli__outputs:not([hidden]) {
    margin-top: 1.75rem;
    color: var(--text);
    font-size: 0.9rem;
}

.cli__outputs pre {
    margin: 0;
    overflow-x: auto;
    font: inherit;
    font-size: 0.88rem;
    line-height: 1.6;
    color: var(--text-muted);
}

/* La commande rappelée au-dessus de sa sortie : c'est ce qui rend la suite lisible quand
   plusieurs réponses se sont empilées. */
.cli__echo {
    margin: 0.9rem 0 0.1rem;
    color: var(--accent);
    font-size: 0.9rem;
    overflow-wrap: anywhere;
}

.cli__output {
    color: var(--text);
    font-size: 0.9rem;
}

.cli__hint {
    color: var(--warning) !important;
}

.cli__rain {
    color: color-mix(in srgb, var(--accent) 55%, transparent) !important;
    line-height: 1.25 !important;
}

/* Les listes chiffrées — statistiques, sujets, langages : deux colonnes qui s'alignent,
   comme la sortie d'un programme qui compte. */
.cli__stats,
.cli__eggs {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    gap: 0.1rem;
    font-size: 0.9rem;
}

.cli__stats li {
    display: grid;
    grid-template-columns: minmax(0, 18rem) auto;
    gap: 1rem;
    color: var(--text-muted);
}

.cli__stats li span {
    color: var(--text);
    font-variant-numeric: tabular-nums;
}

.cli__eggs li {
    color: var(--text-muted);
}

.cli__eggs li::before {
    content: "· ";
    color: var(--text-muted);
}

/* Ce qu'on a déjà essayé, et ce qui reste à trouver. Le sélecteur porte la classe de la
   liste : sans elle, la puce de `.cli__eggs li::before` l'emporterait et la coche ne
   s'afficherait jamais. */
.cli__eggs li.cli__egg--found {
    color: var(--text);
}

.cli__eggs li.cli__egg--found::before {
    content: "✓ ";
    color: var(--accent);
}

.cli__eggs li span {
    color: var(--text-muted);
}

[data-found]::after {
    content: attr(data-found);
    display: block;
    margin-top: 0.5rem;
    color: var(--text-muted);
    font-size: 0.85em;
}

/* Le prompt saisissable, en bas de page. Un champ sans cadre ni fond : ce qui se voit,
   c'est l'invite et le texte tapé, comme dans un terminal. Le bouton d'envoi est là mais
   masqué — la touche Entrée suffit, et un bouton « Appliquer » casserait l'illusion sans
   rien apporter à qui navigue au clavier. */
/* Dans la continuité de l'écran, sans séparateur ni décalage : c'est la dernière ligne du
   terminal, pas un champ posé sous lui. Le calage horizontal reprend celui de l'écran. */
.cli__form {
    display: flex;
    align-items: baseline;
    gap: 0.6ch;
    padding: 0.35rem 1.15rem 0.9rem;
    font-size: 0.95rem;
    background: var(--scanlines);
}

.cli__form input {
    flex: 1;
    min-width: 0;
    border: 0;
    padding: 0;
    background: none;
    color: var(--accent);
    font: inherit;
    caret-color: var(--accent);
}

.cli__form input::placeholder {
    color: color-mix(in srgb, var(--text-muted) 70%, transparent);
}

.cli__form input:focus {
    outline: none;
}

/* La ligne entière prend la mise en avant du focus : le champ n'ayant pas de cadre, un
   contour sur lui seul serait invisible au milieu du texte. */
.cli__form:focus-within {
    background: color-mix(in srgb, var(--accent) 7%, transparent);
}

/* Le bloc du curseur, à la fin de la sortie. Il clignote, sauf si le visiteur a demandé
   qu'on lui épargne les animations. */
.cli__caret {
    display: inline-block;
    width: 0.55em;
    height: 1.05em;
    margin-left: 0.5ch;
    background: var(--accent);
    vertical-align: text-bottom;
    animation: cli-blink 1.1s steps(1) infinite;
}

@keyframes cli-blink {
    50% {
        opacity: 0;
    }
}

/* --- Vitrine -------------------------------------------------------------- */

/* Un bloc encadré, sans illustration : la vitrine est la première sortie de la commande
   « repos --featured », et une sortie de terminal ne montre pas d'images. */
.hero {
    position: relative;
    margin-top: 0.5rem;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background:
        linear-gradient(
            180deg,
            color-mix(in srgb, var(--accent) 6%, transparent) 0%,
            transparent 70%
        ),
        var(--bg-elevated);
}

.hero__body {
    padding: clamp(1.1rem, 3vw, 1.9rem);
}

.hero__eyebrow {
    margin: 0 0 0.6rem;
    font-size: 0.75rem;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--warning);
}

.hero__title {
    margin: 0 0 0.4rem;
    font-size: clamp(1.3rem, 1rem + 1.4vw, 1.9rem);
    color: var(--text);
    overflow-wrap: anywhere;
}

/* La ligne de faits de la vitrine, séparée par des points médians comme un en-tête de
   sortie. Le séparateur est décoratif : il ne s'affiche pas avant le premier élément. */
.hero__facts {
    display: flex;
    flex-wrap: wrap;
    gap: 0.35rem 0.9rem;
    margin: 0 0 0.9rem;
    padding-bottom: 0.9rem;
    border-bottom: 1px dashed var(--border);
    color: var(--text-muted);
    font-size: 0.85rem;
    font-variant-numeric: tabular-nums;
}

.hero__facts span:first-child {
    color: var(--cover-ink, var(--accent));
}

.hero__tagline {
    margin: 0;
    color: var(--text);
    max-width: 62ch;
}

.hero__actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.6rem;
    margin-top: 1.25rem;
}

/* --- Liste des dépôts ----------------------------------------------------- */

/* Des colonnes alignées plutôt qu'un mur de tuiles : quarante-sept dépôts se parcourent,
   ils ne se contemplent pas. Les colonnes fixes en tête, la description en dernier —
   c'est elle qui varie le plus, et c'est elle qu'on tronque si la place manque. */
.listing {
    list-style: none;
    margin: 0;
    padding: 0;
    border-top: 1px solid var(--border);
}

.listing__item {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.5rem 1rem;
    padding: 0.5rem 0.4rem;
    border-bottom: 1px dotted color-mix(in srgb, var(--border) 85%, transparent);
}

.listing__item:hover {
    background: color-mix(in srgb, var(--accent) 7%, transparent);
}

/* Un dépôt archivé reste listé, mais ne se présente pas comme le reste : il est en
   retrait, pas masqué. */
.listing__item--archived {
    opacity: 0.66;
}

.listing__link {
    display: grid;
    grid-template-columns: 7rem 6rem 3.5rem minmax(11rem, auto) minmax(0, 1fr);
    align-items: baseline;
    gap: 0.15rem 1rem;
    flex: 1 1 32rem;
    min-width: 0;
    color: inherit;
    font-size: 0.9rem;
    font-variant-numeric: tabular-nums;
}

.listing__link:hover,
.listing__link:focus-visible {
    color: inherit;
    text-decoration: none;
}

.listing__language {
    color: var(--cover-ink, var(--text-muted));
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.listing__date,
.listing__stars {
    color: var(--text-muted);
    font-size: 0.85em;
}

.listing__stars {
    color: var(--warning);
    text-align: right;
}

.listing__name {
    color: var(--text);
    overflow-wrap: anywhere;
}

.listing__link:hover .listing__name {
    text-decoration: underline;
}

.listing__owner {
    color: var(--text-muted);
}

.listing__description {
    color: var(--text-muted);
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* En dessous de cette largeur, cinq colonnes ne tiennent plus : la ligne se replie en deux
   niveaux — l'identité au-dessus, les chiffres en dessous — plutôt que de se comprimer
   jusqu'à l'illisible. */
@media (max-width: 52rem) {
    .listing__link {
        grid-template-columns: 6rem 5.5rem minmax(0, 1fr);
        flex-basis: 100%;
    }

    .listing__name {
        grid-column: 1 / -1;
        order: -1;
        font-size: 1.05em;
    }

    .listing__description {
        grid-column: 1 / -1;
        white-space: normal;
    }

    .listing__stars {
        text-align: left;
    }
}

/* --- Illustration d'un dépôt ---------------------------------------------- */

/* La vignette est dessinée, pas chargée : la teinte vient du langage, l'inclinaison du
   dégradé du nom — sans quoi deux dépôts du même langage auraient la même image. Elle se lit
   comme une ligne de terminal, et la trame de balayage lui donne le grain d'un écran sans
   rien masquer. La trame est une couche de fond et non un pseudo-élément : la capture se
   pose par-dessus en position absolue, et un ::after passerait devant elle. */
.cover {
    position: relative;
    aspect-ratio: 2 / 1;
    overflow: hidden;
    /* En flux, et non le langage calé en absolu : un nom de dépôt à rallonge passait par
       -dessus la pastille dès que la tuile se resserre — sur la fiche, par exemple. */
    display: flex;
    flex-direction: column;
    /* En rem, et non en pourcentage : un padding en % se calcule sur la largeur du bloc
       conteneur et non sur celle de la tuile — sur la fiche, il valait 78 px dans une tuile
       de 350, et ne laissait plus de place au titre. */
    padding: 0.9rem 1rem;
    font-family: var(--mono);
    background:
        repeating-linear-gradient(
            to bottom,
            rgba(0, 0, 0, 0.16) 0 1px,
            transparent 1px 3px
        ),
        linear-gradient(
            var(--cover-angle, 45deg),
            color-mix(in srgb, var(--cover-accent, var(--accent)) 34%, var(--bg-elevated)) 0%,
            var(--bg) 58%
        );
}

.cover__title {
    margin: 0;
    font-size: clamp(0.8rem, 0.45rem + 1.25vw, 1.05rem);
    font-weight: 600;
    line-height: 1.35;
    color: var(--text);
    /* Les noms de dépôts sont longs et sans espaces : sans cela, un nom déborde la tuile.
       Au-delà de trois lignes il est coupé — la carte l'écrit en entier juste en dessous.
       Une hauteur maximale plutôt que `line-clamp` : le clamp exige un display que le
       conteneur flex remplace, et le titre se retrouve alors réduit à rien. */
    overflow-wrap: anywhere;
    flex: none;
    max-height: 4.05em;
    overflow: hidden;
}

/* Le prompt : il annonce qu'on lit une ligne de terminal, avant même de lire le nom.
   Il prend la teinte écrite du langage, et non celle du fond : les plus sombres — le bleu
   nuit de PowerShell, celui de Lua — disparaîtraient ici. */
.cover__title::before {
    content: "$ ";
    color: var(--cover-ink, var(--accent));
}

.cover__owner {
    color: var(--text-muted);
}

.cover__language {
    margin-top: auto;
    padding-top: 0.4rem;
    font-size: 0.7rem;
    color: var(--text-muted);
}

/* La pastille de langage, à la convention de GitHub : la teinte dit le langage avant le mot. */
.cover__language::before {
    content: "";
    display: inline-block;
    width: 0.55rem;
    height: 0.55rem;
    margin-right: 0.35rem;
    border-radius: 50%;
    background: var(--cover-ink, var(--accent));
}

/* Posée par-dessus la vignette, qu'elle recouvre entièrement quand elle arrive. Si elle
   n'arrive pas, `onerror` la retire et la vignette dessinée reste visible. */
.cover__image {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

/* Variante fiche : une tuile à côté du titre, pas une bande pleine largeur. */
.cover--card {
    width: min(22rem, 100%);
    border: 1px solid var(--border);
    border-radius: var(--radius);
}

/* --- Métadonnées chiffrées ------------------------------------------------ */

.facts {
    list-style: none;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.75rem;
    margin: 0;
    padding: 0;
    font-size: 0.8rem;
    color: var(--text-muted);
}

/* La pastille de langage reprend la convention de GitHub : une couleur unique suffit
   ici, le site ne prétend pas rejouer la palette par langage. */
.facts__item--language::before {
    content: "";
    display: inline-block;
    width: 0.6rem;
    height: 0.6rem;
    margin-right: 0.35rem;
    border-radius: 50%;
    background: var(--accent);
}

/* --- Badges et sujets ----------------------------------------------------- */

.badges,
.tags,
.shots,
.site-footer__links {
    list-style: none;
    margin: 0;
    padding: 0;
}

.badges {
    display: flex;
    flex-wrap: wrap;
    gap: 0.3rem;
}

.badge {
    font-size: 0.7rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    padding: 0.15rem 0.45rem;
    border: 1px solid var(--border-strong);
    border-radius: 4px;
    color: var(--text-muted);
}

.badge--demo {
    border-color: color-mix(in srgb, var(--success) 50%, var(--border-strong));
    color: var(--success);
}

.badge--archived {
    border-color: color-mix(in srgb, var(--warning) 50%, var(--border-strong));
    color: var(--warning);
}

.tags {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
}

.tag {
    display: inline-block;
    padding: 0.25rem 0.7rem;
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-sm);
    font-size: 0.85rem;
    color: var(--text-muted);
}

.tag:hover {
    color: var(--text);
    border-color: var(--accent);
    text-decoration: none;
}

/* --- Fiche dépôt ---------------------------------------------------------- */

/* Le retour à gauche, la langue à droite : c'est tout ce que ces pages gardent de l'ancien
   bandeau, et il n'y a rien entre les deux. */
.breadcrumb {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    margin-bottom: 1.5rem;
    font-size: 0.9rem;
}

.repo__header {
    display: flex;
    flex-wrap: wrap;
    gap: 2rem;
    align-items: flex-start;
}

.repo__intro {
    flex: 1 1 20rem;
}

.repo__fullname {
    margin-top: -0.75rem;
    color: var(--text-muted);
}

.repo__tagline {
    color: var(--text-muted);
    font-size: 1.1rem;
    max-width: 55ch;
}

.repo__facts {
    display: flex;
    flex-wrap: wrap;
    gap: 1.5rem;
    margin: 1.5rem 0;
}

.repo__facts dt {
    font-size: 0.75rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--text-muted);
    margin-bottom: 0.35rem;
}

.repo__facts dd {
    margin: 0;
    font-size: 0.95rem;
}

.repo__actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.6rem;
}

.repo__clone {
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
    margin-top: 1.5rem;
    max-width: 34rem;
}

.repo__clone label {
    font-size: 0.75rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--text-muted);
}

.repo__clone input {
    width: 100%;
    padding: 0.55rem 0.7rem;
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-sm);
    background: var(--bg-input);
    color: var(--text);
    font-family: var(--mono);
    font-size: 0.85rem;
}

.repo__section {
    margin-top: 3rem;
    padding-top: 2rem;
    border-top: 1px solid var(--border);
}

.repo__section h2 {
    font-size: 1.2rem;
}

.repo__section p {
    max-width: 70ch;
}

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

.shots img {
    width: 100%;
    border-radius: var(--radius-sm);
    border: 1px solid var(--border);
}

.prose {
    max-width: 65ch;
}

.prose h2 {
    margin-top: 2rem;
    font-size: 1.2rem;
}

/* --- Pied de page --------------------------------------------------------- */

.site-footer {
    border-top: 1px solid var(--border);
    padding-block: 1.75rem;
    font-size: 0.875rem;
    color: var(--text-muted);
}

.site-footer__inner {
    display: flex;
    flex-wrap: wrap;
    gap: 0.75rem 1.5rem;
    justify-content: space-between;
    align-items: center;
}

.site-footer__text {
    margin: 0;
}

.site-footer__links {
    display: flex;
    gap: 1.25rem;
}

/* --- Préférences d'accessibilité ------------------------------------------ */

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

/* La suite de la liste, annoncée comme un programme le ferait. */
.cli__more {
    margin: 0.75rem 0 0;
    padding-left: 0.4rem;
    color: var(--text-muted);
    font-size: 0.88rem;
}
