/*
 * hub-www — Styles principaux
 * Toute valeur visuelle passe par les tokens (tokens.css).
 */

/* ── Reset minimal ──────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; tab-size: 4; }
body {
    margin: 0;
    background: var(--color-bg);
    color: var(--color-text);
    font-family: var(--font-sans);
    font-size: var(--text-body);
    line-height: var(--leading-normal);
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    background-image:
        radial-gradient(1200px 600px at 85% -20%, var(--color-accent-faint), transparent 60%),
        radial-gradient(800px 400px at -10% 110%, var(--color-accent-faint), transparent 70%);
    background-attachment: fixed;
}
img, svg { display: block; max-width: 100%; height: auto; }
a { color: var(--color-accent); text-decoration: underline dotted; text-decoration-color: var(--color-accent); text-decoration-thickness: 1.5px; text-underline-offset: 4px; transition: text-decoration-color var(--transition-fast), color var(--transition-fast); }
a:hover { color: var(--color-accent-strong); text-decoration-color: currentColor; }
a:focus-visible { outline: none; box-shadow: var(--shadow-glow); border-radius: var(--radius-sm); }

/* Skip link (a11y). */
.skip-link {
    position: absolute; left: -9999px; top: var(--space-2);
    background: var(--color-accent); color: var(--color-bg);
    padding: var(--space-2) var(--space-3);
    border-radius: var(--radius-sm);
    text-decoration: none; font-weight: 600;
    z-index: 100;
}
.skip-link:focus { left: var(--space-2); }

/* ── Layout primitives ──────────────────────────────────────── */
.container {
    max-width: var(--container-max);
    margin-inline: auto;
    padding-inline: var(--space-5);
}

.main { min-height: 60vh; }

.section { padding-block: var(--space-12); border-top: 1px solid var(--color-border); }
.section__head { max-width: 42rem; margin-bottom: var(--space-8); }
.section__title { font-size: var(--text-h2); line-height: var(--leading-tight); letter-spacing: -0.02em; margin: 0 0 var(--space-3); }
.section__lede  { color: var(--color-text-muted); margin: 0; font-size: var(--text-body); }

/* ── Header / Nav ───────────────────────────────────────────── */
.site-header {
    position: sticky; top: 0; z-index: 50;
    background: rgba(2, 6, 23, 0.85);
    backdrop-filter: saturate(120%) blur(8px);
    border-bottom: 1px solid var(--color-border);
}
.site-header__inner {
    display: flex; align-items: center; justify-content: space-between;
    gap: var(--space-5);
    padding-block: var(--space-3);
}
.site-header__brand {
    display: inline-flex; align-items: center; gap: var(--space-2);
    color: var(--color-text); text-decoration: none;
}
.brand__mark { font-family: var(--font-mono); color: var(--color-accent); font-size: var(--text-sm); }
.brand__name { font-weight: 600; letter-spacing: -0.01em; }
.site-nav { flex: 1; }
.site-nav ul { list-style: none; margin: 0; padding: 0; display: flex; gap: var(--space-5); justify-content: center; }
.site-nav a { color: var(--color-text-muted); text-decoration: none; font-size: var(--text-sm); }
.site-nav a:hover { color: var(--color-text); }

/* Toggle hamburger — caché par défaut (desktop) */
.nav-toggle-btn {
    display: none;
    align-items: center; justify-content: center;
    width: 40px; height: 40px;
    padding: 0;
    background: transparent;
    border: 1px solid var(--color-border-strong);
    border-radius: var(--radius-md);
    cursor: pointer;
    transition: border-color var(--transition-fast);
    flex-direction: column;
    gap: 4px;
}
.nav-toggle-btn:hover { border-color: var(--color-accent); }
.nav-toggle-btn span {
    display: block;
    width: 20px; height: 2px;
    background: var(--color-text);
    transition: transform 200ms ease-out, opacity 150ms ease-out;
    transform-origin: center;
}
.nav-toggle:checked ~ .nav-toggle-btn span:nth-child(1) { transform: translateY(6px) rotate(45deg); }
.nav-toggle:checked ~ .nav-toggle-btn span:nth-child(2) { opacity: 0; }
.nav-toggle:checked ~ .nav-toggle-btn span:nth-child(3) { transform: translateY(-6px) rotate(-45deg); }

