/* ==========================================================================
   ASSULIGHT DESIGN SYSTEM : 03. COMPOSANTS
   A charger apres al-tokens.css et al-theme.css.
   Chaque bloc est autonome et ne consomme que des tokens.
   ==========================================================================
   SOMMAIRE
   01. Boutons              08. Etapes / process      15. Formulaires
   02. Etiquettes & puces   09. Statistiques          16. Fil d'Ariane / pagination
   03. Navigation           10. Temoignages           17. Alertes
   04. Heros                11. FAQ (accordeon)       18. Pied de page
   05. Bandeau defilant     12. Offres / tarifs       19. Reveal & curseur
   06. Cartes services      13. Equipe                20. Utilitaires media
   07. Cartes projet        14. Bandeau d'appel        21. Messages flash
                                                       22. Etude de cas
   ========================================================================== */


/* ==========================================================================
   01. BOUTONS
   ========================================================================== */
.al-btn {
  --al-btn-bg: var(--al-canvas);
  --al-btn-fg: var(--al-text-strong);
  --al-btn-border: var(--al-border-strong);
  --al-btn-bg-hover: var(--al-text-strong);
  --al-btn-fg-hover: var(--al-canvas);
  --al-btn-border-hover: var(--al-text-strong);
  --al-btn-py: 0.875rem;
  --al-btn-px: 1.75rem;
  --al-btn-fs: var(--al-fs-sm);

  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--al-space-2);
  padding: var(--al-btn-py) var(--al-btn-px);
  border: 1px solid var(--al-btn-border);
  border-radius: var(--al-radius-pill);
  background: var(--al-btn-bg);
  color: var(--al-btn-fg);
  font-family: var(--al-font-display);
  font-size: var(--al-btn-fs);
  font-weight: var(--al-fw-semibold);
  letter-spacing: -0.01em;
  line-height: 1.2;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  user-select: none;
  white-space: nowrap;
  isolation: isolate;
  overflow: hidden;
  transition:
    color var(--al-dur-base) var(--al-ease-out),
    border-color var(--al-dur-base) var(--al-ease-out),
    box-shadow var(--al-dur-base) var(--al-ease-out),
    transform var(--al-dur-fast) var(--al-ease-out);
}

/* Remplissage qui monte depuis le bas : micro-interaction signature */
.al-btn::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: var(--al-btn-bg-hover);
  transform: translateY(101%);
  transition: transform var(--al-dur-slow) var(--al-ease-out-expo);
}
.al-btn:hover { color: var(--al-btn-fg-hover); border-color: var(--al-btn-border-hover); }
.al-btn:hover::before { transform: translateY(0); }
.al-btn:active { transform: scale(0.98); }
.al-btn:disabled,
.al-btn.is-disabled { opacity: .45; pointer-events: none; }

/* Variantes */
.al-btn--primary {
  --al-btn-bg: var(--al-text-strong);
  --al-btn-fg: var(--al-canvas);
  --al-btn-border: var(--al-text-strong);
  --al-btn-bg-hover: var(--al-azur-500);
  --al-btn-fg-hover: #fff;
  --al-btn-border-hover: var(--al-azur-500);
}
.al-btn--accent {
  --al-btn-bg: var(--al-azur-500);
  --al-btn-fg: #fff;
  --al-btn-border: var(--al-azur-500);
  --al-btn-bg-hover: var(--al-azur-600);
  --al-btn-fg-hover: #fff;
  --al-btn-border-hover: var(--al-azur-600);
}
.al-btn--solaire {
  --al-btn-bg: var(--al-solaire-500);
  --al-btn-fg: var(--al-ink-950);
  --al-btn-border: var(--al-solaire-500);
  --al-btn-bg-hover: var(--al-ink-950);
  --al-btn-fg-hover: var(--al-solaire-500);
  --al-btn-border-hover: var(--al-ink-950);
}
.al-btn--outline {
  --al-btn-bg: var(--al-canvas);
  --al-btn-fg: var(--al-text-strong);
  --al-btn-border: var(--al-border-strong);
}
.al-btn--ghost {
  --al-btn-bg: transparent;
  --al-btn-border: transparent;
  --al-btn-bg-hover: var(--al-surface-sunken);
  --al-btn-fg-hover: var(--al-text-strong);
  --al-btn-border-hover: transparent;
}

/* Bouton a bordure spectre : reserve a l'appel principal d'une page */
.al-btn--spectre {
  --al-btn-bg: var(--al-canvas);
  --al-btn-fg: var(--al-text-strong);
  --al-btn-border: transparent;
  --al-btn-bg-hover: transparent;
  --al-btn-fg-hover: var(--al-text-strong);
  --al-btn-border-hover: transparent;
  background:
    linear-gradient(var(--al-canvas), var(--al-canvas)) padding-box,
    var(--al-spectre-diag) border-box;
  border: 2px solid transparent;
}
.al-btn--spectre::before { background: var(--al-spectre-soft); }

.al-btn--sm { --al-btn-py: 0.5rem;  --al-btn-px: 1.125rem; --al-btn-fs: var(--al-fs-xs); }
.al-btn--lg { --al-btn-py: 1.125rem; --al-btn-px: 2.25rem;  --al-btn-fs: var(--al-fs-body); }
.al-btn--block { display: flex; width: 100%; }

/* Fleche qui glisse */
.al-btn__arrow {
  display: inline-block;
  transition: transform var(--al-dur-base) var(--al-ease-out);
}
.al-btn:hover .al-btn__arrow { transform: translateX(4px); }

/* Bouton icone circulaire */
.al-btn-icon {
  --al-size: 48px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  inline-size: var(--al-size);
  block-size: var(--al-size);
  padding: 0;
  border: 1px solid var(--al-border-strong);
  border-radius: 50%;
  background: var(--al-canvas);
  color: var(--al-text-strong);
  font-size: 1.1rem;
  cursor: pointer;
  transition: background var(--al-dur-base) var(--al-ease-out),
              color var(--al-dur-base) var(--al-ease-out),
              transform var(--al-dur-base) var(--al-ease-spring),
              border-color var(--al-dur-base) var(--al-ease-out);
}
.al-btn-icon:hover {
  background: var(--al-text-strong);
  border-color: var(--al-text-strong);
  color: var(--al-canvas);
  transform: scale(1.06);
}
.al-btn-icon--sm { --al-size: 38px; font-size: .9rem; }
.al-btn-icon--lg { --al-size: 64px; font-size: 1.35rem; }
.al-btn-icon:disabled { opacity: .35; pointer-events: none; }

/* Lien texte a fleche */
.al-link-arrow {
  display: inline-flex;
  align-items: center;
  gap: var(--al-space-2);
  font-weight: var(--al-fw-semibold);
  font-size: var(--al-fs-sm);
  color: var(--al-text-strong);
  padding-bottom: 2px;
  border-bottom: 1px solid var(--al-border-strong);
  transition: border-color var(--al-dur-base) var(--al-ease-out), gap var(--al-dur-base) var(--al-ease-out);
}
.al-link-arrow:hover { gap: var(--al-space-3); border-color: var(--al-azur-500); color: var(--al-text-strong); }


/* ==========================================================================
   02. ETIQUETTES & PUCES
   ========================================================================== */
.al-tag {
  display: inline-flex;
  align-items: center;
  gap: var(--al-space-2);
  padding: 0.375rem 0.75rem;
  border: 1px solid var(--al-border);
  border-radius: var(--al-radius-pill);
  background: var(--al-canvas);
  color: var(--al-text-muted);
  font-family: var(--al-font-mono);
  font-size: 0.6875rem;
  font-weight: var(--al-fw-medium);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  white-space: nowrap;
}
.al-tag--solid  { background: var(--al-surface-sunken); border-color: transparent; color: var(--al-text); }
.al-tag--azur   { background: linear-gradient(var(--al-accent-soft), var(--al-accent-soft)), var(--al-canvas); border-color: transparent; color: var(--al-accent-text); }
.al-tag--glass  { background: var(--al-surface); border-color: var(--al-border-strong); color: var(--al-text-strong); }

/* Puce d'etat avec pastille pulsante */
.al-pill-status {
  display: inline-flex;
  align-items: center;
  gap: var(--al-space-2);
  padding: 0.4375rem 0.875rem 0.4375rem 0.75rem;
  border: 1px solid var(--al-border);
  border-radius: var(--al-radius-pill);
  font-size: var(--al-fs-xs);
  font-weight: var(--al-fw-medium);
  color: var(--al-text-muted);
  background: var(--al-surface);
}
.al-pill-status__dot {
  inline-size: 8px; block-size: 8px;
  border-radius: 50%;
  background: var(--al-success-500);
  position: relative;
  flex: none;
}
.al-pill-status__dot::after {
  content: "";
  position: absolute; inset: 0;
  border-radius: 50%;
  background: inherit;
  animation: al-ping 2.4s var(--al-ease-out) infinite;
}
@keyframes al-ping {
  0%   { transform: scale(1);   opacity: .7; }
  70%  { transform: scale(2.6); opacity: 0; }
  100% { transform: scale(2.6); opacity: 0; }
}


/* ==========================================================================
   03. NAVIGATION
   ========================================================================== */
.al-navbar {
  position: fixed;
  inset-block-start: 0;
  inset-inline: 0;
  z-index: var(--al-z-navbar);
  block-size: var(--al-navbar-h);
  display: flex;
  align-items: center;
  background: var(--al-canvas);
  /* Le filet du bas est une ombre et non une bordure : il se pose sous la
     barre, sur le pixel de la ligne de grille, au lieu d'empieter dessus. */
  box-shadow: 0 1px 0 var(--al-rule);
  transition: background var(--al-dur-slow) var(--al-ease-out),
              transform var(--al-dur-slow) var(--al-ease-out-expo),
              block-size var(--al-dur-slow) var(--al-ease-out);
}
.al-navbar__inner {
  inline-size: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--al-space-5);
}
/* Etat colle : fond plein. La barre garde sa hauteur de deux cases, pour
   que son filet du bas reste sur une ligne de la grille. */
.al-navbar.is-stuck {
  background: var(--al-canvas);
}
/* Masquee au defilement descendant */
.al-navbar.is-hidden { transform: translateY(-100%); }

.al-navbar__brand { display: inline-flex; align-items: center; flex: none; }
.al-navbar__brand img { inline-size: 152px; block-size: auto; }
@media (max-width: 575.98px) { .al-navbar__brand img { inline-size: 124px; } }

.al-navbar__links {
  display: none;
  align-items: center;
  gap: var(--al-space-1);
  list-style: none;
  margin: 0; padding: 0;
}
@media (min-width: 992px) { .al-navbar__links { display: flex; } }
/* Sur grand ecran, les liens sont deja dans la barre : le bouton du menu
   plein ecran ferait doublon. Il reste sur tablette et telephone. */
@media (min-width: 992px) { .al-navbar .al-burger { display: none; } }

.al-nav-link {
  position: relative;
  display: inline-block;
  padding: var(--al-space-2) var(--al-space-4);
  border-radius: var(--al-radius-pill);
  font-size: var(--al-fs-sm);
  font-weight: var(--al-fw-medium);
  color: var(--al-text-muted);
  transition: color var(--al-dur-fast) linear;
}
.al-nav-link::after {
  content: "";
  position: absolute;
  inset-block-end: 4px;
  inset-inline-start: 50%;
  translate: -50% 0;
  inline-size: 0;
  block-size: 2px;
  border-radius: var(--al-radius-pill);
  background: var(--al-spectre);
  transition: inline-size var(--al-dur-base) var(--al-ease-out);
}
.al-nav-link:hover,
.al-nav-link.is-active { color: var(--al-text-strong); }
.al-nav-link:hover::after,
.al-nav-link.is-active::after { inline-size: 20px; }

.al-navbar__actions { display: flex; align-items: center; gap: var(--al-space-3); flex: none; }

/* Bouton menu (burger anime) */
.al-burger {
  --al-size: 46px;
  position: relative;
  inline-size: var(--al-size);
  block-size: var(--al-size);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--al-border-strong);
  border-radius: 50%;
  background: var(--al-canvas);
  cursor: pointer;
  transition: background var(--al-dur-base) var(--al-ease-out), border-color var(--al-dur-base) var(--al-ease-out);
}
.al-burger:hover { background: var(--al-surface-sunken); }
.al-burger__bars { position: relative; inline-size: 18px; block-size: 10px; }
.al-burger__bars span {
  position: absolute;
  inset-inline: 0;
  block-size: 2px;
  border-radius: 2px;
  background: var(--al-text-strong);
  transition: transform var(--al-dur-base) var(--al-ease-out), opacity var(--al-dur-fast) linear;
}
.al-burger__bars span:nth-child(1) { inset-block-start: 0; }
.al-burger__bars span:nth-child(2) { inset-block-end: 0; }
.al-burger[aria-expanded="true"] .al-burger__bars span:nth-child(1) { transform: translateY(4px) rotate(45deg); }
.al-burger[aria-expanded="true"] .al-burger__bars span:nth-child(2) { transform: translateY(-4px) rotate(-45deg); }

/* Bascule clair / sombre. Les deux pictogrammes sont superposes : celui du
   theme a venir est visible, l'autre tourne et s'efface. On montre la lune
   en clair (« passer au sombre »), le soleil en sombre. */
.al-theme-toggle {
  --al-size: 46px;
  position: relative;
  inline-size: var(--al-size);
  block-size: var(--al-size);
  display: inline-grid;
  place-items: center;
  flex: none;
  padding: 0;
  border: 1px solid var(--al-border-strong);
  border-radius: 50%;
  background: var(--al-canvas);
  color: var(--al-text-strong);
  font-size: 1.05rem;
  cursor: pointer;
  overflow: hidden;
  transition: background var(--al-dur-base) var(--al-ease-out), border-color var(--al-dur-base) var(--al-ease-out);
}
.al-theme-toggle:hover { background: var(--al-surface-sunken); }
.al-theme-toggle i {
  grid-area: 1 / 1;
  transition: transform var(--al-dur-slow) var(--al-ease-out-expo), opacity var(--al-dur-base) linear;
}
.al-theme-toggle__sun { opacity: 0; transform: rotate(-90deg) scale(.5); }
[data-bs-theme="dark"] .al-theme-toggle__sun  { opacity: 1; transform: none; }
[data-bs-theme="dark"] .al-theme-toggle__moon { opacity: 0; transform: rotate(90deg) scale(.5); }

/* Menu plein ecran : un rideau dans le theme de la page. */
.al-menu {
  position: fixed;
  inset: 0;
  z-index: var(--al-z-offcanvas);
  display: grid;
  grid-template-rows: auto 1fr auto;
  padding: var(--al-space-5) 0 var(--al-space-6);
  background: var(--al-canvas);
  color: var(--al-text);
  overflow-y: auto;
  clip-path: inset(0 0 100% 0);
  visibility: hidden;
  transition: clip-path var(--al-dur-slower) var(--al-ease-out-expo), visibility 0s linear var(--al-dur-slower);
}
.al-menu.is-open {
  clip-path: inset(0 0 0 0);
  visibility: visible;
  transition: clip-path var(--al-dur-slower) var(--al-ease-out-expo), visibility 0s;
}
.al-menu__list { list-style: none; margin: 0; padding: 0; }
.al-menu__item { border-bottom: 1px solid var(--al-border-subtle); }
.al-menu__link {
  display: flex;
  align-items: baseline;
  gap: var(--al-space-4);
  padding: clamp(.75rem, 2.2vw, 1.5rem) 0;
  font-family: var(--al-font-display);
  font-size: clamp(2rem, 6vw, 4.5rem);
  font-weight: var(--al-fw-extrabold);
  letter-spacing: var(--al-ls-display);
  line-height: 1;
  color: var(--al-text-subtle);
  transition: color var(--al-dur-base) var(--al-ease-out), padding-inline-start var(--al-dur-base) var(--al-ease-out);
}
.al-menu__link:hover,
.al-menu__link.is-active { color: var(--al-text-strong); padding-inline-start: var(--al-space-4); }
.al-menu__link .al-index { color: var(--al-text-subtle); font-size: .75rem; }
.al-menu__meta { color: var(--al-text-muted); font-size: var(--al-fs-sm); }
.al-menu__meta a:hover { color: var(--al-text-strong); }

/* Barre de progression de lecture */
.al-progress {
  position: fixed;
  inset-block-start: 0;
  inset-inline: 0;
  block-size: 2px;
  z-index: calc(var(--al-z-navbar) + 1);
  background: var(--al-spectre);
  transform-origin: 0 50%;
  transform: scaleX(0);
}

/* ==========================================================================
   04. HEROS
   --------------------------------------------------------------------------
   Socle commun des heros : plein ecran, voile de fond, contenu centre dans
   la hauteur. La composition de l'accueil (texte centre, scene du prisme
   qui affleure sous la ligne de flottaison) est decrite en famille 27.
   Regle constante : le texte ne repose jamais sur une image ou une scene,
   chacune a son propre cadre.
   ========================================================================== */
.al-hero {
  position: relative;
  display: flex;
  flex-direction: column;
  min-block-size: 100svh;
  padding-block-start: calc(var(--al-navbar-h) + var(--al-space-7));
  overflow: hidden;
  isolation: isolate;
}
.al-hero__inner {
  flex: 1;
  display: flex;
  align-items: center;
  padding-block: var(--al-space-6);
}


/* Variante compacte : en-tete des pages internes */
.al-hero--compact {
  min-block-size: auto;
  padding-block: calc(var(--al-navbar-h) + var(--al-space-9)) var(--al-space-9);
  display: block;
}
.al-hero--compact .al-hero__inner { display: block; padding-block: 0; }

/* Media plein cadre : reserve aux pages ou aucun texte ne le surplombe */
.al-hero__media { position: absolute; inset: 0; z-index: -2; }
.al-hero__media video,
.al-hero__media img { inline-size: 100%; block-size: 100%; object-fit: cover; }
.al-hero__scrim {
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(180deg, rgb(11 13 17 / .82) 0%, rgb(11 13 17 / .62) 45%, rgb(11 13 17 / .92) 100%);
}

.al-hero__title { margin-bottom: var(--al-space-5); }
.al-hero__lead { max-width: 52ch; }
.al-hero__actions { display: flex; flex-wrap: wrap; gap: var(--al-space-3); margin-top: var(--al-space-7); }

/* --------------------------------------------------------------------------
   Puits media du heros : cadre a filet spectre
   -------------------------------------------------------------------------- */
.al-hero__panel {
  position: relative;
  border-radius: var(--al-radius-xl);
  padding: 1px;                       /* epaisseur du filet degrade */
  background: var(--al-spectre-diag);
  box-shadow: var(--al-shadow-xl);
}
.al-hero__frame {
  position: relative;
  border-radius: calc(var(--al-radius-xl) - 1px);
  overflow: hidden;
  background: var(--al-ink-900);
  aspect-ratio: 16 / 10;
}
@media (min-width: 992px) {
  .al-hero__frame {
    /* Hauteur pilotee plutot que ratio : un `max-block-size` pose sur une
       boite en `aspect-ratio` en reduit la LARGEUR, ce qui laisserait
       apparaitre le filet degrade du cadre sur le cote. Le rail
       d'indicateurs doit par ailleurs rester au-dessus de la ligne
       de flottaison. */
    aspect-ratio: auto;
    block-size: clamp(340px, 52svh, 560px);
  }
}
.al-hero__frame video,
.al-hero__frame img {
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
  filter: grayscale(.35) contrast(1.05);
  transition: filter var(--al-dur-slower) var(--al-ease-out), transform var(--al-dur-slower) var(--al-ease-out-expo);
}
.al-hero__panel:hover video,
.al-hero__panel:hover img { filter: grayscale(0) contrast(1); transform: scale(1.03); }

/* Voile bas du cadre, pour la puce d'etat */
.al-hero__frame::after {
  content: "";
  position: absolute;
  inset-inline: 0;
  inset-block-end: 0;
  block-size: 45%;
  background: linear-gradient(180deg, transparent, rgb(11 13 17 / .85));
  pointer-events: none;
}
.al-hero__badge {
  position: absolute;
  inset-inline-start: var(--al-space-4);
  inset-block-end: var(--al-space-4);
  z-index: 1;
}
.al-hero__caption {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--al-space-3);
  margin-block-start: var(--al-space-3);
  font-family: var(--al-font-mono);
  font-size: var(--al-fs-xs);
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--al-text-subtle);
}

/* Le rail d'indicateurs colle en bas du premier ecran a ete retire avec le
   heros centre : les chiffres cles vivent desormais dans la section de
   preuve qui suit (famille 30), le heros n'en cite que deux. */

/* Indice de defilement */
.al-scroll-cue {
  display: inline-flex;
  align-items: center;
  gap: var(--al-space-3);
  font-family: var(--al-font-mono);
  font-size: 0.6875rem;
  letter-spacing: var(--al-ls-eyebrow);
  text-transform: uppercase;
  color: var(--al-text-muted);
}
.al-scroll-cue__line {
  inline-size: 44px;
  block-size: 1px;
  background: currentColor;
  transform-origin: 0 50%;
  animation: al-cue 2.4s var(--al-ease-in-out) infinite;
}
@keyframes al-cue {
  0%   { transform: scaleX(0); opacity: 0; }
  40%  { transform: scaleX(1); opacity: 1; }
  100% { transform: scaleX(1); opacity: 0; transform-origin: 100% 50%; }
}

/* --------------------------------------------------------------------------
   Machine a ecrire
   Le mot s'ecrit caractere par caractere, s'efface, et le suivant s'ecrit a
   sa place. Remplace le rotateur, qui faisait apparaitre les mots d'un bloc.

   IMPORTANT : le degrade est porte par le NOEUD DE TEXTE, jamais par le
   conteneur. `background-clip: text` sur le conteneur decouperait le fond sur
   la reunion des glyphes du mot et du curseur.

   La largeur n'est pas figee, contrairement au rotateur : une frappe qui
   pousse la fin de ligne est exactement ce qu'on attend d'une saisie. Le mot
   est seul sur sa ligne, rien d'autre ne bouge.
   -------------------------------------------------------------------------- */
.al-type {
  display: inline;
  white-space: nowrap;
}
.al-type__text {
  background: var(--al-spectre);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
}

/* Curseur de saisie. Blanc et non solaire : la charte reserve le jaune a
   l'appel a l'action principal, deja present dans ce heros. */
.al-type__caret {
  display: inline-block;
  inline-size: .055em;
  block-size: .78em;
  margin-inline-start: .05em;
  translate: 0 .04em;
  border-radius: 1px;
  background: var(--al-text-strong);
  animation: al-caret 1.05s steps(1, end) infinite;
}

/* `steps(1)` et non une transition : un curseur de terminal ne fond pas,
   il est allume ou eteint. */
@keyframes al-caret {
  0%, 52%   { opacity: 1; }
  53%, 100% { opacity: 0; }
}

/* Pendant les pauses, le curseur cesse de clignoter : c'est ce que fait un
   curseur reel tant que la frappe continue. */
.al-type.is-typing .al-type__caret { animation: none; opacity: 1; }

