/* =============================================================================
   Aurin Solutions — design system commun
   Sources : docs/design-models/logo.html, docs/design-models/design-system.html
   Valeurs et règles : docs/design.md
   Les règles propres à une page n'ont jamais leur place ici (CLAUDE.md § 5.2).
   ========================================================================== */

/* -----------------------------------------------------------------------------
   1. Polices — auto-hébergées (A-23, A-30), jamais un CDN tiers
   -------------------------------------------------------------------------- */

/* Space Grotesk est une police variable : un fichier couvre les graisses 300 à 700. */
@font-face {
    font-family: 'Space Grotesk';
    font-style: normal;
    font-weight: 300 700;
    font-display: swap;
    src: url('../fonts/space-grotesk-latin.woff2') format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
    font-family: 'Space Grotesk';
    font-style: normal;
    font-weight: 300 700;
    font-display: swap;
    src: url('../fonts/space-grotesk-latin-ext.woff2') format('woff2');
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* IBM Plex Mono est statique : un fichier par graisse et par sous-ensemble. */
@font-face {
    font-family: 'IBM Plex Mono';
    font-style: normal;
    font-weight: 400;
    font-display: swap;
    src: url('../fonts/ibm-plex-mono-latin-400.woff2') format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
    font-family: 'IBM Plex Mono';
    font-style: normal;
    font-weight: 500;
    font-display: swap;
    src: url('../fonts/ibm-plex-mono-latin-500.woff2') format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
    font-family: 'IBM Plex Mono';
    font-style: normal;
    font-weight: 400;
    font-display: swap;
    src: url('../fonts/ibm-plex-mono-latin-ext-400.woff2') format('woff2');
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
    font-family: 'IBM Plex Mono';
    font-style: normal;
    font-weight: 500;
    font-display: swap;
    src: url('../fonts/ibm-plex-mono-latin-ext-500.woff2') format('woff2');
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* -----------------------------------------------------------------------------
   2. Tokens
   Quatre couches (A-29) : valeurs claires par défaut, préférence système, puis
   surcharges explicites. [data-theme="light"] doit pouvoir ramener la page en clair
   quand le système demande le sombre — d'où la quatrième couche.
   -------------------------------------------------------------------------- */

:root {
    /* Typographie */
    --ff-sans: 'Space Grotesk', system-ui, sans-serif;
    --ff-mono: 'IBM Plex Mono', ui-monospace, monospace;

    --fs-4xl: clamp(2.4rem, 5.6vw, 4.1rem);
    --fs-3xl: clamp(1.9rem, 3.6vw, 2.85rem);
    --fs-xl: clamp(18px, 2vw, 22px);
    --fs-lg: clamp(17px, 1.4vw, 19px);
    --fs-base: clamp(15.5px, 1.1vw, 16px);
    /* Fixe, non fluide : elle nomme un contrôle, et un libellé qui grandit avec la
       fenêtre concurrence la valeur saisie à côté. */
    --fs-sm: 13px;
    --fs-mono-xs: clamp(11px, 0.9vw, 12.5px);

    /* Espacement — base 4 */
    --sp-1: 4px;
    --sp-2: 8px;
    --sp-3: 12px;
    --sp-4: 16px;
    --sp-5: 20px;
    --sp-6: 24px;
    --sp-8: 32px;
    --sp-12: 48px;
    --sp-16: 64px;
    --section-y: clamp(56px, 8vw, 104px);

    /* Rayons */
    --r-sm: 4px;
    --r-md: 8px;
    --r-lg: 14px;
    --r-pill: 999px;

    /* Mise en page — telle que déclarée par les maquettes : 1180 px moins des
       gouttières fluides, ce qui donne 1092 px de contenu sur grand écran et laisse
       respirer un téléphone. */
    --container: 1180px;
    --container-narrow: 760px;

    /* Accent de marque, identique dans les deux thèmes. La pastille inversant sa
       propre surface, il lui faut un accent lié à la marque et non au thème de la
       page — c'est la valeur qu'emploient les deux variantes de favicon. */
    --c-accent-brand: #C2410C;

    /* Mouvement */
    --t-fast: 180ms ease-out;
    --t-base: 200ms ease-out;
    --t-reveal: 520ms cubic-bezier(0.2, 0.7, 0.3, 1);

    color-scheme: light dark;
}

/* Palette claire — celle par défaut. */
:root {
    --c-bg: #F6F5F2;
    --c-bg-alt: #EDEBE5;
    --c-surface: #FFFFFF;
    --c-line: #E2DFD7;
    --c-line-strong: #C7C2B6;
    --c-text: #171614;
    --c-text-2: #55524B;
    --c-text-3: #6E6A61;
    --c-accent: #C2410C;
    --c-accent-hover: #9A3412;
    --c-accent-ink: #FFFFFF;
    --c-accent-soft: rgba(194, 65, 12, .08);
    --c-ok: #166534;
    --c-warn: #B7791F;
    --c-err: #B42318;

    --sh-1: 0 1px 2px rgba(23, 22, 20, .06);
    --sh-2: 0 6px 20px -6px rgba(23, 22, 20, .16);
    --sh-3: 0 20px 50px -14px rgba(23, 22, 20, .22);
}

/* Palette sombre, factorisée pour que la media query et la surcharge explicite
   ci-dessous ne puissent pas diverger. */
@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) {
        --c-bg: #12110F;
        --c-bg-alt: #191713;
        --c-surface: #1C1A16;
        --c-line: #2D2A24;
        --c-line-strong: #464137;
        --c-text: #EAE6DE;
        --c-text-2: #A9A39A;
        --c-text-3: #938D83;
        --c-accent: #F97316;
        --c-accent-hover: #FDA45A;
        --c-accent-ink: #17120C;
        --c-accent-soft: rgba(249, 115, 22, .14);
        --c-ok: #6EE7A8;
        --c-warn: #FBD34D;
        --c-err: #FF8A7A;

        --sh-1: 0 1px 2px rgba(0, 0, 0, .5);
        --sh-2: 0 6px 20px -6px rgba(0, 0, 0, .6);
        --sh-3: 0 20px 50px -14px rgba(0, 0, 0, .7);
    }
}

