/* ==========================================================================
   EasyLab - MISE EN FORME DES ÉLÉMENTS
   --------------------------------------------------------------------------
   Aucune valeur littérale ici : tout vient des jetons de theme.css.
   Ordre de chargement SliDesk : slidesk.css → templates/**.css → themes/**.css
   → CSS des plugins. Les règles ci-dessous sont donc préfixées par .sd-app ou
   .sd-slide là où elles doivent passer devant SliDesk ou devant les plugins.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Fontes auto-hébergées (sous-ensemble latin : le deck n'a besoin de rien
   d'autre - accents français, guillemets, tirets cadratins compris)
   -------------------------------------------------------------------------- */
@font-face {
    font-family: "Saira";
    font-style: normal;
    font-weight: 400 700;
    font-stretch: 75% 125%;
    font-display: block;
    src: url("../../assets/fonts/saira-variable.woff2") format("woff2");
}

@font-face {
    font-family: "Saira";
    font-style: italic;
    font-weight: 400 700;
    font-stretch: 75% 125%;
    font-display: block;
    src: url("../../assets/fonts/saira-variable-italic.woff2") format("woff2");
}

@font-face {
    font-family: "JetBrains Mono";
    font-style: normal;
    font-weight: 400 700;
    font-display: block;
    src: url("../../assets/fonts/jetbrains-mono-variable.woff2") format("woff2");
}

/* --------------------------------------------------------------------------
   2. Base typographique
   Une famille, deux voix : les titres sur l'axe wdth poussé au bout (125),
   le texte à la largeur normale.
   -------------------------------------------------------------------------- */
.sd-app {
    font-family: var(--sd-font);
    font-weight: var(--sd-weight-text);
    font-variation-settings: "wght" var(--sd-weight-text), "wdth" var(--sd-width-text);
    -webkit-font-smoothing: antialiased;
    text-rendering: optimizeLegibility;
}

.sd-slide {
    background-color: var(--sd-background-color);
    color: var(--sd-text-color);
    font-size: var(--sd-text-size);
    line-height: var(--sd-text-line-height);
}

.sd-slide h1,
.sd-slide h2,
.sd-slide h3 {
    margin: 0;
    text-align: left;
    text-wrap: balance;
    font-variation-settings:
        "wght" var(--sd-weight-title),
        "wdth" var(--sd-width-title);
    letter-spacing: -0.02em;
}

/* Paragraphes alignés à gauche comme les listes : plus d'alternance
   centré / aligné d'une slide à l'autre. */
.sd-slide p {
    margin: 0 0 0.55em;
    text-align: left;
}

.sd-slide p:last-child {
    margin-bottom: 0;
}

/* Dans le corps de texte, le gras se distingue par la graisse et l'encre,
   pas par la couleur. La couleur est réservée aux marqueurs, aux blocs et
   aux liens - sinon le deck part en sapin de Noël. */
.sd-slide strong {
    color: var(--sd-heading-color);
    font-weight: var(--sd-weight-strong);
    font-variation-settings: "wght" var(--sd-weight-strong), "wdth" var(--sd-width-text);
}

.sd-slide em {
    font-style: italic;
}

.sd-slide a {
    color: var(--sd-primary-color);
    text-underline-offset: 0.18em;
    text-decoration-thickness: var(--sd-hairline);
}

/* Anneau de focus visible sur les deux fonds : celui du navigateur est
   sombre, donc invisible sur le noir. */
.sd-slide a:focus-visible {
    outline: 3px solid var(--sd-primary-color);
    outline-offset: 3px;
}

.sd-slide code {
    font-family: var(--sd-font-mono);
    font-size: 0.86em;
    padding: 0.08em 0.32em;
    background: rgba(0, 108, 232, 0.12);
    color: var(--sd-heading-color);
}

/* Bloc de code : barre d'accent épaisse à gauche. Le code qu'il contient
   perd son propre fond et ses marges. */
.sd-slide pre {
    margin: 0;
    width: fit-content;
    max-width: var(--sd-measure);
    padding: 0.85em 1.15em;
    border-left: 6px solid var(--sd-primary-color);
    background: rgba(0, 108, 232, 0.08);
    font-size: var(--sd-code-size);
    line-height: 1.55;
    white-space: pre-wrap;
    text-align: left;
}

.sd-slide pre code {
    padding: 0;
    background: none;
    font-size: inherit;
    color: var(--sd-text-color);
}

/* --------------------------------------------------------------------------
   3. Listes - SliDesk n'en style aucune, tout est à poser ici
   -------------------------------------------------------------------------- */