/* ── Buttons ────────────────────────────────────────────────── */
.btn {
    display: inline-flex; align-items: center; justify-content: center; gap: var(--space-2);
    padding: var(--space-3) var(--space-5);
    border-radius: var(--radius-md);
    font-family: var(--font-sans); font-weight: 600; font-size: var(--text-sm);
    text-decoration: none;
    cursor: pointer; border: 1px solid transparent;
    transition: background var(--transition-fast), color var(--transition-fast), border-color var(--transition-fast), box-shadow var(--transition-fast);
}
.btn:focus-visible { outline: none; box-shadow: var(--shadow-glow); }
.btn--primary { background: var(--color-accent); color: var(--color-bg); }
.btn--primary:hover { background: var(--color-accent-strong); color: var(--color-bg); }
.btn--ghost { background: transparent; color: var(--color-text); border-color: var(--color-border-strong); }
.btn--ghost:hover { border-color: var(--color-accent); color: var(--color-accent); }
.btn--sm { padding: var(--space-2) var(--space-3); font-size: var(--text-xs); }
.btn--lg { padding: var(--space-4) var(--space-6); font-size: var(--text-body); }

/* ── Hero ───────────────────────────────────────────────────── */
.hero {
    padding-block: var(--space-12) var(--space-10);
    border-bottom: 1px solid var(--color-border);
}
.hero__inner { max-width: 56rem; }
.hero__eyebrow {
    font-family: var(--font-mono); font-size: var(--text-xs); letter-spacing: 0.08em;
    color: var(--color-text-subtle); text-transform: uppercase;
    margin: 0 0 var(--space-4);
}
.hero__title {
    font-size: clamp(2rem, 5vw, var(--text-display));
    line-height: var(--leading-tight); letter-spacing: -0.03em;
    margin: 0 0 var(--space-5); font-weight: 700;
}
.hero__lede {
    font-size: clamp(1.0625rem, 1.5vw, 1.25rem);
    color: var(--color-text-muted); line-height: var(--leading-relaxed);
    max-width: 42rem; margin: 0 0 var(--space-6);
}
.hero__lede--blog {
    color: var(--color-text);
    margin-top: calc(-1 * var(--space-3));
}
.hero__lede--blog strong {
    color: var(--color-accent);
    font-weight: 700;
}
.hero__cta { display: flex; gap: var(--space-3); flex-wrap: wrap; margin-bottom: var(--space-8); }

/* ── MetricStrip ────────────────────────────────────────────── */
.metric-strip {
    list-style: none; margin: 0; padding: var(--space-4) 0 0;
    border-top: 1px solid var(--color-border);
    display: flex; flex-wrap: wrap; gap: var(--space-6) var(--space-8);
}
.metric { display: flex; flex-direction: column; gap: var(--space-1); }
.metric__value {
    font-family: var(--font-mono); font-variant-numeric: tabular-nums;
    font-size: var(--text-h2); font-weight: 500;
    color: var(--color-text); line-height: 1;
}
.metric__unit { font-size: 0.5em; color: var(--color-text-muted); margin-left: 0.1em; }
.metric__label {
    font-family: var(--font-mono); font-size: var(--text-xs);
    letter-spacing: 0.1em; color: var(--color-text-subtle); text-transform: uppercase;
}