@media (prefers-reduced-motion: reduce) {
  .al-type__caret { animation: none; }
}



/* ==========================================================================
   05. BANDEAU DEFILANT (marquee)
   ========================================================================== */
.al-marquee {
  display: flex;
  overflow: hidden;
  user-select: none;
  gap: var(--al-gap, 3rem);
  mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
}
.al-marquee__track {
  flex: none;
  display: flex;
  align-items: center;
  gap: var(--al-gap, 3rem);
  min-inline-size: 100%;
  animation: al-marquee var(--al-speed, 38s) linear infinite;
}
.al-marquee:hover .al-marquee__track { animation-play-state: paused; }
.al-marquee--reverse .al-marquee__track { animation-direction: reverse; }
@keyframes al-marquee { to { transform: translateX(calc(-100% - var(--al-gap, 3rem))); } }

/* Bandeau typographique */
.al-marquee--type .al-marquee__item {
  display: inline-flex;
  align-items: center;
  gap: var(--al-space-6);
  font-family: var(--al-font-display);
  font-size: clamp(2rem, 5vw, 4.5rem);
  font-weight: var(--al-fw-extrabold);
  letter-spacing: var(--al-ls-display);
  color: var(--al-text-strong);
  white-space: nowrap;
}
.al-marquee--type .al-marquee__sep { color: var(--al-magenta-500); }

/* Mur de logos (element section/logos) : une grille fixe de 2, 3, 4 puis
   6 colonnes, sans defilement. Les pieces suivent la grammaire de la
   grille (famille 37). */
.al-logo-wall {
  --al-logo-aire: clamp(3rem, 2.2rem + 1.8vw, 4.5rem);
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  margin: 0;
  padding: 0;
  list-style: none;
}
@media (min-width: 576px) { .al-logo-wall { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (min-width: 768px) { .al-logo-wall { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
@media (min-width: 992px) { .al-logo-wall { grid-template-columns: repeat(6, minmax(0, 1fr)); } }

.al-logo-wall__cell,
.al-logo-wall__vide {
  min-block-size: calc(var(--al-grid-size) * 3);
}
.al-logo-wall__cell {
  display: grid;
  place-items: center;
  padding: var(--al-space-4);
  transition: background var(--al-dur-base) var(--al-ease-out);
}

/* A surface egale : la largeur suit la racine de la proportion (--r),
   bornee par la piece. Un logo carre et un logo en longueur pesent le meme
   poids a l'oeil. */
.al-logo-wall__logo {
  inline-size: min(100%, calc(var(--al-logo-aire) * var(--r, 1.6)));
  block-size: auto;
  max-block-size: calc(var(--al-grid-size) * 2);
  object-fit: contain;
  opacity: .8;
  filter: grayscale(1);
  transition: opacity var(--al-dur-base) var(--al-ease-out);
}
.al-logo-wall__cell:hover .al-logo-wall__logo { opacity: 1; }

/* Logo mis au propre a l'envoi : deja gris, encre foncee. */
.al-logo-wall__logo.is-normalise { filter: none; }
/* SVG : silhouette, quelle que soit sa couleur. */
.al-logo-wall__logo.is-vectoriel { filter: brightness(0); }

/* En sombre, l'encre foncee est inversee. */
[data-bs-theme="dark"] .al-logo-wall__logo { filter: grayscale(1) invert(1); opacity: .75; }
[data-bs-theme="dark"] .al-logo-wall__logo.is-normalise { filter: invert(1); }
[data-bs-theme="dark"] .al-logo-wall__logo.is-vectoriel { filter: brightness(0) invert(1); }
[data-bs-theme="dark"] .al-logo-wall__cell:hover .al-logo-wall__logo { opacity: 1; }

/* Pieces vides de fin de rangee : chacune ne sert qu'aux largeurs ou il
   manque des logos pour finir la rangee. */
.al-logo-wall__vide { display: none; }
@media (max-width: 575.98px) { .al-logo-wall__vide--2 { display: block; } }
@media (min-width: 576px) and (max-width: 767.98px) { .al-logo-wall__vide--3 { display: block; } }
@media (min-width: 768px) and (max-width: 991.98px) { .al-logo-wall__vide--4 { display: block; } }
@media (min-width: 992px) { .al-logo-wall__vide--6 { display: block; } }

/* Sur l'accueil, le mur suit les chiffres, sous un libelle discret. */
.al-clients { margin-block-start: calc(var(--al-grid-size) * 2); }
.al-clients__titre {
  margin: 0 0 var(--al-space-4);
  font-family: var(--al-font-mono);
  font-size: var(--al-fs-eyebrow);
  letter-spacing: var(--al-ls-eyebrow);
  text-transform: uppercase;
  text-align: center;
  color: var(--al-text-muted);
}


/* ==========================================================================
   06. CARTES SERVICES
   ========================================================================== */
.al-service {
  position: relative;
  display: block;
  block-size: 100%;
  padding: var(--al-space-6);
  border: 1px solid var(--al-border);
  border-radius: var(--al-radius-lg);
  background: var(--al-surface);
  overflow: hidden;
  isolation: isolate;
  transition: transform var(--al-dur-slow) var(--al-ease-out-expo),
              border-color var(--al-dur-base) var(--al-ease-out),
              box-shadow var(--al-dur-slow) var(--al-ease-out);
}
.al-service::after {
  content: "";
  position: absolute;
  inset-block-start: 0;
  inset-inline: 0;
  block-size: 3px;
  background: var(--al-spectre);
  transform: scaleX(0);
  transform-origin: 0 50%;
  transition: transform var(--al-dur-slow) var(--al-ease-out-expo);
}
.al-service:hover {
  transform: translateY(-6px);
  border-color: var(--al-border-strong);
  box-shadow: var(--al-shadow-lg);
}
.al-service:hover::after { transform: scaleX(1); }

.al-service__head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--al-space-4); margin-bottom: var(--al-space-6); }
.al-service__icon {
  display: grid;
  place-items: center;
  inline-size: 52px;
  block-size: 52px;
  border-radius: var(--al-radius-md);
  background: var(--al-surface-sunken);
  color: var(--al-text-strong);
  font-size: 1.35rem;
  flex: none;
  transition: background var(--al-dur-base) var(--al-ease-out), color var(--al-dur-base) var(--al-ease-out);
}
.al-service:hover .al-service__icon { background: var(--al-text-strong); color: var(--al-canvas); }
.al-service__title { font-size: var(--al-fs-h3); margin-bottom: var(--al-space-3); }
.al-service__desc  { color: var(--al-text-muted); font-size: var(--al-fs-sm); margin-bottom: var(--al-space-5); }
.al-service__list  { list-style: none; margin: 0 0 var(--al-space-5); padding: 0; display: flex; flex-wrap: wrap; gap: var(--al-space-2); }


/* ==========================================================================
   07. CARTES PROJET
   ========================================================================== */
.al-work {
  position: relative;
  display: block;
  border-radius: var(--al-radius-lg);
  overflow: hidden;
  background: var(--al-surface-sunken);
  isolation: isolate;
}
.al-work__media {
  position: relative;
  display: block;
  aspect-ratio: var(--al-ratio, 4 / 3);
  overflow: hidden;
  background: var(--al-ink-900);
}
.al-work__media img,
.al-work__media video {
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
  transition: transform var(--al-dur-slower) var(--al-ease-out-expo), filter var(--al-dur-slow) var(--al-ease-out);
}
.al-work:hover .al-work__media img,
.al-work:hover .al-work__media video { transform: scale(1.05); }

.al-work__overlay {
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgb(11 13 17 / 0) 35%, rgb(11 13 17 / .88) 100%);
  opacity: .9;
  transition: opacity var(--al-dur-slow) var(--al-ease-out);
}
.al-work:hover .al-work__overlay { opacity: 1; }

.al-work__body {
  position: absolute;
  inset-block-end: 0;
  inset-inline: 0;
  padding: var(--al-space-5);
  color: #fff;
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--al-space-4);
}
.al-work__title { color: #fff; font-size: var(--al-fs-h3); margin: 0 0 var(--al-space-1); }
.al-work__meta  { color: rgb(255 255 255 / .68); font-size: var(--al-fs-xs); margin: 0; }
.al-work__tags  { display: flex; flex-wrap: wrap; gap: var(--al-space-2); margin-bottom: var(--al-space-3); }
.al-work__go {
  flex: none;
  display: grid;
  place-items: center;
  inline-size: 44px; block-size: 44px;
  border-radius: 50%;
  border: 1px solid rgb(255 255 255 / .3);
  color: #fff;
  transition: background var(--al-dur-base) var(--al-ease-out), color var(--al-dur-base) var(--al-ease-out), transform var(--al-dur-base) var(--al-ease-spring);
}
.al-work:hover .al-work__go { background: #fff; color: var(--al-ink-950); transform: rotate(-45deg); }

/* Variante sous-titre externe (grille de portfolio) */
.al-work--stacked { background: transparent; border-radius: 0; overflow: visible; }
.al-work--stacked .al-work__media { border-radius: var(--al-radius-lg); }
.al-work--stacked .al-work__body {
  position: static;
  padding: var(--al-space-4) 0 0;
  color: inherit;
}
.al-work--stacked .al-work__title { color: var(--al-text-strong); }
.al-work--stacked .al-work__meta  { color: var(--al-text-muted); }
.al-work--stacked .al-work__overlay { display: none; }
.al-work--stacked .al-work__go { border-color: var(--al-border-strong); color: var(--al-text-strong); }
.al-work--stacked:hover .al-work__go { background: var(--al-text-strong); color: var(--al-canvas); }

/* --------------------------------------------------------------------------
   Grille bento pour les projets phares
   Deux cartes cote a cote ont la meme hauteur, et leurs images finissent a
   la meme ligne, qu'elles montrent une photo ou un appareil. Des rangees de
   hauteur fixe ecrasaient l'image des que la legende passait sur plusieurs
   lignes : la hauteur suit donc le contenu.

   Sous 992 px, la grille redevient une colonne et c'est le rapport d'image
   de chaque carte qui commande, comme partout ailleurs.
   -------------------------------------------------------------------------- */
.al-bento { display: grid; gap: var(--al-space-4); grid-template-columns: repeat(2, 1fr); }
@media (min-width: 992px) {
  .al-bento { grid-template-columns: repeat(4, 1fr); gap: var(--al-space-5); }
  .al-bento > .al-span-2 { grid-column: span 2; }
  .al-bento > .al-span-3 { grid-column: span 3; }
  .al-bento > .al-row-2  { grid-row: span 2; }

  /*
   * L'image garde son rapport, la legende prend le reste : une longue legende
   * agrandit la carte au lieu d'ecraser l'image. Deux cartes de meme largeur
   * ont le meme rapport, leurs images finissent donc a la meme ligne.
   */
  .al-bento > .al-work { display: grid; grid-template-rows: auto 1fr; }
  .al-bento > .al-work .al-work__media { aspect-ratio: var(--al-ratio); block-size: auto; }
}
@media (max-width: 991.98px) { .al-bento > * { grid-column: span 2; } }


/* ==========================================================================
   08. ETAPES / PROCESS
   ========================================================================== */
.al-steps { display: grid; gap: var(--al-space-5); counter-reset: al-step; }
@media (min-width: 768px) { .al-steps--4 { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1200px) { .al-steps--4 { grid-template-columns: repeat(4, 1fr); } }

.al-step {
  position: relative;
  padding-block-start: var(--al-space-6);
  border-top: 2px solid var(--al-border);
  counter-increment: al-step;
  transition: border-color var(--al-dur-slow) var(--al-ease-out);
}
.al-step::before {
  content: "0" counter(al-step);
  display: block;
  margin-bottom: var(--al-space-4);
  font-family: var(--al-font-mono);
  font-size: var(--al-fs-xs);
  letter-spacing: 0.12em;
  color: var(--al-text-subtle);
}
.al-step:hover { border-top-color: var(--al-azur-500); }
.al-step__title { font-size: var(--al-fs-h4); margin-bottom: var(--al-space-3); }
.al-step__desc  { color: var(--al-text-muted); font-size: var(--al-fs-sm); margin: 0; }


/* ==========================================================================
   09. STATISTIQUES
   ========================================================================== */
.al-stats { display: grid; grid-template-columns: repeat(2, 1fr); gap: 1px; background: var(--al-border); }
@media (min-width: 992px) { .al-stats { grid-template-columns: repeat(4, 1fr); } }
.al-stat { padding: var(--al-space-6) var(--al-space-5); background: var(--al-canvas); }
.al-stat__value {
  display: block;
  font-family: var(--al-font-display);
  font-size: clamp(2.5rem, 5vw, 4rem);
  font-weight: var(--al-fw-black);
  line-height: 1;
  letter-spacing: var(--al-ls-display);
  color: var(--al-text-strong);
  margin-bottom: var(--al-space-3);
}
.al-stat__label { font-size: var(--al-fs-xs); color: var(--al-text-muted); margin: 0; }


/* ==========================================================================
   10. TEMOIGNAGES
   ========================================================================== */
.al-quote {
  block-size: 100%;
  display: flex;
  flex-direction: column;
  gap: var(--al-space-5);
  padding: var(--al-space-6);
  border: 1px solid var(--al-border);
  border-radius: var(--al-radius-lg);
  background: var(--al-surface);
}
.al-quote__mark { font-size: 2.5rem; line-height: 1; color: var(--al-magenta-500); }
.al-quote__text {
  font-size: var(--al-fs-lead);
  font-weight: var(--al-fw-light);
  line-height: var(--al-lh-relaxed);
  color: var(--al-text);
  margin: 0;
  flex: 1;
}
.al-quote__author { display: flex; align-items: center; gap: var(--al-space-3); margin-block-start: auto; }
.al-quote__avatar {
  inline-size: 44px; block-size: 44px;
  border-radius: 50%;
  object-fit: cover;
  background: var(--al-surface-sunken);
  flex: none;
}
.al-quote__name { font-weight: var(--al-fw-semibold); font-size: var(--al-fs-sm); margin: 0; color: var(--al-text-strong); }
.al-quote__role { font-size: var(--al-fs-xs); color: var(--al-text-muted); margin: 0; }


/* ==========================================================================
   11. FAQ (accordeon)
   ========================================================================== */
.al-faq { border-top: 1px solid var(--al-border); }
.al-faq__item { border-bottom: 1px solid var(--al-border); }
.al-faq__btn {
  inline-size: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--al-space-4);
  padding: var(--al-space-5) 0;
  border: 0;
  background: transparent;
  color: var(--al-text-strong);
  font-family: var(--al-font-display);
  font-size: var(--al-fs-h4);
  font-weight: var(--al-fw-semibold);
  text-align: start;
  cursor: pointer;
  transition: color var(--al-dur-fast) linear;
}
.al-faq__btn:hover { color: var(--al-accent-text); }
.al-faq__icon {
  flex: none;
  position: relative;
  inline-size: 18px; block-size: 18px;
}
.al-faq__icon::before,
.al-faq__icon::after {
  content: "";
  position: absolute;
  inset-block-start: 50%;
  inset-inline-start: 0;
  inline-size: 18px; block-size: 2px;
  background: currentColor;
  border-radius: 2px;
  transition: transform var(--al-dur-base) var(--al-ease-out);
}
.al-faq__icon::after { transform: rotate(90deg); }
.al-faq__btn[aria-expanded="true"] .al-faq__icon::after { transform: rotate(0deg); }
.al-faq__panel {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows var(--al-dur-slow) var(--al-ease-out-expo);
}
.al-faq__panel.is-open { grid-template-rows: 1fr; }
.al-faq__panel > div { overflow: hidden; }
.al-faq__panel p { padding-block-end: var(--al-space-5); color: var(--al-text-muted); max-width: var(--al-measure); margin: 0; }


/* ==========================================================================
   12. OFFRES / TARIFS
   ========================================================================== */
.al-offer {
  position: relative;
  block-size: 100%;
  display: flex;
  flex-direction: column;
  padding: var(--al-space-6);
  border: 1px solid var(--al-border);
  border-radius: var(--al-radius-lg);
  background: var(--al-surface);
  transition: transform var(--al-dur-slow) var(--al-ease-out-expo), box-shadow var(--al-dur-slow) var(--al-ease-out);
}
.al-offer:hover { transform: translateY(-4px); box-shadow: var(--al-shadow-lg); }
.al-offer--featured {
  border-color: transparent;
  background:
    linear-gradient(var(--al-surface), var(--al-surface)) padding-box,
    var(--al-spectre-diag) border-box;
  border: 2px solid transparent;
  box-shadow: var(--al-shadow-lg);
}
.al-offer__badge {
  position: absolute;
  inset-block-start: 0; inset-inline-end: var(--al-space-6);
  translate: 0 -50%;
  padding: .3125rem .75rem;
  border-radius: var(--al-radius-pill);
  background: var(--al-spectre);
  color: #fff;
  font-family: var(--al-font-mono);
  font-size: .625rem;
  letter-spacing: .1em;
  text-transform: uppercase;
}
.al-offer__name  { font-size: var(--al-fs-h4); margin-bottom: var(--al-space-2); }
.al-offer__price { font-size: clamp(2rem, 4vw, 2.75rem); font-weight: var(--al-fw-black); letter-spacing: var(--al-ls-display); color: var(--al-text-strong); line-height: 1; margin-bottom: var(--al-space-2); }
.al-offer__unit  { font-size: var(--al-fs-xs); color: var(--al-text-muted); }
.al-offer__features { list-style: none; margin: var(--al-space-5) 0; padding: 0; display: grid; gap: var(--al-space-3); flex: 1; }
.al-offer__features li { display: flex; gap: var(--al-space-3); font-size: var(--al-fs-sm); color: var(--al-text-muted); }
.al-offer__features li::before { content: "\2713"; color: var(--al-success-500); font-weight: var(--al-fw-bold); flex: none; }


/* ==========================================================================
   13. EQUIPE
   ========================================================================== */
.al-person__photo {
  position: relative;
  aspect-ratio: 3 / 4;
  border-radius: var(--al-radius-lg);
  overflow: hidden;
  background: var(--al-surface-sunken);
  margin-bottom: var(--al-space-4);
}
.al-person__photo img {
  inline-size: 100%; block-size: 100%;
  object-fit: cover;
  filter: grayscale(1);
  transition: filter var(--al-dur-slow) var(--al-ease-out), transform var(--al-dur-slower) var(--al-ease-out-expo);
}
.al-person:hover .al-person__photo img { filter: grayscale(0); transform: scale(1.04); }
.al-person__name { font-size: var(--al-fs-h4); margin-bottom: var(--al-space-1); }
.al-person__role { font-family: var(--al-font-mono); font-size: var(--al-fs-xs); letter-spacing: .08em; text-transform: uppercase; color: var(--al-text-muted); margin: 0; }


/* ==========================================================================
   14. BANDEAU D'APPEL
   ========================================================================== */
.al-cta {
  position: relative;
  overflow: hidden;
  isolation: isolate;
  border-radius: var(--al-radius-2xl);
  padding: clamp(2.5rem, 6vw, 5.5rem);
  background: var(--al-surface);
  color: var(--al-text);
  text-align: center;
}
.al-cta__title { color: var(--al-text-strong); margin-bottom: var(--al-space-5); }
.al-cta__lead  { color: var(--al-text-muted); margin-inline: auto; }


/* ==========================================================================
   15. FORMULAIRES
   ========================================================================== */
.al-field { position: relative; margin-bottom: var(--al-space-5); }
.al-label {
  display: block;
  margin-bottom: var(--al-space-2);
  font-family: var(--al-font-mono);
  font-size: var(--al-fs-xs);
  font-weight: var(--al-fw-medium);
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--al-text-muted);
}
.al-label .al-required { color: var(--al-magenta-500); }

.al-input,
.al-select,
.al-textarea {
  inline-size: 100%;
  padding: 0.875rem 1.125rem;
  border: 1px solid var(--al-border-strong);
  border-radius: var(--al-radius-sm);
  background: var(--al-surface);
  color: var(--al-text-strong);
  font-family: var(--al-font-body);
  font-size: var(--al-fs-body);
  line-height: 1.5;
  transition: border-color var(--al-dur-fast) linear, box-shadow var(--al-dur-fast) linear, background var(--al-dur-fast) linear;
}
.al-input::placeholder,
.al-textarea::placeholder { color: var(--al-text-subtle); }
.al-input:hover,
.al-select:hover,
.al-textarea:hover { border-color: var(--al-text-subtle); }
.al-input:focus,
.al-select:focus,
.al-textarea:focus {
  outline: none;
  border-color: var(--al-azur-500);
  box-shadow: 0 0 0 3px rgb(var(--al-azur-500-rgb) / .18);
}
.al-textarea { min-block-size: 148px; resize: vertical; }
.al-select {
  appearance: none;
  padding-inline-end: 2.75rem;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%236b7280'%3E%3Cpath d='M4.5 6l3.5 4 3.5-4z'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 1rem center;
  background-size: 16px;
}
.al-input.is-invalid,
.al-textarea.is-invalid { border-color: var(--al-danger-500); }
.al-error { display: block; margin-top: var(--al-space-2); font-size: var(--al-fs-xs); color: var(--al-danger-700); }
.al-help  { display: block; margin-top: var(--al-space-2); font-size: var(--al-fs-xs); color: var(--al-text-muted); }

/* Choix multiples sous forme de puces cliquables (brief projet) */
.al-choice-grid { display: flex; flex-wrap: wrap; gap: var(--al-space-3); }
.al-choice { position: relative; }
.al-choice input { position: absolute; opacity: 0; inset: 0; cursor: pointer; }
.al-choice span {
  display: inline-flex;
  align-items: center;
  gap: var(--al-space-2);
  padding: 0.6875rem 1.125rem;
  border: 1px solid var(--al-border-strong);
  border-radius: var(--al-radius-pill);
  font-size: var(--al-fs-sm);
  font-weight: var(--al-fw-medium);
  color: var(--al-text-muted);
  cursor: pointer;
  transition: all var(--al-dur-fast) var(--al-ease-out);
}
.al-choice input:hover + span { border-color: var(--al-text-subtle); color: var(--al-text-strong); }
.al-choice input:checked + span {
  background: var(--al-text-strong);
  border-color: var(--al-text-strong);
  color: var(--al-canvas);
}
.al-choice input:focus-visible + span { outline: 2px solid var(--al-focus-ring); outline-offset: 3px; }

/* Formulaire en plusieurs etapes */
.al-steps-bar { display: flex; align-items: center; gap: var(--al-space-3); margin-bottom: var(--al-space-7); }
.al-steps-bar__item { display: flex; align-items: center; gap: var(--al-space-2); font-family: var(--al-font-mono); font-size: var(--al-fs-xs); color: var(--al-text-subtle); }
.al-steps-bar__dot {
  inline-size: 26px; block-size: 26px;
  display: grid; place-items: center;
  border-radius: 50%;
  border: 1px solid var(--al-border-strong);
  font-size: .6875rem;
  transition: all var(--al-dur-base) var(--al-ease-out);
}
.al-steps-bar__item.is-active { color: var(--al-text-strong); }
.al-steps-bar__item.is-active .al-steps-bar__dot { background: var(--al-text-strong); border-color: var(--al-text-strong); color: var(--al-canvas); }
.al-steps-bar__item.is-done .al-steps-bar__dot { background: var(--al-success-500); border-color: var(--al-success-500); color: #fff; }

.al-fieldset { display: none; }
.al-fieldset.is-active { display: block; animation: al-fade-up var(--al-dur-slow) var(--al-ease-out) both; }
@keyframes al-fade-up { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }


/* ==========================================================================
   16. FIL D'ARIANE / PAGINATION
   ========================================================================== */
.al-breadcrumb {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--al-space-2);
  list-style: none; margin: 0; padding: 0;
  font-family: var(--al-font-mono); font-size: var(--al-fs-xs);
  color: var(--al-text-subtle); letter-spacing: .06em; text-transform: uppercase;
}
.al-breadcrumb li + li::before { content: "/"; margin-inline-end: var(--al-space-2); color: var(--al-text-subtle); }
.al-breadcrumb a:hover { color: var(--al-text-strong); }
.al-breadcrumb [aria-current="page"] { color: var(--al-text-strong); }

.al-pagination { display: flex; gap: var(--al-space-2); align-items: center; }
.al-pagination a, .al-pagination span {
  display: grid; place-items: center;
  inline-size: 42px; block-size: 42px;
  border: 1px solid var(--al-border);
  border-radius: 50%;
  font-size: var(--al-fs-sm);
  color: var(--al-text-muted);
  transition: all var(--al-dur-fast) var(--al-ease-out);
}
.al-pagination a:hover { border-color: var(--al-text-strong); color: var(--al-text-strong); }
.al-pagination .is-current { background: var(--al-text-strong); border-color: var(--al-text-strong); color: var(--al-canvas); }


/* ==========================================================================
   17. ALERTES
   ========================================================================== */
.al-alert {
  display: flex; gap: var(--al-space-3);
  padding: var(--al-space-4) var(--al-space-5);
  border: 1px solid var(--al-border);
  border-inline-start: 3px solid var(--al-text-subtle);
  border-radius: var(--al-radius-sm);
  background: var(--al-surface-sunken);
  font-size: var(--al-fs-sm);
  color: var(--al-text);
}
.al-alert--success { border-inline-start-color: var(--al-success-500); }
.al-alert--warning { border-inline-start-color: var(--al-warning-500); }
.al-alert--danger  { border-inline-start-color: var(--al-danger-500); }
.al-alert__icon { flex: none; font-size: 1.125rem; line-height: 1.4; }


/* ==========================================================================
   18. PIED DE PAGE
   ========================================================================== */
/* Pas de fond propre : le pied de page repose sur la grille. Le filet et
   ses reperes qui l'ouvrent viennent des regles d'atelier (al-theme.css). */
.al-footer {
  color: var(--al-text-muted);
  padding-block: var(--al-space-11) var(--al-space-6);
}
.al-footer h2, .al-footer h3, .al-footer h4 { color: var(--al-text-strong); }
.al-footer a { color: var(--al-text-muted); transition: color var(--al-dur-fast) linear; }
.al-footer a:hover { color: var(--al-text-strong); }
.al-footer__title {
  font-family: var(--al-font-mono);
  font-size: var(--al-fs-xs);
  letter-spacing: var(--al-ls-eyebrow);
  text-transform: uppercase;
  color: var(--al-text-subtle);
  margin-bottom: var(--al-space-5);
}
.al-footer__list { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--al-space-3); font-size: var(--al-fs-sm); }
.al-footer__wordmark {
  font-family: var(--al-font-display);
  font-weight: var(--al-fw-black);
  font-size: clamp(3.5rem, 15vw, 13rem);
  line-height: .8;
  letter-spacing: -0.05em;
  /* Une teinte opaque, et non translucide : les lettres resserrees se
     chevauchent (les deux « s »), et une couleur transparente s'y
     doublait, laissant une couture visible. Meme rendu : 7 % du texte
     sur le fond. */
  color: color-mix(in srgb, var(--al-text-strong) 7%, var(--al-canvas));
  margin: var(--al-space-9) 0 var(--al-space-6);
  user-select: none;
  text-align: center;
}
.al-footer__bottom {
  display: flex; flex-wrap: wrap; gap: var(--al-space-4);
  align-items: center; justify-content: space-between;
  padding-block-start: var(--al-space-5);
  border-top: 1px solid var(--al-border);
  font-size: var(--al-fs-xs);
  color: var(--al-text-subtle);
}
.al-social { display: flex; gap: var(--al-space-2); list-style: none; margin: 0; padding: 0; }
.al-social a {
  display: grid; place-items: center;
  inline-size: 40px; block-size: 40px;
  border: 1px solid var(--al-border-strong);
  border-radius: 50%;
  background: var(--al-canvas);
  transition: all var(--al-dur-base) var(--al-ease-out);
}
.al-social a:hover { background: var(--al-text-strong); color: var(--al-canvas); border-color: var(--al-text-strong); transform: translateY(-2px); }