.sd-slide ul,
.sd-slide ol {
    margin: 0;
    padding: 0;
    list-style: none;
}

.sd-slide li {
    position: relative;
    padding-left: 1.5em;
    margin-bottom: var(--sd-list-gap);
}

.sd-slide li:last-child {
    margin-bottom: 0;
}

/* Puce : un carré plein. C'est la cellule du croquis - un workspace, une
   personne. Le même petit carré revient partout dans le deck. */
.sd-slide ul > li::before {
    content: "";
    position: absolute;
    left: 0;
    top: 0.52em;
    width: 0.44em;
    height: 0.44em;
    background: var(--sd-primary-color);
}

/* Second niveau : plus petit, atténué, marqué par un filet vertical */
.sd-slide li ul,
.sd-slide li ol {
    margin-top: 0.35em;
}

.sd-slide li li {
    font-size: 0.86em;
    color: var(--sd-muted-color);
    padding-left: 1.15em;
    margin-bottom: 0.3em;
}

.sd-slide li li::before {
    content: "";
    position: absolute;
    left: 0;
    top: 0.3em;
    bottom: 0.3em;
    width: var(--sd-hairline);
    height: auto;
    background: var(--sd-rule-color);
}

/* Liste numérotée : réservée aux vraies séquences (l'ordre du talk, les
   étapes du wizard). Jamais pour une liste de fonctionnalités. */
.sd-slide ol > li {
    padding-left: 2.9em;
    margin-bottom: 0.7em;
}

.sd-slide ol > li::before {
    content: counter(list-item, decimal-leading-zero);
    position: absolute;
    left: 0;
    top: 0;
    font-family: var(--sd-font-mono);
    font-variant-numeric: tabular-nums;
    font-weight: 700;
    font-size: 1em;
    color: var(--sd-primary-color);
}

/* --------------------------------------------------------------------------
   3 bis. Glyphes de plan - le seul endroit où la puce change de forme.
   + créer   ~ modifier   - détruire : c'est la sortie de `pulumi preview`,
   et ça encode une opération, pas un ordre. À n'utiliser QUE sur les slides
   dont le contenu est vraiment un cycle de vie (dry run, teardown).
   Ailleurs, le carré plein ci-dessus.
   -------------------------------------------------------------------------- */
.sd-slide ul.plan > li {
    padding-left: 2.1em;
    margin-bottom: 0.7em;
}

.sd-slide ul.plan > li::before {
    content: attr(data-op);
    top: 0;
    width: 1.3em;
    height: auto;
    background: none;
    font-family: var(--sd-font-mono);
    font-weight: 700;
    font-size: 1.25em;
    line-height: inherit;
    color: var(--sd-op-change);
}

.sd-slide ul.plan > li[data-op="+"]::before {
    color: var(--sd-op-create);
}

.sd-slide ul.plan > li[data-op="-"]::before {
    color: var(--sd-op-destroy);
}

/* --------------------------------------------------------------------------
   4. Gabarit « slide » - deux colonnes
   Le titre tient dans la colonne de gauche et y reste ; le corps coule à
   droite sur toute la hauteur.
   -------------------------------------------------------------------------- */
.sd-slide .s {
    position: absolute;
    inset: 0;
    display: grid;
    grid-template-columns: var(--sd-col-title) minmax(0, 1fr);
    grid-template-rows: minmax(0, 1fr) auto;
    column-gap: var(--sd-col-gap);
    padding: var(--sd-pad-y) var(--sd-pad-x) calc(var(--sd-chrome-bottom) + 5vh);
    text-align: left;
}

.sd-slide .s > .s-head {
    grid-area: 1 / 1;
    align-self: start;
}

.sd-slide .s > .s-body {
    grid-area: 1 / 2;
}

.sd-slide .s > .s-note {
    grid-area: 2 / 2;
}

.sd-slide .s-head h2 {
    font-size: var(--sd-heading2-size);
    line-height: var(--sd-heading2-line-height);
    color: var(--sd-heading-color);
    text-wrap: pretty;
}

/* Titre à deux niveaux. « ## **Teardown** <br/> précision » : le mot-clé
   prend la voix large, la précision reste en largeur normale, sous lui.
   Indispensable en français, qui court ~15 % plus long qu'en anglais et
   déborderait sinon la colonne étroite en quatre lignes molles. */
.sd-slide .s-head h2:has(strong) {
    font-size: calc(var(--sd-heading2-size) * 0.64);
    line-height: 1.22;
    letter-spacing: 0;
    color: var(--sd-text-color);
    font-variation-settings: "wght" 450, "wdth" var(--sd-width-text);
}