:root[data-theme="dark"] {
    --c-bg: #12110F;
    --c-bg-alt: #191713;
    --c-surface: #1C1A16;
    --c-line: #2D2A24;
    --c-line-strong: #464137;
    --c-text: #EAE6DE;
    --c-text-2: #A9A39A;
    --c-text-3: #938D83;
    --c-accent: #F97316;
    --c-accent-hover: #FDA45A;
    --c-accent-ink: #17120C;
    --c-accent-soft: rgba(249, 115, 22, .14);
    --c-ok: #6EE7A8;
    --c-warn: #FBD34D;
    --c-err: #FF8A7A;

    --sh-1: 0 1px 2px rgba(0, 0, 0, .5);
    --sh-2: 0 6px 20px -6px rgba(0, 0, 0, .6);
    --sh-3: 0 20px 50px -14px rgba(0, 0, 0, .7);
}

/* -----------------------------------------------------------------------------
   3. Base
   -------------------------------------------------------------------------- */

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

/* La règle d'agent utilisateur derrière l'attribut hidden est un simple
   `display: none` sur l'élément : n'importe quelle classe posant un display — un
   composant flex, par exemple — la bat et montre ce que le balisage voulait cacher.
   Ceci rend son sens à l'attribut : il l'emporte sur les composants, ce qui est
   toute sa raison d'être. */
[hidden] {
    display: none !important;
}

html {
    -webkit-text-size-adjust: 100%;
}

body {
    margin: 0;
    background: var(--c-bg);
    color: var(--c-text);
    font-family: var(--ff-sans);
    font-size: var(--fs-base);
    font-weight: 400;
    line-height: 1.6;
    -webkit-font-smoothing: antialiased;
    /* Évite de laisser un mot seul sur la dernière ligne d'un paragraphe. */
    text-wrap: pretty;
}

h1, h2, h3, h4 {
    margin: 0 0 var(--sp-4);
    font-weight: 700;
    line-height: 1.12;
    letter-spacing: -.02em;
}