/* ==========================================================================
   19. REVEAL & CURSEUR
   ========================================================================== */
.al-reveal {
  opacity: 0;
  transform: translateY(24px);
  transition: opacity var(--al-dur-reveal) var(--al-ease-out),
              transform var(--al-dur-reveal) var(--al-ease-out-expo);
  transition-delay: var(--al-delay, 0ms);
}
.al-reveal.is-visible { opacity: 1; transform: none; }
.al-reveal--left  { transform: translateX(-28px); }
.al-reveal--right { transform: translateX(28px); }
.al-reveal--zoom  { transform: scale(.96); }

/* Variante « rideau ».
   Le `clip-path` est pose sur l'ENFANT, jamais sur l'element observe :
   `IntersectionObserver` tient compte du rognage. Un element qui se masque
   lui-meme a donc un `intersectionRect` nul, ne declenche jamais son propre
   observateur, et reste invisible pour toujours. */
.al-reveal--mask { opacity: 1; transform: none; clip-path: none; }
.al-reveal--mask > * {
  clip-path: inset(0 0 100% 0);
  transition: clip-path var(--al-dur-reveal) var(--al-ease-out-expo);
  transition-delay: var(--al-delay, 0ms);
}
.al-reveal--mask.is-visible > * { clip-path: inset(0 0 0 0); }

/* --------------------------------------------------------------------------
   Curseur suiveur (desactive au toucher)

   Deux elements distincts qui se superposent et suivent la meme position :

     .al-cursor        le disque, en `mix-blend-mode: difference`
     .al-cursor-label  le libelle, en fusion normale

   Pourquoi deux elements plutot qu'un parent et son enfant ? Parce que le
   disque est deplace par un `transform` : celui-ci cree un contexte
   d'empilement pour ses DESCENDANTS. Un libelle place a l'interieur serait
   donc fusionne avec le disque au lieu de rester lisible, et un
   `mix-blend-mode` pose sur un enfant ne fusionnerait qu'avec le disque, pas
   avec la page. En les gardant freres, chacun conserve son mode.

   La fusion par difference redonne la lecture par superposition : la ou le
   disque recouvre un element, les couleurs se soustraient au lieu de le
   masquer. Sur les fonds sombres du site, la difference avec l'encre
   (#0b0d11) restitue quasiment la teinte declaree ; sur un fond clair elle
   s'inverse, ce qui est precisement ce qui garde le contenu lisible.

   Le libelle, lui, n'est jamais fusionne : sa couleur reste exactement celle
   qu'impose la paire.

     fond #e4368c (magenta)  ->  texte #fbe824
     fond #1b98d6 (azur)     ->  texte #f4f6f9
     fond #fbe824 (solaire)  ->  texte #0b0d11

   Purement decoratif (`aria-hidden`, `pointer-events: none`) : ce que le
   curseur affiche est toujours porte aussi par l'element survole.
   -------------------------------------------------------------------------- */
.al-cursor,
.al-cursor-label {
  --al-cursor-bg: #e4368c;
  --al-cursor-fg: #fbe824;
  --al-cursor-size: 12px;

  position: fixed;
  inset-block-start: 0;
  inset-inline-start: 0;
  inline-size: var(--al-cursor-size);
  block-size: var(--al-cursor-size);
  pointer-events: none;
  opacity: 0;
  transform: translate(-50%, -50%);
  transition:
    inline-size var(--al-dur-base) var(--al-ease-spring),
    block-size var(--al-dur-base) var(--al-ease-spring),
    background-color var(--al-dur-base) var(--al-ease-out),
    opacity var(--al-dur-base) linear;
}

.al-cursor {
  z-index: var(--al-z-cursor);
  border-radius: 50%;
  background: var(--al-cursor-bg);
  mix-blend-mode: difference;
}

.al-cursor-label {
  z-index: calc(var(--al-z-cursor) + 1);
  display: grid;
  place-items: center;
}

.al-cursor.is-active,
.al-cursor-label.is-active { opacity: 1; }

/* Variantes de fond : chaque paire fond / texte est figee */
.al-cursor--magenta { --al-cursor-bg: #e4368c; --al-cursor-fg: #fbe824; }
.al-cursor--azur    { --al-cursor-bg: #1b98d6; --al-cursor-fg: #f4f6f9; }
.al-cursor--solaire { --al-cursor-bg: #fbe824; --al-cursor-fg: #0b0d11; }

/* Survol d'un controle : le disque grossit, sans libelle */
.al-cursor.is-hover,
.al-cursor-label.is-hover { --al-cursor-size: 46px; }

/* Survol d'une grande surface : le disque s'ouvre et porte son libelle */
.al-cursor.has-label,
.al-cursor-label.has-label { --al-cursor-size: 116px; }

.al-cursor-label__text {
  max-inline-size: 88px;
  color: var(--al-cursor-fg);
  font-family: var(--al-font-display);
  font-size: 0.8125rem;
  font-weight: var(--al-fw-bold);
  line-height: 1.15;
  letter-spacing: -0.01em;
  text-align: center;
  text-wrap: balance;
  opacity: 0;
  transform: scale(.8);
  transition: opacity var(--al-dur-fast) linear, transform var(--al-dur-base) var(--al-ease-spring);
}
.al-cursor-label.has-label .al-cursor-label__text { opacity: 1; transform: scale(1); }

/* Le curseur natif n'est masque que lorsque le suiveur est reellement actif */
body.al-has-cursor,
body.al-has-cursor a,
body.al-has-cursor button { cursor: none; }

/* Le suiveur n'existe que si une souris existe. La question n'est PAS posee a
   une requete media : `pointer`, `hover` et meme `any-pointer` se trompent sur
   les portables a ecran tactile, ou Windows peut annoncer le tactile comme
   pointeur principal alors qu'une souris est branchee, et le curseur
   disparaissait alors sur des machines parfaitement equipees.
   `al-ui.js` pose `al-pointer-fine` sur <html> : d'abord d'apres la requete
   media, puis corrige definitivement par un deplacement de souris avere. */
.al-cursor,
.al-cursor-label { display: none; }
.al-pointer-fine .al-cursor { display: block; }
.al-pointer-fine .al-cursor-label { display: grid; }
@media (prefers-reduced-motion: reduce) {
  .al-cursor,
  .al-cursor-label { display: none; }
  body.al-has-cursor,
  body.al-has-cursor a,
  body.al-has-cursor button { cursor: auto; }
}


/* ==========================================================================
   20. UTILITAIRES MEDIA
   ========================================================================== */
.al-media { position: relative; overflow: hidden; border-radius: var(--al-radius-lg); background: var(--al-surface-sunken); }
.al-media > img, .al-media > video { inline-size: 100%; block-size: 100%; object-fit: cover; }
.al-ratio-1  { aspect-ratio: 1 / 1; }
.al-ratio-43 { aspect-ratio: 4 / 3; }
.al-ratio-32 { aspect-ratio: 3 / 2; }
.al-ratio-169{ aspect-ratio: 16 / 9; }
.al-ratio-34 { aspect-ratio: 3 / 4; }
.al-ratio-219{ aspect-ratio: 21 / 9; }

.al-sticky { position: sticky; inset-block-start: calc(var(--al-navbar-h) + var(--al-space-5)); }
.al-round-lg { border-radius: var(--al-radius-lg); overflow: hidden; }
.al-round-xl { border-radius: var(--al-radius-xl); overflow: hidden; }
.al-border   { border: 1px solid var(--al-border); }
.al-border-t { border-top: 1px solid var(--al-border); }
.al-shadow-lg { box-shadow: var(--al-shadow-lg); }


/* ==========================================================================
   21. MESSAGES FLASH (surcouche)
   Posés hors du flux : la plupart des pages ouvrent sur un héros plein écran
   qu'un bandeau décalerait sous la barre de navigation fixe.
   ========================================================================== */
.al-toast-zone {
  position: fixed;
  inset-block-start: calc(var(--al-navbar-h) + var(--al-space-3));
  inset-inline-end: var(--al-gutter);
  z-index: var(--al-z-toast);
  display: flex;
  flex-direction: column;
  gap: var(--al-space-3);
  inline-size: min(420px, calc(100vw - 2 * var(--al-gutter)));
  pointer-events: none;
}
.al-toast-zone:empty { display: none; }
.al-toast-zone > * { pointer-events: auto; }

.al-toast-zone .al-alert {
  background: var(--al-surface);
  box-shadow: var(--al-shadow-lg);
  animation: al-toast-in var(--al-dur-slow) var(--al-ease-out-expo) both;
}
@keyframes al-toast-in {
  from { opacity: 0; transform: translateY(-10px) scale(.98); }
  to   { opacity: 1; transform: none; }
}


/* ==========================================================================
   22. ETUDE DE CAS
   --------------------------------------------------------------------------
   Construite comme une page projet Behance : un en-tete court (titre,
   auteur, domaines), puis le projet en une seule colonne ou visuels et
   textes s'empilent bord a bord, sans cadre ni marge, avec une barre
   d'actions qui suit la lecture. Viennent ensuite une cloture centree,
   la fiche du projet et les autres realisations.

   La colonne est un groupe de pieces (famille 37) : chaque module trace
   son bord haut et son bord gauche, la colonne le bord droit et le bas,
   et le calage (al-ui.js) ramene chaque hauteur a un multiple du pas.
   ========================================================================== */

/* Sortie de conteneur : un bloc qui occupe toute la largeur de la fenetre */
.al-bleed {
  inline-size: 100vw;
  margin-inline: calc(50% - 50vw);
}

/* --------------------------------------------------------------------------
   En-tete : titre, auteur, actions
   -------------------------------------------------------------------------- */
.al-case-head { padding-block: calc(var(--al-navbar-h) + var(--al-space-7)) var(--al-space-7); }
.al-case-head__grid { display: grid; gap: var(--al-space-5); align-items: end; }
@media (min-width: 992px) {
  .al-case-head__grid { grid-template-columns: minmax(0, 1fr) auto; }
}
.al-case-head__title { margin: 0 0 var(--al-space-4); max-inline-size: 24ch; text-wrap: balance; }

/* Apercu d'un projet non publie : un bandeau solaire, impossible a manquer. */
.al-case-apercu {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--al-space-3) var(--al-space-4);
  margin: 0 0 var(--al-space-6);
  padding: var(--al-space-3) var(--al-space-4);
  background: var(--al-solaire-500);
  color: var(--al-ink-950);
  font-size: var(--al-fs-sm);
}
.al-case-apercu span { flex: 1; min-inline-size: 16rem; }
.al-case-apercu .al-btn { --bs-btn-color: var(--al-ink-950); color: var(--al-ink-950); border-color: var(--al-ink-950); background: transparent; }

/* L'auteur, comme sous un titre Behance : un avatar rond et deux lignes. */
.al-case-owner { display: flex; align-items: center; gap: var(--al-space-3); margin: 0; }
.al-case-owner__avatar {
  flex: none;
  inline-size: 40px;
  block-size: 40px;
  padding: 8px;
  border-radius: 50%;
  /* Le fond du site : le monogramme change de version avec le theme. */
  background: var(--al-canvas);
  box-shadow: 0 0 0 1px var(--al-rule);
}
.al-case-owner__name {
  display: block;
  font-weight: var(--al-fw-semibold);
  color: var(--al-text-strong);
  text-decoration: none;
}
a.al-case-owner__name:hover { text-decoration: underline; text-underline-offset: 3px; }
.al-case-owner__sub { display: block; font-size: var(--al-fs-sm); color: var(--al-text-muted); }
.al-case-owner--lg .al-case-owner__avatar { inline-size: 56px; block-size: 56px; padding: 11px; }
.al-case-owner--lg .al-case-owner__name { font-size: var(--al-fs-h4); }

/* --------------------------------------------------------------------------
   Le projet : une seule colonne
   -------------------------------------------------------------------------- */
/* Deux colonnes sur telephone (les chiffres vont par paire), douze au-dela. */
.al-case-canvas {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  box-shadow: 1px 1px 0 0 var(--al-rule);
}
@media (min-width: 768px) {
  .al-case-canvas { grid-template-columns: repeat(12, minmax(0, 1fr)); }
}
.al-case-module {
  position: relative;
  grid-column: 1 / -1;
  min-inline-size: 0;
  margin: 0;
  padding: 1px 0 0 1px;
  background: var(--al-canvas);
  box-shadow: inset 1px 1px 0 0 var(--al-rule);
  /* Une piece qui porte un rapport (aspect-ratio) se cale sinon a gauche,
     et sa hauteur arrondie par le calage lui rendrait de la largeur. */
  justify-self: stretch;
}
@media (min-width: 768px) {
  .al-case-module { grid-column: span var(--al-shot-span, 12); }
}

/* Couverture : l'image a fond perdu. */
.al-case-module__img { display: block; inline-size: 100%; block-size: 100%; object-fit: contain; }

/* Texte : une mesure courte, centree dans la piece, avec de l'air. */
.al-case-module--text { padding: calc(var(--al-grid-size) * 2) var(--al-space-5); }
.al-case-text { max-inline-size: 42rem; margin-inline: auto; }
.al-case-text__lead {
  margin: 0;
  font-size: var(--al-fs-h4);
  line-height: var(--al-lh-snug);
  color: var(--al-text-strong);
  text-wrap: pretty;
}
.al-case-text__title {
  display: flex;
  align-items: baseline;
  gap: var(--al-space-3);
  margin: 0 0 var(--al-space-4);
  font-size: var(--al-fs-h3);
  font-weight: var(--al-fw-bold);
  letter-spacing: var(--al-ls-heading);
}
.al-case-text__title span {
  font-family: var(--al-font-mono);
  font-size: var(--al-fs-xs);
  font-weight: var(--al-fw-regular);
  letter-spacing: .08em;
  color: var(--al-text-subtle);
}
.al-case-text p {
  margin: 0;
  color: var(--al-text-muted);
  font-size: var(--al-fs-lead);
  font-weight: var(--al-fw-light);
  line-height: var(--al-lh-relaxed);
}

/* La phrase a retenir : grande, centree, sur un lavis de la teinte. */
.al-case-module--quote { display: grid; place-items: center; padding: calc(var(--al-grid-size) * 2) var(--al-space-5); }
.al-case-module--quote.al-tint {
  background: linear-gradient(rgb(var(--al-tint) / .12), rgb(var(--al-tint) / .12)), var(--al-canvas);
}
.al-case-quote { margin: 0; max-inline-size: 48rem; text-align: center; }
.al-case-quote p {
  margin: 0;
  font-size: clamp(1.5rem, 1rem + 1.8vw, 2.5rem);
  font-weight: var(--al-fw-bold);
  line-height: var(--al-lh-snug);
  letter-spacing: var(--al-ls-heading);
  color: var(--al-text-strong);
  text-wrap: balance;
}

/* Un chiffre : la valeur en haut, sa legende en bas. */
@media (max-width: 767.98px) {
  .al-case-module--stat { grid-column: span 1; }
}
.al-case-module--stat {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: var(--al-space-4);
  padding: var(--al-space-6) var(--al-space-5);
}
.al-case-stat__value {
  margin: 0;
  font-size: clamp(2.5rem, 1.5rem + 3vw, 4rem);
  font-weight: var(--al-fw-black);
  line-height: 1;
  letter-spacing: var(--al-ls-display);
  color: var(--al-text-strong);
}
.al-case-stat__value small { font-size: .5em; margin-inline-start: .1em; }
.al-case-stat__label { margin: 0; font-size: var(--al-fs-sm); color: var(--al-text-muted); }

/* Un visuel : bord a bord, sans rayon ni ombre. Chaque visuel est un
   bouton : il ouvre la visionneuse.
   Une capture se montre toujours en entier (contain). Le calage allonge la
   piece de quelques pixels pour la poser sur une ligne, et une image en
   `cover` s'agrandissait d'autant : ses bords etaient rognes. Les pixels
   en trop deviennent une fine marge, du fond de la page. */
.al-case-shot { display: grid; }
.al-case-shot__media {
  position: relative;
  display: block;
  inline-size: 100%;
  block-size: 100%;
  padding: 0;
  border: 0;
  overflow: hidden;
  background: var(--al-canvas);
  cursor: zoom-in;
}
.al-case-shot__media > img {
  display: block;
  inline-size: 100%;
  block-size: 100%;
  object-fit: contain;
}
.al-case-shot__media--device .al-stage { inline-size: 100%; block-size: 100%; }

/* La loupe : elle ne se montre qu'au survol, et jamais sans souris. */
.al-case-shot__loupe {
  position: absolute;
  inset-block-end: var(--al-space-4);
  inset-inline-end: var(--al-space-4);
  display: grid;
  place-items: center;
  inline-size: 40px;
  block-size: 40px;
  border-radius: 50%;
  color: #fff;
  background: var(--al-ink-950);
  box-shadow: 0 0 0 1px rgb(255 255 255 / .18);
  opacity: 0;
  translate: 0 6px;
  transition: opacity var(--al-dur-base) var(--al-ease-out), translate var(--al-dur-base) var(--al-ease-out);
}
.al-case-shot__media:hover .al-case-shot__loupe,
.al-case-shot__media:focus-visible .al-case-shot__loupe { opacity: 1; translate: 0 0; }

/* --------------------------------------------------------------------------
   Le defile de maquettes (projets web, mobile, UI/UX)
   Une bande de navigateurs et de telephones de meme hauteur, qui glisse de
   droite a gauche. Le script (al-ui.js, initDefile) place chaque maquette
   et la tourne selon sa distance au centre : celles des bords pivotent et
   reculent, comme posees sur un cylindre, puis s'effacent dans le fond.
   La hauteur de la bande est un multiple du pas : la piece tombe juste.
   -------------------------------------------------------------------------- */
.al-case-module--defile { overflow: hidden; }
.al-defile {
  /* Hauteur commune des maquettes, et ecart entre elles. */
  --al-defile-h: calc(var(--al-grid-size) * 7);
  --al-defile-gap: calc(var(--al-grid-size) * .8);
  position: relative;
  block-size: calc(var(--al-grid-size) * 10);
  overflow: hidden;
  perspective: 1600px;
  perspective-origin: 50% 45%;
  touch-action: pan-y;
  cursor: grab;
  user-select: none;
  -webkit-user-select: none;
  /* Les bords s'effacent dans le fond de la piece, quel que soit le theme. */
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 16%, #000 84%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 16%, #000 84%, transparent);
}
@media (max-width: 767.98px) {
  .al-defile {
    --al-defile-h: calc(var(--al-grid-size) * 6);
    block-size: calc(var(--al-grid-size) * 8);
    -webkit-mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
    mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
  }
}
.al-defile.is-tire { cursor: grabbing; }
.al-defile__piste {
  position: absolute;
  inset: 0;
  transform-style: preserve-3d;
}
.al-defile__item {
  position: absolute;
  inset-block-start: 50%;
  inset-inline-start: 0;
  margin: 0;
  translate: 0 -50%;
  will-change: transform, opacity;
  /* Les cadres d'appareil se mesurent en cqi : la maquette est leur
     conteneur, sinon ils se mesureraient sur la fenetre. */
  container-type: inline-size;
}
/* L'ecran prend les proportions reelles de la capture (--al-ecran), qui
   s'affiche donc en entier ; la largeur du cadre en decoule (--al-defile-k,
   calcule par le gabarit), pour une hauteur commune. La montre garde son
   cadran et sa largeur propre. */
.al-defile__item.is-ajuste { inline-size: calc(var(--al-defile-h) * var(--al-defile-k)); }
.al-defile__item.is-ajuste .al-device__screen { aspect-ratio: var(--al-ecran); }
.al-defile__item--montre   { inline-size: calc(var(--al-defile-h) * .667); }

.al-defile__bouton {
  display: block;
  inline-size: 100%;
  padding: 0;
  border: 0;
  background: none;
  cursor: inherit;
  -webkit-user-drag: none;
}
.al-defile__bouton img { pointer-events: none; -webkit-user-drag: none; }
.al-defile__bouton:focus-visible { outline: 2px solid var(--al-azur-500); outline-offset: 6px; border-radius: 4px; }

/* Sans script : une rangee qui defile au doigt, sans perspective. */
.al-defile:not(.is-pret) { overflow-x: auto; cursor: auto; }
.al-defile:not(.is-pret) .al-defile__piste {
  position: static;
  display: flex;
  align-items: center;
  gap: var(--al-defile-gap);
  block-size: 100%;
  padding-inline: var(--al-defile-gap);
}
.al-defile:not(.is-pret) .al-defile__item { position: static; flex: none; translate: none; }

/* --------------------------------------------------------------------------
   Cloture : l'appel rond, le titre, les domaines, la date
   -------------------------------------------------------------------------- */
.al-case-end { text-align: center; }
.al-case-end__inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--al-space-4);
  padding-block: calc(var(--al-grid-size) * 2);
}
.al-case-end__cta {
  display: grid;
  place-items: center;
  inline-size: calc(var(--al-grid-size) * 2);
  block-size: calc(var(--al-grid-size) * 2);
  border-radius: 50%;
  background: var(--al-solaire-500);
  color: var(--al-ink-950);
  font-size: 1.9rem;
  text-decoration: none;
  transition: scale var(--al-dur-base) var(--al-ease-out);
}
.al-case-end__cta:hover { scale: 1.06; color: var(--al-ink-950); }
.al-case-end__hint { margin: 0; font-size: var(--al-fs-sm); color: var(--al-text-muted); }
.al-case-end__title { margin: var(--al-space-3) 0 0; max-inline-size: 24ch; text-wrap: balance; }
.al-case-end__meta {
  margin: 0;
  font-family: var(--al-font-mono);
  font-size: var(--al-fs-xs);
  letter-spacing: .04em;
  color: var(--al-text-subtle);
}