.sd-slide .s-head h2 strong {
    display: block;
    margin-bottom: 0.2em;
    font-size: 1.78em;
    line-height: 0.98;
    letter-spacing: -0.025em;
    color: var(--sd-heading-color);
    font-variation-settings: "wght" var(--sd-weight-title), "wdth" var(--sd-width-title);
}

.sd-slide .s-head h2 br {
    display: none;
}

.sd-slide .s-body {
    align-self: stretch;
    width: 100%;
    height: 100%;
    display: flex;
    flex-direction: column;
    gap: 1em;
    /* aligne optiquement la première ligne du corps sur celle du titre,
       qui est plus gros donc pose sa ligne de base un peu plus bas */
    padding-top: 0.35vw;
}

.sd-slide .s-lead,
.sd-slide .s-main,
.sd-slide .s-punch,
.sd-slide .s-note {
    max-width: var(--sd-measure);
}

.sd-slide .s-lead {
    font-size: var(--sd-lead-size);
    line-height: 1.32;
    color: var(--sd-heading-color);
    text-wrap: pretty;
}

.sd-slide .s-main > :not(:first-child) {
    margin-top: 0.75em;
}

/* La punchline : un bloc plein, pas un filet. C'est le coup de poing de la
   slide - il doit se voir du fond de la salle et couper net avec le texte
   qui le précède. Il suit le contenu à un intervalle fixe, il ne tombe pas
   en bas de la colonne : la conclusion appartient au raisonnement qui la
   précède. */
.sd-slide .s-punch {
    font-size: var(--sd-punch-size);
    line-height: 1.22;
    padding: 0.6em 0.8em;
    background: var(--sd-primary-color);
    color: var(--sd-punch-ink);
    font-variation-settings: "wght" var(--sd-weight-title), "wdth" 112;
    margin-top: 0.5em;
    text-wrap: pretty;
}

.sd-slide .s-punch strong {
    color: var(--sd-punch-hl);
    font-weight: inherit;
    font-variation-settings: inherit;
}

/* Renvoi / source, en bas du bloc de contenu */
.sd-slide .s-note {
    align-self: end;
    font-size: var(--sd-note-size);
    line-height: 1.4;
    color: var(--sd-muted-color);
    border-top: var(--sd-hairline) solid var(--sd-rule-color);
    padding-top: 0.7em;
}

/* Une colonne : la comparaison, le bloc de code, et toute slide marquée
   « wide » dans ses classes (## Titre .[sbs wide #slide]). */
.sd-slide .s-wide,
.sd-slide.wide .s {
    --sd-measure: 68vw;
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: auto minmax(0, 1fr) auto;
}

.sd-slide .s-wide > .s-head,
.sd-slide.wide .s > .s-head {
    grid-area: 1 / 1;
}

.sd-slide .s-wide > .s-body,
.sd-slide.wide .s > .s-body {
    grid-area: 2 / 1;
    padding-top: 1.5vw;
}

.sd-slide .s-wide > .s-note,
.sd-slide.wide .s > .s-note {
    grid-area: 3 / 1;
}

.sd-slide .s-wide .s-head h2,
.sd-slide.wide .s-head h2 {
    font-size: calc(var(--sd-heading2-size) * 1.12);
    max-width: 24em;
}

/* Trois échappatoires d'échelle, à poser dans les classes du titre
   (## Titre .[sbs dense #slide]). Elles ne valent que pour la slide marquée.
   « dense » resserre une slide trop pleine ; « large » ouvre une slide courte ;
   « mid » centre verticalement le bloc titre + corps au lieu de l'accrocher
   en haut, pour les slides qui laisseraient sinon les deux tiers bas vides.
   L'alignement haut reste la règle : c'est lui qui fait partager une ligne de
   base au titre et à la première ligne du corps. */
.sd-slide.dense {
    --sd-text-size: 1.45vw;
    --sd-lead-size: 1.65vw;
    --sd-punch-size: 1.88vw;
    --sd-text-line-height: 1.4;
    --sd-list-gap: 0.45em;
    /* la mesure suit la taille : sans ça, « dense » rallonge la ligne à
       ~75 signes au lieu de la resserrer */
    --sd-measure: 44vw;
}

.sd-slide.large {
    --sd-text-size: 1.95vw;
}

.sd-slide.mid .s > .s-head {
    align-self: center;
}

.sd-slide.mid .s > .s-body {
    align-self: center;
    height: auto;
}