/* ── StatusGrid ─────────────────────────────────────────────── */
.status-grid__list {
    list-style: none; margin: 0; padding: 0;
    /* Desktop : CSS Grid avec masonry-via-JS (cf. status-grid.js).
       grid-auto-rows: 10px sert d'unité fine pour le span calculé en JS ;
       grid-auto-flow:dense permet aux cells suivantes de combler les
       trous laissés par une carte expanded (grid-column: span 2).
       Mobile (≤640px) bascule en CSS columns natif — cf. media query. */
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
    gap: var(--space-3);
    grid-auto-rows: 10px;
    grid-auto-flow: dense;
    /* Anti-CLS : tant que le JS n'a pas peuplé les cellules, on réserve
       une bande proche du rendu final pour ne pas faire sauter le bloc
       « derniers articles » dessous. */
    min-height: 380px;
}
.status-cell {
    /* position:relative = containing block pour le bouton × en absolute
       (le × doit se positionner par rapport à la carte entière, pas par
       rapport au panneau details qui commence sous le trigger). */
    position: relative;
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    transition: border-color var(--transition-fast), background var(--transition-fast);
    overflow: hidden;
}
.status-cell__trigger {
    /* Le trigger remplit toute la cellule en mode compact — c'est lui qui
       capture le click. On reset les styles bouton natifs pour qu'il se
       comporte comme un div cliquable. 2 colonnes : dot, name+desc. Le
       badge catégorie est masqué en compact (la border-left colorée suffit)
       et apparaît en absolute top-right uniquement en mode expanded. */
    all: unset;
    display: grid; grid-template-columns: auto 1fr; gap: var(--space-2) var(--space-3);
    align-items: center;
    width: 100%;
    padding: var(--space-3) var(--space-4);
    cursor: pointer;
}
.status-cell__trigger:focus-visible {
    outline: 2px solid var(--color-accent);
    outline-offset: -2px;
    border-radius: var(--radius-md);
}
.status-cell:hover {
    /* Même règle que .is-expanded : on ne touche que top/right/bottom pour
       préserver la border-left colorée portée par .status-cell--<cat>. */
    border-block-color: var(--color-border-strong);
    border-inline-end-color: var(--color-border-strong);
    background: var(--color-surface-elev);
}
.status-cell__dot {
    width: 12px; height: 12px; border-radius: var(--radius-full);
    background: var(--color-text-subtle);
    flex-shrink: 0;
    grid-row: 1; grid-column: 1;
}
.status-cell__dot[data-state="up"]      { background: var(--color-success); animation: pulse-status 2s ease-in-out infinite; }
.status-cell__dot[data-state="warn"]    { background: var(--color-warning); }
.status-cell__dot[data-state="down"]    { background: var(--color-error); }
.status-cell__dot[data-state="unknown"] { background: var(--color-text-subtle); }
.status-cell__name { font-family: var(--font-mono); font-size: var(--text-sm); color: var(--color-text); grid-row: 1; grid-column: 2; min-width: 0; }
.status-cell__category {
    /* Mini-badge catégorie — masqué par défaut (compact), affiché en
       absolute top-right de la carte uniquement quand .is-expanded.
       Couleur overridée plus bas par classe parente .status-cell--<X>. */
    display: none;
    font-family: var(--font-mono);
    font-size: 0.6875rem;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--color-text-subtle);
    padding: 2px 6px;
    border: 1px solid currentColor;
    border-radius: var(--radius-sm);
    line-height: 1.2;
    white-space: nowrap;
}
.status-cell__desc {
    /* Baseline publique du projet — première phrase de Project.description.
       Tronquée visuellement à une ligne en mode compact. */
    grid-row: 2; grid-column: 2;
    font-size: var(--text-xs); color: var(--color-text-subtle);
    line-height: 1.4;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* ── StatusGrid — état expanded ────────────────────────────── */
.status-cell.is-expanded {
    /* Desktop : span 2 colonnes du grid (mobile bascule en column-span:all
       dans la media query plus bas). */
    grid-column: span 2;
    /* On change uniquement les bords top/right/bottom — la border-left
       est préservée pour rester colorée par la catégorie (cf.
       .status-cell--<X> plus bas). */
    border-block-color: var(--color-accent-muted);
    border-inline-end-color: var(--color-accent-muted);
    background: var(--color-surface-elev);
    box-shadow: var(--shadow-glow);
}
.status-cell.is-expanded .status-cell__desc {
    /* En mode étendu, on masque le résumé compact : la description
       complète (avec sa 1ʳᵉ phrase incluse) est déjà affichée dans le
       panneau details juste en dessous. Sans ça, on aurait un doublon
       entre la 1ʳᵉ phrase et le 1ᵉʳ paragraphe complet. */
    display: none;
}
.status-cell.is-expanded .status-cell__category {
    /* En mode expanded, le badge réapparaît en absolute top-right, à
       gauche du bouton ×. C'est l'inverse du mode compact : en compact
       la couleur de la border-left suffit (et le badge serait tronqué
       sur les cartes étroites) ; en expanded on a la place et c'est
       l'occasion de nommer la catégorie en toutes lettres. */
    display: inline-flex;
    align-items: center;
    position: absolute;
    top: var(--space-3);
    /* var(--space-2) + largeur visuelle du × (~32px) + var(--space-2) gap */
    right: calc(var(--space-2) + 2.5rem);
    z-index: 1;
}
.status-cell__details {
    /* Panneau étendu : ordre interne = meta d'abord, puis description full
       (cf. renderCell). Le bouton × n'est plus ici — il vit comme enfant
       direct de .status-cell pour être positionné en haut absolu. */
    padding: 0 var(--space-4) var(--space-4);
    border-top: 1px solid var(--color-border);
    color: var(--color-text-muted);
    font-size: var(--text-sm);
    line-height: var(--leading-relaxed);
}
.status-cell__details[hidden] { display: none; }
.status-cell__meta {
    /* Premier bloc du panneau étendu — pas de séparateur en haut, juste
       le padding héritage du parent. */
    display: flex; flex-wrap: wrap; gap: var(--space-2) var(--space-4);
    padding-top: var(--space-3);
}
.status-cell__desc-full {
    /* Suit le meta — séparé par un dashed discret. */
    padding-top: var(--space-3);
    margin-top: var(--space-3);
    border-top: 1px dashed var(--color-border);
}
.status-cell__desc-full p {
    margin: 0 0 var(--space-3);
}
.status-cell__desc-full p:last-child { margin-bottom: 0; }
.status-cell__close {
    /* Coin haut-droit absolu de la carte entière (alignement vertical sur
       le titre du trigger). Caché tant que la carte n'est pas expanded. */
    position: absolute;
    top: var(--space-2); right: var(--space-2);
    z-index: 1;
    display: none;
    background: transparent; border: 0;
    color: var(--color-text-subtle);
    font-size: 1.5rem; line-height: 1;
    cursor: pointer;
    padding: var(--space-1) var(--space-2);
    border-radius: var(--radius-sm);
    transition: color var(--transition-fast), background var(--transition-fast);
}
.status-cell.is-expanded .status-cell__close { display: block; }
.status-cell__close:hover { color: var(--color-text); background: var(--color-surface); }
.status-cell__close:focus-visible {
    outline: 2px solid var(--color-accent);
    outline-offset: 2px;
}
.status-cell__meta-item {
    color: var(--color-text-muted);
    font-family: var(--font-mono);
    font-size: var(--text-xs);
    letter-spacing: 0.05em;
    text-transform: none;
}
.status-cell__meta-key {
    color: var(--color-text-subtle);
    text-transform: uppercase;
    letter-spacing: 0.1em;
    margin-right: var(--space-2);
}

/* View Transitions API — l'élément nommé `status-cell-active` (appliqué
   dynamiquement sur la carte cliquée) anime sa taille/position du petit
   format vers le format étendu. Le reste de la page est snapshotté en
   root et anime via cross-fade par défaut, ce qui donne le sentiment
   « le reste bouge » demandé. */
::view-transition-old(status-cell-active),
::view-transition-new(status-cell-active) {
    animation-duration: 280ms;
    animation-timing-function: cubic-bezier(0.2, 0.8, 0.2, 1);
}

/* Mobile (≤640px) : on bascule complètement le layout en CSS columns natif.
   Le navigateur place chaque cell dans la prochaine colonne disponible
   à hauteur naturelle (pas de masonry JS, pas de scrollHeight à mesurer),
   et une cell expanded prend column-span:all → toute la largeur de la
   grille. Plus de coupure de panneau, hauteurs auto. */
@media (max-width: 640px) {
    .status-grid__list {
        display: block;
        column-width: 220px;
        column-gap: var(--space-3);
        grid-auto-rows: auto;
        grid-auto-flow: row;
    }
    .status-cell {
        break-inside: avoid;
        margin-bottom: var(--space-3);
        /* Reset du grid-row éventuellement appliqué en desktop par le JS
           (le ResizeObserver desktop continue d'observer même pendant
           qu'on est en mobile via la même session — au-cas-où). */
        grid-row: auto !important;
    }
    .status-cell.is-expanded {
        grid-column: auto;
        column-span: all;
    }
    .status-cell__trigger {
        padding-inline: var(--space-3);
        gap: var(--space-2) var(--space-2);
    }
}

/* ── StatusGrid — colorisation par catégorie ────────────────────
   Border-left 3px qui reprend les tokens --color-cat-<X> de tokens.css
   (mêmes catégories que .project-badge--<X> utilisé dans les posts).
   Catégorie dérivée côté backend depuis le ProjectGroup du projet
   (cf. public.py _GROUP_TO_VISUAL_CATEGORY). Projets sans catégorie
   visuelle (groupes racine plateforme / hub-home-ai) restent neutres. */
.status-cell--pilotage       { border-left: 3px solid var(--color-cat-pilotage); }
.status-cell--connaissance   { border-left: 3px solid var(--color-cat-connaissance); }
.status-cell--infrastructure { border-left: 3px solid var(--color-cat-infrastructure); }
.status-cell--outils         { border-left: 3px solid var(--color-cat-outils); }
.status-cell--facade         { border-left: 3px solid var(--color-cat-facade); }
.status-cell--produits       { border-left: 3px solid var(--color-cat-produits); }
.status-cell--atelier        { border-left: 3px solid var(--color-cat-atelier); }
.status-cell--deprecie       { border-left: 3px solid var(--color-cat-deprecie); }

/* Couleur du badge catégorie alignée sur le border-left. La border du badge
   est en currentColor (cf. .status-cell__category) donc elle suit aussi. */
.status-cell--pilotage       .status-cell__category { color: var(--color-cat-pilotage); }
.status-cell--connaissance   .status-cell__category { color: var(--color-cat-connaissance); }
.status-cell--infrastructure .status-cell__category { color: var(--color-cat-infrastructure); }
.status-cell--outils         .status-cell__category { color: var(--color-cat-outils); }
.status-cell--facade         .status-cell__category { color: var(--color-cat-facade); }
.status-cell--produits       .status-cell__category { color: var(--color-cat-produits); }
.status-cell--atelier        .status-cell__category { color: var(--color-cat-atelier); }
.status-cell--deprecie       .status-cell__category { color: var(--color-cat-deprecie); }
.status-grid__caption {
    margin-top: var(--space-4); padding-top: var(--space-4);
    border-top: 1px solid var(--color-border);
    color: var(--color-text-subtle);
}
.mono-label {
    font-family: var(--font-mono); font-size: var(--text-xs); letter-spacing: 0.1em;
    text-transform: uppercase; color: var(--color-text-subtle);
}
.status-grid__count { color: var(--color-text); font-variant-numeric: tabular-nums; }

/* ── PillarBadge ────────────────────────────────────────────── */
.pillar-badge {
    display: inline-block;
    padding: var(--space-1) var(--space-2);
    background: var(--color-accent-muted);
    border: 1px solid var(--color-accent-muted);
    border-radius: var(--radius-sm);
    color: var(--color-accent);
    font-family: var(--font-mono); font-size: var(--text-xs);
    letter-spacing: 0.1em; text-transform: uppercase; font-weight: 500;
    text-decoration: none;
    transition: background var(--transition-fast), border-color var(--transition-fast);
}
.pillar-badge:hover { background: rgba(34, 211, 238, 0.2); border-color: var(--color-accent); color: var(--color-accent); }

/* ── Article grid + card ────────────────────────────────────── */
.article-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
    gap: var(--space-5);
}
.article-card {
    /* position:relative + .article-card__title a::before en position:absolute
       = pattern « stretched link ». Toute la surface de la card devient
       cliquable, mais un seul <a> reste dans le DOM (le titre) — bon pour
       l'accessibilité et le SEO. Les autres liens internes (pillar-badge)
       conservent leur clic grâce à `position:relative; z-index:1`. */
    position: relative;
    display: flex; flex-direction: column; gap: var(--space-3);
    padding: var(--space-5);
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-lg);
    cursor: pointer;
    transition: border-color var(--transition-fast), transform var(--transition-fast), box-shadow var(--transition-fast);
}
.article-card:hover {
    border-color: var(--color-accent);
    transform: translateY(-2px);
    box-shadow: var(--shadow-md);
}
.article-card:focus-within {
    border-color: var(--color-accent);
    box-shadow: var(--shadow-glow);
}
.article-card__title { margin: 0; font-size: var(--text-h3); line-height: var(--leading-snug); letter-spacing: -0.015em; }
.article-card__title a {
    color: var(--color-text);
    text-decoration: none;
}
.article-card__title a::before {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: inherit;
    z-index: 0;
}
.article-card:hover .article-card__title a { color: var(--color-accent); }
/* Les autres éléments interactifs (pillar-badge) doivent passer DEVANT le
   ::before stretched, sinon ils ne reçoivent plus le clic.
   ⚠ NE PAS inclure `.article-card__title` ici : si le <h3> est positionné,
   le ::before du <a> enfant se réfère au <h3> (titre seul) au lieu de la
   .article-card, et le stretched link couvre alors uniquement le titre. */