/* --------------------------------------------------------------------------
   Fiche du projet : l'auteur et son equipe, puis les informations
   -------------------------------------------------------------------------- */
.al-site .al-cells.al-case-info > * {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--al-space-4);
  padding: var(--al-space-6) var(--al-space-5);
}
.al-case-info__key {
  margin: var(--al-space-2) 0 0;
  font-family: var(--al-font-mono);
  font-size: var(--al-fs-xs);
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--al-text-subtle);
}

.al-case-meta { display: grid; gap: 0; inline-size: 100%; margin: 0; }
.al-case-meta__row {
  display: grid;
  grid-template-columns: minmax(0, .8fr) minmax(0, 1.2fr);
  gap: var(--al-space-4);
  padding-block: var(--al-space-3);
  border-block-start: 1px solid var(--al-border);
}
.al-case-meta__row:last-child { border-block-end: 1px solid var(--al-border); }
.al-case-meta__key {
  margin: 0;
  font-family: var(--al-font-mono);
  font-size: var(--al-fs-xs);
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--al-text-subtle);
}
.al-case-meta__val { margin: 0; font-size: var(--al-fs-sm); color: var(--al-text); }

.al-case-credits {
  display: grid;
  gap: var(--al-space-4);
  inline-size: 100%;
  margin: 0;
  padding: 0;
  list-style: none;
}
@media (min-width: 576px) { .al-case-credits { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.al-case-credit { display: flex; align-items: center; gap: var(--al-space-3); }
.al-case-credit__avatar {
  display: grid;
  place-items: center;
  flex: none;
  inline-size: 40px;
  block-size: 40px;
  overflow: hidden;
  border-radius: 50%;
  background: var(--al-surface-sunken);
  font-size: var(--al-fs-xs);
  font-weight: var(--al-fw-bold);
  color: var(--al-text-strong);
}
.al-case-credit__avatar img { inline-size: 100%; block-size: 100%; object-fit: cover; }
.al-case-credit__name { font-size: var(--al-fs-sm); font-weight: var(--al-fw-semibold); color: var(--al-text-strong); }
.al-case-credit__role { font-size: var(--al-fs-xs); color: var(--al-text-muted); }


/* --------------------------------------------------------------------------
   La visionneuse : un <dialog> natif, construit par al-ui.js
   Echap ferme, les fleches parcourent, le fond ferme au clic. Sans
   JavaScript, rien ne s'ouvre et les visuels restent lisibles en place.
   -------------------------------------------------------------------------- */
.al-viewer {
  inline-size: 100%;
  max-inline-size: 100%;
  block-size: 100%;
  max-block-size: 100%;
  padding: 0;
  border: 0;
  background: transparent;
  color: #fff;
}
.al-viewer::backdrop { background: rgb(6 7 10 / .94); }
.al-viewer__scene {
  block-size: 100%;
  display: grid;
  grid-template-rows: auto minmax(0, 1fr) auto;
  gap: var(--al-space-4);
  padding: clamp(.75rem, 2vw, 1.5rem);
}
.al-viewer__bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--al-space-4);
  font-family: var(--al-font-mono);
  font-size: var(--al-fs-xs);
  letter-spacing: .08em;
  color: rgb(255 255 255 / .7);
}
.al-viewer__frame { position: relative; display: grid; place-items: center; min-block-size: 0; }
.al-viewer__frame img {
  max-inline-size: 100%;
  max-block-size: 100%;
  object-fit: contain;
  border-radius: var(--al-radius-md);
}
.al-viewer__legend {
  text-align: center;
  font-family: var(--al-font-mono);
  font-size: var(--al-fs-xs);
  color: rgb(255 255 255 / .62);
}
.al-viewer__btn {
  display: grid;
  place-items: center;
  inline-size: 44px;
  block-size: 44px;
  flex: none;
  padding: 0;
  border: 1px solid rgb(255 255 255 / .18);
  border-radius: 50%;
  background: rgb(255 255 255 / .06);
  color: #fff;
  font-size: 1.1rem;
  cursor: pointer;
  transition: background var(--al-dur-base) var(--al-ease-out), border-color var(--al-dur-base) var(--al-ease-out);
}
.al-viewer__btn:hover { background: rgb(255 255 255 / .14); border-color: rgb(255 255 255 / .34); }
.al-viewer__btn--prec,
.al-viewer__btn--suiv {
  position: absolute;
  inset-block-start: 50%;
  translate: 0 -50%;
}
.al-viewer__btn--prec { inset-inline-start: 0; }
.al-viewer__btn--suiv { inset-inline-end: 0; }
@media (max-width: 575.98px) {
  .al-viewer__btn--prec { inset-inline-start: -.25rem; }
  .al-viewer__btn--suiv { inset-inline-end: -.25rem; }
}


/* ==========================================================================
   23. LISTE EDITORIALE
   --------------------------------------------------------------------------
   Une liste numerotee de lignes cliquables, avec une vignette optionnelle
   qui suit le pointeur. Sert aujourd'hui de table des matieres a la page
   Services. Nee dans un heros d'accueil qui listait les realisations, et
   qui a ete abandonne : ses regles propres ont ete retirees, la liste reste.
   ========================================================================== */
/* --------------------------------------------------------------------------
   La liste
   -------------------------------------------------------------------------- */
.al-listing { display: flex; flex-direction: column; }
.al-listing__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--al-space-4);
  margin: 0 0 var(--al-space-2);
  padding-block-end: var(--al-space-3);
  border-block-end: 1px solid var(--al-border);
  font-family: var(--al-font-mono);
  font-size: var(--al-fs-eyebrow);
  letter-spacing: var(--al-ls-eyebrow);
  text-transform: uppercase;
  color: var(--al-text-subtle);
}

.al-listing__row {
  position: relative;
  display: grid;
  /* Quatre colonnes par defaut : numero, vignette, titre, queue. La vignette
     disparait des qu'une souris est confirmee, et la piste avec elle. */
  grid-template-columns: auto auto minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--al-space-4);
  padding-block: var(--al-space-4);
  border-block-end: 1px solid var(--al-border-subtle);
  color: inherit;
  text-decoration: none;
  transition: color var(--al-dur-base) var(--al-ease-out);
}
/* Le trait de survol se peint SOUS le texte sans z-index negatif : dans un
   heros en `isolation: isolate`, un `z-index: -1` passerait derriere le fond
   de section et disparaitrait. */
.al-listing__row::before {
  content: "";
  position: absolute;
  inset-inline-start: 0;
  inset-block-end: -1px;
  block-size: 1px;
  inline-size: 0;
  background: var(--al-spectre);
  transition: inline-size var(--al-dur-slow) var(--al-ease-out-expo);
}
.al-listing__row:hover::before,
.al-listing__row:focus-visible::before { inline-size: 100%; }
.al-listing__row:hover .al-listing__num { color: var(--al-text-strong); }

.al-listing__num {
  font-family: var(--al-font-mono);
  font-size: var(--al-fs-xs);
  color: var(--al-text-subtle);
  font-variant-numeric: tabular-nums;
}
.al-listing__name {
  min-inline-size: 0;
  font-family: var(--al-font-display);
  font-size: clamp(1.125rem, 1.6vw, 1.5rem);
  font-weight: var(--al-fw-bold);
  letter-spacing: var(--al-ls-heading);
  color: var(--al-text-strong);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.al-listing__tail {
  display: flex;
  align-items: center;
  gap: var(--al-space-4);
  font-family: var(--al-font-mono);
  font-size: var(--al-fs-xs);
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--al-text-muted);
}
.al-listing__cat { display: none; }
@media (min-width: 480px) { .al-listing__cat { display: inline; } }
.al-listing__year { font-variant-numeric: tabular-nums; }

/* Vignette de repli : elle porte l'information quand le survol n'existe pas
   (mobile, pointeur grossier, mouvement reduit). */
.al-listing__thumb {
  inline-size: 56px;
  aspect-ratio: 4 / 3;
  border-radius: var(--al-radius-xs);
  overflow: hidden;
  background: var(--al-surface-sunken);
  flex: none;
}
.al-listing__thumb img { inline-size: 100%; block-size: 100%; object-fit: cover; }
.al-pointer-fine .al-listing__thumb { display: none; }

.al-listing__more {
  display: inline-flex;
  align-items: center;
  gap: var(--al-space-3);
  margin-block-start: var(--al-space-5);
  font-family: var(--al-font-mono);
  font-size: var(--al-fs-xs);
  letter-spacing: var(--al-ls-eyebrow);
  text-transform: uppercase;
  color: var(--al-text-strong);
  text-decoration: none;
}
.al-listing__more i { transition: transform var(--al-dur-base) var(--al-ease-out-expo); }
.al-listing__more:hover i { transform: translateX(6px); }

/* --------------------------------------------------------------------------
   Vignette flottante, pilotee au pointeur
   -------------------------------------------------------------------------- */
.al-listing-preview {
  position: fixed;
  inset-block-start: 0;
  inset-inline-start: 0;
  z-index: calc(var(--al-z-cursor) - 10);
  inline-size: clamp(200px, 20vw, 300px);
  pointer-events: none;
  /* La position vient du JS via `transform`. L'ouverture est donc portee par
     un enfant : sinon chaque frame de suivi ecraserait la transition. */
}
.al-listing-preview__inner {
  aspect-ratio: 4 / 3;
  border-radius: var(--al-radius-md);
  overflow: hidden;
  box-shadow: var(--al-shadow-xl);
  opacity: 0;
  transform: scale(.86) rotate(-2deg);
  transition: opacity var(--al-dur-base) var(--al-ease-out),
              transform var(--al-dur-slow) var(--al-ease-out-expo);
}
.al-listing-preview.is-active .al-listing-preview__inner {
  opacity: 1;
  transform: scale(1) rotate(0deg);
}
.al-listing-preview img {
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
  display: block;
}
.al-listing-preview { display: none; }
.al-pointer-fine .al-listing-preview { display: block; }
@media (prefers-reduced-motion: reduce) {
  .al-listing-preview { display: none; }
}

/* ==========================================================================
   25. ILLUSTRATIONS DE METIER
   --------------------------------------------------------------------------
   Chaque metier est illustre par une petite scene d'interface, dessinee en
   HTML et CSS : panneaux de verre, lueur de la teinte du metier, poussiere
   d'etoiles, pastilles numerotees. Registre emprunte aux illustrations
   d'uxpeak, palette et sujets AssuLight.

   Geometrie : la scene mesure 22 x 16 em, et son corps de texte suit la
   largeur du conteneur (unites cqi). Tout est exprime en em : la scene se
   met a l'echelle d'un bloc, sans aucun point de rupture.

   Mouvement : des boucles lentes, suspendues hors ecran par le script
   (data-al-play). En mouvement reduit, l'etat de repos est une image
   complete : chaque boucle part d'un etat visible, jamais d'un etat vide.

   Pastilles : texte selon la regle du curseur. Azur sur #f4f6f9, magenta
   sur #fbe824, solaire sur #0b0d11.
   ========================================================================== */