/* « panne » bascule toute la slide sur le pôle orange-rouge du logo : puces,
   intitulés, bloc de punchline, pastille de numéro. Une classe, et la slide
   dit « ça brûle » avant qu'on ait lu un mot. Elle passe par les mêmes deux
   encres qu'un acte, donc elle reste lisible sur les deux fonds. */
.sd-slide.panne {
    --acte-light: var(--sd-signal-color);
    --acte-dark: var(--lab-amber);
    --acte-hl: #ffffff;
}

/* Blocs par rôle (<div class="step role"> + ### Rôle) : l'intitulé passe en
   marge, sur la ligne de base du premier paragraphe. Les rôles se lisent d'un
   coup d'œil en colonne, et le texte garde sa mesure sans ajouter de lignes. */
.sd-slide .role {
    display: grid;
    grid-template-columns: var(--sd-role-width) minmax(0, 1fr);
    align-items: baseline;
}

.sd-slide .role > * {
    grid-column: 2;
}

.sd-slide .role > h3 {
    grid-column: 1;
    font-size: var(--sd-heading3-size);
    line-height: var(--sd-heading3-line-height);
    color: var(--sd-primary-color);
}

/* Plus d'air entre deux rôles qu'entre deux paragraphes d'un même rôle */
.sd-slide .s-main > .role + .role {
    margin-top: 1.1em;
}

/* --------------------------------------------------------------------------
   5. Slides noires - couverture, intercalaires, démo, fin
   Elles réutilisent tout le CSS du papier : seules les encres changent.
   Le noir est celui du logo, au pixel près : voir theme.css.
   -------------------------------------------------------------------------- */
.sd-slide[data-num="0"],
.sd-slide.chapter {
    --sd-background-color: var(--sd-dark-bg);
    --sd-heading-color: var(--sd-dark-heading-color);
    --sd-text-color: var(--sd-dark-text-color);
    --sd-muted-color: var(--sd-dark-muted-color);
    --sd-rule-color: var(--sd-dark-rule-color);
    /* sur le noir, l'acte sort sa version vive - jamais la foncée */
    --sd-primary-color: var(--acte-dark, var(--easy-cyan));
    --sd-punch-ink: var(--el-black);

    /* Le néon du logo, repris en lueur derrière le titre. C'est l'unique
       ornement du deck, et il ne sort que sur le noir. */
    background-image: radial-gradient(
        var(--sd-bloom-size) at 26% 52%,
        rgb(from var(--sd-primary-color) r g b / var(--sd-bloom-strength)),
        transparent 72%
    );
}

.sd-slide[data-num="0"] code,
.sd-slide.chapter code {
    background: rgba(255, 255, 255, 0.14);
}

.sd-slide .c {
    position: absolute;
    inset: 0;
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: center;
    gap: 5vw;
    padding: var(--sd-pad-y) var(--sd-pad-x);
}

.sd-slide .c-text {
    color: var(--sd-text-color);
}

/* Le numéro d'acte, en très gros : il dit où on en est dans le plan, et il
   porte la couleur de l'acte. C'est lui qui donne au deck ses trois temps. */
.sd-slide .c-num {
    margin: 0 0 0.14em;
    font-family: var(--sd-font-mono);
    font-size: var(--sd-chapter-num-size);
    font-weight: 700;
    line-height: 0.88;
    font-variant-numeric: tabular-nums;
    letter-spacing: -0.04em;
    color: var(--sd-primary-color);
}

.sd-slide .c-text h2 {
    font-size: var(--sd-chapter-size);
    line-height: 0.98;
    max-width: 11em;
}

.sd-slide .c-lead {
    margin-top: 1.1em;
    max-width: 26em;
}

/* Slide de fin : elle reste affichée pendant tout le temps des questions.
   Elle doit donner le nom, les liens et la doc sans se replier. */
.sd-slide.outro .c-lead {
    max-width: 34em;
}

.sd-slide .c-art .sd-img {
    display: block;
    margin: 0;
    width: min(30vw, 52vh);
}

.sd-slide .c-art .sd-img img {
    display: block;
    width: 100%;
    height: auto;
}

/* Le QR de la slide de fin : une étiquette claire posée sur le noir.
   Modules sombres sur fond clair - c'est le sens qui scanne le plus
   sûrement depuis le fond d'une salle. */
.sd-slide .c-art .qr {
    width: min(15vw, 28vh);
}

