/* =========================================================================
   Nuriva — système de design
   Direction : le réseau maison. Auto-hébergement, inclusion numérique,
   open source, cybersécurité accessible — l'informatique comme un lieu
   habité, pas une salle des machines. Encre pin chaude, papier, un ambre
   "fenêtre allumée le soir", et un motif signature de nœuds reliés en
   pointillé (le réseau, rendu concret) qui structure les listes de
   thématiques et les séparateurs de section.
   ========================================================================= */

@import url("https://fonts.googleapis.com/css2?family=Fraunces:opsz,wght@9..144,400;9..144,500;9..144,600&family=Public+Sans:wght@400;500;600;700&family=IBM+Plex+Mono:wght@400;500&display=swap");

:root {
    /* Palette brute — sert de "chrome" toujours sombre (header, footer, hero,
       boutons, bloc de code) quel que soit le thème actif. Ne pas rebasculer
       ces variables entre clair/sombre : c'est la charte, elles ne bougent pas. */
    --ink: #141c27;          /* bleu nuit du logo — fonds sombres, texte fort */
    --ink-soft: #4b5c6b;     /* texte de corps sur papier (clair uniquement) */
    --paper: #f7f5ef;        /* papier chaud — fond principal (clair uniquement) */
    --paper-dim: #efece2;    /* variante papier pour cartes/zones (clair uniquement) */
    --line: #d8d2c2;         /* hairlines sur papier (clair uniquement) */
    --line-dark: #26333f;    /* hairlines sur fond sombre */

    --cyan: #0a86b8;         /* bleu de la vague, foncé — accent principal sur papier */
    --cyan-bright: #17c4f2;  /* bleu de la vague, vif — sur fond sombre */
    --green: #5c9d17;        /* vert de la vague, foncé — accent tertiaire sur papier */
    --green-bright: #8fe01f; /* vert de la vague, vif — sur fond sombre */
    --orange: #d97a0f;       /* point orange, foncé — accent/interaction sur papier */
    --orange-bright: #fc8d09; /* point orange, vif — sur fond sombre */

    /* Rôles sémantiques — CE SONT CES VARIABLES qui basculent entre thème
       clair et sombre. Le contenu (sections, cartes, formulaires) les utilise
       ; le "chrome" toujours-sombre (header/footer/hero) continue d'utiliser
       --ink/--paper directement, ci-dessus. */
    --surface: var(--paper);
    --surface-alt: var(--paper-dim);
    --surface-input: #ffffff;
    --text: var(--ink);
    --text-muted: var(--ink-soft);
    --line-soft: var(--line);
    --accent-cyan: var(--cyan);
    --accent-green: var(--green);
    --accent-orange: var(--orange);

    /* Typographie */
    --font-display: "Fraunces", ui-serif, Georgia, serif;
    --font-body: "Public Sans", ui-sans-serif, system-ui, sans-serif;
    --font-mono: "IBM Plex Mono", ui-monospace, "SFMono-Regular", Menlo, monospace;

    /* Échelle */
    --step-0: clamp(1rem, 0.95rem + 0.25vw, 1.0625rem);
    --step-1: clamp(1.25rem, 1.15rem + 0.5vw, 1.5rem);
    --step-2: clamp(1.75rem, 1.5rem + 1.1vw, 2.25rem);
    --step-3: clamp(2.25rem, 1.85rem + 1.9vw, 3.25rem);

    --radius: 3px;
    --content-width: 52rem;
    --wide-width: 72rem;
}

@media (prefers-reduced-motion: no-preference) {
    :root {
        --transition: 160ms ease;
    }
}

/* === Thème sombre ===
   Activé via [data-theme="dark"] sur <html>, posé par nuriva.js. Seuls les
   rôles sémantiques changent — le bandeau header/footer/hero reste identique
   dans les deux thèmes, c'est la charte graphique du site. */
[data-theme="dark"] {
    --surface: var(--ink);
    --surface-alt: #1c2530;
    --surface-input: #1c2530;
    --text: var(--paper);
    --text-muted: #a9b4c0;
    --line-soft: var(--line-dark);
    --accent-cyan: var(--cyan-bright);
    --accent-green: var(--green-bright);
    --accent-orange: var(--orange-bright);
}

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

html {
    scroll-behavior: smooth;
}

/* === Sticky footer ===
   html/body en pleine hauteur, .site-wrapper en colonne flex, <main> prend
   tout l'espace disponible (flex: 1) : le footer reste en bas même quand le
   contenu de la page est court. Nécessite d'envelopper header+main+footer
   dans <div class="site-wrapper"> côté template (voir base.html). */
html, body {
    height: 100%;
}

.site-wrapper {
    display: flex;
    flex-direction: column;
    min-height: 100vh;
    min-height: 100dvh;
}

.site-wrapper > main {
    flex: 1 0 auto;
}

body {
    margin: 0;
    background: var(--surface);
    color: var(--text);
    font-family: var(--font-body);
    font-size: var(--step-0);
    line-height: 1.6;
    -webkit-font-smoothing: antialiased;
    transition: background var(--transition, 160ms ease), color var(--transition, 160ms ease);
}

@media (prefers-reduced-motion: reduce) {
    html { scroll-behavior: auto; }
}

img { max-width: 100%; display: block; }

a {
    color: var(--accent-cyan);
    text-decoration-thickness: 1px;
    text-underline-offset: 3px;
}
a:hover { color: var(--accent-orange); }

a:focus-visible, button:focus-visible {
    outline: 2px solid var(--accent-orange);
    outline-offset: 3px;
}

h1, h2, h3 {
    font-family: var(--font-display);
    font-weight: 600;
    line-height: 1.15;
    margin: 0 0 0.5em;
    letter-spacing: -0.01em;
}
h1 { font-size: var(--step-3); }
h2 { font-size: var(--step-2); }
h3 { font-size: var(--step-1); }