.al-illu {
  --illu-rgb: var(--al-azur-500-rgb);
  --illu: var(--al-azur-300);
  --illu-on: #f4f6f9;

  position: relative;
  aspect-ratio: 4 / 3;
  display: grid;
  place-items: center;
  container-type: inline-size;
  overflow: hidden;
  isolation: isolate;
  color: rgb(var(--illu-ink));
}
.al-illu--magenta { --illu-rgb: var(--al-magenta-500-rgb); --illu: var(--al-magenta-300); --illu-on: #fbe824; }
.al-illu--solaire { --illu-rgb: var(--al-solaire-500-rgb); --illu: var(--al-solaire-300); --illu-on: #0b0d11; }

/* Les illustrations et les cartes a illustration suivent le theme. L'encre
   (traits, textes, etoiles, verre) est blanche en sombre et noire en clair ;
   les panneaux pleins (telephone, ecran, calques) passent du gris nuit au
   blanc ; les ombres s'allegent en clair (--illu-ombre multiplie leur
   opacite). Les reflets poses sur des surfaces colorees restent blancs. */
.al-illu,
.al-feature {
  --illu-ink: 255 255 255;
  --illu-ombre: 1;
  --illu-fond: #14161c;
  --illu-tel-a: #2a2f3a;
  --illu-tel-b: #111419;
  --illu-ecran: #0c0f14;
  --illu-calque-a: #1b1520;
  --illu-calque-b: #121218;
  --illu-pastille: rgb(18 21 28 / .82);
  --illu-notif-a: rgb(40 45 56 / .92);
  --illu-notif-b: rgb(20 23 30 / .92);
}
[data-bs-theme="light"] .al-illu,
[data-bs-theme="light"] .al-feature {
  --illu-ink: 11 13 17;
  --illu-ombre: .22;
  --illu-fond: #ffffff;
  --illu-tel-a: #ffffff;
  --illu-tel-b: #eef1f5;
  --illu-ecran: #f7f8fa;
  --illu-calque-a: #ffffff;
  --illu-calque-b: #f3f4f7;
  --illu-pastille: rgb(255 255 255 / .94);
  --illu-notif-a: rgb(255 255 255 / .97);
  --illu-notif-b: rgb(244 246 249 / .97);
}
/* Les teintes 300 se lisent sur fond sombre ; en clair il faut les 600-700. */
[data-bs-theme="light"] .al-illu           { --illu: var(--al-azur-600); }
[data-bs-theme="light"] .al-illu--magenta  { --illu: var(--al-magenta-600); }
[data-bs-theme="light"] .al-illu--solaire  { --illu: var(--al-solaire-700); }

/* Poussiere d'etoiles et lueur centrale. */
.al-illu::before,
.al-illu::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
}
.al-illu::before {
  background-image:
    radial-gradient(1px 1px at 12% 18%, rgb(var(--illu-ink) / .55), transparent),
    radial-gradient(1px 1px at 84% 12%, rgb(var(--illu-ink) / .4), transparent),
    radial-gradient(1.5px 1.5px at 70% 82%, rgb(var(--illu-ink) / .45), transparent),
    radial-gradient(1px 1px at 26% 76%, rgb(var(--illu-ink) / .35), transparent),
    radial-gradient(1px 1px at 92% 58%, rgb(var(--illu-ink) / .3), transparent),
    radial-gradient(1.5px 1.5px at 6% 52%, rgb(var(--illu-ink) / .35), transparent),
    radial-gradient(1px 1px at 48% 8%, rgb(var(--illu-ink) / .3), transparent);
  animation: al-illu-scintille 5s ease-in-out infinite alternate;
}
.al-illu::after {
  background: radial-gradient(46% 50% at 50% 46%, rgb(var(--illu-rgb) / .26), transparent 72%);
}

.al-illu__scene {
  position: relative;
  inline-size: 22em;
  block-size: 16em;
  font-size: 14px;
  font-size: 4.2cqi;
  line-height: 1.2;
}

/* -- Pieces communes ------------------------------------------------------
   Les pieces qui changent de corps de texte (pastilles, etiquettes) sont
   placees en pourcentages de la scene : en em, leur decalage suivrait leur
   propre corps et non celui de la scene. */
.al-illu__panel {
  position: absolute;
  border-radius: .9em;
  background: linear-gradient(160deg, rgb(var(--illu-ink) / .09), rgb(var(--illu-ink) / .025) 60%, rgb(var(--illu-ink) / .04));
  box-shadow:
    inset 0 0 0 1px rgb(var(--illu-ink) / .12),
    inset 0 1px 0 rgb(var(--illu-ink) / .1),
    0 1.6em 3em -1.2em rgb(0 0 0 / calc(.7 * var(--illu-ombre)));
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
}

.al-illu__line {
  display: block;
  inline-size: var(--w, 100%);
  block-size: .5em;
  border-radius: 1em;
  background: rgb(var(--illu-ink) / .16);
}
.al-illu__line--dim { block-size: .38em; background: rgb(var(--illu-ink) / .09); }
.al-illu__line--strong { background: rgb(var(--illu-ink) / .7); }
.al-illu__line--hue { background: linear-gradient(90deg, rgb(var(--illu-rgb)), rgb(var(--illu-rgb) / .45)); }

.al-illu__chip {
  position: absolute;
  z-index: 2;
  display: grid;
  place-items: center;
  inline-size: 1.55em;
  block-size: 1.55em;
  border-radius: 50%;
  background: rgb(var(--illu-rgb));
  box-shadow: 0 0 0 .22em rgb(var(--illu-rgb) / .25), 0 0 1.4em rgb(var(--illu-rgb) / .7);
  color: var(--illu-on);
  font-weight: var(--al-fw-bold);
  line-height: 1;
}
.al-illu__chip b { font-size: .78em; }
.al-illu__chip--sm {
  position: static;
  inline-size: 1.3em;
  block-size: 1.3em;
  font-size: .9em;
  box-shadow: 0 0 .8em rgb(var(--illu-rgb) / .6);
}

.al-illu__link {
  position: absolute;
  block-size: 1px;
  background: linear-gradient(90deg, rgb(var(--illu-rgb) / .9), rgb(var(--illu-ink) / .35));
  transform-origin: 0 50%;
}

.al-illu__pill {
  position: absolute;
  display: inline-flex;
  align-items: center;
  gap: .45em;
  padding: .38em .8em .38em .45em;
  border-radius: 2em;
  background: var(--illu-pastille);
  box-shadow: inset 0 0 0 1px rgb(var(--illu-ink) / .12), 0 1em 2em -1em rgb(0 0 0 / calc(.8 * var(--illu-ombre)));
  font-size: .62em;
  font-weight: var(--al-fw-semibold);
  white-space: nowrap;
  color: rgb(var(--illu-ink) / .86);
}
.al-illu__pill > .bi { color: var(--illu); font-size: 1.15em; margin-inline-start: .3em; }

/* -- Web : l'anatomie d'une page ----------------------------------------- */
.al-illu-web { inset: 1.9em auto auto 3.4em; inline-size: 13.6em; block-size: 12em; overflow: hidden; }
.al-illu-web__bar {
  display: flex;
  align-items: center;
  gap: .3em;
  block-size: 1.7em;
  padding-inline: .7em;
  border-block-end: 1px solid rgb(var(--illu-ink) / .08);
}
.al-illu-web__bar > i { inline-size: .42em; block-size: .42em; border-radius: 50%; background: rgb(var(--illu-ink) / .22); }
.al-illu-web__url {
  margin-inline-start: .5em;
  padding: .12em .7em;
  border-radius: 1em;
  background: rgb(var(--illu-ink) / .06);
  font-family: var(--al-font-mono);
  font-size: .5em;
  color: rgb(var(--illu-ink) / .5);
}
.al-illu-web__body { display: grid; gap: .55em; padding: 1.05em 1.1em; }
.al-illu-web__cta {
  inline-size: 4.6em;
  block-size: 1.35em;
  margin-block-start: .35em;
  border-radius: 1em;
  background: linear-gradient(90deg, rgb(var(--illu-rgb)), rgb(var(--illu-rgb) / .7));
  box-shadow: 0 .5em 1.4em -.3em rgb(var(--illu-rgb) / .7);
  animation: al-illu-web-clic 8s ease-in-out infinite;
}
.al-illu-web__tiles { display: grid; grid-template-columns: repeat(3, 1fr); gap: .5em; margin-block-start: .45em; }
.al-illu-web__tiles > i {
  block-size: 2.5em;
  border-radius: .45em;
  background: linear-gradient(110deg, rgb(var(--illu-ink) / .06) 30%, rgb(var(--illu-ink) / .16) 50%, rgb(var(--illu-ink) / .06) 70%) 0 0 / 300% 100%;
  animation: al-illu-reflet 2.8s linear infinite;
}

.al-illu-web__n1 { inset: 25.8% auto auto 3.4%; }
.al-illu-web__l1 { inset: 4.9em auto auto 2.3em; inline-size: 2.6em; }
.al-illu-web__n2 { inset: 50% auto auto 87.3%; }
.al-illu-web__l2 {
  inset: 8.78em auto auto 9.3em;
  inline-size: 9.9em;
  transform-origin: 100% 50%;
  background: linear-gradient(270deg, rgb(var(--illu-rgb) / .9), rgb(var(--illu-ink) / .35));
}
.al-illu-web__n3 { inset: 69.7% auto auto 3.4%; }
.al-illu-web__l3 { inset: 11.92em auto auto 2.3em; inline-size: 2.3em; }

.al-illu-web__n1, .al-illu-web__l1 { animation: al-illu-note 8s var(--al-ease-out-expo) infinite; }
.al-illu-web__n2, .al-illu-web__l2 { animation: al-illu-note 8s .35s var(--al-ease-out-expo) infinite; }
.al-illu-web__n3, .al-illu-web__l3 { animation: al-illu-note 8s .7s var(--al-ease-out-expo) infinite; }

.al-illu-web__score {
  inset: .6em auto auto 15.6em;
  inline-size: 5.4em;
  display: grid;
  justify-items: center;
  gap: .15em;
  padding: .7em .4em .6em;
}
.al-illu-web__score svg { inline-size: 2.6em; block-size: 2.6em; rotate: -90deg; }
.al-illu-web__score circle { fill: none; stroke: rgb(var(--illu-ink) / .1); stroke-width: 3; }
.al-illu-web__score .al-illu-web__ring {
  stroke: rgb(var(--illu-rgb));
  stroke-linecap: round;
  stroke-dasharray: 100;
  stroke-dashoffset: 0;
  filter: drop-shadow(0 0 3px rgb(var(--illu-rgb) / .8));
  animation: al-illu-web-anneau 8s var(--al-ease-out) infinite;
}
.al-illu-web__score b {
  margin-block-start: -2.15em;
  margin-block-end: .75em;
  font-size: .8em;
  font-weight: var(--al-fw-bold);
}
.al-illu-web__score small { font-family: var(--al-font-mono); font-size: .48em; letter-spacing: .12em; text-transform: uppercase; color: rgb(var(--illu-ink) / .5); }

.al-illu-web__pointer {
  position: absolute;
  inset: 58.1% auto auto 32.7%;
  z-index: 3;
  font-size: 1.05em;
  color: rgb(var(--illu-ink));
  filter: drop-shadow(0 .2em .4em rgb(0 0 0 / calc(.6 * var(--illu-ombre))));
  animation: al-illu-web-pointeur 8s var(--al-ease-in-out) infinite;
}
.al-illu-web__pointer .bi { display: block; }

@keyframes al-illu-note {
  0%, 8%    { opacity: 0; transform: scale(.4); }
  16%, 84%  { opacity: 1; transform: scale(1); }
  94%, 100% { opacity: 0; transform: scale(1); }
}
@keyframes al-illu-web-anneau {
  0%, 30%   { stroke-dashoffset: 100; }
  62%, 90%  { stroke-dashoffset: 0; }
  100%      { stroke-dashoffset: 0; }
}
@keyframes al-illu-web-pointeur {
  0%, 30%   { translate: 5em 3em; opacity: 0; }
  38%       { opacity: 1; }
  52%, 58%  { translate: 0 0; opacity: 1; }
  74%       { translate: 0 0; opacity: 1; }
  86%, 100% { translate: 5em 3em; opacity: 0; }
}
@keyframes al-illu-web-clic {
  0%, 54%, 62%, 100% { transform: scale(1); }
  57%                { transform: scale(.92); }
}

/* -- Mobile : une application qui vit ------------------------------------ */
.al-illu-mobile__ghost {
  position: absolute;
  inset: 2.3em auto auto 5.3em;
  inline-size: 6.4em;
  block-size: 12.8em;
  border-radius: 1.2em;
  border: 1px dashed rgb(var(--illu-ink) / .2);
  rotate: -11deg;
}
.al-illu-mobile__phone {
  position: absolute;
  inset: 1.2em auto auto 8.4em;
  inline-size: 7em;
  block-size: 14.2em;
  padding: .32em;
  border-radius: 1.45em;
  background: linear-gradient(160deg, var(--illu-tel-a), var(--illu-tel-b));
  box-shadow:
    inset 0 0 0 1px rgb(var(--illu-ink) / .14),
    0 2em 3em -1.4em rgb(0 0 0 / calc(.85 * var(--illu-ombre))),
    0 0 3em -.6em rgb(var(--illu-rgb) / .35);
}
.al-illu-mobile__screen {
  position: relative;
  block-size: 100%;
  display: grid;
  align-content: start;
  gap: .5em;
  padding: 1.1em .6em 0;
  border-radius: 1.15em;
  background: var(--illu-ecran);
  overflow: hidden;
}
.al-illu-mobile__screen::before {
  content: "";
  position: absolute;
  inset: .35em auto auto 50%;
  translate: -50% 0;
  inline-size: 2.2em;
  block-size: .45em;
  border-radius: 1em;
  background: #000;
}
.al-illu-mobile__head { display: flex; align-items: center; gap: .4em; }
.al-illu-mobile__head > i { inline-size: 1em; block-size: 1em; border-radius: 50%; background: rgb(var(--illu-rgb)); }
.al-illu-mobile__hero {
  block-size: 3.4em;
  border-radius: .6em;
  background:
    radial-gradient(80% 90% at 85% 10%, rgb(255 255 255 / .35), transparent 60%),
    linear-gradient(140deg, rgb(var(--illu-rgb)), rgb(var(--al-magenta-500-rgb) / .8));
}
.al-illu-mobile__row { display: flex; align-items: center; gap: .45em; }
.al-illu-mobile__row > i { flex: none; inline-size: 1.25em; block-size: 1.25em; border-radius: .35em; background: rgb(var(--illu-ink) / .1); }
.al-illu-mobile__row > span { flex: 1; display: grid; gap: .25em; }
.al-illu-mobile__tabs {
  position: absolute;
  inset: auto 0 0;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  place-items: center;
  block-size: 1.9em;
  background: rgb(var(--illu-ink) / .04);
  border-block-start: 1px solid rgb(var(--illu-ink) / .07);
  font-size: .95em;
  color: rgb(var(--illu-ink) / .38);
}
.al-illu-mobile__tabs > .bi { font-size: .7em; }
.al-illu-mobile__tab-mark {
  position: absolute;
  inset: .2em auto auto 0;
  inline-size: 33.33%;
  display: grid;
  place-items: center;
  animation: al-illu-mobile-onglet 9s var(--al-ease-in-out) infinite;
}
.al-illu-mobile__tab-mark::before {
  content: "";
  inline-size: 1.1em;
  block-size: .16em;
  border-radius: 1em;
  background: rgb(var(--illu-rgb));
  box-shadow: 0 0 .6em rgb(var(--illu-rgb));
}

.al-illu-mobile__notif {
  inset: 3.1em auto auto 5.1em;
  z-index: 2;
  inline-size: 13.4em;
  display: flex;
  align-items: center;
  gap: .55em;
  padding: .55em .7em;
  border-radius: .85em;
  background: linear-gradient(160deg, var(--illu-notif-a), var(--illu-notif-b));
  animation: al-illu-mobile-notif 9s var(--al-ease-out-expo) infinite;
}
.al-illu-mobile__app {
  flex: none;
  display: grid;
  place-items: center;
  inline-size: 1.7em;
  block-size: 1.7em;
  border-radius: .45em;
  background: rgb(var(--illu-rgb));
  color: var(--illu-on);
  font-size: .95em;
}
.al-illu-mobile__app .bi { font-size: .75em; }
.al-illu-mobile__notif-text { flex: 1; display: grid; gap: .3em; min-inline-size: 0; }
.al-illu-mobile__notif-text b { font-size: .56em; font-weight: var(--al-fw-semibold); white-space: nowrap; }
.al-illu-mobile__notif small { align-self: start; font-size: .45em; color: rgb(var(--illu-ink) / .45); }

.al-illu-mobile__os { inset: 60% auto auto 62%; z-index: 2; }
.al-illu-mobile__offline { inset: 76% auto auto 9%; z-index: 2; }

@keyframes al-illu-mobile-notif {
  0%, 6%    { opacity: 0; translate: 0 -1.6em; scale: .96; }
  14%, 62%  { opacity: 1; translate: 0 0; scale: 1; }
  72%, 100% { opacity: 0; translate: 0 -1.6em; scale: .96; }
}
@keyframes al-illu-mobile-onglet {
  0%, 26%   { translate: 0 0; }
  34%, 60%  { translate: 100% 0; }
  68%, 92%  { translate: 200% 0; }
  100%      { translate: 0 0; }
}

/* -- Design : avant, apres ----------------------------------------------- */
.al-illu-design {
  --pos: 50%;
  inset: 2.2em auto auto 1.6em;
  inline-size: 17.2em;
  block-size: 11.6em;
  overflow: hidden;
}
.al-illu-design__layer {
  position: absolute;
  inset: 0;
  display: grid;
  grid-template-columns: 1fr;
  align-content: start;
  gap: .55em;
  padding: 2.3em 1.4em 1em;
}
.al-illu-design__head {
  position: absolute;
  inset: 0 0 auto;
  block-size: 1.6em;
}
.al-illu-design__media { block-size: 3.6em; border-radius: .5em; margin-block-end: .25em; }
.al-illu-design__btn { inline-size: 5em; block-size: 1.4em; margin-block-start: .35em; border-radius: 1em; }

/* Le filaire : pointilles, croix de place tenante, aucun parti pris. */
.al-illu-design__layer--avant .al-illu-design__head { border-block-end: 1px dashed rgb(var(--illu-ink) / .2); }
.al-illu-design__layer--avant .al-illu-design__media {
  border: 1px dashed rgb(var(--illu-ink) / .25);
  background:
    linear-gradient(to top right, transparent calc(50% - .5px), rgb(var(--illu-ink) / .16) 50%, transparent calc(50% + .5px)),
    linear-gradient(to bottom right, transparent calc(50% - .5px), rgb(var(--illu-ink) / .16) 50%, transparent calc(50% + .5px));
}
.al-illu-design__layer--avant .al-illu__line { background: rgb(var(--illu-ink) / .1); }
.al-illu-design__layer--avant .al-illu-design__btn { border: 1px dashed rgb(var(--illu-ink) / .3); }

/* La version finie : la meme grille, habillee. */
.al-illu-design__layer--apres {
  background: linear-gradient(160deg, var(--illu-calque-a), var(--illu-calque-b));
  clip-path: inset(0 0 0 var(--pos));
  animation: al-illu-design-volet 7s var(--al-ease-in-out) infinite alternate;
}
.al-illu-design__layer--apres .al-illu-design__head {
  background: rgb(var(--illu-ink) / .04);
  border-block-end: 1px solid rgb(var(--illu-ink) / .08);
}
.al-illu-design__layer--apres .al-illu-design__media {
  background:
    radial-gradient(60% 90% at 80% 0%, rgb(255 255 255 / .35), transparent 60%),
    linear-gradient(120deg, rgb(var(--illu-rgb)), var(--al-azur-500));
}
.al-illu-design__layer--apres .al-illu-design__btn {
  background: rgb(var(--illu-rgb));
  box-shadow: 0 .4em 1.2em -.2em rgb(var(--illu-rgb) / .8);
}

.al-illu-design__tag {
  position: absolute;
  inset-block-start: .35em;
  z-index: 2;
  padding: .25em .6em;
  border-radius: .3em;
  font-family: var(--al-font-mono);
  font-size: .46em;
  font-weight: var(--al-fw-bold);
  letter-spacing: .16em;
  text-transform: uppercase;
}
.al-illu-design__tag--avant { inset-inline-start: .9em; box-shadow: inset 0 0 0 1px rgb(var(--illu-ink) / .22); color: rgb(var(--illu-ink) / .6); }
.al-illu-design__tag--apres { inset-inline-end: .9em; background: rgb(var(--illu-rgb)); color: var(--illu-on); }

.al-illu-design__split {
  position: absolute;
  inset-block: 0;
  inset-inline-start: var(--pos);
  z-index: 3;
  inline-size: 2px;
  margin-inline-start: -1px;
  background: linear-gradient(180deg, transparent, rgb(var(--illu-ink)) 20%, rgb(var(--illu-ink)) 80%, transparent);
  box-shadow: 0 0 1em rgb(var(--illu-rgb));
  animation: al-illu-design-trait 7s var(--al-ease-in-out) infinite alternate;
}
.al-illu-design__handle {
  position: absolute;
  inset: 50% auto auto 50%;
  translate: -50% -50%;
  inline-size: 1.5em;
  block-size: 1.5em;
  border-radius: 50%;
  background: var(--illu-fond);
  box-shadow: inset 0 0 0 2px rgb(var(--illu-ink)), 0 0 1.2em rgb(var(--illu-rgb) / .9);
}
.al-illu-design__handle::after {
  content: "";
  position: absolute;
  inset: 50% auto auto 50%;
  translate: -50% -50%;
  inline-size: .35em;
  block-size: .35em;
  border-radius: 50%;
  background: rgb(var(--illu-ink));
}

.al-illu-design__type {
  inset: 11em auto auto 16.4em;
  z-index: 4;
  display: grid;
  justify-items: center;
  gap: .3em;
  padding: .45em .8em .6em;
  rotate: 6deg;
  animation: al-illu-flotte 6s ease-in-out infinite;
}
.al-illu-design__type b {
  font-family: var(--al-font-display);
  font-size: 1.5em;
  font-weight: var(--al-fw-black);
  line-height: 1;
  letter-spacing: -.04em;
}
.al-illu-design__type span { display: flex; gap: .22em; }
.al-illu-design__type i { inline-size: .55em; block-size: .55em; border-radius: 50%; }

/* Deux animations synchrones plutot qu'une propriete personnalisee animee :
   @property n'est pas encore partout, les pourcentages de clip-path si. */
@keyframes al-illu-design-volet {
  0%, 12%   { clip-path: inset(0 0 0 72%); }
  88%, 100% { clip-path: inset(0 0 0 26%); }
}
@keyframes al-illu-design-trait {
  0%, 12%   { inset-inline-start: 72%; }
  88%, 100% { inset-inline-start: 26%; }
}

/* -- Motion : l'image cle ------------------------------------------------ */
.al-illu-motion__rays {
  position: absolute;
  inset: -.6em auto auto 4.5em;
  inline-size: 13em;
  block-size: 13em;
  border-radius: 50%;
  background: repeating-conic-gradient(from 0deg, rgb(var(--illu-rgb) / .3) 0deg 3deg, transparent 3deg 15deg);
  -webkit-mask-image: radial-gradient(circle, #000 18%, transparent 68%);
  mask-image: radial-gradient(circle, #000 18%, transparent 68%);
  animation: al-illu-tourne 40s linear infinite;
}
.al-illu-motion__medal {
  position: absolute;
  inset: 3.35em auto auto 8.4em;
  z-index: 1;
  display: grid;
  place-items: center;
  inline-size: 5.2em;
  block-size: 5.2em;
  border-radius: 50%;
  background:
    radial-gradient(circle at 34% 28%, rgb(255 255 255 / .75), transparent 42%),
    radial-gradient(circle, rgb(var(--illu-rgb)) 55%, rgb(var(--illu-rgb) / .7));
  box-shadow:
    0 0 0 .35em rgb(var(--illu-rgb) / .18),
    0 0 0 .75em rgb(var(--illu-rgb) / .07),
    0 0 3em rgb(var(--illu-rgb) / .65);
  color: var(--illu-on);
  font-size: 1em;
  animation: al-illu-motion-temps 4s var(--al-ease-out) infinite;
}
.al-illu-motion__medal .bi { font-size: 2.3em; margin-inline-start: .12em; line-height: 1; }

.al-illu-motion__spark {
  position: absolute;
  inset: var(--y) auto auto var(--x);
  inline-size: .9em;
  block-size: .9em;
  background: rgb(var(--illu-ink));
  clip-path: polygon(50% 0, 60% 40%, 100% 50%, 60% 60%, 50% 100%, 40% 60%, 0 50%, 40% 40%);
  filter: drop-shadow(0 0 4px rgb(var(--illu-rgb)));
  animation: al-illu-etincelle 3.2s var(--d, 0s) ease-in-out infinite;
}

.al-illu-motion__timeline {
  inset: 12.1em auto auto 2.8em;
  inline-size: 16.4em;
  block-size: 2.7em;
  padding: 0 1.1em;
  display: grid;
  align-items: center;
}
.al-illu-motion__track {
  position: relative;
  block-size: 1.3em;
  background:
    linear-gradient(rgb(var(--illu-ink) / .14), rgb(var(--illu-ink) / .14)) center / 100% 1px no-repeat,
    repeating-linear-gradient(90deg, rgb(var(--illu-ink) / .16) 0 1px, transparent 1px 1.1em) 0 0 / 100% .35em no-repeat;
}
.al-illu-motion__track > i {
  position: absolute;
  inset: 50% auto auto var(--k);
  inline-size: .62em;
  block-size: .62em;
  translate: -50% -50%;
  rotate: 45deg;
  border-radius: .1em;
  background: rgb(var(--illu-rgb));
  box-shadow: 0 0 .6em rgb(var(--illu-rgb) / .8);
}
.al-illu-motion__head {
  position: absolute;
  inset: -.45em auto -.45em 50%;
  inline-size: 1px;
  background: rgb(var(--illu-ink));
  box-shadow: 0 0 .5em rgb(var(--illu-ink));
  animation: al-illu-motion-tete 4s linear infinite;
}
.al-illu-motion__head::before {
  content: "";
  position: absolute;
  inset: -.1em auto auto 50%;
  translate: -50% 0;
  inline-size: .55em;
  block-size: .4em;
  background: rgb(var(--illu-ink));
  clip-path: polygon(0 0, 100% 0, 50% 100%);
}

/* La tete de lecture passe l'image cle du milieu a mi-parcours : c'est la
   que le medaillon rebondit. */
@keyframes al-illu-motion-tete {
  from { inset-inline-start: 4%; }
  to   { inset-inline-start: 96%; }
}
@keyframes al-illu-motion-temps {
  0%, 44%, 100% { scale: 1; }
  50%           { scale: 1.1; }
  58%           { scale: .97; }
  66%           { scale: 1.02; }
}
@keyframes al-illu-etincelle {
  0%, 100% { opacity: .15; scale: .5; }
  50%      { opacity: 1;   scale: 1; }
}

/* -- Boucles communes ----------------------------------------------------- */
@keyframes al-illu-scintille { from { opacity: .55; } to { opacity: 1; } }
@keyframes al-illu-reflet { from { background-position: 100% 0; } to { background-position: -50% 0; } }
@keyframes al-illu-tourne { to { rotate: 360deg; } }
@keyframes al-illu-flotte {
  0%, 100% { translate: 0 0; }
  50%      { translate: 0 -.35em; }
}

/* Hors ecran, tout s'arrete : c'est le script qui pose `is-paused`. */
.al-illu.is-paused,
.al-illu.is-paused *,
.al-illu.is-paused::before { animation-play-state: paused; }

/* Mouvement reduit : l'image posee, avec toutes ses annotations. */
@media (prefers-reduced-motion: reduce) {
  .al-illu::before,
  .al-illu *,
  .al-illu-design__layer--apres,
  .al-illu-design__split { animation: none !important; }
  .al-illu-web__pointer { translate: 0 0; }
  .al-illu-design__layer--apres { clip-path: inset(0 0 0 50%); }
  .al-illu-design__split { inset-inline-start: 50%; }
}

/* ==========================================================================
   26. MATRICE DE COMPETENCES
   --------------------------------------------------------------------------
   L'inventaire complet des prestations, en clair. Une agence qui liste
   precisement ce qu'elle sait faire rassure plus qu'une agence qui
   l'illustre.
   ========================================================================== */
.al-capability {
  display: grid;
  gap: var(--al-space-8) clamp(1.5rem, 4vw, 4rem);
}
@media (min-width: 768px) { .al-capability { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1200px) { .al-capability { grid-template-columns: repeat(4, minmax(0, 1fr)); } }

.al-capability__col { display: flex; flex-direction: column; }
.al-capability__head {
  display: flex;
  align-items: baseline;
  gap: var(--al-space-3);
  padding-block-end: var(--al-space-4);
  border-block-end: 2px solid var(--al-text-strong);
  margin-block-end: var(--al-space-4);
}
.al-capability__num {
  font-family: var(--al-font-mono);
  font-size: var(--al-fs-xs);
  color: var(--al-text-muted);
}
.al-capability__title {
  margin: 0;
  font-size: var(--al-fs-h4);
  font-weight: var(--al-fw-extrabold);
  letter-spacing: var(--al-ls-heading);
  color: var(--al-text-strong);
}
.al-capability__list { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--al-space-3); }
.al-capability__list li {
  position: relative;
  padding-inline-start: var(--al-space-5);
  font-size: var(--al-fs-sm);
  color: var(--al-text-muted);
  line-height: var(--al-lh-heading);
}
.al-capability__list li::before {
  content: "";
  position: absolute;
  inset-inline-start: 0;
  inset-block-start: .5em;
  inline-size: 10px;
  block-size: 1px;
  background: var(--al-border-strong);
}

/* --------------------------------------------------------------------------
   Liste editoriale : survol des lignes
   -------------------------------------------------------------------------- */
/* La ligne survolee avance legerement : le mouvement designe la cible sans
   deplacer les voisines. */
.al-listing__row .al-listing__name {
  transition: transform var(--al-dur-base) var(--al-ease-out-expo);
}
.al-listing__row:hover .al-listing__name { transform: translateX(8px); }
.al-listing__row:hover .al-listing__num { color: var(--al-solaire-500); }

/* La vignette de repli occupe sa propre colonne. Sans cela, la ligne compte
   quatre enfants pour trois colonnes et le dernier bascule sur un second rang.
   Meme condition que la regle qui masque la vignette : les deux ne peuvent
   pas diverger. */
.al-pointer-fine .al-listing__row { grid-template-columns: auto minmax(0, 1fr) auto; }


/* ==========================================================================
   27. HEROS « SCENE »
   --------------------------------------------------------------------------
   Composition centree sur tout le premier ecran : surtitre en pastille,
   titre, chapeau, preuve chiffree, deux appels a l'action et deux
   engagements. Pas de lumiere derriere le texte : le heros repose sur la
   grille du site, comme toutes les pages, et la grille vivante suffit a
   l'animer.
   ========================================================================== */
.al-hero--scene {
  min-block-size: min(100svh, 60rem);
  justify-content: center;
  padding-block: calc(var(--al-navbar-h) + clamp(2rem, 5vw, 4.5rem)) clamp(6rem, 13vw, 10rem);
  text-align: center;
}


.al-hero__center {
  display: flex;
  flex-direction: column;
  align-items: center;
  max-inline-size: 62rem;
  margin-inline: auto;
}
.al-hero--scene .al-eyebrow { margin-block-end: var(--al-space-6); }

.al-hero--scene .al-hero__title {
  /* Taille du titre du heros. Trois nombres : le plancher sur petit ecran,
     la croissance avec la largeur, le plafond sur grand ecran. */
  font-size: clamp(2.125rem, .9rem + 4.5vw, 4.3rem);
  line-height: 1;
  margin-block-end: var(--al-space-5);
}
.al-hero--scene .al-hero__lead {
  max-inline-size: 38rem;
  margin-inline: auto;
  color: var(--al-text-muted);
}

.al-hero--scene .al-hero__actions {
  justify-content: center;
  margin-block-start: var(--al-space-6);
}

/* Le seul jaune de l'ecran recoit un halo discret, comme une touche allumee. */
.al-hero--scene .al-btn--solaire { box-shadow: 0 10px 30px -6px rgb(var(--al-solaire-500-rgb) / .32); }

.al-hero__ticks {
  list-style: none;
  margin: var(--al-space-5) 0 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--al-space-2) var(--al-space-5);
  font-size: var(--al-fs-xs);
  color: var(--al-text-muted);
}
.al-hero__ticks li { display: inline-flex; align-items: center; gap: .4rem; }
.al-hero__ticks i { color: var(--al-success-500); font-size: 1rem; }

/* --------------------------------------------------------------------------
   Le heros sur telephone
   Un seul objectif : que les deux boutons soient visibles sans defiler. Ce
   qui les repoussait n'etait pas un element de trop, mais la somme des
   respirations calibrees pour un grand ecran.
   -------------------------------------------------------------------------- */
@media (max-width: 575.98px) {
  .al-hero--scene { padding-block-end: clamp(3rem, 12vw, 5rem); }
  .al-hero--scene .al-eyebrow { margin-block-end: var(--al-space-4); }
  .al-hero--scene .al-hero__title { margin-block-end: var(--al-space-4); }
  .al-hero--scene .al-hero__lead { font-size: 1rem; }
  .al-hero--scene .al-hero__actions { margin-block-start: var(--al-space-5); }
  .al-hero__ticks { margin-block-start: var(--al-space-4); }
}

/* ==========================================================================
   29. PILE DE CARTES (.al-deck)
   --------------------------------------------------------------------------
   Presentation des metiers : une carte par discipline, texte d'un cote et
   specimen de l'autre, en alternance. Au defilement, chaque carte se colle
   sous la barre de navigation et la suivante vient la recouvrir, en laissant
   depasser un liseret de celle d'en dessous. On lit une discipline a la fois,
   et l'on sent qu'elles forment un tout.

   Numero 29 et non 28 : la famille 28 designe la coque du back office, qui
   vit dans al-admin.css.

   Nom : .al-deck, et non .al-stack. L'utilitaire de pile verticale .al-stack
   existe deja dans al-theme.css et sert sur la page Contact : le reprendre
   l'aurait casse sans bruit, comme .al-index avant lui.
   ========================================================================== */
.al-deck {
  position: relative;
  display: grid;
  gap: var(--al-space-5);
}

/* Teinte de la discipline, selon l'architecture de marque : azur pour le
   developpement, magenta pour le design, solaire pour le motion. Variantes
   700 en clair et 300 en sombre : ce sont elles qui passent AA en texte. */
.al-deck__card {
  --hue: var(--al-azur-700);
  --hue-rgb: var(--al-azur-500-rgb);

  position: relative;
  border-radius: var(--al-radius-xl);
  padding: clamp(1.5rem, 4vw, 3.5rem) clamp(1.25rem, 5vw, 5rem);
  background: var(--al-surface);
  box-shadow: 0 0 0 1px var(--al-border);
  scroll-margin-block-start: calc(var(--al-navbar-h) + var(--al-space-5));
}
.al-deck__card--magenta { --hue: var(--al-magenta-700); --hue-rgb: var(--al-magenta-500-rgb); }
.al-deck__card--solaire { --hue: var(--al-solaire-700); --hue-rgb: var(--al-solaire-500-rgb); }

[data-bs-theme="dark"] .al-deck__card {
  --hue: var(--al-azur-300);
  background: var(--al-surface);
  /* L'ombre reste pour l'empilement : la carte du dessus doit se detacher
     de celle qu'elle recouvre. */
  box-shadow: 0 0 0 1px var(--al-border), 0 -20px 40px -30px rgb(0 0 0 / .6);
}
[data-bs-theme="dark"] .al-deck__card--magenta { --hue: var(--al-magenta-300); }
[data-bs-theme="dark"] .al-deck__card--solaire { --hue: var(--al-solaire-300); }

.al-deck__inner {
  display: grid;
  gap: clamp(2rem, 5vw, 4.5rem);
  align-items: center;
}
@media (min-width: 992px) {
  .al-deck__inner { grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr); }
  .al-deck__card--flip .al-deck__body { order: 2; }
}

/* Numero et famille de la discipline. Le filet a la fin, comme sur tous les
   surtitres, mais dans la teinte du metier. */
.al-deck__kicker {
  display: flex;
  align-items: baseline;
  gap: .75rem;
  margin: 0 0 var(--al-space-4);
  font-family: var(--al-font-mono);
  font-size: var(--al-fs-eyebrow);
  letter-spacing: var(--al-ls-eyebrow);
  text-transform: uppercase;
  color: var(--hue);
}
.al-deck__kicker b { color: var(--al-text-strong); font-weight: var(--al-fw-bold); }
/* Le filet est porte par le texte et non par le conteneur flex : quand le
   libelle se replie sur deux lignes, il reste accroche au dernier mot au
   lieu de partir seul au bord droit. */
.al-deck__kicker span::after {
  content: "";
  display: inline-block;
  vertical-align: middle;
  inline-size: 32px;
  block-size: 2px;
  margin-inline-start: .75rem;
  border-radius: var(--al-radius-pill);
  background: linear-gradient(90deg, var(--hue), transparent);
}

.al-deck__title {
  margin: 0 0 var(--al-space-4);
  font-size: clamp(1.75rem, 1.15rem + 1.9vw, 2.875rem);
  font-weight: var(--al-fw-extrabold);
  line-height: 1.04;
  letter-spacing: -0.03em;
  color: var(--al-text-strong);
  text-wrap: balance;
}
.al-deck__desc {
  margin: 0;
  max-inline-size: 46ch;
  font-size: var(--al-fs-lead);
  line-height: 1.6;
  color: var(--al-text-muted);
}

.al-deck__list {
  list-style: none;
  margin: var(--al-space-5) 0 0;
  padding: 0;
  display: grid;
  gap: .55rem;
}
.al-deck__list li {
  display: flex;
  gap: .65rem;
  align-items: baseline;
  font-size: var(--al-fs-sm);
  color: var(--al-text);
}
.al-deck__list i { color: var(--hue); flex: none; }

.al-deck__tags {
  display: flex;
  flex-wrap: wrap;
  gap: var(--al-space-2);
  margin-block-start: var(--al-space-5);
}
.al-deck__foot { margin-block-start: var(--al-space-6); }

/* --------------------------------------------------------------------------
   Les cartes sur telephone
   Sous 992 px, la pile perd son empilement : les quatre cartes se suivent
   en pleine hauteur, et l'on traverse quatre fois le meme rythme. On ne peut
   pas raccourcir le texte, qui est le propos ; on resserre donc tout ce qui
   n'en est pas, et le liseret de teinte marque chaque carte pour qu'on sente
   qu'on avance.
   -------------------------------------------------------------------------- */
@media (max-width: 991.98px) {
  .al-deck { gap: var(--al-space-4); }
  .al-deck__inner { gap: var(--al-space-5); }
  .al-deck__foot { margin-block-start: var(--al-space-5); }
  .al-deck__visual { aspect-ratio: 16 / 10; }

  /* Un filet dans la teinte du metier, en haut de chaque carte : quatre
     cartes identiques deviennent quatre etapes. */
  .al-deck__card::after {
    content: '';
    position: absolute;
    inset-block-start: 0;
    inset-inline: clamp(1.25rem, 5vw, 5rem);
    block-size: 3px;
    border-radius: 0 0 3px 3px;
    background: var(--hue);
  }
}

/* Le visuel : un panneau interieur eclaire par la teinte du metier, ou
   l'illustration (famille 25) prend toute la place. Fond du site et filet
   du theme : l'illustration suit le mode clair ou sombre. */
.al-deck__visual {
  position: relative;
  border-radius: var(--al-radius-lg);
  padding: 0;
  background: var(--al-canvas);
  box-shadow: inset 0 0 0 1px var(--al-border);
  overflow: hidden;
  isolation: isolate;
}

/* --------------------------------------------------------------------------
   L'empilement
   Pose par le script, qui ajoute `is-stackable` seulement si chaque carte
   tient entiere sous son point de collage. Une carte plus haute que la place
   restante ne se lirait jamais en entier : la suivante la recouvrirait avant
   qu'on en voie le bas. Une hauteur d'ecran fixe en requete media ne suffit
   pas : la hauteur des cartes depend de la largeur, et de leur contenu.
   Sans script, ou si une carte deborde, les cartes se suivent simplement.

   Le sommet de collage ignore volontairement le masquage de la barre de
   navigation. Suivre --al-sticky-top ferait sauter toute la pile a chaque
   apparition de la barre : un ecart fixe vaut mieux qu'une pile qui bouge.
   -------------------------------------------------------------------------- */
@media (min-width: 992px) {
  .al-deck.is-stackable {
    gap: 0;
    padding-block-end: 8vh;
  }
  .al-deck.is-stackable .al-deck__card {
    position: sticky;
    inset-block-start: calc(var(--al-navbar-h) + var(--al-space-5) + var(--i, 0) * 14px);
    margin-block-end: 28vh;
  }
  .al-deck.is-stackable .al-deck__card:last-of-type { margin-block-end: 0; }

  /* Une carte s'efface a mesure que la suivante la recouvre. --cover va de
     0 a 1, ecrit par le script au defilement : un effacement progressif,
     lie au geste, et non une bascule a un seuil. */
  .al-deck.is-stackable .al-deck__inner { opacity: calc(1 - var(--cover, 0) * .72); }
}

/* --------------------------------------------------------------------------
   Pastilles de progression
   Une par carte, fixees au bord droit tant que la pile est a l'ecran. La
   pastille active s'allonge et prend la teinte de son metier.
   -------------------------------------------------------------------------- */
.al-deck__dots {
  position: fixed;
  inset-inline-end: clamp(12px, 1.8vw, 28px);
  inset-block-start: 50%;
  translate: 0 -50%;
  z-index: 40;
  display: none;
  flex-direction: column;
  gap: 10px;
  margin: 0;
  padding: 0;
  list-style: none;
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--al-dur-base) linear;
}
.al-deck.is-stackable .al-deck__dots { display: flex; }
.al-deck.is-in-view .al-deck__dots { opacity: 1; pointer-events: auto; }