/* --------------------------------------------------------------------------
   6. Couverture (première slide : un h1, pas de gabarit possible)
   Le logo est le héros. Il arrive sur SON fond, le même noir au pixel près,
   donc ses lueurs se fondent dans la slide sans carré visible autour.
   Deux lueurs l'encadrent, une par pôle du logo : cyan à gauche derrière le
   titre, orange à droite derrière le logo.
   -------------------------------------------------------------------------- */
.sd-slide[data-num="0"] {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-rows: minmax(0, 1fr) auto;
    align-items: center;
    justify-content: initial;
    column-gap: 3vw;
    padding: var(--sd-pad-y) var(--sd-pad-x);
    /* Pas de lueur ici, et c'est délibéré : le PNG du logo n'a pas de canal
       alpha. Le moindre dégradé sous lui éclaircit le fond autour sans
       éclaircir le logo, et son carré noir se découpe sur la slide. Le logo
       porte déjà son propre néon - il éclaire la couverture tout seul. */
    background-image: none;
}

.sd-slide[data-num="0"] h1 {
    grid-area: 1 / 1;
    align-self: center;
    font-size: calc(var(--sd-heading1-size) * 0.5);
    line-height: 1.28;
    font-variation-settings: "wght" 400, "wdth" var(--sd-width-text);
    color: var(--sd-dark-text-color);
    max-width: 17em;
    letter-spacing: 0;
}

.sd-slide[data-num="0"] h1 br {
    display: none;
}

.sd-slide[data-num="0"] h1 strong {
    display: block;
    margin-bottom: 0.18em;
    font-size: 2.75em;
    line-height: var(--sd-heading1-line-height);
    color: var(--sd-dark-heading-color);
    letter-spacing: -0.03em;
    font-variation-settings: "wght" var(--sd-weight-title), "wdth" var(--sd-width-title);
}

.sd-slide[data-num="0"] .brand {
    grid-area: 1 / 2;
    align-self: center;
    margin: 0;
    width: min(38vw, 68vh);
}

.sd-slide[data-num="0"] .brand img {
    display: block;
    width: 100%;
    height: auto;
}

/* La pastille d'événement : un bloc ambre plein, en bas à gauche. Elle
   remplace à elle seule le pavé de métadonnées - et c'est le seul endroit
   du deck où la date est écrite. */
.sd-slide[data-num="0"] .event {
    grid-area: 2 / 1;
    justify-self: start;
    align-self: end;
    padding: 0.55em 0.9em;
    background: var(--lab-amber);
    color: var(--el-black);
    font-family: var(--sd-font-mono);
    font-size: var(--sd-label-size);
    font-weight: 700;
    line-height: 1;
}

/* Le logo de l'événement, dans l'angle opposé à celui d'EasyLab : la dernière
   cellule libre de la grille. Les deux marques se regardent en diagonale, et
   la couverture dit en un coup d'œil de quel produit on parle et où.

   Il arrive tel quel depuis bdxio.fr - un bloc périwinkle et du blanc, qui
   portent seuls sur le noir. Pas de filtre, pas de recoloration : c'est la
   marque de quelqu'un d'autre. */
.sd-slide[data-num="0"] .event-logo {
    grid-area: 2 / 2;
    justify-self: end;
    align-self: end;
    margin: 0;
    width: var(--sd-event-logo-size);
}

.sd-slide[data-num="0"] .event-logo img {
    display: block;
    width: 100%;
    height: auto;
}

/* --------------------------------------------------------------------------
   7. Slide orateur
   -------------------------------------------------------------------------- */
.sd-slide .sp {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 4vw;
    padding: 0 var(--sd-pad-x) calc(var(--sd-chrome-bottom) + 4vh);
}

/* La photo est cadrée franc : un bord épais dans la couleur de l'accent,
   pas d'arrondi, pas d'ombre.

   La photo est peinte en background du cadre, pas posée en <img>. SliDesk
   interpose une <figure> entre le cadre et l'image, et ce niveau de plus ne
   se dimensionnait jamais juste à l'export : ni height:100%, ni une hauteur
   en vh, ni display:contents, ni un recadrage de la source en 4/5 - il
   restait toujours un liseré de fond sur un bord. Un background-size:cover
   n'a pas de boîte intermédiaire, donc pas de joint possible.

   La <figure> reste dans le DOM, masquée par le motif « visually hidden » :
   l'image et son texte alternatif restent lisibles par un lecteur d'écran.
   Si vous changez de photo, changez AUSSI l'url ci-dessous.
   -------------------------------------------------------------------------- */