p { margin: 0 0 1.1em; }

code, pre {
    font-family: var(--font-mono);
}

.wrap {
    max-width: var(--wide-width);
    margin-inline: auto;
    padding-inline: 1.5rem;
}
.wrap--narrow {
    max-width: var(--content-width);
    /* Centre systématiquement, même utilisée seule sur un élément imbriqué
       dans un .wrap parent (qui ne transmet pas son propre margin-inline:
       auto à ses enfants) — voir le piège documenté dans 07-nuriva.md :
       avant ce correctif, .wrap--narrow plafonnait la largeur sans centrer,
       collant la colonne au bord gauche dès qu'elle n'était pas combinée à
       .wrap sur la même balise (class="wrap wrap--narrow"). */
    margin-inline: auto;
}

/* =========================================================================
   En-tête / navigation
   ========================================================================= */

/* --- Lien d'évitement ---
   Hors écran par défaut (translateY plutôt que display:none, qui empêcherait
   le focus clavier de l'atteindre) ; ramené dans l'écran au focus. z-index
   généreux : doit passer au-dessus du header, potentiellement sticky. */
.skip-link {
    position: absolute;
    top: 0;
    left: 1rem;
    transform: translateY(-120%);
    background: var(--orange-bright);
    color: var(--ink);
    font-weight: 600;
    padding: 0.6rem 1rem;
    border-radius: 0 0 var(--radius) var(--radius);
    z-index: 1000;
    transition: transform var(--transition, 160ms ease);
}
.skip-link:focus {
    transform: translateY(0);
}

.site-header {
    background: var(--ink);
    color: var(--paper);
}

.site-header__bar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1.5rem;
    padding-block: 1.1rem;
    flex-wrap: wrap;
    position: relative;
}

.site-header__brand {
    font-family: var(--font-display);
    font-size: 1.35rem;
    font-weight: 600;
    color: var(--paper);
    text-decoration: none;
    display: inline-flex;
    align-items: center;
    gap: 0.55rem;
}
.site-header__brand:hover { color: var(--cyan-bright); }
.site-header__logo {
    height: 2rem;
    width: auto;
    display: block;
}

.site-header__controls {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    /* Pas de margin-left: auto ici : .site-header__bar est déjà en
       justify-content: space-between sur ses 3 enfants (logo / nav /
       controls) — un margin-left: auto sur le dernier absorbait tout
       l'espace disponible pour lui seul, empêchant space-between de
       répartir quoi que ce soit entre le logo et le menu (les marges auto
       sur un item flex passent avant justify-content dans le calcul de
       l'espace libre). Le retirer restore l'espacement voulu entre le logo
       et le menu, sans rien changer au fait que .controls reste pinné à
       l'extrémité droite (comportement déjà garanti par space-between avec
       .controls en dernier enfant). */
}

.site-nav {
    display: flex;
    gap: 1.75rem;
    flex-wrap: wrap;
    list-style: none;
    margin: 0;
    padding: 0;
    font-size: 0.95rem;
}
.site-nav a {
    color: var(--paper);
    text-decoration: none;
    position: relative;
    padding-block: 0.2rem;
}
.site-nav a::after {
    content: "";
    position: absolute;
    left: 0; right: 0; bottom: -2px;
    height: 1px;
    background: var(--orange-bright);
    transform: scaleX(0);
    transform-origin: left;
    transition: transform var(--transition, 160ms ease);
}
.site-nav a:hover { color: var(--paper); }
.site-nav a:hover::after,
.site-nav a[aria-current="page"]::after { transform: scaleX(1); }
.site-nav a[aria-current="page"] { color: var(--orange-bright); }

/* --- Bouton de bascule de thème --- */
.theme-toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.25rem;
    height: 2.25rem;
    border-radius: 50%;
    background: transparent;
    border: none;
    color: var(--paper);
    cursor: pointer;
    flex-shrink: 0;
    transition: background var(--transition, 160ms ease), color var(--transition, 160ms ease);
}
.theme-toggle:hover {
    background: rgba(247, 245, 239, 0.12);
    color: var(--orange-bright);
}
.theme-toggle svg { width: 1.15rem; height: 1.15rem; }

/* --- Menu burger (mobile) --- */
.nav-toggle {
    display: none;
    align-items: center;
    justify-content: center;
    width: 2.25rem;
    height: 2.25rem;
    background: transparent;
    border: none;
    color: var(--paper);
    cursor: pointer;
    flex-shrink: 0;
}
.nav-toggle svg { width: 1.4rem; height: 1.4rem; }

@media (max-width: 760px) {
    .nav-toggle { display: inline-flex; }

    /* z-index nécessaire : depuis que des éléments de contenu (.post-card,
       bouton favori) sont position: relative avec leur propre z-index,
       le menu déplié doit explicitement passer au-dessus, sinon l'ordre
       du DOM les fait passer devant lui (le header étant tout en haut). */
    .site-nav {
        display: none;
        position: absolute;
        top: 100%;
        left: 0;
        right: 0;
        z-index: 100;
        flex-direction: column;
        gap: 0;
        background: var(--ink);
        border-top: 1px solid var(--line-dark);
        padding: 0.5rem 1.5rem 1.25rem;
        box-shadow: 0 12px 24px rgba(0, 0, 0, 0.25);
    }
    .site-nav.site-nav--open {
        display: flex;
    }
    .site-nav a {
        display: block;
        padding-block: 0.65rem;
        border-bottom: 1px solid var(--line-dark);
    }
    .site-nav li:last-child a { border-bottom: none; }
}

/* =========================================================================
   Pied de page
   ========================================================================= */