.al-deck__dot {
  display: block;
  inline-size: 8px;
  block-size: 8px;
  padding: 0;
  border: 0;
  border-radius: var(--al-radius-pill);
  background: var(--al-border-strong);
  cursor: pointer;
  transition: block-size var(--al-dur-base) var(--al-ease-out), background var(--al-dur-base) linear;
}
.al-deck__dot:hover { background: var(--al-text-subtle); }
.al-deck__dot.is-active {
  block-size: 28px;
  background: var(--hue, var(--al-text-strong));
  box-shadow: 0 0 14px rgb(var(--hue-rgb, var(--al-ink-500-rgb)) / .55);
}
.al-deck__dot:focus-visible { outline: 2px solid var(--al-focus-ring); outline-offset: 3px; }

@media (prefers-reduced-motion: reduce) {
  .al-deck__dot { transition: none; }
}

/* ==========================================================================
   30. PREUVES CHIFFREES
   --------------------------------------------------------------------------
   Les chiffres cles de config/site.php, un par carte : pictogramme teinte,
   nombre en tres grand, libelle en capitales. Le suffixe est porte hors du
   compteur pour pouvoir etre compose plus petit que le nombre.
   ========================================================================== */
.al-proof {
  display: grid;
  gap: var(--al-space-4);
  grid-template-columns: repeat(2, minmax(0, 1fr));
}
@media (min-width: 992px) { .al-proof { grid-template-columns: repeat(4, minmax(0, 1fr)); } }

/* Teintes en variantes 700 sur fond clair : ce sont elles qui passent AA. */
.al-proof__card {
  --tint: var(--al-azur-700);
  --tint-bg: var(--al-azur-050);

  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  padding: var(--al-space-6) var(--al-space-4);
  border-radius: var(--al-radius-lg);
  background: var(--al-surface);
  box-shadow: 0 0 0 1px var(--al-border);
}
.al-proof__card--magenta { --tint: var(--al-magenta-700); --tint-bg: var(--al-magenta-050); }
.al-proof__card--solaire { --tint: var(--al-solaire-700); --tint-bg: var(--al-solaire-100); }
.al-proof__card--ink     { --tint: var(--al-ink-800);     --tint-bg: var(--al-ink-100); }

.al-proof__icon {
  inline-size: 46px;
  block-size: 46px;
  display: grid;
  place-items: center;
  border-radius: 14px;
  background: var(--tint-bg);
  color: var(--tint);
  font-size: 1.2rem;
  box-shadow: inset 0 0 0 1px rgb(0 0 0 / .04);
}
.al-proof__value {
  margin: var(--al-space-5) 0 0;
  font-size: clamp(2.25rem, 1.5rem + 2.2vw, 3.25rem);
  font-weight: var(--al-fw-black);
  line-height: 1;
  letter-spacing: -0.045em;
  color: var(--al-text-strong);
  font-variant-numeric: tabular-nums;
}
.al-proof__value small {
  margin-inline-start: .06em;
  font-size: .5em;
  font-weight: var(--al-fw-bold);
  color: var(--tint);
  vertical-align: .55em;
}
.al-proof__label {
  margin: var(--al-space-3) 0 0;
  font-family: var(--al-font-mono);
  font-size: 11px;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--al-text-muted);
}

/* Cartes de preuve sur fond sombre : les variantes 700 y seraient eteintes,
   on passe aux 300 et a des fonds de verre. */
[data-bs-theme="dark"] .al-proof__card {
  --tint: var(--al-azur-300);
  --tint-bg: rgb(var(--al-azur-500-rgb) / .16);
  background: var(--al-surface);
  box-shadow: inset 0 0 0 1px rgb(255 255 255 / .09), inset 0 1px 0 rgb(255 255 255 / .06);
}
[data-bs-theme="dark"] .al-proof__card--magenta { --tint: var(--al-magenta-300); --tint-bg: rgb(var(--al-magenta-500-rgb) / .16); }
[data-bs-theme="dark"] .al-proof__card--solaire { --tint: var(--al-solaire-300); --tint-bg: rgb(var(--al-solaire-500-rgb) / .14); }
[data-bs-theme="dark"] .al-proof__card--ink     { --tint: #fff; --tint-bg: rgb(255 255 255 / .08); }


/* ==========================================================================
   31. EN-TETE DE PAGE CENTRE
   --------------------------------------------------------------------------
   Pages internes. Meme grammaire que le heros de l'accueil : fil d'Ariane,
   surtitre en pastille, grand titre, chapeau, puis ce que la page propose.
   Comme le heros, il repose directement sur la grille du site.
   ========================================================================== */
.al-page-head {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  padding-block: calc(var(--al-navbar-h) + clamp(2.5rem, 6vw, 5rem)) clamp(3.5rem, 8vw, 6.5rem);
  color: var(--al-text);
  text-align: center;
}
.al-page-head--tall {
  min-block-size: 100svh;
  display: grid;
  align-items: center;
}

.al-page-head__center {
  display: flex;
  flex-direction: column;
  align-items: center;
  max-inline-size: 58rem;
  margin-inline: auto;
}
.al-page-head__crumbs { justify-content: center; margin-block-end: var(--al-space-6); }
.al-page-head .al-eyebrow { margin-block-end: var(--al-space-5); }
.al-page-head__title {
  margin: 0;
  color: var(--al-text-strong);
  text-wrap: balance;
}
.al-page-head__lead {
  max-inline-size: 40rem;
  margin: var(--al-space-5) auto 0;
  color: var(--al-text-muted);
}
.al-page-head__actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--al-space-3);
  margin-block-start: var(--al-space-7);
}
.al-page-head .al-btn--solaire { box-shadow: 0 10px 30px -6px rgb(var(--al-solaire-500-rgb) / .32); }

.al-page-head__chips {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: .6rem;
  margin-block-start: var(--al-space-7);
}

/* Raccourci en pastille, marque d'un point dans la teinte de sa cible. */
.al-chip-link {
  display: inline-flex;
  align-items: center;
  gap: .6rem;
  padding: .6rem 1.05rem;
  border-radius: var(--al-radius-pill);
  background: var(--al-surface);
  box-shadow: inset 0 0 0 1px var(--al-border);
  color: var(--al-text);
  font-size: var(--al-fs-sm);
  font-weight: var(--al-fw-medium);
  text-decoration: none;
  transition: background var(--al-dur-fast) linear, box-shadow var(--al-dur-fast) linear, color var(--al-dur-fast) linear;
}
.al-chip-link i {
  inline-size: 8px;
  block-size: 8px;
  border-radius: 50%;
  background: var(--c, var(--al-text-strong));
  box-shadow: 0 0 10px var(--c, transparent);
}
.al-chip-link:hover {
  background: var(--al-surface);
  box-shadow: inset 0 0 0 1px var(--al-border-strong);
  color: var(--al-text-strong);
}
.al-chip-link:focus-visible { outline: 2px solid var(--al-focus-ring); outline-offset: 3px; }


/* ==========================================================================
   32. CARTES A ILLUSTRATION (.al-feature)
   --------------------------------------------------------------------------
   Etapes de methode, convictions, suite d'un brief. Chaque carte ouvre sur
   une vignette sombre, quel que soit le theme de la section : une tuile de
   verre porte le pictogramme, la teinte l'eclaire, un satellite tourne sur
   une orbite en pointilles. La pastille de rang n'apparait que si l'ordre
   compte. Registre des cartes d'uxpeak, sujets AssuLight.
   ========================================================================== */
.al-features { display: grid; gap: var(--al-space-4); }
@media (min-width: 768px) {
  .al-features--2,
  .al-features--4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (min-width: 1200px) {
  .al-features--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

/* Texte des pastilles selon la regle du curseur. */
.al-feature {
  --f-rgb: var(--al-azur-500-rgb);
  --f: var(--al-azur-300);
  --f-on: #f4f6f9;

  block-size: 100%;
  display: flex;
  flex-direction: column;
  border-radius: var(--al-radius-xl);
  overflow: hidden;
  background: var(--al-surface);
  box-shadow: 0 0 0 1px var(--al-border), var(--al-shadow-sm);
  transition: transform var(--al-dur-slow) var(--al-ease-out-expo), box-shadow var(--al-dur-slow) var(--al-ease-out);
}
.al-feature--magenta { --f-rgb: var(--al-magenta-500-rgb); --f: var(--al-magenta-300); --f-on: #fbe824; }
.al-feature--solaire { --f-rgb: var(--al-solaire-500-rgb); --f: var(--al-solaire-300); --f-on: #0b0d11; }
[data-bs-theme="light"] .al-feature          { --f: var(--al-azur-600); }
[data-bs-theme="light"] .al-feature--magenta { --f: var(--al-magenta-600); }
[data-bs-theme="light"] .al-feature--solaire { --f: var(--al-solaire-700); }
.al-feature:hover {
  transform: translateY(-4px);
  box-shadow: 0 0 0 1px var(--al-border-strong), var(--al-shadow-lg);
}
[data-bs-theme="dark"] .al-feature {
  background: var(--al-surface);
  box-shadow: inset 0 0 0 1px rgb(var(--illu-ink) / .08);
}

.al-feature__art {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  display: grid;
  place-items: center;
  block-size: 10.5rem;
  margin: .5rem .5rem 0;
  border-radius: calc(var(--al-radius-xl) - .5rem);
  background: var(--al-canvas);
  box-shadow: inset 0 0 0 1px var(--al-border);
}
.al-feature__art::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background-image:
    radial-gradient(1px 1px at 14% 22%, rgb(var(--illu-ink) / .5), transparent),
    radial-gradient(1px 1px at 82% 16%, rgb(var(--illu-ink) / .35), transparent),
    radial-gradient(1.5px 1.5px at 74% 80%, rgb(var(--illu-ink) / .4), transparent),
    radial-gradient(1px 1px at 24% 74%, rgb(var(--illu-ink) / .3), transparent),
    radial-gradient(1px 1px at 92% 52%, rgb(var(--illu-ink) / .3), transparent);
}

.al-feature__orbit {
  position: absolute;
  inline-size: 8.25rem;
  block-size: 8.25rem;
  border-radius: 50%;
  border: 1px dashed rgb(var(--illu-ink) / .14);
  animation: al-illu-tourne 22s linear infinite;
}
.al-feature__orbit::after {
  content: "";
  position: absolute;
  inset-block-start: -4px;
  inset-inline-start: calc(50% - 4px);
  inline-size: 8px;
  block-size: 8px;
  border-radius: 50%;
  background: rgb(var(--f-rgb));
  box-shadow: 0 0 12px rgb(var(--f-rgb));
}

.al-feature__glyph {
  position: relative;
  display: grid;
  place-items: center;
  inline-size: 4.25rem;
  block-size: 4.25rem;
  border-radius: 1.15rem;
  background: linear-gradient(160deg, rgb(var(--illu-ink) / .13), rgb(var(--illu-ink) / .03));
  box-shadow:
    inset 0 0 0 1px rgb(var(--illu-ink) / .16),
    inset 0 1px 0 rgb(var(--illu-ink) / .2),
    0 1.25rem 2rem -1rem rgb(0 0 0 / calc(.85 * var(--illu-ombre))),
    0 0 2.5rem -.5rem rgb(var(--f-rgb) / .55);
  color: var(--f);
  font-size: 1.7rem;
  transition: transform var(--al-dur-slow) var(--al-ease-out-expo);
}
.al-feature__glyph .bi { filter: drop-shadow(0 0 10px rgb(var(--f-rgb) / .8)); }
.al-feature:hover .al-feature__glyph { transform: translateY(-4px) rotate(-5deg); }

.al-feature__rank {
  position: absolute;
  inset-block-start: .85rem;
  inset-inline-start: .85rem;
  padding: .2rem .55rem;
  border-radius: var(--al-radius-pill);
  background: rgb(var(--f-rgb));
  box-shadow: 0 0 16px rgb(var(--f-rgb) / .55);
  color: var(--f-on);
  font-family: var(--al-font-mono);
  font-size: 11px;
  font-weight: var(--al-fw-bold);
  letter-spacing: .08em;
}

.al-feature__body { padding: var(--al-space-5) var(--al-space-5) var(--al-space-6); }
.al-feature__title {
  margin: 0 0 var(--al-space-2);
  font-size: var(--al-fs-h4);
  color: var(--al-text-strong);
  text-wrap: balance;
}
.al-feature__text { margin: 0; font-size: var(--al-fs-sm); color: var(--al-text-muted); }

@media (prefers-reduced-motion: reduce) {
  .al-feature,
  .al-feature__glyph { transition: none; }
  .al-feature__orbit { animation: none; }
}


/* ==========================================================================
   33. CONTACT : COORDONNEES ET BRIEF
   --------------------------------------------------------------------------
   Deux pieces bord a bord sur la grille (famille 37) : les moyens de nous
   joindre a gauche (8 cases), le brief a droite (16 cases). Sous 992 px,
   elles s'empilent. Chaque moyen de contact est une ligne haute de deux
   cases, separee de la suivante par un filet : les filets tombent donc sur
   les lignes du fond. Plus de cartes flottantes ni de halo sous le
   formulaire : la piece est plate et opaque, comme le reste du site.
   ========================================================================== */
.al-contact {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  box-shadow: 1px 1px 0 0 var(--al-rule);
}
@media (min-width: 992px) {
  .al-contact { grid-template-columns: minmax(0, 8fr) minmax(0, 16fr); }
}
.al-contact > * {
  min-inline-size: 0;
  background: var(--al-canvas);
  box-shadow: inset 1px 1px 0 0 var(--al-rule);
}

/* L'en-tete de la colonne : une case de haut, le titre et l'etat. */
.al-contact__entete {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--al-space-3);
  block-size: var(--al-grid-size);
  padding-inline: var(--al-space-5);
}
.al-contact__titre {
  margin: 0;
  font-family: var(--al-font-mono);
  font-size: var(--al-fs-xs);
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--al-text-subtle);
}
.al-contact__entete .al-pill-status { font-size: var(--al-fs-xs); }
/* Sur telephone, la case ne fait que 32 px : l'etat deborderait. Le delai
   de reponse est deja annonce dans l'en-tete de la page. */
@media (max-width: 575.98px) {
  .al-contact__entete .al-pill-status { display: none; }
}

/* Une ligne par moyen de contact, deux cases de haut au moins. */
.al-contact-list { list-style: none; margin: 0; padding: 0; }
.al-contact-list__item {
  display: flex;
  align-items: center;
  gap: var(--al-space-4);
  min-block-size: calc(var(--al-grid-size) * 2);
  padding: var(--al-space-3) var(--al-space-5);
  box-shadow: inset 0 1px 0 var(--al-rule);
  color: inherit;
  text-decoration: none;
  transition: background var(--al-dur-fast) linear;
}
a.al-contact-list__item:hover { background: var(--al-surface-sunken); }
.al-contact-list__icon {
  flex: none;
  display: grid;
  place-items: center;
  inline-size: 40px;
  block-size: 40px;
  border-radius: 50%;
  box-shadow: inset 0 0 0 1px var(--al-border-strong);
  color: var(--al-text-strong);
  font-size: 1.05rem;
}
.al-contact-list__text { display: grid; gap: .1rem; flex: 1; min-inline-size: 0; }
.al-contact-list__label {
  font-family: var(--al-font-mono);
  font-size: 11px;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--al-text-subtle);
}
.al-contact-list__value { font-weight: var(--al-fw-semibold); color: var(--al-text-strong); overflow-wrap: anywhere; }
.al-contact-list__go {
  flex: none;
  color: var(--al-text-subtle);
  transition: color var(--al-dur-fast) linear, translate var(--al-dur-base) var(--al-ease-out-expo);
}
a.al-contact-list__item:hover .al-contact-list__go { color: var(--al-text-strong); translate: 2px -2px; }