.article-card .pillar-badge,
.article-card__excerpt,
.article-card__meta { position: relative; z-index: 1; }
.article-card__excerpt { margin: 0; color: var(--color-text-muted); font-size: var(--text-sm); line-height: var(--leading-relaxed); pointer-events: none; }
.article-card__meta { margin-top: auto; display: flex; gap: var(--space-2); align-items: center; font-family: var(--font-mono); font-size: var(--text-xs); color: var(--color-text-subtle); pointer-events: none; }
.article-card__sep { color: var(--color-border-strong); }

/* ── Post / Page ────────────────────────────────────────────── */
.post, .page { padding-block: var(--space-10); max-width: 44rem; }
.section--prose .prose { max-width: 44rem; margin-inline: auto; }
.post__head, .page__head { margin-bottom: var(--space-8); }
.post__head .pillar-badge { margin-bottom: var(--space-4); }
.post__title, .page__title { font-size: clamp(2rem, 4vw, var(--text-h1)); line-height: var(--leading-tight); letter-spacing: -0.02em; margin: 0 0 var(--space-4); }
.post__excerpt, .page__lede { color: var(--color-text-muted); font-size: 1.125rem; line-height: var(--leading-relaxed); margin: 0 0 var(--space-5); }
.post__meta {
    display: flex; gap: var(--space-2); align-items: center; flex-wrap: wrap;
    font-family: var(--font-mono); font-size: var(--text-xs); color: var(--color-text-subtle);
}
.post__sep { color: var(--color-border-strong); }
.post__feature, .page__feature { margin: 0 0 var(--space-8); border-radius: var(--radius-lg); overflow: hidden; }
.post__feature img, .page__feature img { width: 100%; cursor: zoom-in; }
.post__feature figcaption { padding: var(--space-3) var(--space-4); font-size: var(--text-sm); color: var(--color-text-muted); }