.site-footer {
    background: var(--ink);
    color: var(--paper-dim);
    border-top: 1px solid var(--line-dark);
    flex-shrink: 0;
}
.site-footer__bar {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: 1.5rem;
    flex-wrap: wrap;
    padding-block: 2rem;
    font-size: 0.875rem;
}
.site-footer a { color: var(--paper-dim); }
.site-footer a:hover { color: var(--orange-bright); }
.site-footer__brand {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    font-family: var(--font-display);
    font-size: 1rem;
    color: var(--paper);
    text-decoration: none;
}
.site-footer__logo {
    height: 1.4rem;
    width: auto;
    display: block;
}
.site-footer__tagline {
    margin: 0.3rem 0 0;
    font-size: 0.8rem;
    color: var(--paper-dim);
    opacity: 0.75;
}
.site-footer__copyright { margin: 0.75rem 0 0; }
.site-footer__note {
    margin: 0.75rem 0 0;
    font-size: 0.8rem;
    opacity: 0.75;
}
.site-footer__links {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem 1.25rem;
    list-style: none;
    margin: 0.4rem 0 0;
    padding: 0;
}

/* Colonnes du footer (siteconfig/models.py:FooterLink), en repli sur
   .site-footer__links (liste plate ci-dessus) tant qu'aucun lien n'est
   configuré. Rangée flex plutôt qu'empilée : occupe l'espace déjà réservé à
   côté du bloc marque, sans agrandir la hauteur totale du footer. */
.site-footer__columns {
    display: flex;
    flex-wrap: wrap;
    gap: 2rem 3rem;
}
.site-footer__column-title {
    margin: 0 0 0.75rem;
    font-size: 0.75rem;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--paper);
}
.site-footer__column-links {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    list-style: none;
    margin: 0;
    padding: 0;
}
/* Même traitement que .site-nav (menu du header) : pas de soulignement au
   repos, un trait qui apparaît au survol plutôt qu'un text-decoration natif.
   Dupliqué plutôt que factorisé en classe commune — regrouper les deux sous
   un même sélecteur toucherait aussi la mise en page (flex row vs colonne),
   pas seulement l'habillage du lien. */
.site-footer__column-links a {
    color: var(--paper-dim);
    text-decoration: none;
    position: relative;
    padding-block: 0.1rem;
}
.site-footer__column-links a::after {
    content: "";
    position: absolute;
    left: 0; right: 0; bottom: -2px;
    height: 1px;
    background: var(--orange-bright);
    transform: scaleX(0);
    transform-origin: left;
    transition: transform var(--transition, 160ms ease);
}
.site-footer__column-links a:hover {
    color: var(--paper-dim);
}
.site-footer__column-links a:hover::after {
    transform: scaleX(1);
}

/* =========================================================================
   Motif signature — nœuds reliés (le réseau, rendu concret)
   Utilisé pour les séparateurs de section et la liste des thématiques.
   ========================================================================= */

.node-divider {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    margin-block: 3rem;
    color: var(--line-soft);
}
.node-divider::before,
.node-divider::after {
    content: "";
    flex: 1;
    height: 0;
    border-top: 1px dashed currentColor;
}
.node-divider__dot {
    width: 6px; height: 6px;
    border-radius: 50%;
    background: var(--accent-orange);
    flex: none;
}

.node-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    gap: 0;
    border: 1px dashed var(--line-soft);
    border-radius: var(--radius);
    overflow: hidden;
}
.node-grid__item {
    padding: 1.75rem 1.5rem;
    border-left: 1px dashed var(--line-soft);
    position: relative;
    text-decoration: none;
    color: inherit;
    transition: background var(--transition, 160ms ease);
}
.node-grid__item:first-child { border-left: none; }
.node-grid__item:hover { background: var(--surface-alt); }
.node-grid__item h3 {
    font-size: 1.05rem;
    margin-bottom: 0.35rem;
}
.node-grid__item p {
    font-size: 0.9rem;
    color: var(--text-muted);
    margin: 0;
}

/* =========================================================================
   Accueil
   ========================================================================= */

.hero {
    background: var(--ink);
    color: var(--paper);
    padding-block: 5rem 4.5rem;
    position: relative;
    overflow: hidden;
}
.hero::before {
    content: "";
    position: absolute;
    inset: 0;
    background-image:
        radial-gradient(circle, rgba(23,196,242,0.30) 1.5px, transparent 1.5px),
        radial-gradient(circle, rgba(23,196,242,0.15) 1.5px, transparent 1.5px);
    background-size: 140px 140px, 90px 90px;
    background-position: 0 0, 45px 60px;
    opacity: 0.5;
    pointer-events: none;
}
.hero__inner {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 3rem;
}
.hero__content {
    max-width: 38rem;
    /* Empêche le texte de se compresser à l'excès quand l'illustration
       prend sa taille "Grande" sur un écran moyen. */
    flex: 1 1 24rem;
}
.hero__eyebrow {
    font-family: var(--font-mono);
    font-size: 0.8rem;
    letter-spacing: 0.06em;
    color: var(--orange-bright);
    text-transform: uppercase;
    margin-bottom: 1rem;
    display: inline-flex;
    align-items: center;
    gap: 0.5em;
}
.hero__eyebrow::before {
    content: "";
    width: 6px; height: 6px;
    border-radius: 50%;
    background: var(--orange-bright);
    display: inline-block;
}
.hero h1 {
    color: var(--paper);
    margin-bottom: 0.6em;
}
.hero__subtitle {
    font-size: 1.15rem;
    color: var(--paper-dim);
    max-width: 34rem;
}

/* --- Illustration du hero ---
   Décorative, à droite du texte d'accroche ; masquée en dessous de 860px
   plutôt que rapetissée, pour ne jamais entrer en compétition avec le texte
   ou le bouton sur un écran étroit. Trois tailles au choix dans l'admin
   (HomePage.hero_image_size), en largeur maximale plutôt qu'en pixels
   d'image bruts pour rester cohérent d'une page à l'autre. */