.sd-slide .sp-photo {
    flex: none;
    width: 24vh;
    aspect-ratio: 4 / 5;
    border: 6px solid var(--sd-primary-color);
    background-image: url("../../assets/mat.jpg");
    background-size: cover;
    background-position: center;
    background-repeat: no-repeat;
}

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

.sd-slide .sp-id h2 {
    font-size: calc(var(--sd-heading2-size) * 1.25);
    margin-bottom: 0.3em;
}

.sd-slide .sp-id p,
.sd-slide .sp-id p strong {
    font-size: var(--sd-lead-size);
    color: var(--sd-muted-color);
}

/* La répartition du temps, en mono : elle tient la place de la slide d'agenda,
   et elle doit se lire comme une donnée, pas comme une phrase de plus. */
.sd-slide .sp-id .roadmap,
.sd-slide .sp-id .roadmap strong {
    margin-top: 0.9em;
    font-family: var(--sd-font-mono);
    font-size: var(--sd-note-size);
    color: var(--sd-primary-color);
}

.sd-slide .sp-id .company-logo {
    display: block;
    margin: 1.2em 0 0;
}

.sd-slide .sp-id .company-logo img {
    width: 11vw;
    height: auto;
}

/* --------------------------------------------------------------------------
   8. Agenda - l'ordre du talk est une vraie séquence, donc numérotée
   -------------------------------------------------------------------------- */
.sd-slide .a-list {
    font-size: 1.15em;
}

.sd-slide .a-list ol > li {
    margin-bottom: 0.85em;
}

/* --------------------------------------------------------------------------
   9. Comparaison en deux colonnes
   La colonne de droite est toujours « ce qui ne marche pas » : elle part sur
   le pôle orange-rouge, l'autre reste neutre.
   -------------------------------------------------------------------------- */
.sd-slide .cmp {
    display: grid;
    grid-template-columns: 1fr 1fr;
    align-items: start;
    max-width: var(--sd-measure);
}

.sd-slide .cmp-a {
    padding-right: 3vw;
}

.sd-slide .cmp-b {
    padding-left: 3vw;
    border-left: var(--sd-hairline) solid var(--sd-rule-color);
}

.sd-slide .cmp-col h3 {
    font-size: var(--sd-heading3-size);
    line-height: var(--sd-heading3-line-height);
    margin-bottom: 0.7em;
}

.sd-slide .cmp-a h3 {
    color: var(--sd-muted-color);
}

.sd-slide .cmp-a li::before {
    background: var(--sd-muted-color);
}

.sd-slide .cmp-b h3 {
    color: var(--sd-signal-color);
}

.sd-slide .cmp-b li::before {
    background: var(--sd-signal-color);
}

.sd-slide .cmp li {
    font-size: 0.94em;
}

/* --------------------------------------------------------------------------
   10. La slide héros : l'URL que reçoit la personne
   Le moment magique du produit tient en une ligne de mono. Rien d'autre sur
   la slide ne doit lutter avec elle - et le sous-domaine, la seule partie
   qui change d'une personne à l'autre, est en cyan.
   -------------------------------------------------------------------------- */
.sd-slide .url {
    font-family: var(--sd-font-mono);
    font-size: var(--sd-url-size);
    font-weight: 700;
    line-height: 1.1;
    letter-spacing: -0.03em;
    color: var(--sd-heading-color);
    word-break: break-all;
}

.sd-slide .url .host {
    color: var(--sd-primary-color);
}

.sd-slide .url-meta {
    margin: 0.55em 0 0.5em;
    font-family: var(--sd-font-mono);
    font-size: var(--sd-note-size);
    color: var(--sd-muted-color);
}

/* --------------------------------------------------------------------------
   11. La pile - les logos des outils portent le contenu

   Cinq couches, deux logos chacune, et le nom de la couche écrit par CSS
   depuis data-layer : le markdown ne garde qu'une ligne par couche, et le
   libellé ne peut pas se désynchroniser du texte.

   Les logos viennent de simple-icons (assets/logos/), chacun figé à la
   couleur de sa marque dans le fichier SVG lui-même - pas de currentColor :
   SliDesk les pose en <img>, qui n'hérite d'aucune encre. Pour en ajouter un,
   reprendre la recette dans le README de assets/logos.

   La grille est posée en trois colonnes de largeur fixe pour que les logos
   s'alignent verticalement d'une couche à l'autre : c'est cet alignement qui
   fait lire la slide en cinq secondes.
   -------------------------------------------------------------------------- */