/* Prose — corps d'article. */
.prose { font-size: var(--text-body); line-height: var(--leading-relaxed); color: var(--color-text); }
.prose h2 { margin-top: var(--space-10); margin-bottom: var(--space-4); font-size: var(--text-h2); line-height: var(--leading-tight); letter-spacing: -0.02em; }
.prose h3 { margin-top: var(--space-8);  margin-bottom: var(--space-3); font-size: var(--text-h3); line-height: var(--leading-snug); letter-spacing: -0.015em; }
.prose p  { margin: 0 0 var(--space-4); }
.prose ul, .prose ol { margin: 0 0 var(--space-4); padding-left: var(--space-5); }
.prose li { margin-bottom: var(--space-2); }
.prose code {
    font-family: var(--font-mono); font-size: 0.9em;
    background: var(--color-surface); padding: 0.15em 0.4em;
    border-radius: var(--radius-sm); color: var(--color-accent);
    border: 1px solid var(--color-border);
}
.prose pre {
    background: var(--color-surface); border: 1px solid var(--color-border);
    border-radius: var(--radius-md); padding: var(--space-4);
    overflow-x: auto; font-size: var(--text-sm);
    margin: 0 0 var(--space-5);
}
.prose pre code { background: none; padding: 0; border: none; color: var(--color-text); }
.prose blockquote {
    border-left: 3px solid var(--color-accent);
    padding: var(--space-2) var(--space-5);
    margin: 0 0 var(--space-5);
    color: var(--color-text-muted); font-style: italic;
}
.prose hr { border: 0; border-top: 1px solid var(--color-border); margin: var(--space-8) 0; }
.prose img { border-radius: var(--radius-md); margin: var(--space-5) 0; max-width: 100%; height: auto; cursor: zoom-in; }
.prose figure { margin: var(--space-5) 0; }
.prose figure img { margin: 0; }
.prose figcaption {
    text-align: center;
    padding: var(--space-3) var(--space-4) 0;
    font-size: var(--text-sm);
    color: var(--color-text-muted);
    line-height: var(--leading-relaxed);
}