h1 { font-size: var(--fs-4xl); }
h2 { font-size: var(--fs-3xl); }
h3 { font-size: var(--fs-xl); }
h4 { font-size: var(--fs-lg); }

p {
    margin: 0 0 var(--sp-4);
}

a {
    color: var(--c-accent);
    text-decoration-thickness: 1px;
    text-underline-offset: .2em;
    transition: color var(--t-fast);
}

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

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

hr {
    height: 1px;
    margin: var(--sp-8) 0;
    border: 0;
    background: var(--c-line);
}

/* L'anneau de focus n'est jamais retiré — règle d'accessibilité, pas choix de style. */
:focus-visible {
    outline: 2px solid var(--c-accent);
    outline-offset: 2px;
    border-radius: var(--r-sm);
}

::selection {
    background: var(--c-accent);
    color: var(--c-accent-ink);
}

/* -----------------------------------------------------------------------------
   4. Aides de mise en page
   La réactivité vient de clamp() et de grilles auto-fit, pas de points de rupture.
   -------------------------------------------------------------------------- */

.container {
    width: 100%;
    max-width: var(--container);
    margin-inline: auto;
    padding-inline: clamp(18px, 4vw, 44px);
}

.container--narrow {
    max-width: var(--container-narrow);
}

.section {
    padding-block: var(--section-y);
}

.section--alt {
    background: var(--c-bg-alt);
}

.section__label {
    margin-bottom: var(--sp-3);
    color: var(--c-accent);
    font-family: var(--ff-mono);
    font-size: var(--fs-mono-xs);
    font-weight: 500;
    letter-spacing: .12em;
    text-transform: uppercase;
}

.lead {
    max-width: 62ch;
    color: var(--c-text-2);
    font-size: var(--fs-lg);
}

.grid {
    display: grid;
    gap: var(--sp-6);
    grid-template-columns: repeat(auto-fit, minmax(min(280px, 100%), 1fr));
}

.grid--wide {
    grid-template-columns: repeat(auto-fit, minmax(min(360px, 100%), 1fr));
}

/* -----------------------------------------------------------------------------
   5. Logo
   Le logo est du texte, jamais une image : net à toute résolution, sans poids, et
   il suit le thème de lui-même. Des <span> neutres portent les classes — les
   original charter snippet misused <b>/<i>/<u>/<em>/<s> (A-22).
   -------------------------------------------------------------------------- */

.logo {
    --logo-size: 96px;
    --logo-ink: currentColor;
    --logo-accent: var(--c-accent);

    display: inline-flex;
    flex-direction: column;
    align-items: stretch;
    color: var(--logo-ink);
    font-family: var(--ff-sans);
    font-size: var(--logo-size);
    line-height: 1;
    text-decoration: none;
}

.logo__wordmark {
    font-weight: 700;
    line-height: .86;
    letter-spacing: -.045em;
    padding-right: .045em;
}

.logo__dot {
    color: var(--logo-accent);
}

.logo__tagline {
    display: flex;
    justify-content: space-between;
    color: var(--c-text-2);
    font-size: .19em;
    font-weight: 500;
    line-height: 1;
}

/* Variante en ligne — barres de navigation, pieds de page, en-têtes d'email. */
.logo--inline {
    flex-direction: row;
    align-items: baseline;
    gap: .24em;
}

.logo--inline .logo__tagline {
    display: inline;
    letter-spacing: .19em;
}

/* Variante pastille — avatar, icône d'application, réseaux. Jamais associée au
   mot-signe complet. Le rayon vaut 22 % du côté, il suit donc la taille tout seul. */
.logo--mark {
    --logo-accent: var(--c-accent-brand);

    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: var(--logo-size);
    height: var(--logo-size);
    border-radius: 22%;
    background: var(--c-text);
    color: var(--c-bg);
    font-size: calc(var(--logo-size) * .58);
}

.logo--mark .logo__tagline {
    display: none;
}

/* -----------------------------------------------------------------------------
   6. Boutons — cibles >= 48 px, transition 200 ms ease-out
   -------------------------------------------------------------------------- */