.hero__media {
    display: block;
    width: auto;
    flex-shrink: 0;
    /* Un plafond de largeur de secours : la taille se pilote surtout par
       max-height ci-dessous (voir les 3 classes), pour rester équilibrée
       avec la hauteur du texte quel que soit le format de l'image — mais
       une image très large (panoramique) suivrait sinon une largeur propre
       proportionnellement énorme une fois contrainte seulement en hauteur. */
    max-width: 28rem;
}
/* Hauteur plutôt que largeur : une image au format paysage (le cas le plus
   courant pour une illustration de hero) reste sinon courte même en
   "Grande", donc visuellement petite à côté du bloc de texte, plus haut que
   large. Contraindre par la hauteur équilibre l'image sur celle du texte
   quel que soit son format d'origine (paysage, portrait, carré). */
.hero__media--small  { max-height: 12rem; }
.hero__media--medium { max-height: 16rem; }
.hero__media--large  { max-height: 20rem; }

@media (max-width: 860px) {
    .hero__media { display: none; }
}

/* --- Paragraphe « Pourquoi Nuriva » ---
   Pleine largeur, alignée sur la grille d'atouts en dessous et le titre
   au-dessus. Pas de .prose ici volontairement : son plafond de largeur
   (--content-width, pensé pour la lisibilité d'un texte long) raccourcissait
   ce paragraphe par rapport au reste de la section, pour un texte qui ne
   fait généralement que quelques phrases. */
.home-intro-text {
    margin-bottom: 2rem;
}
.home-intro-text > :last-child { margin-bottom: 0; }

/* --- Bloc "Contenu libre" de la home (ContentBlocks imbriqué) ---
   Section autonome, sans titre ni grille juxtaposés (contrairement à
   .home-intro-text) : centrée par défaut, comme sur une page standard ou un
   article. .prose plafonne déjà la largeur à --content-width ; seul le
   centrage manque (margin-inline: auto, réservé à .wrap — voir le piège
   .wrap--narrow/.prose documenté). */
.content-blocks {
    margin-inline: auto;
}

/* --- Bande newsletter ---
   Pleine largeur et toujours sombre, comme le header, le hero et le footer :
   son fond est un token de palette brut (--ink), pas une variable sémantique,
   pour qu'elle ne bascule pas avec le thème clair/sombre. Le contenu est
   centré par .newsletter__inner, qui porte aussi .wrap pour les gouttières. */
.newsletter {
    background: var(--ink);
    color: var(--paper);
    padding-block: 4.5rem;
    border-top: 1px solid var(--line-dark);
}
.newsletter__inner {
    max-width: var(--content-width);
    text-align: center;
}
.newsletter__title {
    color: var(--paper);
    margin-bottom: 0.6em;
}
.newsletter__text {
    color: var(--paper-dim);
    font-size: 1.05rem;
    max-width: 38rem;
    margin-inline: auto;
}
.newsletter__action { margin: 0; }

/* Prévu pour un futur champ e-mail en place du bouton sortant : nécessite un
   endpoint d'inscription côté outil de newsletter (pas de vue Django dédiée). */
.newsletter__form {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    align-items: center;
    gap: 0.75rem;
    margin: 0;
}
.newsletter__form input[type="email"] {
    flex: 1 1 18rem;
    max-width: 24rem;
    padding: 0.7rem 1rem;
    border: 1px solid var(--line-dark);
    border-radius: var(--radius);
    /* Tokens bruts et non sémantiques : la bande reste sombre dans les deux
       thèmes, le champ doit donc rester clair dans les deux aussi. */
    background: var(--paper);
    color: var(--ink);
    font: inherit;
}

.button {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    margin-top: 0.5rem;
    background: var(--orange-bright);
    color: var(--ink);
    border: none;
    border-radius: var(--radius);
    padding: 0.7rem 1.5rem;
    font-family: var(--font-body);
    font-size: 0.95rem;
    font-weight: 600;
    text-decoration: none;
    cursor: pointer;
    transition: background var(--transition, 160ms ease), transform var(--transition, 160ms ease);
}
.button:hover {
    background: var(--cyan-bright);
    color: var(--ink);
    transform: translateY(-1px);
}
.button--primary { /* alias explicite : identique à .button par défaut */ }
.button--secondary {
    background: transparent;
    color: var(--text);
    border: 1px solid var(--line-soft);
}
.button--secondary:hover {
    background: var(--surface-alt);
    border-color: var(--accent-cyan);
    color: var(--accent-cyan);
    transform: translateY(-1px);
}

.section {
    padding-block: 4rem;
}
.section__heading {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 1rem;
    margin-bottom: 2rem;
    flex-wrap: wrap;
}
.section__heading h2 { margin-bottom: 0; }
.section__link {
    font-size: 0.9rem;
    white-space: nowrap;
}

.post-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
    gap: 2rem;
}
.post-card {
    position: relative;
    display: block;
    text-decoration: none;
    color: inherit;
    border-top: 1px solid var(--line-soft);
    padding-top: 1.25rem;
}
.post-card__meta {
    font-family: var(--font-mono);
    font-size: 0.75rem;
    color: var(--accent-cyan);
    text-transform: uppercase;
    letter-spacing: 0.03em;
    margin-bottom: 0.6rem;
}
.post-card h2, .post-card h3 {
    font-size: 1.05rem;
    margin-bottom: 0.4rem;
    color: var(--text);
}
.post-card p {
    font-size: 0.92rem;
    color: var(--text-muted);
    margin: 0;
}
/* Le titre est le seul lien qui couvre toute la carte (pseudo-élément étiré
   en ::after), plutôt que toute la carte étant un <a>. Ça laisse la place à
   un élément interactif indépendant (ex. bouton favori) à l'intérieur, tout
   en gardant "cliquer n'importe où sur la carte" comme comportement. */