/* ── Koenig editor wide/full image classes ────────────────────────
   Ghost expose ces classes pour les images plus larges que le contenu.
   .kg-width-wide  : déborde de quelques pourcents au-delà de la prose.
   .kg-width-full  : pleine largeur du viewport (utile pour les couvertures). */
.kg-width-wide {
    position: relative;
    width: calc(100% + 8vw);
    max-width: 64rem;
    left: 50%;
    transform: translateX(-50%);
    border-radius: var(--radius-lg);
    overflow: hidden;
}
.kg-width-full {
    position: relative;
    width: 100vw;
    max-width: 100vw;
    left: 50%;
    margin-left: -50vw;
    border-radius: 0;
}
.kg-width-wide img,
.kg-width-full img { width: 100%; height: auto; display: block; margin: 0; border-radius: inherit; }

/* ── Lightbox click-to-zoom ──────────────────────────────────────
   Click sur une image de contenu (prose ou hero) → overlay fullscreen.
   Click overlay ou Escape → ferme. Aucune dépendance externe. */
.lightbox-overlay {
    position: fixed;
    top: 0; left: 0;
    width: 100vw; height: 100vh;
    z-index: 9999;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 2rem;
    box-sizing: border-box;
    background: #0a0a0a;
    cursor: zoom-out;
    opacity: 0;
    transition: opacity 0.18s ease-out;
    overflow: hidden;
}
.lightbox-overlay[data-state="open"] { opacity: 1; }
.lightbox-overlay img {
    display: block;
    /* Neutralise la règle globale `img { height: auto }` pour permettre
       au flex+contain de gérer correctement les SVG à ratio extrême. */
    width: auto !important;
    height: auto !important;
    max-width: 100%;
    max-height: 100%;
    object-fit: contain;
    border-radius: var(--radius-md);
    box-shadow: 0 10px 50px rgba(0, 0, 0, 0.6);
    margin: 0;
}
.lightbox-overlay__close {
    position: absolute; top: var(--space-4); right: var(--space-4);
    background: rgba(255, 255, 255, 0.1); border: 0;
    color: white; width: 2.5rem; height: 2.5rem; border-radius: 9999px;
    font-size: 1.5rem; line-height: 1; cursor: pointer;
}
.lightbox-overlay__close:hover { background: rgba(255, 255, 255, 0.2); }

/* ── Project badges ──────────────────────────────────────────────
   Signale visuellement les références aux projets internes de l'écosystème
   (hub-*, knowledge*, mcp-unified, hubtree, ledger, memories, etc.) — pour
   les distinguer des liens externes et autres mentions techniques.
   À terme : cliquables avec deep-link vers la page Stack + panel projet ouvert. */
.project-badge {
    display: inline-block;
    padding: 0.05em 0.5em;
    background: rgba(34, 211, 238, 0.12);
    color: var(--color-accent);
    border: 1px solid rgba(34, 211, 238, 0.32);
    border-radius: var(--radius-sm);
    font-family: var(--font-mono);
    font-size: 0.88em;
    font-weight: 500;
    letter-spacing: -0.01em;
    white-space: nowrap;
    line-height: 1.4;
}