.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--sp-2);
    min-height: 48px;
    padding: var(--sp-3) var(--sp-6);
    border: 1px solid transparent;
    border-radius: var(--r-md);
    background: var(--c-accent);
    color: var(--c-accent-ink);
    font-family: inherit;
    font-size: var(--fs-base);
    font-weight: 500;
    line-height: 1.2;
    text-decoration: none;
    cursor: pointer;
    transition: background var(--t-base), border-color var(--t-base), color var(--t-base);
}

.btn:hover {
    background: var(--c-accent-hover);
    color: var(--c-accent-ink);
}

/* La flèche est dans le registre technique, comme tout glyphe qui figure un
   mouvement plutôt qu'un mot. Le gap de .btn l'espace déjà. */
.btn__arrow {
    font-family: var(--ff-mono);
}

/* Inerte mais toujours lisible : un contrôle désactivé échappe au minimum de
   contraste, son libellé non. */
.btn:disabled,
.btn[aria-disabled="true"] {
    background: var(--c-line);
    border-color: var(--c-line-strong);
    color: var(--c-text-3);
    cursor: not-allowed;
}

.btn--secondary {
    background: var(--c-surface);
    border-color: var(--c-line-strong);
    color: var(--c-text);
}

.btn--secondary:hover {
    background: var(--c-bg-alt);
    border-color: var(--c-text);
    color: var(--c-text);
}

.btn--link {
    min-height: 0;
    padding: 0;
    background: none;
    border: 0;
    color: var(--c-accent);
    font-weight: 500;
}

.btn--link:hover {
    background: none;
    color: var(--c-accent-hover);
}

/* Un lien qui referme un bloc et pointe vers la suite. Garde une cible de 44 px
   bien qu'il n'ait pas l'habillage d'un bouton, et se place en début de ligne quelle
   que soit la largeur du parent flex. */
.link-arrow {
    display: inline-flex;
    gap: var(--sp-2);
    align-items: center;
    align-self: flex-start;
    min-height: 44px;
    font-size: 15px;
    font-weight: 400;
    text-decoration: none;
}

/* -----------------------------------------------------------------------------
   7. Badges
   Les badges techno restent gris : une preuve, jamais un argument. Les badges d'état
   meaning, so they carry colour.
   -------------------------------------------------------------------------- */

.badge {
    display: inline-flex;
    align-items: center;
    padding: var(--sp-1) var(--sp-3);
    border: 1px solid var(--c-line);
    border-radius: var(--r-sm);
    background: var(--c-surface);
    color: var(--c-text-2);
    font-family: var(--ff-mono);
    font-size: var(--fs-mono-xs);
    font-weight: 400;
    line-height: 1.6;
    white-space: nowrap;
}

.badge--status {
    border-radius: var(--r-pill);
    font-weight: 500;
    letter-spacing: .08em;
    text-transform: uppercase;
}

.badge--accent {
    border-color: transparent;
    background: var(--c-accent-soft);
    color: var(--c-accent);
}

.badge--ok {
    border-color: transparent;
    background: var(--c-accent-soft);
    background: color-mix(in srgb, var(--c-ok) 12%, transparent);
    color: var(--c-ok);
}

.badge--err {
    border-color: transparent;
    background: color-mix(in srgb, var(--c-err) 12%, transparent);
    color: var(--c-err);
}

.badge--neutral {
    background: var(--c-bg-alt);
    color: var(--c-text-3);
}

/* -----------------------------------------------------------------------------
   8. Champs de formulaire — repos / focus / erreur / succès
   -------------------------------------------------------------------------- */

.field {
    display: flex;
    flex-direction: column;
    gap: var(--sp-2);
    margin-bottom: var(--sp-4);
}

.field__label {
    font-size: var(--fs-sm);
    font-weight: 500;
    line-height: 1.3;
}

/* Un <legend> n'est pas un élément flex : il est placé dans la boîte de bordure du
   fieldset, donc le gap du fieldset ne l'atteint jamais. Son espacement doit passer
   par une marge. */