.sd-slide .stack {
    display: grid;
    grid-template-columns: var(--sd-stack-label) var(--sd-stack-logos) 1fr;
    align-items: center;
    column-gap: var(--sd-stack-gap);
    row-gap: var(--sd-stack-row);
    margin: 0;
    padding: 0;
    max-width: var(--sd-measure);
    list-style: none;
}

.sd-slide .stack > li {
    display: grid;
    grid-column: 1 / -1;
    grid-template-columns: subgrid;
    align-items: center;
    margin: 0;
    padding: 0;
}

/* Le carré de puce des listes du deck n'a rien à faire ici */
.sd-slide .stack > li::before {
    content: var(--stack-layer, attr(data-layer));
    position: static;
    width: auto;
    height: auto;
    margin: 0;
    background: none;
    font-family: var(--sd-font-mono);
    font-size: var(--sd-stack-label-size);
    font-weight: 700;
    line-height: 1.1;
    letter-spacing: 0.02em;
    text-transform: uppercase;
    color: var(--sd-primary-color);
}

.sd-slide .stack-logos {
    display: flex;
    align-items: center;
    gap: var(--sd-stack-logo-gap);
}

.sd-slide .stack-logos .logo {
    display: block;
    flex: none;
    margin: 0;
    width: var(--sd-logo-size);
}

.sd-slide .stack-logos .logo img {
    display: block;
    width: 100%;
    height: auto;
}

.sd-slide .stack-text {
    font-size: var(--sd-stack-text-size);
    line-height: 1.3;
    color: var(--sd-text-color);
}

/* --------------------------------------------------------------------------
   11 bis. Les trois topologies - trois croquis côte à côte

   Même principe que la pile juste au-dessus : l'intitulé est écrit par CSS
   depuis data-topo, et le markdown ne porte que le dessin et sa légende. Un
   seul endroit à corriger si une topologie change de nom.

   Les croquis sont dans assets/topo-*.svg. Ils sont SANS TEXTE et aux encres
   FONCÉES du logo, parce qu'un <img> ne charge pas la fonte du deck et
   n'hérite d'aucune de ses couleurs - la note complète est en tête de
   topo-poste.svg. Ne pas les reprendre sur une slide noire : le bleu profond
   s'y noie.
   -------------------------------------------------------------------------- */
/* Les colonnes sont posées à leur largeur de croquis, puis RÉPARTIES sur
   toute la mesure : sans ça, les trois dessins s'arrêtent bien avant le bord
   droit du chapeau et de la punchline, et le tiers droit de la slide reste
   vide. C'est la gouttière qui absorbe la différence, pas les croquis. */
.sd-slide .topo {
    display: grid;
    grid-template-columns: repeat(3, var(--sd-topo-art));
    justify-content: space-between;
    column-gap: var(--sd-topo-gap);
    margin: 0;
    padding: 0;
    width: var(--sd-measure);
    max-width: var(--sd-measure);
    list-style: none;
}

.sd-slide .topo > li {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: var(--sd-topo-row);
    margin: 0;
    padding: 0;
}

/* Le carré de puce des listes du deck n'a rien à faire ici non plus */
.sd-slide .topo > li::before {
    content: attr(data-topo);
    position: static;
    width: auto;
    height: auto;
    margin: 0;
    background: none;
    font-family: var(--sd-font-mono);
    font-size: var(--sd-topo-label-size);
    font-weight: 700;
    line-height: 1.1;
    letter-spacing: 0.02em;
    text-transform: uppercase;
    color: var(--sd-primary-color);
}

/* Largeur explicite, jamais un pourcentage : la figure de SliDesk est en
   inline-block et ne résout pas une largeur relative ici - elle retomberait
   à zéro, sans rien signaler. Même recette que .stack-logos .logo. */
.sd-slide .topo .topo-art {
    display: block;
    flex: none;
    margin: 0;
    width: var(--sd-topo-art);
}

.sd-slide .topo .topo-art img {
    display: block;
    width: 100%;
    height: auto;
}

.sd-slide .topo-text {
    display: block;
    font-size: var(--sd-topo-text-size);
    line-height: 1.3;
    color: var(--sd-text-color);
}

/* Un logo seul, posé au-dessus d'un chapeau : la marque de la slide Pulumi */
.sd-slide .logo-mark {
    display: block;
    margin: 0 0 0.5em;
    width: var(--sd-logo-mark-size);
}

.sd-slide .logo-mark img {
    display: block;
    width: 100%;
    height: auto;
}