/* Variantes par catégorie (taxonomie hub-projects).
   Surcharge color / background / border seulement. */
.project-badge--pilotage       { color: var(--color-cat-pilotage);       background: rgba(34, 211, 238, 0.12);  border-color: rgba(34, 211, 238, 0.32); }
.project-badge--connaissance   { color: var(--color-cat-connaissance);   background: rgba(167, 139, 250, 0.12); border-color: rgba(167, 139, 250, 0.32); }
.project-badge--infrastructure { color: var(--color-cat-infrastructure); background: rgba(251, 191, 36, 0.12);  border-color: rgba(251, 191, 36, 0.32); }
.project-badge--outils         { color: var(--color-cat-outils);         background: rgba(148, 163, 184, 0.12); border-color: rgba(148, 163, 184, 0.32); }
.project-badge--facade         { color: var(--color-cat-facade);         background: rgba(244, 114, 182, 0.12); border-color: rgba(244, 114, 182, 0.32); }
.project-badge--produits       { color: var(--color-cat-produits);       background: rgba(16, 185, 129, 0.12);  border-color: rgba(16, 185, 129, 0.32); }
.project-badge--atelier        { color: var(--color-cat-atelier);        background: rgba(251, 146, 60, 0.12);  border-color: rgba(251, 146, 60, 0.32); }
.project-badge--deprecie       { color: var(--color-cat-deprecie);       background: rgba(248, 113, 113, 0.12); border-color: rgba(248, 113, 113, 0.32); }

/* ── Category legend ─────────────────────────────────────────
   Ligne de badges colorés (1 par catégorie) affichée sous le lede du
   status-grid pour décoder les bordures colorées des cellules. */
.category-legend {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
    list-style: none;
    padding: 0;
    margin: calc(var(--space-8) * -1 + var(--space-3)) 0 var(--space-5);
}

/* ── Callout ─────────────────────────────────────────────────
   Encadré coloré pour mettre en valeur une phrase clé ou un insight.
   À insérer dans le markdown via <aside class="callout callout--<variant>">…</aside> */
.callout {
    margin: var(--space-6) 0;
    padding: var(--space-4) var(--space-5);
    border-left: 3px solid var(--color-accent);
    background: rgba(34, 211, 238, 0.06);
    border-radius: 0 var(--radius-md) var(--radius-md) 0;
    color: var(--color-text);
}
.callout p { margin: 0; }
.callout p + p { margin-top: var(--space-3); }

.callout--win   { border-left-color: var(--color-cat-produits);       background: rgba(16, 185, 129, 0.06); }
.callout--warn  { border-left-color: var(--color-cat-infrastructure); background: rgba(251, 191, 36, 0.06); }
.callout--quote { border-left-color: var(--color-cat-outils);         background: rgba(148, 163, 184, 0.06); font-style: italic; }
.callout--quote p { font-size: 1.0625em; line-height: 1.55; }

.post__foot { margin-top: var(--space-10); padding-top: var(--space-5); border-top: 1px solid var(--color-border); }
.post__tags { display: flex; gap: var(--space-2); flex-wrap: wrap; }
.tag {
    font-family: var(--font-mono); font-size: var(--text-xs);
    color: var(--color-text-muted); text-decoration: none;
    padding: var(--space-1) var(--space-2);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
}
.tag:hover { color: var(--color-accent); border-color: var(--color-accent-muted); }

/* ── Newsletter ─────────────────────────────────────────────── */
.section--newsletter { background: linear-gradient(180deg, transparent, var(--color-accent-faint)); }
.newsletter { text-align: center; max-width: 36rem; margin-inline: auto; }
.newsletter__title { font-size: var(--text-h2); line-height: var(--leading-tight); letter-spacing: -0.02em; margin: 0 0 var(--space-3); }
.newsletter__lede { color: var(--color-text-muted); margin: 0 0 var(--space-6); }

/* ── Footer ─────────────────────────────────────────────────── */
.site-footer { border-top: 1px solid var(--color-border); padding-block: var(--space-8); margin-top: var(--space-12); }
.site-footer__inner {
    display: flex; flex-direction: column; gap: var(--space-3);
    align-items: center; text-align: center;
}
.site-footer__copy { margin: 0; color: var(--color-text-muted); font-size: var(--text-sm); }
.site-footer__meta { margin: 0; }

@media (min-width: 768px) {
    .site-footer__inner { flex-direction: row; justify-content: space-between; text-align: left; }
}

/* ── Empty state ────────────────────────────────────────────── */
.empty-state {
    padding: var(--space-8) var(--space-5);
    text-align: center; color: var(--color-text-muted);
    border: 1px dashed var(--color-border);
    border-radius: var(--radius-lg);
}