legend.field__label {
    margin-bottom: var(--sp-3);
    padding: 0;
}

.field__control {
    width: 100%;
    min-height: 48px;
    padding: var(--sp-3) var(--sp-4);
    border: 1px solid var(--c-line);
    border-radius: var(--r-md);
    background: var(--c-surface);
    color: var(--c-text);
    font-family: inherit;
    font-size: var(--fs-base);
    line-height: 1.5;
    transition: border-color var(--t-base), box-shadow var(--t-base);
}

.field__control::placeholder {
    color: var(--c-text-3);
}

/* Volontairement limité à une classe plus une pseudo-classe : :focus et les
   modificateurs d'état ci-dessous ont la même spécificité, et c'est de déclarer le
   survol en premier qui les laisse gagner. Un :not(:disabled) ici passerait devant
   les trois. */
.field__control:hover {
    border-color: var(--c-line-strong);
}

.field__control:focus {
    outline: none;
    border-color: var(--c-accent);
    box-shadow: 0 0 0 3px var(--c-accent-soft);
}

.field__control:focus-visible {
    outline: none;
}

/* Bascule de langue et bascule de thème. Elles vivent ici parce que la vitrine ET le sas de
   l'espace démo les emploient : un composant réutilisé se factorise (§ 5.2). Le disque à moitié
   rempli, lui, y était déjà — il sert en plus au back-office. */

/* Bascule de langue — un contrôle segmenté, les deux options toujours visibles
   pour que l'autre langue soit un lien qu'un robot peut suivre. */
.lang-switch {
    display: inline-flex;
    overflow: hidden;
    border: 1px solid var(--c-line-strong);
    border-radius: var(--r-md);
}

.lang-switch__option {
    padding: var(--sp-2) var(--sp-3);
    color: var(--c-text-3);
    font-family: var(--ff-mono);
    font-size: var(--fs-mono-xs);
    font-weight: 500;
    text-decoration: none;
    transition: background var(--t-fast), color var(--t-fast);
}

.lang-switch__option + .lang-switch__option {
    border-left: 1px solid var(--c-line-strong);
}

.lang-switch__option:hover {
    color: var(--c-text);
}

.lang-switch__option.is-current {
    background: var(--c-bg-alt);
    color: var(--c-text);
}

.theme-toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 42px;
    height: 42px;
    padding: 0;
    border: 1px solid var(--c-line-strong);
    border-radius: var(--r-md);
    background: var(--c-surface);
    color: var(--c-text);
    cursor: pointer;
    transition: border-color var(--t-fast), background var(--t-fast);
}

.theme-toggle:hover {
    border-color: var(--c-text);
}

/* Pastille de la bascule de thème : un disque à moitié rempli, sans image ni
   requête. Elle vit ici parce que la vitrine et le back-office l'emploient tous
   deux (§ 5.2). */
.theme-toggle__icon {
    flex: none;
    width: 18px;
    height: 18px;
    border: 1.5px solid currentColor;
    border-radius: var(--r-pill);
    background: linear-gradient(to right, currentColor 50%, transparent 50%);
}

/* Un contrôle inerte doit se voir comme tel : ni bordure d'appel, ni curseur qui
   promet une saisie. C'est ce que rend l'écran de connexion pendant un blocage. */
.field__control:disabled {
    border-color: var(--c-line);
    background: var(--c-bg-alt);
    color: var(--c-text-3);
    cursor: not-allowed;
}

.field__control:disabled:hover {
    border-color: var(--c-line);
}

.field__hint {
    color: var(--c-text-3);
    font-size: var(--fs-mono-xs);
}

/* Les états d'erreur et de succès sont pilotés par l'enveloppe du champ, pour que
   libellé, contrôle et message restent accordés. */
.field--error .field__control {
    border-color: var(--c-err);
}

.field--error .field__message {
    color: var(--c-err);
}

.field--ok .field__control {
    border-color: var(--c-ok);
}

.field--ok .field__message {
    color: var(--c-ok);
}

/* Remise à zéro de marge, pas de la décoration : c'est un <p>, et la règle globale
   des paragraphes ajouterait une marge basse que la gouttière du champ fournit
   déjà. */