/* Le brief : une case de marge interieure, les etapes en onglets en haut. */
.al-contact__brief { display: flex; flex-direction: column; }
.al-contact__brief .al-brief { flex: 1; padding: 0 var(--al-grid-size) var(--al-grid-size); }
@media (max-width: 575.98px) {
  .al-contact__brief .al-brief { padding-inline: var(--al-space-5); }
}
.al-contact__brief .al-steps-bar {
  gap: 0;
  margin: 0 calc(-1 * var(--al-grid-size)) var(--al-grid-size);
  box-shadow: inset 0 -1px 0 var(--al-rule);
}
@media (max-width: 575.98px) {
  .al-contact__brief .al-steps-bar { margin-inline: calc(-1 * var(--al-space-5)); }
}
.al-contact__brief .al-steps-bar__item {
  position: relative;
  flex: 1;
  justify-content: center;
  block-size: var(--al-grid-size);
}
.al-contact__brief .al-steps-bar__item + .al-steps-bar__item { box-shadow: inset 1px 0 0 var(--al-rule); }
/* L'etape en cours : un filet azur sur le bord bas de son onglet. */
.al-contact__brief .al-steps-bar__item.is-active::after {
  content: "";
  position: absolute;
  inset-inline: 0;
  inset-block-end: 0;
  block-size: 2px;
  background: var(--al-azur-500);
}

.al-contact__note {
  display: flex;
  align-items: center;
  gap: var(--al-space-3);
  min-block-size: var(--al-grid-size);
  margin: 0;
  padding: var(--al-space-3) var(--al-space-5);
  box-shadow: inset 0 1px 0 var(--al-rule);
  font-size: var(--al-fs-xs);
  color: var(--al-text-muted);
}
@media (min-width: 576px) {
  .al-contact__note { padding-inline: var(--al-grid-size); }
}


/* ==========================================================================
   34. BANDEAU D'APPEL : LE CADRE
   --------------------------------------------------------------------------
   Plus d'eventail : une piece posee sur la grille, cadree d'un filet, avec
   un repere en croix a chaque angle comme sur une planche a decouper.
   ========================================================================== */
.al-cta {
  box-shadow: inset 0 0 0 1px var(--al-border-strong);
  background:
    linear-gradient(var(--al-tick), var(--al-tick)) 0 0 / 14px 1px,
    linear-gradient(var(--al-tick), var(--al-tick)) 0 0 / 1px 14px,
    linear-gradient(var(--al-tick), var(--al-tick)) 100% 0 / 14px 1px,
    linear-gradient(var(--al-tick), var(--al-tick)) 100% 0 / 1px 14px,
    linear-gradient(var(--al-tick), var(--al-tick)) 0 100% / 14px 1px,
    linear-gradient(var(--al-tick), var(--al-tick)) 0 100% / 1px 14px,
    linear-gradient(var(--al-tick), var(--al-tick)) 100% 100% / 14px 1px,
    linear-gradient(var(--al-tick), var(--al-tick)) 100% 100% / 1px 14px,
    var(--al-surface);
  background-repeat: no-repeat;
  border-radius: 0;
}

/* Pages d'erreur : le code en tres grand, traverse par le spectre. */
.al-error-code {
  margin: 0 0 var(--al-space-4);
  font-family: var(--al-font-display);
  font-size: clamp(6rem, 3rem + 14vw, 13rem);
  font-weight: var(--al-fw-black);
  line-height: .85;
  letter-spacing: -.06em;
  background: var(--al-spectre);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
  filter: drop-shadow(0 0 40px rgb(var(--al-magenta-500-rgb) / .35));
}

/* ==========================================================================
   35. ZONES TACTILES
   --------------------------------------------------------------------------
   Sur un ecran tactile, toute cible doit offrir au moins 44 px de haut
   (WCAG 2.5.5). Les liens de texte gardent leur dessin : on agrandit leur
   zone de toucher par un pseudo-element invisible, sans rien deplacer.
   Les listes du pied de page, elles, respirent davantage : leurs liens
   etaient hauts de 18 px et serres de 16 px.
   ========================================================================== */
@media (pointer: coarse) {
  .al-breadcrumb a,
  .al-link-arrow,
  .al-navbar__brand,
  .al-footer__bottom a {
    position: relative;
  }
  .al-breadcrumb a::after,
  .al-link-arrow::after,
  .al-navbar__brand::after,
  .al-footer__bottom a::after {
    content: "";
    position: absolute;
    inset: -12px -6px;
  }
  /* Le fil d'Ariane est compose en 12 px : il lui faut plus de marge. */
  .al-breadcrumb a::after { inset: -15px -6px; }

  .al-footer__list { gap: 0; }
  .al-footer__list a {
    display: inline-flex;
    align-items: center;
    min-block-size: 44px;
  }

  .al-btn--sm { min-block-size: 44px; }
  .al-social a { inline-size: 44px; block-size: 44px; }
}

/* Libelles des cartes de preuve : 12 px sur petit ecran, 11 px restait a la
   limite de la lecture en capitales espacees. */
@media (max-width: 575.98px) {
  .al-proof__label { font-size: 12px; }
}

/* ==========================================================================
   36. APPAREILS (.al-device)
   --------------------------------------------------------------------------
   Une capture d'ecran n'est plus une image finie : c'est un ecran, que le
   site pose lui-meme dans un appareil. Le cadre est dessine en CSS, jamais
   incruste dans le fichier : la meme capture sert de vignette, de couverture
   et de visuel, et changer d'appareil ne demande aucun nouveau fichier.

   Cinq appareils : `--pc` (fenetre de navigateur), `--portable`,
   `--tablette`, `--mobile`, `--montre`. La valeur vient de la base
   (colonne `device`), le gabarit est `element/device.php`.

   Toutes les proportions sont en `cqi` : chaque appareil est un conteneur
   de requete, donc un centieme de sa propre largeur. Un telephone garde
   ainsi ses bords fins qu'il fasse 90 px de large dans une vignette ou
   600 px en pleine page, sans une seule media query.
   ========================================================================== */