.post-card__link {
    color: inherit;
    text-decoration: none;
}
.post-card__link::after {
    content: "";
    position: absolute;
    inset: 0;
}
.post-card__link:hover { color: var(--accent-orange); }
/* Élément interactif à l'intérieur d'une carte (ex. bouton favori) : doit
   passer au-dessus du lien étiré pour rester cliquable indépendamment. */
.post-card__action {
    position: relative;
    z-index: 1;
}

/* --- Icône des "atouts" de la home (StreamField highlights) ---
   Layout fixe en classe ; seule la couleur reste inline car elle dépend du
   choix éditorial fait dans Wagtail (block.value.color). */
.highlight-icon {
    display: block;
    width: 1.75rem;
    height: 1.75rem;
    margin-bottom: 0.85rem;
}
/* Un SVG personnalisé uploadé peut avoir n'importe quelle dimension propre
   (viewBox, width/height) — sans cette règle, il ignorerait la taille de
   .highlight-icon. Sans effet visible sur les icônes de icons/, déjà
   calibrées à peu près à cette taille. */
.highlight-icon svg {
    width: 100%;
    height: 100%;
    display: block;
}

/* --- Grille du bloc "Texte + atouts" (highlights_block.html) ---
   Classes dédiées, volontairement séparées de .node-grid (utilisé ailleurs
   pour la vitrine des thématiques, qui n'a pas de disposition configurable) :
   voir le commentaire dans highlights_block.html. --hg-cols/--hg-rows sont
   posées en style inline par le template, depuis les champs
   HighlightsBlock.columns/rows choisis dans l'admin. */
.highlight-grid {
    display: grid;
    gap: 1rem;
}
.highlight-grid--row {
    grid-auto-flow: row;
    grid-template-columns: repeat(var(--hg-cols, 4), minmax(220px, 1fr));
}
.highlight-grid--column {
    /* Remplit chaque colonne de haut en bas avant de passer à la suivante :
       grid-template-rows fixe la hauteur de la grille (le nombre de cartes
       empilées), grid-auto-flow: column fait naître de nouvelles colonnes
       plutôt que de nouvelles lignes une fois cette hauteur atteinte. */
    grid-auto-flow: column;
    grid-template-rows: repeat(var(--hg-rows, 3), auto);
    grid-auto-columns: minmax(220px, 1fr);
    overflow-x: auto;
}
@media (max-width: 720px) {
    /* Un nombre de colonnes/lignes fixe ne se replie pas tout seul comme le
       faisait l'ancien repeat(auto-fit, ...) : on impose une colonne unique
       en dessous de 720px, quelle que soit la disposition choisie. */
    .highlight-grid--row,
    .highlight-grid--column {
        grid-auto-flow: row;
        grid-template-columns: 1fr;
        grid-template-rows: none;
        overflow-x: visible;
    }
}

.highlight-grid__item {
    padding: 1.5rem 1.375rem;
    border: 1px dashed var(--line-soft);
    border-radius: var(--radius);
    text-decoration: none;
    color: inherit;
    transition: background var(--transition, 160ms ease);
}
.highlight-grid__item:hover { background: var(--surface-alt); }
.highlight-grid__item h3 {
    font-size: 1.05rem;
    margin-bottom: 0.35rem;
}
.highlight-grid__item p {
    font-size: 0.9rem;
    color: var(--text-muted);
    margin: 0;
}

/* Position de l'icône par carte (HighlightItemBlock.icon_position). À gauche
   est la valeur par défaut et ne nécessite aucune règle (comportement
   naturel du flux). */
.highlight-grid__item--icon-center { text-align: center; }
.highlight-grid__item--icon-center .highlight-icon { margin-inline: auto; }
.highlight-grid__item--icon-right { text-align: right; }
.highlight-grid__item--icon-right .highlight-icon { margin-left: auto; margin-right: 0; }

/* Icône personnalisée (image uploadée) sans couleur choisie : affichée nue,
   à la même taille que les icônes de la bibliothèque du site. */
.highlight-icon--custom img {
    width: 100%;
    height: 100%;
    object-fit: contain;
}
/* Icône personnalisée AVEC une couleur choisie : la couleur ne peut pas
   teinter une image (contrairement aux icônes SVG de la bibliothèque, qui
   utilisent currentColor) — elle devient donc un fond en pastille derrière
   l'image plutôt qu'une teinte appliquée à l'image elle-même. */
.highlight-icon--chip {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.75rem;
    height: 2.75rem;
    border-radius: 50%;
    margin-bottom: 0.85rem;
}
.highlight-icon--chip img {
    width: 60%;
    height: 60%;
    object-fit: contain;
}
.highlight-icon--chip.highlight-icon--cyan { background: var(--accent-cyan); }
.highlight-icon--chip.highlight-icon--green { background: var(--accent-green); }
.highlight-icon--chip.highlight-icon--orange { background: var(--accent-orange); }

/* --- Vignette de couverture sur les cartes .post-card ---
   Dupliquée à l'identique dans home_page.html, blog_index_page.html et
   product_index_page.html. */
.post-card__cover {
    border-radius: var(--radius);
    margin-bottom: 1rem;
}

/* États vides — même motif que .node-divider (bordure pointillée + point
   orange) plutôt qu'un simple texte italique gris. Pur ajout CSS : les
   <p class="empty-note"> existants dans les templates n'ont pas besoin de
   changer, y compris les deux basculés en display:none/"" par le JS de
   filtrage et de liste de lecture. */
/* Contenu masqué visuellement mais toujours lu par un lecteur d'écran —
   utilisé pour l'annonce du nombre de résultats après filtrage. */
.sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