.field__message {
    margin: 0;
    font-family: var(--ff-mono);
    font-size: var(--fs-mono-xs);
}

/* Aucune hauteur n'est réservée à un message qui n'existe pas encore.
   `display: none` plutôt qu'une boîte vide, car un élément flex vide dessinerait
   quand même la gouttière du champ au-dessus de lui. L'emplacement réapparaît dès
   que le script y écrit, ce qui décale la suite — accepté : le décalage répond à un
   blur ou à un clic, c'est donc l'action du visiteur qui déplace la page, jamais le
   chargement initial. */
.field__message:empty {
    display: none;
}

.form__feedback {
    display: flex;
    margin: 0;
    align-items: center;
    gap: var(--sp-2);
    padding: var(--sp-3) var(--sp-4);
    border-radius: var(--r-md);
    background: color-mix(in srgb, var(--c-ok) 10%, transparent);
    color: var(--c-ok);
    font-size: var(--fs-base);
}

.form__feedback::before {
    content: "";
    width: var(--sp-2);
    height: var(--sp-2);
    border-radius: var(--r-pill);
    background: currentColor;
}

.form__feedback--error {
    background: color-mix(in srgb, var(--c-err) 10%, transparent);
    color: var(--c-err);
}

/* -----------------------------------------------------------------------------
   9. Cartes
   Des filets de 1 px font le travail — pas d'ombres empilées, l'alignement porte la
   hiérarchie.
   -------------------------------------------------------------------------- */

.card {
    display: flex;
    flex-direction: column;
    gap: var(--sp-3);
    padding: var(--sp-6);
    border: 1px solid var(--c-line);
    border-radius: var(--r-lg);
    background: var(--c-surface);
    transition: border-color var(--t-base), transform var(--t-base), box-shadow var(--t-base);
}

.card__index {
    color: var(--c-accent);
    font-family: var(--ff-mono);
    font-size: var(--fs-mono-xs);
    font-weight: 500;
    letter-spacing: .08em;
}

.card__title {
    margin: 0;
    font-size: var(--fs-xl);
}

.card__text {
    margin: 0;
    color: var(--c-text-2);
}

.card--service:hover {
    border-color: var(--c-line-strong);
}

/* Au survol, la bordure passe à l'accent et la carte monte de 2 px. */
.card--work {
    flex-direction: row;
    align-items: center;
    gap: var(--sp-4);
    text-decoration: none;
    color: inherit;
}

.card--work:hover {
    border-color: var(--c-accent);
    transform: translateY(-2px);
    box-shadow: var(--sh-2);
    color: inherit;
}

.card--work .card__arrow {
    margin-left: auto;
    color: var(--c-accent);
}

.card__tags {
    display: flex;
    flex-wrap: wrap;
    gap: var(--sp-2);
}

/* --- Closing call to action ------------------------------------------------
   La carte qui termine une page publique. Deux colonnes de poids égal : les mots
   d'un côté, les actions de l'autre. Chacune porte trois niveaux — pour les mots un
   sur-titre, un titre et un chapô ; pour les actions les boutons et la note de
   réassurance. C'est cette symétrie qui tient le bloc : retirez la note et la
   colonne d'action s'effondre sur une seule rangée face à un paragraphe, ce qui se
   lit comme un bloc inachevé (A-56).
   -------------------------------------------------------------------------- */

/* Empilée par défaut, en deux colonnes dès qu'il y a la place. La colonne d'action prend
   **exactement ce que ses boutons demandent** (`auto`), le texte prend le reste : le partage en
   deux moitiés égales était arbitraire, et c'est lui qui mettait les deux boutons à quelques
   pixels de passer à la ligne (A-154).

   Le texte ne s'étale pas pour autant — `.cta-card__title` et `.cta-card__lead` sont bornés en
   `ch` : la place gagnée devient de la gouttière, pas des lignes trop longues. */