/* ────────────────────────────────────────────────────────────── */
/* Responsive — tablette                                          */
/* ────────────────────────────────────────────────────────────── */

@media (max-width: 1024px) {
    .section { padding-block: var(--space-10); }
    .hero { padding-block: var(--space-10) var(--space-8); }
}

/* ────────────────────────────────────────────────────────────── */
/* Responsive — mobile (≤ 640 px)                                 */
/* ────────────────────────────────────────────────────────────── */

@media (max-width: 640px) {
    /* Reset bg radial — coûteux sur petit GPU mobile */
    body { background-image: none; }

    /* Container plus serré */
    .container { padding-inline: var(--space-4); }

    /* Header → hamburger */
    .site-header__inner {
        gap: var(--space-3);
        flex-wrap: wrap;
        position: relative;
    }
    .nav-toggle-btn { display: inline-flex; order: 3; }
    .site-header__actions { order: 2; }
    .site-nav {
        order: 4;
        flex-basis: 100%;
        max-height: 0;
        overflow: hidden;
        transition: max-height 250ms ease-out;
    }
    .nav-toggle:checked ~ .site-nav {
        max-height: 80vh;
    }
    .site-nav ul {
        flex-direction: column;
        align-items: flex-start;
        justify-content: flex-start;
        gap: 0;
        padding: var(--space-3) 0 var(--space-4);
    }
    .site-nav li { width: 100%; }
    .site-nav a {
        display: block;
        padding: var(--space-3) 0;
        font-size: 1rem;
        color: var(--color-text);
        border-bottom: 1px solid var(--color-border);
    }
    .site-nav a:hover { color: var(--color-accent); }
    .site-nav li:last-child a { border-bottom: 0; }

    /* Hero condensé */
    .hero { padding-block: var(--space-8) var(--space-6); }
    .hero__title {
        font-size: clamp(1.75rem, 8vw, 2.25rem);
        letter-spacing: -0.02em;
    }
    .hero__lede { font-size: 1rem; line-height: var(--leading-normal); }
    .hero__cta { flex-direction: column; align-items: stretch; gap: var(--space-2); margin-bottom: var(--space-6); }
    .hero__cta .btn { justify-content: center; padding-block: var(--space-3); }

    /* MetricStrip empilable */
    .metric-strip {
        gap: var(--space-4) var(--space-5);
        padding-top: var(--space-3);
    }
    .metric__value { font-size: 1.5rem; }
    .metric__label { font-size: 0.65rem; }

    /* Sections compactes */
    .section { padding-block: var(--space-8); }
    .section__head { margin-bottom: var(--space-6); }
    .section__title { font-size: 1.5rem; }
    .section__lede { font-size: 0.95rem; }

    /* StatusGrid colonnes plus étroites */
    .status-grid__list {
        grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
        gap: var(--space-2);
    }
    .status-cell { padding: var(--space-3); }
    .status-cell__name { font-size: var(--text-xs); }

    /* Article grid 1 col */
    .article-grid {
        grid-template-columns: 1fr;
        gap: var(--space-4);
    }
    .article-card { padding: var(--space-4); }
    .article-card__title { font-size: 1.125rem; }

    /* Post / Page compacts */
    .post, .page { padding-block: var(--space-6); }
    .post__title, .page__title {
        font-size: clamp(1.5rem, 6vw, 2rem);
        letter-spacing: -0.015em;
    }
    .post__excerpt, .page__lede { font-size: 1rem; }
    .post__meta { gap: var(--space-1); }
    .post__feature, .page__feature { border-radius: var(--radius-md); }

    /* Prose responsive */
    .prose { font-size: 1rem; }
    .prose h2 {
        margin-top: var(--space-6);
        margin-bottom: var(--space-3);
        font-size: 1.375rem;
    }
    .prose h3 {
        margin-top: var(--space-5);
        margin-bottom: var(--space-2);
        font-size: 1.125rem;
    }
    .prose pre { padding: var(--space-3); font-size: 0.8125rem; }
    .prose blockquote { padding: var(--space-1) var(--space-4); }
    .prose img { margin: var(--space-4) 0; }

    /* Newsletter compacte */
    .newsletter__title { font-size: 1.5rem; }
    .newsletter .btn--lg { width: 100%; }

    /* Footer */
    .site-footer { padding-block: var(--space-6); margin-top: var(--space-8); }
}

/* ────────────────────────────────────────────────────────────── */
/* Responsive — très petit (≤ 400 px)                             */
/* ────────────────────────────────────────────────────────────── */

@media (max-width: 400px) {
    .container { padding-inline: var(--space-3); }
    .brand__name { display: none; }  /* garde juste le mark mono */
    .hero { padding-block: var(--space-6) var(--space-5); }
    .hero__title { font-size: 1.625rem; }
    .metric { gap: 0; }
    .metric__value { font-size: 1.25rem; }
}