.empty-note {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 1.5rem;
    border: 1px dashed var(--line-soft);
    border-radius: var(--radius);
    font-size: 0.9rem;
    color: var(--text-muted);
    font-style: italic;
}
.empty-note::before {
    content: "";
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--accent-orange);
    flex: none;
}

/* =========================================================================
   Contenu générique (about, links, blog, contact)
   ========================================================================= */

.page-header {
    padding-block: 3.5rem 2rem;
    border-bottom: 1px solid var(--line-soft);
}
.page-header--no-border { border-bottom: none; }
.page-header .intro {
    color: var(--text-muted);
    font-size: 1.05rem;
    max-width: var(--content-width);
}

/* --- Fil d'Ariane --- */
.breadcrumb {
    font-size: 0.8rem;
    color: var(--text-muted);
}
.breadcrumb a { color: var(--text-muted); }
.breadcrumb a:hover { color: var(--accent-orange); }
.breadcrumb span[aria-hidden] { margin: 0 0.35rem; }
.breadcrumb span[aria-current] { color: var(--text); }

/* --- Sommaire automatique --- */
.toc {
    border: 1px dashed var(--line-soft);
    border-radius: var(--radius);
    padding: 1rem 1.25rem;
    margin: 0 0 2em;
    font-size: 0.9rem;
}
.toc:empty { display: none; }
.toc__title {
    font-family: var(--font-mono);
    font-size: 0.75rem;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    color: var(--text-muted);
    margin: 0 0 0.5rem;
}
.toc ul {
    margin: 0;
    padding-left: 1.1rem;
}
.toc li { margin-bottom: 0.3rem; }
.toc a { color: var(--text); }
.toc a:hover { color: var(--accent-orange); }

/* --- Image de couverture (blog) ---
   Taille pilotée depuis l'admin (BlogPage.cover_image_size) : évite qu'une
   image très haute (portrait, grand format) domine toute la page. */
.cover-image {
    border-radius: var(--radius);
    overflow: hidden;
}
.cover-image img { width: 100%; display: block; }

.cover-image--compact { height: 260px; }
.cover-image--standard { height: 420px; }
.cover-image--compact img,
.cover-image--standard img {
    height: 100%;
    object-fit: cover;
}
.cover-image--large img { height: auto; }

@media (min-width: 760px) {
    .cover-image--compact { height: 320px; }
    .cover-image--standard { height: 480px; }
}

.prose {
    max-width: var(--content-width);
}
.prose h2 { margin-top: 1.6em; }
.prose blockquote {
    margin: 1.5em 0;
    padding-inline-start: 1rem;
    border-left: 2px solid var(--accent-cyan);
    color: var(--text-muted);
    font-style: italic;
}

.theme-filter {
    display: flex;
    gap: 0.5rem 1.25rem;
    flex-wrap: wrap;
    margin-bottom: 2.5rem;
    font-size: 0.9rem;
}
.theme-filter a {
    text-decoration: none;
    color: var(--text-muted);
    padding-bottom: 0.15rem;
    border-bottom: 1px solid transparent;
}
.theme-filter a:hover,
.theme-filter a.active {
    color: var(--text);
    border-bottom-color: var(--accent-orange);
}

.blog-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    gap: 2.25rem;
    max-width: var(--content-width);
}
.blog-list li {
    border-top: 1px solid var(--line-soft);
    padding-top: 1.5rem;
}
.blog-list a { text-decoration: none; color: inherit; }
.blog-list h2 { font-size: 1.3rem; margin-bottom: 0.3rem; }
.blog-list a:hover h2 { color: var(--accent-orange); }
.blog-list .meta {
    font-family: var(--font-mono);
    font-size: 0.75rem;
    color: var(--accent-cyan);
    text-transform: uppercase;
    letter-spacing: 0.03em;
    margin: 0 0 0.5rem;
}

article .meta {
    font-family: var(--font-mono);
    font-size: 0.8rem;
    color: var(--accent-cyan);
    text-transform: uppercase;
    letter-spacing: 0.03em;
}
article .tags {
    margin: 0.75rem 0 2rem;
    display: flex;
    gap: 0.5rem;
    flex-wrap: wrap;
}
.tag {
    font-size: 0.75rem;
    background: var(--surface-alt);
    border: 1px solid var(--line-soft);
    border-radius: 999px;
    padding: 0.2rem 0.7rem;
    color: var(--text-muted);
}

.links-list {
    list-style: none;
    margin: 0;
    padding: 0;
    max-width: var(--content-width);
    display: grid;
    gap: 1.5rem;
}
.links-list li {
    border-top: 1px solid var(--line-soft);
    padding-top: 1.25rem;
}
.links-list a {
    font-family: var(--font-display);
    font-size: 1.15rem;
    text-decoration: none;
}
.links-list p {
    margin: 0.3rem 0 0;
    color: var(--text-muted);
    font-size: 0.92rem;
}

/* --- Encadré (callout) --- */
.callout {
    display: flex;
    align-items: flex-start;
    gap: 0.85rem;
    background: var(--surface-alt);
    border-left: 2px solid var(--accent-orange);
    padding: 1rem 1.25rem;
    border-radius: 0 var(--radius) var(--radius) 0;
    margin: 1.5em 0;
}
.callout__icon {
    flex-shrink: 0;
    width: 1.4rem;
    height: 1.4rem;
    color: var(--accent-orange);
    margin-top: 0.15rem;
}
.callout__icon svg {
    width: 100%;
    height: 100%;
    display: block;
}
.callout--cyan { border-left-color: var(--accent-cyan); }
.callout--cyan .callout__icon { color: var(--accent-cyan); }
.callout--green { border-left-color: var(--accent-green); }
.callout--green .callout__icon { color: var(--accent-green); }
.callout--orange { border-left-color: var(--accent-orange); }
.callout--orange .callout__icon { color: var(--accent-orange); }