.cta-card {
    display: grid;
    align-items: center;
    gap: clamp(24px, 4vw, 56px);
    grid-template-columns: 1fr;
    padding: clamp(28px, 4vw, 48px);
    border: 1px solid var(--c-line);
    border-radius: var(--r-lg);
    background: var(--c-surface);
}

/* Première requête de largeur de ce fichier : `auto-fit` savait s'empiler seul, `auto` non — une
   colonne dimensionnée sur ses boutons déborderait d'un téléphone. Le seuil est celui de
   `public.css`, et la logique reste mobile d'abord. */
@media (min-width: 900px) {
    .cta-card {
        grid-template-columns: 1fr auto;
    }
}

/* 14 px, hors de l'échelle base 4 (A-56). */
.cta-card__text {
    display: flex;
    flex-direction: column;
    gap: 14px;
}

.cta-card__eyebrow {
    margin: 0;
    color: var(--c-text-3);
    font-family: var(--ff-mono);
    font-size: 11.5px;
    font-weight: 500;
    letter-spacing: .07em;
    line-height: 1;
    text-transform: uppercase;
}

.cta-card__title {
    max-width: 24ch;
    margin: 0;
    font-size: clamp(1.6rem, 2.8vw, 2.3rem);
    letter-spacing: -.026em;
    line-height: 1.1;
}

.cta-card__lead {
    max-width: 44ch;
    margin: 0;
    color: var(--c-text-2);
    font-size: 15.5px;
    line-height: 1.65;
}

.cta-card__actions {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: var(--sp-3);
}

.cta-card__buttons {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--sp-3);
    margin: 0;
}

.cta-card__note {
    margin: 2px 0 0;
    color: var(--c-text-3);
    font-family: var(--ff-mono);
    font-size: 12.5px;
    line-height: 1.5;
}

/* -----------------------------------------------------------------------------
   10. État vide — jamais une impasse : il offre toujours une sortie.
   -------------------------------------------------------------------------- */

.empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--sp-4);
    padding: var(--sp-12) var(--sp-6);
    border: 1px dashed var(--c-line-strong);
    border-radius: var(--r-lg);
    text-align: center;
}

.empty__title {
    margin: 0;
    color: var(--c-text-3);
    font-family: var(--ff-mono);
    font-size: var(--fs-mono-xs);
    font-weight: 500;
    letter-spacing: .12em;
    text-transform: uppercase;
}

.empty__text {
    max-width: 46ch;
    margin: 0;
    color: var(--c-text-2);
}

/* -----------------------------------------------------------------------------
   11. Apparition au défilement
   Le contenu est dans le HTML ; seules l'opacité et la position sont animées, donc rien
   depends on JavaScript to be read or indexed.
   -------------------------------------------------------------------------- */

/* Masqué seulement si le script est disponible — voir reveal.js. */
html.js .reveal {
    opacity: 0;
    transform: translateY(14px);
    transition: opacity var(--t-reveal), transform var(--t-reveal);
}

html.js .reveal.is-visible {
    opacity: 1;
    transform: none;
}

html.js .reveal--d1 { transition-delay: 70ms; }
html.js .reveal--d2 { transition-delay: 140ms; }
html.js .reveal--d3 { transition-delay: 210ms; }
html.js .reveal--d4 { transition-delay: 280ms; }

/* Le mouvement est un confort, jamais une condition d'accès au contenu. */
@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        animation-duration: .01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: .01ms !important;
        scroll-behavior: auto !important;
    }

    html.js .reveal {
        opacity: 1;
        transform: none;
    }
}

/* -----------------------------------------------------------------------------
   12. Utilitaires
   -------------------------------------------------------------------------- */

.mono {
    font-family: var(--ff-mono);
}

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

/* Visible des seuls lecteurs d'écran — pour les libellés qui ne doivent pas s'afficher. */
.visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

.skip-link {
    position: absolute;
    top: var(--sp-2);
    left: var(--sp-2);
    z-index: 100;
    padding: var(--sp-2) var(--sp-4);
    border-radius: var(--r-md);
    background: var(--c-surface);
    color: var(--c-text);
    transform: translateY(-200%);
}

.skip-link:focus {
    transform: none;
}