.al-device {
  container-type: inline-size;
  position: relative;
  display: block;
  inline-size: 100%;
  --al-dev-corps: linear-gradient(160deg, #23262d, #121419);
  --al-dev-bord: rgb(255 255 255 / .12);
  --al-dev-ombre: 0 6cqi 12cqi -4cqi rgb(0 0 0 / .65);
}
.al-device__screen {
  position: relative;
  z-index: 1;
  display: block;
  overflow: hidden;
  background: var(--al-ink-900);
}
/* Une capture se lit par le haut : on ancre l'image en haut, jamais au centre. */
.al-device__screen img,
.al-device__screen video {
  display: block;
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
  object-position: 50% 0;
}

/* -- PC : une fenetre de navigateur, barre et pastilles comprises ---------- */
.al-device--pc {
  padding-block-start: 5.4cqi;
  border-radius: 2.2cqi;
  background: var(--al-dev-corps);
  box-shadow: var(--al-dev-ombre), 0 0 0 1px var(--al-dev-bord);
  overflow: hidden;
}
.al-device--pc::before {
  content: "";
  position: absolute;
  inset-block-start: 0;
  inset-inline: 0;
  block-size: 5.4cqi;
  background: rgb(255 255 255 / .05);
}
/* Les trois pastilles : une seule boite, deux ombres portees. */
.al-device--pc::after {
  content: "";
  position: absolute;
  inset-block-start: 2.05cqi;
  inset-inline-start: 2.6cqi;
  inline-size: 1.3cqi;
  block-size: 1.3cqi;
  border-radius: 50%;
  background: rgb(255 255 255 / .22);
  box-shadow: 2.2cqi 0 0 rgb(255 255 255 / .22), 4.4cqi 0 0 rgb(255 255 255 / .22);
}
.al-device--pc .al-device__screen { aspect-ratio: 16 / 9; }

/* -- Portable : l'ecran, puis le socle qui depasse ------------------------- */
.al-device--portable {
  padding: 1.5cqi 1.5cqi 2.2cqi;
  margin-block-end: 3cqi;
  border-radius: 1.8cqi 1.8cqi .6cqi .6cqi;
  background: var(--al-dev-corps);
  box-shadow: var(--al-dev-ombre), 0 0 0 1px var(--al-dev-bord);
}
.al-device--portable .al-device__screen { aspect-ratio: 16 / 10; border-radius: .6cqi; }
/* La camera, au milieu du bord haut. */
.al-device--portable::before {
  content: "";
  position: absolute;
  inset-block-start: .55cqi;
  inset-inline-start: 50%;
  translate: -50% 0;
  inline-size: .55cqi;
  block-size: .55cqi;
  border-radius: 50%;
  background: rgb(255 255 255 / .28);
}
/* Le socle deborde de chaque cote, comme un vrai capot. */
.al-device--portable::after {
  content: "";
  position: absolute;
  inset-block-start: 100%;
  inset-inline: -6cqi;
  block-size: 2.4cqi;
  border-radius: 0 0 2cqi 2cqi;
  background: linear-gradient(#20242b, #101216);
  box-shadow: inset 0 1px 0 rgb(255 255 255 / .1);
}

/* -- Tablette ------------------------------------------------------------- */
.al-device--tablette {
  padding: 2.6cqi;
  border-radius: 4.6cqi;
  background: var(--al-dev-corps);
  box-shadow: var(--al-dev-ombre), 0 0 0 1px var(--al-dev-bord);
}
.al-device--tablette .al-device__screen { aspect-ratio: 3 / 4; border-radius: 2.4cqi; }
.al-device--tablette::before {
  content: "";
  position: absolute;
  inset-block-start: 1.1cqi;
  inset-inline-start: 50%;
  translate: -50% 0;
  inline-size: .8cqi;
  block-size: .8cqi;
  border-radius: 50%;
  background: rgb(255 255 255 / .3);
}

/* -- Mobile : l'ilot en haut, le bouton sur la tranche -------------------- */
.al-device--mobile {
  padding: 2.4cqi;
  border-radius: 13cqi;
  background: var(--al-dev-corps);
  box-shadow: var(--al-dev-ombre), 0 0 0 1px var(--al-dev-bord);
}
.al-device--mobile .al-device__screen { aspect-ratio: 9 / 19.5; border-radius: 10.6cqi; }
.al-device--mobile::before {
  content: "";
  position: absolute;
  z-index: 2;
  inset-block-start: 4.2cqi;
  inset-inline-start: 50%;
  translate: -50% 0;
  inline-size: 28cqi;
  block-size: 4.4cqi;
  border-radius: 999px;
  background: #06070a;
}
.al-device--mobile::after {
  content: "";
  position: absolute;
  inset-block-start: 24cqi;
  inset-inline-end: -.7cqi;
  inline-size: .7cqi;
  block-size: 12cqi;
  border-radius: 0 1cqi 1cqi 0;
  background: rgb(255 255 255 / .16);
}

/* -- Montre : le boitier, le bracelet derriere, la couronne --------------- */
.al-device--montre { padding-block: 17cqi; }
.al-device--montre .al-device__screen {
  aspect-ratio: 1 / 1.16;
  border: 4.2cqi solid transparent;
  border-radius: 27cqi;
  background:
    linear-gradient(#05070a, #05070a) padding-box,
    var(--al-dev-corps) border-box;
  box-shadow: var(--al-dev-ombre), 0 0 0 1px var(--al-dev-bord);
}
/* Le bracelet passe derriere le boitier : il part de plus haut et plus bas. */
.al-device--montre::before {
  content: "";
  position: absolute;
  inset-block: 0;
  inset-inline: 21cqi;
  border-radius: 7cqi;
  background: linear-gradient(#262a32, #14161b);
}
.al-device--montre::after {
  content: "";
  position: absolute;
  z-index: 2;
  inset-block-start: 40%;
  inset-inline-end: -1.4cqi;
  inline-size: 2.2cqi;
  block-size: 9cqi;
  border-radius: 1.2cqi;
  background: linear-gradient(90deg, #2a2e36, #191c22);
}

/* --------------------------------------------------------------------------
   La scene : le fond sur lequel l'appareil se pose
   Elle est un conteneur de taille, ce qui permet de dimensionner chaque
   appareil a la fois selon la largeur (cqi) et la hauteur (cqh) : un
   telephone tient toujours dans la carte, un ordinateur aussi.
   -------------------------------------------------------------------------- */
.al-stage {
  position: relative;
  container-type: size;
  display: grid;
  place-items: center;
  overflow: hidden;
  /* Un plan de travail uni, du noir du site, sans halo ni trame :
     l'appareil se detache par lui-meme. */
  background: var(--al-ink-950);
}
/* Les appareils descendent jusqu'au bord bas : ils semblent poses dessus. */
.al-stage--pose { place-items: end center; }

/* La scene prend la teinte du projet, quand il en a une : un lavis uni,
   sans halo ni trame. */
.al-stage.al-tint {
  background:
    linear-gradient(rgb(var(--al-tint) / .22), rgb(var(--al-tint) / .22)),
    var(--al-ink-950);
}

/* Scene sans fond : elle sert seulement a dimensionner l'appareil, le fond
   est deja pose par le conteneur (un visuel de galerie, par exemple). */
.al-stage--nu { background: none; }

.al-stage .al-device--pc       { inline-size: min(96cqi, 178cqh); }
.al-stage .al-device--portable { inline-size: min(92cqi, 160cqh); }
.al-stage .al-device--tablette { inline-size: min(74cqi, 82cqh); }
.al-stage .al-device--mobile   { inline-size: min(52cqi, 52cqh); }
.al-stage .al-device--montre   { inline-size: min(48cqi, 48cqh); }


/* ==========================================================================
   37. PIECES DE GRILLE
   --------------------------------------------------------------------------
   Les blocs se posent sur la grille du fond et leurs contours se confondent
   avec ses lignes. Deux familles :
   - les groupes (chiffres, cartes de methode, projets, offres, avis, logos)
     mettent leurs pieces bord a bord, sans espace : chaque piece trace son
     bord gauche et son bord haut, le groupe trace le bord droit et le bord
     bas. Chaque filet occupe ainsi exactement le pixel d'une ligne ;
   - les blocs seuls (cartes des metiers, bandeau d'appel) tracent leurs
     quatre bords de la meme facon.
   Largeurs : le contenu compte 24 cases (12 sous 992 px), les colonnes des
   groupes en sont des diviseurs. Hauteurs : arrondies au pas par le script
   (al-ui.js, initCalage), qui cale aussi le haut de chaque bloc.
   Les pieces sont opaques : la grille ne se voit pas a travers.
   ========================================================================== */
.al-site .al-proof,
.al-site .al-features,
.al-site .al-bento,
.al-site .al-cells,
.al-site .al-logo-wall {
  gap: 0;
  border: 0;
  border-radius: 0;
  background: none;
  overflow: visible;
  box-shadow: 1px 1px 0 0 var(--al-rule);
}
.al-site .al-proof > *,
.al-site .al-features > *,
.al-site .al-bento > *,
.al-site .al-cells > *,
.al-site .al-logo-wall > * {
  border-radius: 0;
  background: var(--al-canvas);
  box-shadow: inset 1px 1px 0 0 var(--al-rule);
}
/* Equipe : la fiche prend une marge interieure dans sa piece. */
.al-site .al-cells .al-person { padding: var(--al-space-5); }

/* Les pieces qui portent une carte : un pixel de retrait en haut et a
   gauche, pour que l'image ou le fond de la carte ne recouvre pas le filet. */
.al-site .al-features > *,
.al-site .al-bento > *,
.al-site .al-cells > * { padding: 1px 0 0 1px; }

/* Groupe de cellules generique : 1 colonne, puis 2, puis 3. */
.al-cells { display: grid; grid-template-columns: minmax(0, 1fr); }
@media (min-width: 768px) { .al-cells--2, .al-cells--3 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 992px) { .al-cells--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.al-cells--4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
@media (min-width: 992px) { .al-cells--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); } }

/* Mur de logos : 2, 3 puis 6 colonnes, des diviseurs du contenu. */
@media (min-width: 992px) { .al-site .al-logo-wall { grid-template-columns: repeat(6, minmax(0, 1fr)); } }

/* Les cartes posees dans une piece perdent leur propre cadre : c'est la
   piece qui le trace. Pas de soulevement au survol, il decollerait le
   contour de sa ligne : la piece s'eclaire a la place. */
.al-site .al-features .al-feature,
.al-site .al-cells .al-offer,
.al-site .al-cells .al-quote {
  border: 0;
  border-radius: 0;
  background: transparent;
  box-shadow: none;
}
.al-site .al-features .al-feature:hover,
.al-site .al-cells .al-offer:hover { transform: none; box-shadow: none; }
.al-site .al-features > *:hover,
.al-site .al-cells > *:hover,
.al-site .al-bento > *:hover { background: var(--al-surface-sunken); }
.al-site .al-cells .al-offer--featured::before {
  content: "";
  position: absolute;
  inset: 0 0 auto;
  block-size: 2px;
  background: var(--al-spectre);
}

/* Vignette des cartes de methode : pleine largeur, quatre cases de haut,
   son filet du bas tombe lui aussi sur une ligne. */
.al-site .al-features .al-feature__art {
  margin: 0;
  border-radius: 0;
  block-size: calc(var(--al-grid-size) * 4);
  box-shadow: 0 1px 0 var(--al-rule);
}

/* Projets : image a fond perdu dans la piece. La hauteur suit le contenu,
   et le calage la ramene a un multiple de la grille. */
.al-site .al-bento .al-work__media,
.al-site .al-cells .al-work__media { border-radius: 0; }
.al-site .al-bento .al-work--stacked .al-work__body,
.al-site .al-cells .al-work--stacked .al-work__body { padding: var(--al-space-4) var(--al-space-5); align-items: flex-start; }
/* Les titres d'une rangee partent sous l'image, la fleche reste en bas. */
.al-site .al-bento .al-work--stacked .al-work__go,
.al-site .al-cells .al-work--stacked .al-work__go { align-self: flex-end; }
/* Dans une cellule, la carte remplit sa piece : la legende prend le reste. */
.al-site .al-cells > * > .al-work { display: grid; grid-template-rows: auto 1fr; block-size: 100%; }

/* Blocs seuls : les quatre bords sur les lignes. */
.al-site .al-deck__card,
.al-site .al-cta {
  border-radius: 0;
  box-shadow: inset 1px 1px 0 0 var(--al-rule), 1px 1px 0 0 var(--al-rule);
}
.al-site .al-deck__visual { border-radius: 0; }

/* Pile des metiers : l'ecart entre deux cartes est une case, et en mode
   empile la marge de defilement est arrondie au pas. */
.al-site .al-deck { gap: var(--al-grid-size); }
@media (min-width: 992px) {
  .al-site .al-deck.is-stackable { gap: 0; }
  .al-site .al-deck.is-stackable .al-deck__card {
    margin-block-end: calc(var(--al-grid-size) * 6);
    margin-block-end: round(28vh, var(--al-grid-size));
  }
  .al-site .al-deck.is-stackable .al-deck__card:last-of-type { margin-block-end: 0; }
}

/* ==========================================================================
   38. CHIFFRES, METIERS ET METHODE SUR LA GRILLE
   --------------------------------------------------------------------------
   Trois sections redessinees dans la grammaire de la grille :
   - les chiffres se lisent comme un tableau de bord : un rang en haut, un
     repere de teinte pose sur la ligne du haut, le nombre en tres grand en
     bas de la piece, aligne a gauche ;
   - chaque metier devient une fiche coupee en deux par une ligne de la
     grille : le texte sur 11 cases, l'illustration sur 13, posee sur un
     papier quadrille au meme pas que le fond ;
   - la methode est une frise : une piste court sur une ligne de la grille
     d'un bout a l'autre du groupe, chaque etape y pose son jalon centre sur
     une intersection, et finit par ce qu'elle livre.
   ========================================================================== */

/* -- Chiffres ------------------------------------------------------------- */
.al-site .al-proof { counter-reset: al-preuve; }
.al-site .al-proof__card {
  position: relative;
  counter-increment: al-preuve;
  align-items: flex-start;
  text-align: start;
  min-block-size: calc(var(--al-grid-size) * 5);
  padding: var(--al-space-5);
}
.al-site .al-proof__card::before {
  content: counter(al-preuve, decimal-leading-zero);
  font-family: var(--al-font-mono);
  font-size: 11px;
  font-weight: var(--al-fw-bold);
  letter-spacing: .14em;
  color: var(--al-text-subtle);
}
/* Le repere : deux cases de teinte sur la ligne du haut. */
.al-site .al-proof__card::after {
  content: "";
  position: absolute;
  inset-block-start: 0;
  inset-inline-start: 0;
  inline-size: calc(var(--al-grid-size) * 2);
  block-size: 2px;
  background: var(--tint);
}
.al-site .al-proof__icon {
  position: absolute;
  inset-block-start: calc(var(--al-space-5) - .3rem);
  inset-inline-end: var(--al-space-5);
  inline-size: auto;
  block-size: auto;
  border-radius: 0;
  background: none;
  box-shadow: none;
  color: var(--tint);
  font-size: 1.15rem;
}
.al-site .al-proof__value {
  margin-block-start: auto;
  padding-block-start: var(--al-space-6);
  font-size: clamp(2.75rem, 1.6rem + 3.4vw, 5rem);
}
.al-site .al-proof__label {
  max-inline-size: 24ch;
  line-height: 1.5;
}

/* -- Metiers -------------------------------------------------------------- */
.al-site .al-deck__card { padding: 0; overflow: hidden; }
.al-site .al-deck__inner { gap: 0; align-items: stretch; }
.al-site .al-deck__body { padding: clamp(1.5rem, 4vw, 3.5rem) clamp(1.25rem, 4vw, 3.5rem); }

.al-site .al-deck__visual {
  display: grid;
  place-items: center;
  background-color: var(--al-canvas);
  background-image:
    linear-gradient(var(--al-grid-line) 1px, transparent 1px),
    linear-gradient(90deg, var(--al-grid-line) 1px, transparent 1px);
  background-size: var(--al-grid-size) var(--al-grid-size);
  box-shadow: inset 0 1px 0 var(--al-rule);
}
.al-site .al-deck__visual .al-illu { inline-size: 100%; }

@media (min-width: 992px) {
  /* 11 cases de texte, 13 d'image : la coupure tombe sur une ligne. */
  .al-site .al-deck__inner { grid-template-columns: minmax(0, 11fr) minmax(0, 13fr); }
  .al-site .al-deck__card--flip .al-deck__inner { grid-template-columns: minmax(0, 13fr) minmax(0, 11fr); }
  .al-site .al-deck__body { align-self: center; }
  .al-site .al-deck__visual { box-shadow: inset 1px 0 0 var(--al-rule); }
  .al-site .al-deck__card--flip .al-deck__visual { box-shadow: inset -1px 0 0 var(--al-rule); }
}

/* Le numero du metier dans une case de sa teinte : plus de filet. */
.al-site .al-deck__kicker { align-items: center; }
.al-site .al-deck__kicker b {
  display: inline-grid;
  place-items: center;
  flex: none;
  min-inline-size: 2.25rem;
  block-size: 2.25rem;
  padding-inline: .4rem;
  letter-spacing: .04em;
  color: var(--hue);
  background: color-mix(in srgb, var(--hue) 12%, var(--al-surface));
  box-shadow: inset 0 0 0 1px var(--hue);
}
.al-site .al-deck__kicker span::after { display: none; }

/* -- Methode -------------------------------------------------------------- */
.al-frise {
  margin: 0;
  padding: 0;
  list-style: none;
}
.al-etape {
  --e: var(--al-azur-600);
  position: relative;
  display: flex;
  flex-direction: column;
}
.al-etape--magenta { --e: var(--al-magenta-600); }
.al-etape--solaire { --e: var(--al-solaire-700); }
[data-bs-theme="dark"] .al-etape          { --e: var(--al-azur-300); }
[data-bs-theme="dark"] .al-etape--magenta { --e: var(--al-magenta-300); }
[data-bs-theme="dark"] .al-etape--solaire { --e: var(--al-solaire-300); }

/* La piste : deux cases de haut, son trait sur la ligne du milieu. Le
   jalon et le pictogramme sont centres sur des intersections. */
.al-etape__piste {
  position: relative;
  block-size: calc(var(--al-grid-size) * 2);
}
.al-etape__piste::before,
.al-etape__piste::after {
  content: "";
  position: absolute;
  inset-inline: 0;
  /* Moins le pixel de retrait de la piece : le trait tombe sur la ligne. */
  inset-block-start: calc(var(--al-grid-size) - 1px);
  block-size: 1px;
  background: var(--al-border-strong);
}
.al-etape__piste::after {
  block-size: 2px;
  background: var(--e);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform var(--al-dur-slow) var(--al-ease-out-expo);
}
.al-etape:hover .al-etape__piste::after { transform: scaleX(1); }

.al-etape__jalon,
.al-etape__icone {
  position: absolute;
  z-index: 1;
  inset-block-start: calc(var(--al-grid-size) / 2);
  display: grid;
  place-items: center;
  inline-size: var(--al-grid-size);
  block-size: var(--al-grid-size);
  background: var(--al-canvas);
}
.al-etape__jalon {
  inset-inline-start: calc(var(--al-grid-size) / 2);
  box-shadow: inset 0 0 0 1px var(--e);
  color: var(--e);
  font-family: var(--al-font-mono);
  font-size: 12px;
  font-weight: var(--al-fw-bold);
  letter-spacing: .04em;
}
.al-etape__icone {
  inset-inline-end: calc(var(--al-grid-size) / 2);
  color: var(--al-text-subtle);
  font-size: 1.05rem;
  transition: color var(--al-dur-fast) linear;
}
/* La piece s'eclaire au survol : jalon et pictogramme suivent son fond. */
.al-site .al-features > .al-etape:hover .al-etape__icone { background: var(--al-surface-sunken); color: var(--e); }
.al-site .al-features > .al-etape:hover .al-etape__jalon { background: color-mix(in srgb, var(--e) 16%, var(--al-surface-sunken)); }

.al-etape__corps { padding: var(--al-space-3) calc(var(--al-grid-size) / 2) var(--al-space-5); }
.al-etape__titre {
  margin: 0 0 var(--al-space-2);
  font-size: var(--al-fs-h4);
  color: var(--al-text-strong);
}
.al-etape__texte { margin: 0; font-size: var(--al-fs-sm); color: var(--al-text-muted); }

.al-etape__livrable {
  margin: auto 0 0;
  padding: var(--al-space-4) calc(var(--al-grid-size) / 2);
  box-shadow: inset 0 1px 0 var(--al-rule);
  font-size: var(--al-fs-sm);
  font-weight: var(--al-fw-semibold);
  color: var(--al-text-strong);
}
.al-etape__livrable span {
  display: block;
  margin-block-end: .25rem;
  font-family: var(--al-font-mono);
  font-size: 11px;
  font-weight: var(--al-fw-medium);
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--e);
}

@media (prefers-reduced-motion: reduce) {
  .al-etape__piste::after { transition: none; }
}

/* ==========================================================================
   39. ASSU, LE GUIDE DU SITE
   --------------------------------------------------------------------------
   La main tiree de l'icone (element assu.php, script al-assu.js). Elle se
   tient sur le bord bas de l'ecran, en bas a droite : le bas de l'anneau et
   celui de la barre touchent le sol, et c'est entre ces deux appuis qu'elle
   pivote et respire. Discrete, elle se baisse et seuls ses doigts depassent.
   La bulle reprend les codes du site : cadre d'un pixel, angles vifs,
   libelle en capitales monospace, liseré de la couleur du type de message.
   ========================================================================== */
.al-assu {
  --assu-largeur: 96px;
  position: fixed;
  inset-inline-end: max(var(--al-space-4), env(safe-area-inset-right, 0px));
  inset-block-end: 0;
  z-index: calc(var(--al-z-navbar) - 10);
  display: flex;
  align-items: flex-end;
  gap: var(--al-space-2);
  max-inline-size: calc(100vw - 2 * var(--al-space-4));
  pointer-events: none;
}
.al-assu[hidden] { display: none; }
.al-assu > * { pointer-events: auto; }

/* Le personnage. La boite du dessin s'arrete au sol. */
.al-assu__perso {
  flex: none;
  inline-size: var(--assu-largeur);
  aspect-ratio: 620 / 571;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  transition: translate .5s cubic-bezier(.3, 1.3, .5, 1);
  animation: assu-arrive .7s cubic-bezier(.3, 1.3, .5, 1) both;
}
.al-assu__perso:focus-visible { outline: 2px solid var(--al-focus-ring); outline-offset: 4px; }
.al-assu__perso svg { display: block; inline-size: 100%; block-size: 100%; overflow: visible; }
.al-assu.est-discret .al-assu__perso,
.al-assu.est-au-pied .al-assu__perso { translate: 0 64%; }
.al-assu.est-au-pied .al-assu__bulle { display: none; }
@keyframes assu-arrive { from { translate: 0 110%; } }
@media (max-width: 991.98px) { .al-assu { --assu-largeur: 80px; } }
@media (max-width: 575.98px) { .al-assu { --assu-largeur: 64px; } }

/* Couleurs du dessin : encre du logo, noire en clair et blanche en sombre. */
.al-assu-dessin .m-paume { fill: var(--al-canvas); }
.al-assu-dessin .m-anneau { stroke: var(--al-text-strong); }
.al-assu-dessin .m-bras { fill: var(--al-text-strong); }
.al-assu-dessin .m-blanc { fill: #fff; }
.al-assu-dessin .m-pupilles circle,
.al-assu-dessin .m-bouche--pleine { fill: var(--al-ink-950); }
.al-assu-dessin .m-bouche { fill: none; stroke: var(--al-ink-950); stroke-linecap: round; }
.al-assu-dessin .m-bouche--pleine { stroke: var(--al-ink-950); stroke-linejoin: round; }
.al-assu-dessin .m-trait { fill: none; stroke: #fff; stroke-linecap: round; }
.al-assu-dessin .m-zzz { fill: var(--al-text-strong); font-family: var(--al-font-mono); font-weight: 700; }

/* Mecanique : tout pivote en coordonnees du dessin. */
.al-assu-dessin * { transform-box: view-box; }
.al-assu-dessin .m-main { transform-origin: 410px 531px; transition: rotate .45s cubic-bezier(.3, 1.2, .5, 1); }
.al-assu-dessin .m-corps { transform-origin: 410px 531px; animation: assu-respire 3.4s ease-in-out infinite; }
.al-assu-dessin .m-doigt {
  transform-origin: 319.42px 324.11px;
  transition: scale .3s cubic-bezier(.3, 1.3, .5, 1), rotate .3s cubic-bezier(.3, 1.3, .5, 1);
}
.al-assu-dessin .m-visage { transform-origin: 319.42px 324.11px; transition: scale .3s cubic-bezier(.2, .8, .2, 1); }
.al-assu-dessin .m-yeux { transform-origin: 319.42px 306px; transition: transform .08s linear; }
.al-assu-dessin .m-pupilles { transition: transform .14s linear; }
.al-assu-dessin.cligne .m-yeux { transform: scaleY(.08); }

/* Visages selon la pose. */
.al-assu-dessin .m-contents, .al-assu-dessin .m-fermes,
.al-assu-dessin .m-b-grand, .al-assu-dessin .m-b-o, .al-assu-dessin .m-b-plat, .al-assu-dessin .m-zzz { display: none; }
.al-assu-dessin[data-etat="content"] .m-ouverts,
.al-assu-dessin[data-etat="dort"] .m-ouverts { display: none; }
.al-assu-dessin[data-etat="content"] .m-contents { display: inline; }
.al-assu-dessin[data-etat="dort"] .m-fermes { display: inline; }
.al-assu-dessin[data-etat="content"] .m-b-sourire, .al-assu-dessin[data-etat="salut"] .m-b-sourire,
.al-assu-dessin[data-etat="etonne"] .m-b-sourire, .al-assu-dessin[data-etat="dort"] .m-b-sourire,
.al-assu-dessin[data-etat="reflechit"] .m-b-sourire { display: none; }
.al-assu-dessin[data-etat="content"] .m-b-grand, .al-assu-dessin[data-etat="salut"] .m-b-grand { display: inline; }
.al-assu-dessin[data-etat="etonne"] .m-b-o { display: inline; }
.al-assu-dessin[data-etat="dort"] .m-b-plat, .al-assu-dessin[data-etat="reflechit"] .m-b-plat { display: inline; }

/* Salue : la main se balance sur ses appuis, les doigts fretillent. */
.al-assu-dessin[data-etat="salut"] .m-main { animation: assu-balance 1.1s ease-in-out 2; }
.al-assu-dessin[data-etat="salut"] .m-doigt { animation: assu-fretille .36s ease-in-out 6 alternate; }
.al-assu-dessin[data-etat="salut"] .m-d2 { animation-delay: .08s; }
.al-assu-dessin[data-etat="salut"] .m-d3 { animation-delay: .16s; }
/* Designe : il penche vers le contenu, deux doigts tendus. */
.al-assu-dessin[data-etat="designe"] .m-main { rotate: -12deg; }
.al-assu-dessin[data-etat="designe"] .m-d1, .al-assu-dessin[data-etat="designe"] .m-d2 { scale: 1.16; }
.al-assu-dessin[data-etat="designe"] .m-d3 { scale: .84; }
/* Compte : poing ferme, puis un, deux, trois doigts. */
.al-assu-dessin[data-etat="compte"] .m-d3 { animation: assu-compte-1 3s ease-in-out infinite; }
.al-assu-dessin[data-etat="compte"] .m-d2 { animation: assu-compte-2 3s ease-in-out infinite; }
.al-assu-dessin[data-etat="compte"] .m-d1 { animation: assu-compte-3 3s ease-in-out infinite; }
/* Reflechit : les doigts pianotent. */
.al-assu-dessin[data-etat="reflechit"] .m-doigt { animation: assu-pianote 1.1s ease-in-out infinite; }
.al-assu-dessin[data-etat="reflechit"] .m-d2 { animation-delay: .14s; }
.al-assu-dessin[data-etat="reflechit"] .m-d1 { animation-delay: .28s; }
.al-assu-dessin[data-etat="reflechit"] .m-main { rotate: 4deg; }
/* Content : il saute, doigts ouverts. */
.al-assu-dessin[data-etat="content"] .m-corps { animation: assu-saute .62s cubic-bezier(.3, .7, .4, 1) 3; }
.al-assu-dessin[data-etat="content"] .m-doigt { scale: 1.14; }
.al-assu-dessin[data-etat="content"] .m-d1 { rotate: 8deg; }
.al-assu-dessin[data-etat="content"] .m-d3 { rotate: -8deg; }
/* Etonne : doigts ecartes au maximum. */
.al-assu-dessin[data-etat="etonne"] .m-doigt { scale: 1.26; }
.al-assu-dessin[data-etat="etonne"] .m-visage { scale: 1.06; }
.al-assu-dessin[data-etat="etonne"] .m-corps { animation: assu-sursaut .4s ease-out 1; }
/* Dort : poing ferme, il s'affaisse un peu. */
.al-assu-dessin[data-etat="dort"] .m-doigt { scale: .84; }
.al-assu-dessin[data-etat="dort"] .m-main { rotate: 5deg; }
.al-assu-dessin[data-etat="dort"] .m-corps { animation-duration: 5.5s; }
.al-assu-dessin[data-etat="dort"] .m-zzz { display: inline; }
.al-assu-dessin .m-zzz text { animation: assu-zzz 2.6s ease-in-out infinite; }
.al-assu-dessin .m-zzz text:nth-child(2) { animation-delay: 1.3s; }

@keyframes assu-respire { 0%, 100% { scale: 1 1; } 50% { scale: 1.012 .986; } }
@keyframes assu-balance { 0%, 100% { rotate: 0deg; } 25% { rotate: 8deg; } 75% { rotate: -6deg; } }
@keyframes assu-fretille { from { rotate: -7deg; } to { rotate: 7deg; } }
@keyframes assu-compte-1 { 0%, 12% { scale: .84; } 22%, 86% { scale: 1.14; } 96%, 100% { scale: .84; } }
@keyframes assu-compte-2 { 0%, 34% { scale: .84; } 44%, 86% { scale: 1.14; } 96%, 100% { scale: .84; } }
@keyframes assu-compte-3 { 0%, 56% { scale: .84; } 66%, 86% { scale: 1.14; } 96%, 100% { scale: .84; } }
@keyframes assu-pianote { 0%, 60%, 100% { scale: 1; } 30% { scale: .9; } }
@keyframes assu-saute {
  0%, 100% { translate: 0 0; scale: 1 1; }
  18% { translate: 0 0; scale: 1.06 .9; }
  50% { translate: 0 -70px; scale: .96 1.05; }
  82% { translate: 0 0; scale: 1.05 .93; }
}
@keyframes assu-sursaut { 30% { translate: 0 -26px; } }
@keyframes assu-zzz {
  0% { opacity: 0; transform: translate(0, 20px); }
  30% { opacity: 1; }
  100% { opacity: 0; transform: translate(30px, -40px); }
}

/* La bulle, a gauche du personnage, sa pointe vers lui. */
.al-assu__bulle {
  position: relative;
  inline-size: min(320px, calc(100vw - var(--assu-largeur) - 3 * var(--al-space-4)));
  margin-block-end: calc(var(--assu-largeur) * .55);
  padding: var(--al-space-4) var(--al-space-4) var(--al-space-4);
  display: grid;
  gap: var(--al-space-2);
  background: var(--al-canvas);
  box-shadow: inset 0 0 0 1px var(--al-text-strong);
  transform-origin: 100% 100%;
}
.al-assu__bulle[hidden] { display: none; }
.al-assu__bulle.is-entree { animation: assu-bulle .32s cubic-bezier(.2, .8, .2, 1); }
.al-assu__bulle::before {
  content: "";
  position: absolute;
  inset: 0 0 auto;
  block-size: 3px;
  background: var(--assu-teinte, var(--al-text-strong));
}
.al-assu__bulle::after {
  content: "";
  position: absolute;
  inset-inline-end: -9px;
  inset-block-end: var(--al-space-4);
  inline-size: 9px;
  block-size: 14px;
  background: var(--al-text-strong);
  clip-path: polygon(0 0, 100% 100%, 0 100%);
}
.al-assu__bulle[data-type="suggestion"] { --assu-teinte: var(--al-azur-500); }
.al-assu__bulle[data-type="question"] { --assu-teinte: var(--al-magenta-500); }
.al-assu__bulle[data-type="explication"] { --assu-teinte: var(--al-solaire-500); }
@keyframes assu-bulle { from { opacity: 0; transform: scale(.92) translateY(8px); } }

.al-assu__type {
  margin: 0;
  font-family: var(--al-font-mono);
  font-size: 11px;
  font-weight: var(--al-fw-bold);
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--al-text-muted);
}
.al-assu__texte {
  margin: 0;
  padding-inline-end: var(--al-space-4);
  font-size: var(--al-fs-sm);
  line-height: 1.45;
  color: var(--al-text-strong);
}
.al-assu__actions { display: flex; flex-wrap: wrap; gap: 6px; }
.al-assu__actions:empty { display: none; }
.al-assu__action {
  display: inline-flex;
  align-items: center;
  padding: .5rem .75rem;
  border: 0;
  background: var(--al-canvas);
  box-shadow: inset 0 0 0 1px var(--al-rule);
  color: var(--al-text-strong);
  font: var(--al-fw-semibold) 13px/1 var(--al-font-body);
  text-decoration: none;
  cursor: pointer;
}
.al-assu__action:first-child { background: var(--al-text-strong); color: var(--al-canvas); box-shadow: none; }
.al-assu__action:hover { box-shadow: inset 0 0 0 1px var(--al-text-strong); }
.al-assu__action:focus-visible,
.al-assu__fermer:focus-visible { outline: 2px solid var(--al-focus-ring); outline-offset: 2px; }
.al-assu__fermer {
  position: absolute;
  inset-block-start: 6px;
  inset-inline-end: 6px;
  display: grid;
  place-items: center;
  inline-size: 32px;
  block-size: 32px;
  padding: 0;
  border: 0;
  background: none;
  color: var(--al-text-muted);
  font-size: 12px;
  cursor: pointer;
}
.al-assu__fermer:hover { color: var(--al-text-strong); }

/* Telephone : la bulle passe au-dessus, sur toute la largeur. */
@media (max-width: 575.98px) {
  .al-assu { flex-direction: column; align-items: flex-end; inset-inline-start: var(--al-space-4); }
  .al-assu__bulle { inline-size: 100%; margin-block-end: 0; }
  .al-assu__bulle::after {
    inset-inline-end: calc(var(--assu-largeur) * .3);
    inset-block-end: -9px;
    inline-size: 14px;
    block-size: 9px;
    clip-path: polygon(0 0, 100% 0, 100% 100%);
  }
}

@media (prefers-reduced-motion: reduce) {
  .al-assu-dessin *, .al-assu__perso { animation: none !important; transition: none !important; }
  .al-assu-dessin[data-etat="salut"] .m-main { rotate: 6deg; }
  .al-assu-dessin[data-etat="compte"] .m-doigt { scale: 1.14; }
  .al-assu-dessin .m-zzz text { opacity: 1; }
}

@media print { .al-assu { display: none; } }

/* Le dessin pose dans une page (404, charte) : sans script, il cligne seul,
   et les poses courtes rejouent en boucle pour rester lisibles. */
.al-assu-scene {
  display: block;
  inline-size: var(--assu-largeur, 160px);
  max-inline-size: 100%;
  aspect-ratio: 620 / 571;
}
.al-assu-scene svg { display: block; inline-size: 100%; block-size: 100%; overflow: visible; }
.al-assu-scene .m-yeux { animation: assu-cligne 5.2s steps(1, end) infinite; }
.al-assu-scene[data-etat="salut"] .m-main { animation-iteration-count: infinite; animation-delay: 1.2s; }
.al-assu-scene[data-etat="salut"] .m-doigt { animation-iteration-count: infinite; }
.al-assu-scene[data-etat="content"] .m-corps { animation-iteration-count: infinite; animation-duration: 1.4s; }
.al-assu-scene[data-etat="etonne"] .m-corps { animation: assu-sursaut 2.8s ease-out infinite; }
@keyframes assu-cligne { 0%, 96% { transform: scaleY(1); } 97%, 99% { transform: scaleY(.08); } }

/* Page introuvable : Assu, etonne, pose sur le code d'erreur. */
.al-erreur-assu { --assu-largeur: clamp(120px, 22vw, 180px); margin: 0 auto var(--al-space-4); }

@media (prefers-reduced-motion: reduce) {
  .al-assu-scene .m-yeux { animation: none; }
}