/* Titre + texte à l'intérieur d'un callout — répété à l'identique dans le
   bloc callout du contenu, l'encart Liberapay et l'encart de téléchargement
   (blog_page, course_page, product_page, standard_page). */
.callout__title { margin: 0; font-weight: 600; }
.callout__text { margin: 0.25rem 0 0; }

/* Variante "action" : texte + bouton côte à côte plutôt qu'icône + texte
   (ex. encart de téléchargement sur product_page.html). */
.callout--action {
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
}

/* --- FAQ en accordéon (natif HTML, pas de JS) --- */
.faq-list {
    display: grid;
    gap: 0.75rem;
    margin: 1.5em 0;
}
.faq-item {
    border: 1px dashed var(--line-soft);
    border-radius: var(--radius);
    padding: 0.9rem 1.1rem;
}
.faq-item summary {
    cursor: pointer;
    font-weight: 600;
    list-style: none;
}
.faq-item summary::-webkit-details-marker { display: none; }
.faq-item summary::before {
    content: "+";
    display: inline-block;
    width: 1.2em;
    color: var(--accent-cyan);
    font-family: var(--font-mono);
}
.faq-item[open] summary::before { content: "–"; }
.faq-item > div { margin-top: 0.75rem; color: var(--text-muted); }
.faq-item > div p:last-child { margin-bottom: 0; }

/* --- Deux colonnes --- */
.two-col {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 2rem;
    margin: 1.5em 0;
}
@media (max-width: 640px) {
    .two-col { grid-template-columns: 1fr; }
}

/* --- Tableau (bloc TableBlock) --- */
.prose table {
    width: 100%;
    border-collapse: collapse;
    margin: 1.5em 0;
    font-size: 0.92rem;
}
.prose table th, .prose table td {
    border: 1px solid var(--line-soft);
    padding: 0.5rem 0.75rem;
    text-align: left;
}
.prose table th {
    background: var(--surface-alt);
    font-family: var(--font-mono);
    font-size: 0.78rem;
    text-transform: uppercase;
    letter-spacing: 0.02em;
}

/* --- Vidéo intégrée (bloc StreamField "video") ---
   Identique dans blog_page.html, course_page.html, product_page.html et
   standard_page.html : un seul endroit à modifier désormais. */
.content-video {
    aspect-ratio: 16 / 9;
    margin: 1.5em 0;
}
.content-video iframe {
    width: 100%;
    height: 100%;
    border: 0;
    border-radius: var(--radius);
}

/* --- Espaceur manuel (bloc StreamField "spacer") --- */
.content-spacer {
    height: 2.5rem;
}

.code-block {
    background: var(--ink);
    color: var(--paper);
    border-radius: var(--radius);
    padding: 1.25rem 1.5rem;
    overflow-x: auto;
    margin: 1.5em 0;
    font-size: 0.85rem;
}
.code-block__lang {
    display: block;
    font-family: var(--font-mono);
    font-size: 0.7rem;
    color: var(--orange-bright);
    text-transform: uppercase;
    letter-spacing: 0.05em;
    margin-bottom: 0.75rem;
}
.code-block pre { margin: 0; }

/* Champs de formulaire génériques — utilisé par le formulaire de contact
   ET la barre de recherche (renommé depuis .contact-form, trompeur pour
   ce deuxième usage). */
.form ul { padding-left: 1.1rem; }
.form label {
    display: block;
    font-weight: 600;
    margin-bottom: 0.35rem;
    margin-top: 1.25rem;
}
.form input,
.form textarea,
.form select {
    width: 100%;
    max-width: var(--content-width);
    padding: 0.65rem 0.8rem;
    border: 1px solid var(--line-soft);
    border-radius: var(--radius);
    background: var(--surface-input);
    color: var(--text);
    font: inherit;
}
.form button {
    margin-top: 1.75rem;
    background: var(--ink);
    color: var(--paper);
    border: none;
    border-radius: var(--radius);
    padding: 0.75rem 1.75rem;
    font: inherit;
    font-weight: 600;
    cursor: pointer;
    transition: background var(--transition, 160ms ease);
}
.form button:hover { background: var(--cyan); }
.form--compact { max-width: 28rem; }

@media (max-width: 640px) {
    .node-grid__item { border-left: none; border-top: 1px dashed var(--line-soft); }
    .node-grid__item:first-child { border-top: none; }
}

/* =========================================================================
   Composants additifs — annuaire d'outils, glossaire, formations, produits,
   parcours. Réutilisent les mêmes tokens (--accent-*, --line-soft, --radius)
   que le reste du design, pas un nouveau système de tokens.
   ========================================================================= */

/* --- Utilitaires d'espacement (échelle : n × 0.25rem, comme .mt-8 déjà en place) --- */
.pt-6 { padding-top: 1.5rem; }
.mt-3 { margin-top: 0.75rem; }
.mt-8 { margin-top: 2rem; }
.mt-10 { margin-top: 2.5rem; }
.mt-12 { margin-top: 3rem; }

/* --- Modificateurs de section (remplacent les style="padding-top/bottom: 0"
   et style="text-align: center" dispersés dans les templates) --- */
.section--flush-top { padding-top: 0; }
.section--flush-bottom { padding-bottom: 0; }
.section--center { text-align: center; }

/* --- Barre de filtre par catégorie --- */
/* --- Panneau de filtres repliable en mobile ---
   Bouton + classe togglée en JS (même mécanisme que le menu burger),
   plutôt que <details>/<summary> : les navigateurs modernes cachent le
   contenu fermé d'un <details> via content-visibility sur un nœud interne
   de leur shadow DOM, invisible depuis notre CSS — impossible à forcer en
   "toujours ouvert" au-delà d'une certaine largeur d'écran avec ce
   mécanisme natif. Un bouton classique n'a pas ce problème. */