/* --------------------------------------------------------------------------
   12. Bas de page - le nom du talk à gauche, et le numéro de feuille dans
   une pastille pleine calée dans l'angle. La pastille prend la couleur de la
   slide : elle vire au rouge sur les slides « panne ».
   Les slides noires sont des respirations pleine page : aucun bandeau.
   -------------------------------------------------------------------------- */
.sd-slide:not([data-num="0"])::before {
    content: var(--sd-chrome-left);
    position: absolute;
    left: var(--sd-pad-x);
    bottom: var(--sd-chrome-bottom);
    z-index: 2;
    font-family: var(--sd-font-mono);
    font-size: var(--sd-chrome-size);
    line-height: 1;
    color: var(--sd-muted-color);
}

.sd-slide:not([data-num="0"])::after {
    content: attr(data-num);
    position: absolute;
    right: 0;
    bottom: 0;
    z-index: 2;
    min-width: 3.4vw;
    padding: 1.1vh 1vw;
    background: var(--sd-primary-color);
    color: #ffffff;
    font-family: var(--sd-font-mono);
    font-size: var(--sd-chrome-size);
    font-weight: 700;
    line-height: 1;
    text-align: center;
    font-variant-numeric: tabular-nums;
}

.sd-slide.chapter::before,
.sd-slide.chapter::after {
    content: none;
}

/* --------------------------------------------------------------------------
   13. Apparition pas à pas
   Seule animation du deck, et elle répond à une action : rien ne bouge à
   l'arrivée sur une slide.
   Le CSS des plugins est chargé après celui-ci : il faut une spécificité
   supérieure pour ajouter le déplacement à leur fondu.
   -------------------------------------------------------------------------- */
.sd-app .sbs .step {
    opacity: 0;
    transform: translateY(0.25em);
    transition:
        opacity var(--animationSBSSteps),
        transform var(--animationSBSSteps);
}

.sd-app .sbs .step.step-shown {
    opacity: 1;
    transform: none;
}

.sd-app .steps li {
    opacity: 0;
    transition: opacity var(--animationSteps);
}

.sd-app .steps li.step-shown {
    opacity: 1;
}

@media (prefers-reduced-motion: reduce) {
    .sd-app .sbs .step {
        transform: none;
    }
}

@media print {
    .sd-app .sbs .step,
    .sd-app .steps li {
        opacity: 1;
        transform: none;
    }
}

/* Reste de la slide pour les gabarits sans zone de contenu (chapitre, agenda,
   comparaison) : n'y arrivent normalement que les notes du conférencier, déjà
   masquées par SliDesk. display:contents évite d'introduire une boîte, tout en
   laissant apparaître un contenu oublié hors bloc - donc visible à la relecture. */
.sd-slide .s-rest {
    display: contents;
}

/* --------------------------------------------------------------------------
   14. Vue conférencier - le déroulé de la démo

   La démo vaut douze des vingt minutes, et son déroulé est la note la plus
   longue du deck. Le volet de notes défile (overflow:scroll, posé par
   slidesk-notes.css) : l'index chiffré en tête de la note doit donc tenir
   dans le premier écran, sinon il ne sert à rien en salle.

   Rien ici ne touche aux slides : notes.html charge ce fichier après celui de
   SliDesk, et ces règles ne valent que pour le volet de droite.
   -------------------------------------------------------------------------- */
#sd-sv-notes ol,
#sd-sv-notes ul {
    margin: 0.4em 0;
    padding-left: 1.6em;
}

#sd-sv-notes li {
    margin-bottom: 0.25em;
}

/* Les durées sont ce qu'on vient chercher d'un coup d'œil : on les sort du
   gris du texte courant. Ambre, comme la pastille d'événement. */
#sd-sv-notes li strong {
    color: var(--lab-amber);
}

#sd-sv-notes li em {
    color: var(--lab-orange);
    font-style: normal;
}

/* --------------------------------------------------------------------------
   15. Conteneurs de bloc vides
   Un bloc [[...]] non utilisé laisse son conteneur en place : il ne doit rien
   occuper. :not(:has(*)) couvre aussi le cas « uniquement des blancs ».
   À garder en dernier : même spécificité que les règles de bloc ci-dessus,
   donc c'est l'ordre qui tranche.
   -------------------------------------------------------------------------- */
.sd-slide .s-lead:not(:has(*)),
.sd-slide .s-main:not(:has(*)),
.sd-slide .s-punch:not(:has(*)),
.sd-slide .s-note:not(:has(*)),
.sd-slide .c-lead:not(:has(*)),
.sd-slide .c-art:not(:has(*)),
.sd-slide .c-num:not(:has(*)) {
    display: none;
}