.filter-panel {
    margin-bottom: 1rem;
}
.filter-panel__summary {
    display: none;
    width: 100%;
    text-align: left;
    cursor: pointer;
    font-weight: 600;
    font-size: 0.9rem;
    padding: 0.75rem 1rem;
    background: transparent;
    border: 1px solid var(--line-soft);
    border-radius: var(--radius);
    color: var(--text);
    font-family: var(--font-body);
}
.filter-panel__summary::after {
    content: "▾";
    float: right;
    color: var(--text-muted);
    transition: transform 160ms ease;
}
.filter-panel__summary[aria-expanded="true"]::after { transform: rotate(180deg); }
.filter-panel__count { color: var(--accent-orange); }

@media (max-width: 760px) {
    .filter-panel__summary { display: block; }
    .filter-panel .filter-bar {
        display: none;
        margin-top: 0.75rem;
    }
    .filter-panel--open .filter-bar { display: flex; }
}

.filter-bar {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
    margin-bottom: 1rem;
}
.filter-bar__group {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    flex-wrap: wrap;
}
.filter-bar__label {
    font-family: var(--font-mono);
    font-size: 0.75rem;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    color: var(--text-muted);
    margin-right: 0.25rem;
    flex: none;
}
.filter-btn {
    font-family: var(--font-mono);
    font-size: 0.8rem;
    background: transparent;
    border: 1px solid var(--line-soft);
    border-radius: 999px;
    padding: 0.35rem 0.9rem;
    color: var(--text-muted);
    cursor: pointer;
    transition: border-color var(--transition, 160ms ease), color var(--transition, 160ms ease);
}
.filter-btn:hover { border-color: var(--accent-cyan); color: var(--text); }
.filter-btn--active {
    border-color: var(--accent-orange);
    color: var(--text);
    font-weight: 600;
}

/* --- Étoiles de recommandation --- */
.rating {
    font-size: 0.9rem;
    color: var(--accent-orange);
    letter-spacing: 1px;
    white-space: nowrap;
}

/* --- Cartes outils : en-tête + tags --- */
.tool-card__header {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 0.75rem;
}
.tool-card__header h2, .tool-card__header h3 { margin-bottom: 0; }
.tool-card__tags {
    display: flex;
    gap: 0.4rem;
    flex-wrap: wrap;
    margin-top: 0.6rem;
}

/* --- Fiche détaillée (outil, parcours...) --- */
.tool-detail {
    border: 1px dashed var(--line-soft);
    border-radius: var(--radius);
    margin: 1.5rem 0;
}
.tool-detail__row {
    display: flex;
    justify-content: space-between;
    gap: 1rem;
    padding: 0.65rem 1rem;
    border-top: 1px dashed var(--line-soft);
    font-size: 0.92rem;
}
.tool-detail__row:first-child { border-top: none; }
.tool-detail__row > span:first-child {
    color: var(--text-muted);
    font-family: var(--font-mono);
    font-size: 0.8rem;
    text-transform: uppercase;
    letter-spacing: 0.02em;
}

/* --- Bouton "À lire plus tard" --- */
.bookmark {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    flex-wrap: wrap;
    margin: 1rem 0 0;
}
.bookmark-btn {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    background: transparent;
    border: 1px solid var(--line-soft);
    border-radius: 999px;
    padding: 0.4rem 0.9rem;
    font-size: 0.8rem;
    font-weight: 500;
    font-family: var(--font-body);
    color: var(--text);
    cursor: pointer;
    flex-shrink: 0;
    transition: border-color var(--transition, 160ms ease), color var(--transition, 160ms ease), background var(--transition, 160ms ease);
}
.bookmark-btn svg { width: 0.95rem; height: 0.95rem; flex-shrink: 0; }
.bookmark-btn:hover { border-color: var(--accent-cyan); color: var(--accent-cyan); }
.bookmark-btn--active {
    background: var(--surface-alt);
    border-color: var(--accent-orange);
    color: var(--accent-orange);
}
.bookmark-btn--active svg { fill: currentColor; }
.bookmark__hint {
    font-size: 0.8rem;
    color: var(--text-muted);
}

.reading-list-item__remove {
    display: block;
    margin-top: 0.5rem;
    background: transparent;
    border: none;
    color: var(--text-muted);
    font-size: 0.8rem;
    cursor: pointer;
    padding: 0;
    text-decoration: underline;
}
.reading-list-item__remove:hover { color: var(--accent-orange); }

.reading-list-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.75rem;
}

/* --- Commentaires Isso — habillage minimal des classes qu'Isso génère --- */
#isso-thread {
    font-family: var(--font-body);
    color: var(--text);
}
#isso-thread h4 {
    font-family: var(--font-display);
    font-size: 1.3rem;
}
.isso-comment {
    border-top: 1px solid var(--line-soft);
    padding-top: 1rem;
    margin-top: 1rem;
}
.isso-comment-header {
    font-size: 0.85rem;
    color: var(--text-muted);
}
.isso-comment-header .isso-author { color: var(--text); font-weight: 600; }
.isso-comment-header a { color: var(--accent-cyan); }
.isso-textarea, .isso-postbox input[type="text"], .isso-postbox input[type="email"] {
    width: 100%;
    padding: 0.65rem 0.8rem;
    border: 1px solid var(--line-soft);
    border-radius: var(--radius);
    background: var(--surface-input);
    color: var(--text);
    font: inherit;
}
.isso-postbox .isso-submit,
.isso-comment .isso-button-reply,
.isso-comment .isso-button-edit,
.isso-comment .isso-button-delete {
    background: var(--ink);
    color: var(--paper);
    border: none;
    border-radius: var(--radius);
    padding: 0.5rem 1.1rem;
    font: inherit;
    font-weight: 600;
    cursor: pointer;
}
.isso-postbox .isso-submit:hover { background: var(--cyan); }
