/* ASHA Solution — Redesign stylesheet
   Loads after css/tokens.css. Uses tokens defined there.
*/

/* ── Reset + base ─────────────────────────────────────────────── */

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

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

body {
  margin: 0;
  font-family: var(--font-sans);
  font-size: var(--text-base);
  line-height: var(--leading-body);
  color: var(--color-fg);
  background: var(--color-bg);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

img, svg { max-width: 100%; height: auto; display: block; }

a { color: inherit; text-decoration: none; transition: color var(--duration-fast) var(--ease-out); }
a:hover { color: var(--color-primary); }

button { font-family: inherit; cursor: pointer; }

:focus-visible {
  outline: 2px solid var(--color-ring);
  outline-offset: 3px;
  border-radius: 2px;
}

/* ── Skip-to-content link (WCAG 2.4.1) ────────────────────────── */
.skip-link {
  position: absolute;
  top: -120px;
  left: var(--space-4);
  z-index: var(--z-toast);
  padding: 12px 18px;
  background: var(--color-primary);
  color: var(--color-fg);
  font-weight: 600;
  font-size: var(--text-sm);
  text-decoration: none;
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-lg);
  transition: top var(--duration-normal) var(--ease-out);
}
.skip-link:focus,
.skip-link:focus-visible {
  top: var(--space-3);
  outline: 2px solid var(--color-fg);
  outline-offset: 2px;
}

h1, h2, h3, h4, h5, h6 {
  margin: 0 0 var(--space-4);
  font-weight: 700;
  line-height: var(--leading-tight);
  letter-spacing: -0.02em;
}

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

/* ── Layout primitives ────────────────────────────────────────── */

.container {
  width: 100%;
  max-width: var(--container-max);
  margin-inline: auto;
  padding-inline: var(--container-px);
}

.section {
  padding-block: var(--space-24);
}
@media (max-width: 768px) {
  .section { padding-block: var(--space-16); }
}

.section--dark  { background: var(--color-bg);    color: var(--color-fg); }
.section--light { background: var(--color-bg-light); color: var(--color-fg-light); }

.eyebrow {
  display: inline-block;
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  /* Mesure du 2026-08-12 : --color-primary #DC2626 a 12 px sur le navy donne
     3,94:1 pour un seuil de 4,5. Douze pixels en gras ne sont PAS du texte
     large (seuil 3:1 a partir de 18,66 px en gras) : cet eyebrow etait donc en
     echec partout sur le site, huit fois sur la seule page d'accueil.
     --color-primary-lift #EF4444 mesure 5,05:1 sur le meme navy, meme teinte,
     saturation conservee. */
  color: var(--color-primary-lift);
  margin-bottom: var(--space-4);
}
/* Sur fond clair la mesure s'inverse : #DC2626 sur #F8FAFC donne 4,62:1 et
   passe, tandis que #EF4444 y tombe a 3,58:1. Le rouge de base reste donc
   l'encre de l'eyebrow sur les sols clairs. */
.section--light .eyebrow { color: var(--color-primary-ink); }

/* ── Buttons ──────────────────────────────────────────────────── */

.btn {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: 14px 26px;
  border-radius: var(--radius-md);
  font-weight: 600;
  font-size: var(--text-base);
  letter-spacing: -0.01em;
  border: 1px solid transparent;
  transition: all var(--duration-normal) var(--ease-out);
  white-space: nowrap;
  cursor: pointer;
}
.btn:hover { color: var(--color-fg); transform: translateY(-1px); }
.btn .icon { width: 18px; height: 18px; }

.btn-primary {
  background: var(--color-primary);
  color: var(--color-fg);
}
.btn-primary:hover {
  background: var(--color-primary-hover);
  box-shadow: var(--glow-primary);
}

.btn-secondary {
  background: rgba(255, 255, 255, 0.03);
  color: var(--color-fg);
  border-color: var(--color-border-strong);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  /* Liquid Glass refraction */
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.06),
    inset 0 0 0 1px rgba(255, 255, 255, 0.02);
}
.btn-secondary:hover {
  border-color: rgba(255,255,255,0.4);
  background: rgba(255,255,255,0.06);
  color: var(--color-fg);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.10),
    inset 0 0 0 1px rgba(255, 255, 255, 0.04);
}
.section--light .btn-secondary {
  color: var(--color-fg-light);
  border-color: var(--color-border-light);
}
.section--light .btn-secondary:hover {
  background: rgba(0,0,0,0.04);
  color: var(--color-fg-light);
}

/* ── Header ───────────────────────────────────────────────────── */

.site-header {
  position: sticky;
  top: 0;
  z-index: var(--z-header);
  background: rgba(16, 16, 16, 0.85);
  backdrop-filter: saturate(160%) blur(12px);
  -webkit-backdrop-filter: saturate(160%) blur(12px);
  border-bottom: 1px solid var(--color-border);
}
.site-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-6);
  height: var(--header-h);
}
.site-header__brand {
  display: inline-flex;
  align-items: center;
  flex: 0 0 auto;
}
.site-header__logo {
  height: 40px;
  width: auto;
  border-radius: 4px;
}

.main-nav { display: none; }
@media (min-width: 1024px) {
  .main-nav { display: block; }
}
.main-nav__list {
  display: flex;
  gap: var(--space-2);
  list-style: none;
  margin: 0;
  padding: 0;
}
.main-nav__link {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 10px 14px;
  border-radius: var(--radius-md);
  font-weight: 500;
  font-size: var(--text-sm);
  color: var(--color-fg);
  transition: all var(--duration-fast) var(--ease-out);
}
.main-nav__link:hover,
.main-nav__link.is-active {
  color: var(--color-primary);
  background: rgba(220, 38, 38, 0.08);
}
.main-nav__link .icon { width: 14px; height: 14px; opacity: 0.7; }

.main-nav__item--has-children { position: relative; }
.main-nav__submenu {
  position: absolute;
  top: calc(100% + 8px);
  left: 0;
  min-width: 320px;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: var(--space-2);
  box-shadow: var(--shadow-lg);
  list-style: none;
  margin: 0;
  opacity: 0;
  visibility: hidden;
  transform: translateY(-4px);
  transition: all var(--duration-normal) var(--ease-out);
}
.main-nav__item--has-children:hover .main-nav__submenu,
.main-nav__item--has-children:focus-within .main-nav__submenu {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
}
.main-nav__submenu a {
  display: block;
  padding: 10px 14px;
  border-radius: var(--radius-sm);
  font-size: var(--text-sm);
  color: var(--color-fg);
  transition: background var(--duration-fast) var(--ease-out);
}
.main-nav__submenu a:hover {
  background: rgba(255,255,255,0.06);
  color: var(--color-primary);
}

.site-header__cta {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
}
.site-header__cta .btn { padding: 10px 18px; font-size: var(--text-sm); }

.mobile-menu-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px; height: 40px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: transparent;
  color: var(--color-fg);
}
@media (min-width: 1024px) {
  .mobile-menu-toggle { display: none; }
}
.mobile-menu-toggle .icon { width: 20px; height: 20px; }

/* ── Hero ─────────────────────────────────────────────────────── */

.hero {
  position: relative;
  overflow: hidden;
  min-height: 100vh;            /* fallback */
  min-height: 100dvh;           /* iOS Safari fix */
  display: flex;
  align-items: center;
  /* Padding reduit (le titre garde sa taille) : avec la rangee de chips et le
     bloc de confiance du bas supprimes, c'est le padding qui empechait encore
     le bandeau de logos d'affleurer au bas du premier ecran. */
  padding: clamp(92px, 10.5vw, 120px) 0 clamp(30px, 3.8vw, 44px);
  background:
    /* Brand red on the upper-left to spotlight the H1/eyebrow */
    radial-gradient(ellipse 55% 60% at 18% 8%,  rgba(220, 38, 38, 0.20), transparent 60%),
    /* Cyan accent matched on intensity & moved to upper-right so the SOC panel
       breathes inside a glow instead of floating in the dark */
    radial-gradient(ellipse 55% 55% at 88% 22%, rgba(  6,182,212, 0.18), transparent 60%),
    /* A second cyan beat lower-right keeps the right column "alive" all the way
       down to the trust strip — fixes the visual hole the user noticed */
    radial-gradient(ellipse 45% 45% at 92% 72%, rgba(  6,182,212, 0.10), transparent 60%),
    /* Soft floor that fades into the next section */
    radial-gradient(ellipse at 50% 100%, rgba(226, 232, 240, 0.05), transparent 45%),
    var(--color-bg);
  isolation: isolate;
}
.hero__inner {
  width: 100%;
}
.hero::before {
  /* Meme grille que le hero des autres pages (.page-hero__bg-grid) : carres de
     64 px, lignes blanches, masque radial. Elle remplace l'ancienne grille
     rouge a 5 %, invisible en pratique. */
  content: '';
  position: absolute; inset: 0;
  background-image:
    linear-gradient(rgba(255,255,255,0.07) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255,255,255,0.07) 1px, transparent 1px);
  background-size: 64px 64px;
  /* Masque etendu vers la gauche : la grille se lit sur la zone sombre du
     visuel, la ou vit le texte, et s'efface sur le cadenas pour ne pas le
     quadriller. */
  mask-image: linear-gradient(to right, black 0%, black 45%, transparent 78%);
  -webkit-mask-image: linear-gradient(to right, black 0%, black 45%, transparent 78%);
  /* Recalibree le 2026-08-11 : elle etait montee a 0,12 x 0,8 tant que le visuel
     de fond etait OPAQUE et la concurrencait. Depuis que .hero__bg-img est passe
     a 0,55 comme sur les autres pages, la grille se lit sans etre forcee. On
     reste juste au-dessus du canon (0,04 x 0,4) parce qu'il y a une image
     dessous et pas un degrade lisse. */
  opacity: 0.55;
  pointer-events: none;
  /* 1 et non 0 : le visuel du hero est une image OPAQUE, egalement en z-index 0
     mais placee apres dans le DOM, donc elle recouvrait la grille et on ne la
     voyait plus. La grille doit se poser PAR-DESSUS le visuel. */
  z-index: 1;
}
.hero::after {
  /* Bottom fade into next section.
     HAUTEUR RAMENEE DE 220 A 110 PX — 2026-09-06, en deux fois a la demande
     de Gabriel : d abord 150, puis « reduit encore un peu ». Moitie moins que
     l origine. Le bas de l animation, ses trainees lumineuses et le circuit
     restent visibles presque jusqu au bord.
     Le point d arrivee du degrade est passe de 85 a 96 % pour la meme raison :
     sur une course deux fois plus courte, atteindre le noir a 85 % gaspillait
     le dernier tiers en aplat.
     PLANCHER A CONNAITRE : la bande qui suit est BLANCHE (les logos clients).
     Sous ~80 px, la course ne suffit plus a amener le noir du hero au blanc
     sans que la jonction se lise comme un trait. 110 garde de la marge.
     ATTENTION SI TU Y REVIENS : `.hero__inner` porte `z-index: 5` uniquement
     a cause de ce degrade, qui est en z-index 2 et recouvrait la plaque des
     sceaux. Changer la hauteur ne touche pas cette logique, la supprimer si. */
  content: '';
  position: absolute; bottom: 0; left: 0; right: 0; height: 110px;
  background: linear-gradient(to bottom, transparent, var(--color-bg) 96%);
  pointer-events: none;
  z-index: 2;
}

/* Neural network canvas */
.hero__canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  z-index: 1;
  /* Soft fade only at very edges — keep most of the network visible */
  mask-image: radial-gradient(ellipse 130% 110% at center 50%, black 60%, transparent 100%);
  -webkit-mask-image: radial-gradient(ellipse 130% 110% at center 50%, black 60%, transparent 100%);
}

/* .hero__scan retire le 2026-08-11.
   C'etait une bande de blanc a 75 % en mix-blend-mode screen, haute de 14 % du
   hero, animee sur 7 s en boucle : elle balayait toute la section et traversait
   donc le H1 une fois par cycle, delavant « ataques sofisticados ». Un effet qui
   rend le titre illisible une seconde sur sept n'est pas un effet.
   La regle ET l'element du DOM sont supprimes, pas masques, pour ne pas laisser
   une animation qui tourne derriere un display:none. */

/* Center vignette — light, just enough to ground text without killing particles */
.hero__vignette {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 2;
  background:
    radial-gradient(ellipse 60% 50% at center 50%, rgba(16, 16, 16,0.35) 0%, transparent 70%);
}

/* Scroll indicator at the bottom of hero */
.hero__scroll {
  position: absolute;
  left: 50%;
  bottom: 28px;
  transform: translateX(-50%);
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--color-muted);
  text-decoration: none;
  z-index: 5;
  opacity: 0.85;
  transition: opacity var(--duration-fast) var(--ease-out);
}
.hero__scroll:hover { opacity: 1; color: var(--color-fg); }
.hero__scroll-mouse {
  width: 22px;
  height: 36px;
  border: 1.5px solid rgba(255,255,255,0.5);
  border-radius: 12px;
  position: relative;
  box-shadow: 0 0 16px rgba(220,38,38,0.25);
}
.hero__scroll-mouse::before {
  content: '';
  position: absolute;
  top: 6px; left: 50%;
  width: 3px; height: 8px;
  background: var(--color-primary);
  border-radius: 2px;
  transform: translateX(-50%);
  animation: hero-scroll-dot 1.8s cubic-bezier(0.4, 0, 0.2, 1) infinite;
  box-shadow: 0 0 6px rgba(220,38,38,0.45);
}
@keyframes hero-scroll-dot {
  0%   { transform: translate(-50%, 0); opacity: 0; }
  20%  { opacity: 1; }
  80%  { opacity: 1; }
  100% { transform: translate(-50%, 14px); opacity: 0; }
}

/* Title word reveal (used by hero-reveal.js) */
.hero__word,
.page-hero__word {
  display: inline-block;
  overflow: hidden;
  vertical-align: top;
  line-height: 1.05;
}
.hero__word-inner,
.page-hero__word-inner {
  display: inline-block;
  will-change: transform, opacity;
}
.hero__inner {
  position: relative;
  z-index: 5;
}
.hero__title,
.hero__eyebrow,
.hero__subtitle,
.hero__actions,
.hero__trust { position: relative; z-index: 6; }

@media (max-width: 700px) {
  .hero__canvas {
    mask-image: radial-gradient(ellipse 110% 80% at center 50%, black 25%, transparent 95%);
    -webkit-mask-image: radial-gradient(ellipse 110% 80% at center 50%, black 25%, transparent 95%);
  }
}
/* Hero une seule colonne (2026-08-11) : le panneau SOC a ete retire, le texte
   occupe la gauche et la composition de losanges tient la droite. La grille a
   2 colonnes n'a plus lieu d'etre. */
.hero__inner {
  position: relative;
  /* 5 et non 1 : .hero::after (le degrade de 220 px qui fond vers la section
     suivante) est en z-index 2. Le hero etant desormais plus court, la plaque
     des sceaux tombe dans cette zone et le degrade navy la recouvrait, ce qui
     rendait la plaque claire toute grise. Le contenu doit passer au-dessus. */
  z-index: 5;
  display: block;
  text-align: left;
  width: 100%;
}
.hero__col-left {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  max-width: 680px;
}
/* l'eyebrow doit tenir sur une ligne : le detail des normes est deja porte
   par les sceaux de la bande de confiance juste en dessous */
.hero__eyebrow { max-width: none; white-space: nowrap; }
@media (max-width: 760px) { .hero__eyebrow { white-space: normal; } }
.hero__col-left .hero__chips { justify-content: flex-start; }
.hero__col-left .hero__actions { justify-content: flex-start; }
.hero__col-left .hero__trust { justify-content: flex-start; }
/* l'eyebrow doit tenir sur une ligne : le detail des normes est deja porte
   par les sceaux de la bande de confiance juste en dessous */
.hero__eyebrow { max-width: none; white-space: nowrap; }
@media (max-width: 760px) { .hero__eyebrow { white-space: normal; } }
.hero__col-left .hero__chips { justify-content: flex-start; }
.hero__col-left .hero__actions { justify-content: flex-start; }
.hero__col-left .hero__trust { justify-content: flex-start; }

/* Status panel — Liquid Glass terminal v3 (SOC-grade professional) */
.hero__panel {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  padding: var(--space-4) var(--space-5) var(--space-4);
  background: linear-gradient(180deg, rgba(23, 23, 23, 0.55) 0%, rgba(16, 16, 16, 0.48) 100%);
  border: 1px solid rgba(255, 255, 255, 0.06);
  border-radius: 12px;
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  /* Liquid Glass refraction — saturate removed for perf */
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.08),
    inset 0 -1px 0 rgba(0, 0, 0, 0.35),
    0 20px 50px rgba(0, 0, 0, 0.40);
  overflow: hidden;
  isolation: isolate;
  will-change: auto;
}
/* Cyan glow detrás del panel para integrarlo con el bg orgánico (fix hueco) */
.hero__panel::after {
  content: '';
  position: absolute;
  inset: -40% -25% -40% -25%;
  background:
    radial-gradient(ellipse 60% 50% at 50% 50%, rgba(6, 182, 212, 0.18), transparent 70%);
  pointer-events: none;
  z-index: -2;
  filter: blur(20px);
}
/* Subtle scan-line decoration */
.hero__panel::before {
  content: '';
  position: absolute; inset: 0;
  background:
    repeating-linear-gradient(180deg, transparent 0px, transparent 2px, rgba(255, 255, 255, 0.012) 3px, transparent 4px);
  pointer-events: none;
  z-index: -1;
}

/* SESSION PROMPT LINE — auténtico shell prompt */
.hero__panel-session {
  font: 500 11.5px/1.2 var(--font-mono);
  letter-spacing: 0;
  padding-bottom: var(--space-3);
  border-bottom: 1px solid rgba(255, 255, 255, 0.05);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  opacity: 0;
  transform: translateX(-6px);
  animation: panel-line-in 500ms cubic-bezier(0.16, 1, 0.3, 1) 200ms forwards;
}
.hero__panel-user   { color: rgb(110, 231, 183); }
.hero__panel-sep    { color: rgba(255, 255, 255, 0.35); }
.hero__panel-path   { color: rgb(165, 243, 252); }
.hero__panel-dollar { color: rgba(255, 255, 255, 0.55); margin: 0 8px 0 6px; }
.hero__panel-cmd    { color: rgba(241, 245, 249, 0.92); }

/* HEADER (label + clock) */
.hero__panel-head {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding-bottom: var(--space-3);
  border-bottom: 1px solid rgba(255, 255, 255, 0.05);
  opacity: 0;
  animation: panel-fade-in 400ms cubic-bezier(0.16, 1, 0.3, 1) 600ms forwards;
}
.hero__panel-pulse {
  width: 7px; height: 7px;
  border-radius: 50%;
  background: rgb(34, 211, 238);
  box-shadow: 0 0 8px rgba(34, 211, 238, 0.7), inset 0 0 4px rgba(255,255,255,0.4);
  animation: hero-panel-pulse 2s ease-in-out infinite;
  flex-shrink: 0;
}
@keyframes hero-panel-pulse {
  0%, 100% { opacity: 1; transform: scale(1); }
  50%      { opacity: 0.55; transform: scale(0.82); }
}
.hero__panel-label {
  font: 600 10.5px/1 var(--font-mono);
  letter-spacing: 0.10em;
  color: rgba(203, 213, 225, 0.92);
  flex: 1;
}
.hero__panel-clock {
  font: 600 10px/1 var(--font-mono);
  letter-spacing: 0.06em;
  color: rgba(148, 163, 184, 0.75);
  font-variant-numeric: tabular-nums;
}

/* LIST — staggered streaming log */
.hero__panel-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0;
}
.hero__panel-list li {
  display: grid;
  grid-template-columns: 24px 92px 1fr;
  align-items: center;
  gap: var(--space-3);
  padding: 5px 0;
  border-bottom: 1px solid rgba(255, 255, 255, 0.025);
  transition: background 240ms var(--ease-out);
  opacity: 0;
  transform: translateX(-6px);
  animation: panel-line-in 500ms cubic-bezier(0.16, 1, 0.3, 1) forwards;
  animation-delay: calc(750ms + var(--i, 0) * 90ms);
}
@keyframes panel-line-in {
  to { opacity: 1; transform: translateX(0); }
}
@keyframes panel-fade-in {
  to { opacity: 1; }
}
.hero__panel-list li:last-child { border-bottom: 0; }
.hero__panel-list li:hover { background: rgba(6, 182, 212, 0.04); }
.hero__panel-ln {
  font: 600 9.5px/1 var(--font-mono);
  letter-spacing: 0.06em;
  color: rgba(148, 163, 184, 0.30);
  font-variant-numeric: tabular-nums;
}
.hero__panel-key {
  font: 600 10px/1 var(--font-mono);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: rgba(148, 163, 184, 0.72);
}
.hero__panel-val {
  font: 700 12px/1 var(--font-mono);
  letter-spacing: 0.04em;
  color: var(--color-fg);
  font-variant-numeric: tabular-nums;
  text-align: right;
  display: inline-flex;
  align-items: center;
  justify-content: flex-end;
  gap: 6px;
}
.hero__panel-val--ok {
  color: rgb(110, 231, 183);
}
.hero__panel-val small {
  font-size: 0.7em;
  color: rgba(148, 163, 184, 0.7);
  margin-left: 1px;
}
.hero__panel-check {
  width: 11px;
  height: 11px;
  color: rgb(34, 197, 94);
  flex-shrink: 0;
  filter: drop-shadow(0 0 4px rgba(34, 197, 94, 0.45));
}

/* FOOTER */
.hero__panel-foot {
  display: flex;
  align-items: center;
  gap: 8px;
  padding-top: var(--space-3);
  border-top: 1px solid rgba(255, 255, 255, 0.05);
  opacity: 0;
  animation: panel-fade-in 500ms cubic-bezier(0.16, 1, 0.3, 1) 1400ms forwards;
}
.hero__panel-foot .hero__panel-dollar {
  margin: 0;
  color: rgba(34, 211, 238, 0.85);
  font: 700 11px/1 var(--font-mono);
}
.hero__panel-foot-text {
  font: 600 10px/1 var(--font-mono);
  letter-spacing: 0.10em;
  color: rgba(134, 239, 172, 0.85);
  flex: 1;
}
/* Cursor — thin underscore (auténtico Unix, no block) */
.hero__panel-cursor {
  display: inline-block;
  width: 8px;
  height: 2px;
  background: rgba(34, 211, 238, 0.9);
  vertical-align: 2px;
  animation: hero-panel-cursor 1.05s steps(2) infinite;
}
@keyframes hero-panel-cursor {
  0%, 50%   { opacity: 1; }
  50.01%, 100% { opacity: 0; }
}

@media (max-width: 1023px) {
  .hero__panel { max-width: 480px; width: 100%; }
}
@media (max-width: 720px) {
  .hero__panel { padding: var(--space-4); }
  .hero__panel-list li { padding: 5px 0; grid-template-columns: 22px 84px 1fr; }
  .hero__panel-clock, .hero__panel-session { font-size: 10px; }
}
@media (prefers-reduced-motion: reduce) {
  .hero__panel-pulse, .hero__panel-cursor { animation: none; }
  .hero__panel-session, .hero__panel-head, .hero__panel-list li, .hero__panel-foot {
    opacity: 1 !important;
    transform: none !important;
    animation: none !important;
  }
}
.hero__eyebrow {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  padding: 8px 16px;
  background: rgba(220, 38, 38, 0.08);
  border: 1px solid rgba(220, 38, 38, 0.25);
  border-radius: var(--radius-full);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--color-danger-soft);
  margin-bottom: var(--space-6);
}
.hero__eyebrow .pulse {
  width: 8px; height: 8px;
  background: var(--color-primary);
  border-radius: 50%;
  box-shadow: 0 0 0 4px rgba(220,38,38,0.2);
  animation: pulse 2.4s ease-in-out infinite;
}
@keyframes pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(220,38,38,0.40); }
  50%      { box-shadow: 0 0 0 6px rgba(220,38,38,0.0); }
}

.hero__title {
  font-size: clamp(var(--text-4xl), 6vw, var(--text-6xl));
  line-height: 1.05;
  letter-spacing: -0.03em;
  font-weight: 800;
  margin-bottom: var(--space-6);
  color: #FFFFFF;
  text-shadow:
    0 0 32px rgba(255, 255, 255, 0.18),
    0 0 6px rgba(220, 38, 38, 0.35),
    0 2px 18px rgba(0, 0, 0, 0.45);
  position: relative;
  z-index: 10;
}
.hero__subtitle {
  font-size: clamp(var(--text-lg), 1.6vw, var(--text-xl));
  color: var(--color-muted);
  max-width: 640px;
  margin: 0 auto var(--space-8);
}
.hero__actions {
  display: inline-flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-3);
  margin-bottom: var(--space-12);
}
.hero__trust {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-6) var(--space-8);
  padding-top: var(--space-8);
  border-top: 1px solid var(--color-border);
  max-width: 760px;
  margin-inline: auto;
}
.hero__trust-label {
  width: 100%;
  font-size: var(--text-xs);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--color-muted);
  margin-bottom: var(--space-2);
}
.hero__trust-item {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--color-fg);
  opacity: 0.85;
  transition: opacity var(--duration-fast) var(--ease-out);
}
.hero__trust-item:hover { opacity: 1; }
.hero__trust-item .icon { width: 16px; height: 16px; color: var(--color-primary); }

/* Sceaux officiels (ISO 9001 / ISO 27001 / FIRST) : pastille claire pour
   garder les sellos noirs lisibles sur le fond navy */
.hero__trust-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 6px 10px;
  border-radius: var(--radius-md);
  background: rgba(248, 250, 252, 0.92);
  border: 1px solid rgba(255, 255, 255, 0.25);
}
.hero__trust-badge img { display: block; height: 40px; width: auto; }

/* Sceaux officiels dans le footer (remplacent la carte LATAM redondante
   avec le globe) : pastilles claires individuelles */
.site-footer__badges { display: flex; gap: 10px; align-items: center; margin: var(--space-4) 0; }
.site-footer__coverage {
  font-size: var(--text-sm);
  color: var(--color-muted);
  margin: 0 0 var(--space-5);
  line-height: 1.6;
}
.site-footer__contact-title { margin-top: 0; }
.site-footer__contact {
  font-style: normal;
  font-size: var(--text-sm);
  color: var(--color-muted);
  line-height: 1.7;
}
.site-footer__contact a { color: var(--color-muted); }
.site-footer__contact a:hover { color: var(--color-fg); }
.site-footer__contact-cta {
  display: inline-block;
  margin-top: var(--space-2);
  font-weight: 600;
  color: var(--color-primary) !important;
}
/* LA HAUTEUR ANNONCEE N'ETAIT PAS LA HAUTEUR VUE. height: 38px avec 5 px de
   padding vertical en content-box laissait 28 px de visuel utile : c'est la
   mesure qui explique le « on le voit quasiment pas ». Le sceau utile passe a
   52 px, presque le double, et box-sizing rend la valeur lisible telle qu'elle
   est ecrite. Les fichiers sources font 400 px de haut, aucun risque de flou. */
.site-footer__badges img {
  display: block;
  box-sizing: border-box;
  height: 66px;
  width: auto;
  padding: 7px 10px;
  border-radius: var(--radius-sm);
  background: rgba(248, 250, 252, 0.92);
}

/* Placeholder du globe pendant le chargement : radar pulse discret,
   disparait des que globe.gl injecte son canvas (:empty) */
.presence__globe:empty {
  position: relative;
  min-height: 420px;
}
.presence__globe:empty::before {
  content: '';
  position: absolute;
  top: 50%; left: 50%;
  width: 120px; height: 120px;
  margin: -60px 0 0 -60px;
  border-radius: 50%;
  border: 1px solid rgba(220, 38, 38, 0.5);
  animation: globe-pulse 1.6s var(--ease-out) infinite;
}
.presence__globe:empty::after {
  content: '';
  position: absolute;
  top: 50%; left: 50%;
  width: 8px; height: 8px;
  margin: -4px 0 0 -4px;
  border-radius: 50%;
  background: var(--color-primary);
}
@keyframes globe-pulse {
  0%   { transform: scale(0.4); opacity: 0.9; }
  100% { transform: scale(2.2); opacity: 0; }
}

/* ── La Liga ASHA (heroes section) ───────────────────────────── */

.liga {
  background: var(--color-bg);
  position: relative;
  overflow: hidden;
}
.liga::before {
  content: '';
  position: absolute; inset: 0;
  background: radial-gradient(ellipse at center top, rgba(220,38,38,0.08) 0%, transparent 60%);
  pointer-events: none;
}
.liga__header {
  position: relative;
  text-align: center;
  max-width: 760px;
  margin: 0 auto var(--space-16);
}
.liga__title {
  font-size: clamp(var(--text-3xl), 4vw, var(--text-5xl));
  line-height: 1.05;
  letter-spacing: -0.02em;
}
.liga__lede {
  font-size: var(--text-lg);
  color: var(--color-muted);
  margin-top: var(--space-4);
}
.liga__grid {
  position: relative;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: var(--space-6);
}
@media (min-width: 1024px) {
  .liga__grid { grid-template-columns: repeat(6, 1fr); gap: var(--space-4); }
}

.persona {
  position: relative;
  display: block;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  overflow: hidden;
  transition: all var(--duration-normal) var(--ease-out);
  isolation: isolate;
}
.persona::after {
  content: '';
  position: absolute; inset: 0;
  background: linear-gradient(180deg, transparent 35%, rgba(16, 16, 16,0.92) 100%);
  pointer-events: none;
  z-index: 1;
}
.persona__img {
  width: 100%;
  aspect-ratio: 3 / 4;
  object-fit: cover;
  object-position: center top;
  filter: saturate(1.05);
  transition: transform var(--duration-slow) var(--ease-out);
  /* heros detoures (webp alpha) : aura radiale tintee persona derriere le sujet */
  background: radial-gradient(70% 55% at 50% 42%,
    color-mix(in srgb, var(--persona-color, var(--color-primary)) 22%, transparent) 0%,
    transparent 72%);
}
.persona:hover .persona__img { transform: scale(1.04); }
.persona__body {
  position: absolute;
  bottom: 0; left: 0; right: 0;
  padding: var(--space-4);
  z-index: 2;
}
.persona__name {
  font-size: var(--text-base);
  font-weight: 800;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  margin: 0 0 4px;
}
.persona__role {
  font-size: var(--text-xs);
  color: var(--color-muted);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  margin: 0;
}

/* persona color glow on hover */
.persona[data-persona="zerotrust"] .persona__name { color: var(--color-zerotrust); }
.persona[data-persona="ngsoc"]     .persona__name { color: var(--color-ngsoc); }
.persona[data-persona="asha"]      .persona__name { color: var(--color-primary); }
.persona[data-persona="csirt"]     .persona__name { color: var(--color-csirt); }
.persona[data-persona="ctem"]      .persona__name { color: var(--color-ctem); }
.persona[data-persona="grc"]       .persona__name { color: var(--color-grc); }

.persona[data-persona="zerotrust"]:hover { border-color: var(--color-zerotrust); box-shadow: var(--glow-zerotrust); transform: translateY(-3px); }
.persona[data-persona="ngsoc"]:hover     { border-color: var(--color-ngsoc);     box-shadow: var(--glow-ngsoc);     transform: translateY(-3px); }
.persona[data-persona="asha"]:hover      { border-color: var(--color-primary);   box-shadow: var(--glow-primary);   transform: translateY(-3px); }
.persona[data-persona="csirt"]:hover     { border-color: var(--color-csirt);     box-shadow: var(--glow-csirt);     transform: translateY(-3px); }
.persona[data-persona="ctem"]:hover      { border-color: var(--color-ctem);      box-shadow: var(--glow-ctem);      transform: translateY(-3px); }
.persona[data-persona="grc"]:hover       { border-color: var(--color-grc);       box-shadow: var(--glow-grc);       transform: translateY(-3px); }

/* ── Generic section helpers ─────────────────────────────────── */

.section-head {
  max-width: 760px;
  margin: 0 auto var(--space-12);
  text-align: center;
}
.section-head--left {
  margin-inline: 0;
  text-align: left;
  max-width: 640px;
}
.section-title {
  font-size: clamp(var(--text-3xl), 4vw, var(--text-5xl));
  line-height: 1.05;
  letter-spacing: -0.02em;
}
.section-lede {
  font-size: var(--text-lg);
  margin-top: var(--space-4);
  color: var(--color-muted);
}
.section--light .section-lede { color: var(--color-muted-light); }
/* Secondary lede — additional context below the main lede */
.section-lede--secondary {
  font-size: var(--text-base);
  margin-top: var(--space-3);
  padding-top: var(--space-4);
  border-top: 1px dashed rgba(255, 255, 255, 0.06);
  color: rgba(165, 243, 252, 0.85);
  max-width: 760px;
  margin-inline: auto;
}
.section-lede--secondary strong { color: var(--color-fg); font-weight: 700; }

/* ── How: split image / text ─────────────────────────────────── */

.how__grid {
  display: grid;
  gap: var(--space-12);
  align-items: center;
}
@media (min-width: 900px) {
  .how__grid { grid-template-columns: 1.05fr 1fr; gap: var(--space-16); }
}
.how__media {
  position: relative;
  /* Rayon aligne sur le reste du site. Pas de plateau noir ici : le cadre porte
     une PHOTO opaque qui le remplit, son fond ne se voit jamais. */
  border-radius: var(--radius-lg);
  overflow: hidden;
  aspect-ratio: 4 / 3;
  background: var(--color-surface);
  box-shadow: var(--shadow-md);
}
.how__media img {
  width: 100%; height: 100%;
  object-fit: cover;
}
.how__media::after {
  /* subtle red glow accent ring */
  content: '';
  position: absolute; inset: 0;
  border-radius: inherit;
  pointer-events: none;
  box-shadow: inset 0 0 0 1px rgba(220,38,38,0.08);
}
.how__text p {
  font-size: var(--text-lg);
  color: var(--color-muted-light);
}
.promises {
  list-style: none;
  margin: var(--space-6) 0 0;
  padding: 0;
  display: grid;
  gap: var(--space-3);
  grid-template-columns: 1fr;
}
@media (min-width: 540px) { .promises { grid-template-columns: repeat(2, 1fr); } }
.promise {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-md);
  background: rgba(220,38,38,0.05);
  border: 1px solid rgba(220,38,38,0.18);
  font-weight: 600;
  font-size: var(--text-sm);
  color: var(--color-fg-light);
}
.promise .icon {
  width: 20px; height: 20px;
  color: var(--color-primary);
  flex-shrink: 0;
}

/* ── Differentiator (dark) ───────────────────────────────────── */

.diff {
  position: relative;
  overflow: hidden;
}
.diff::before {
  content: '';
  position: absolute; inset: 0;
  background:
    radial-gradient(ellipse 60% 50% at 90% 0%, rgba(220,38,38,0.08) 0%, transparent 60%),
    radial-gradient(ellipse 50% 60% at 10% 100%, rgba(6,182,212,0.10) 0%, transparent 60%);
  pointer-events: none;
}
.diff__grid {
  position: relative;
  display: grid;
  gap: var(--space-12);
}
@media (min-width: 900px) {
  .diff__grid { grid-template-columns: 1.1fr 1fr; gap: var(--space-16); align-items: start; }
}
.diff__title .accent {
  color: var(--color-primary);
  font-weight: 800;
  font-style: italic;
}
.diff__copy p {
  color: var(--color-muted);
  font-size: var(--text-base);
}
.diff__cta {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  margin-top: var(--space-4);
  font-weight: 600;
  color: var(--color-primary);
  border-bottom: 1px solid transparent;
  transition: border-color var(--duration-fast) var(--ease-out);
}
.diff__cta:hover { border-color: currentColor; color: var(--color-primary); }
.diff__cta .icon { width: 18px; height: 18px; }

/* Metric chips */
.metrics {
  display: grid;
  gap: var(--space-4);
  grid-template-columns: repeat(2, 1fr);
}
@media (min-width: 480px) {
  .metrics { grid-template-columns: repeat(4, 1fr); }
}
.metric {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: var(--space-4) var(--space-4);
  text-align: left;
  transition: all var(--duration-normal) var(--ease-out);
}
.metric:hover {
  border-color: rgba(220,38,38,0.4);
  transform: translateY(-2px);
}
.metric__num {
  font-size: clamp(var(--text-3xl), 3vw, var(--text-4xl));
  font-weight: 800;
  line-height: 1;
  letter-spacing: -0.03em;
  color: var(--color-fg);
  font-feature-settings: 'tnum' 1;
}
.metric__num .unit {
  font-size: var(--text-xl);
  color: var(--color-primary);
  margin-left: 2px;
}
.metric__label {
  margin-top: var(--space-2);
  font-size: var(--text-xs);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--color-muted);
}

/* Framework grid */
.frameworks {
  margin-top: var(--space-12);
}
.frameworks__label {
  font-size: var(--text-xs);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--color-muted);
  margin-bottom: var(--space-4);
}
.frameworks__grid {
  display: grid;
  gap: var(--space-2);
  grid-template-columns: repeat(2, 1fr);
}
@media (min-width: 540px) { .frameworks__grid { grid-template-columns: repeat(4, 1fr); } }
@media (min-width: 1024px) { .frameworks__grid { grid-template-columns: repeat(8, 1fr); } }
.framework {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 10px 12px;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.06em;
  color: var(--color-fg);
  text-align: center;
  transition: all var(--duration-normal) var(--ease-out);
}
.framework:hover {
  border-color: var(--color-border-strong);
  background: rgba(255,255,255,0.04);
}
.framework .icon { width: 14px; height: 14px; color: var(--color-primary); }

/* ── Industries (light) ──────────────────────────────────────── */

.industries__head {
  display: grid;
  gap: var(--space-8);
  align-items: end;
  margin-bottom: var(--space-12);
}
@media (min-width: 900px) {
  .industries__head { grid-template-columns: 1fr 1.4fr; gap: var(--space-16); }
}
.industries__sectors {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}
.industries__sector {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 12px;
  background: rgba(220,38,38,0.06);
  border: 1px solid rgba(220,38,38,0.18);
  border-radius: var(--radius-full);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--color-primary);
}
.industries__sector--secondary {
  background: transparent;
  border-color: var(--color-border-light);
  color: var(--color-muted-light);
}
.industries__sector .dot {
  width: 6px; height: 6px; border-radius: 50%;
  background: currentColor;
}

.industries__grid {
  display: grid;
  gap: var(--space-6);
}
@media (min-width: 900px) {
  .industries__grid { grid-template-columns: repeat(2, 1fr); gap: var(--space-8); }
}
.industry-card {
  position: relative;
  /* --radius-lg (16 px) et non --radius-xl (24 px) : c'etait la seule carte de
     la home a sortir du rayon commun, que partagent .pillar, .practice et
     .case-row. Releve le 2026-08-11 en comparant les six familles de cartes. */
  border-radius: var(--radius-lg);
  overflow: hidden;
  background: var(--color-surface);
  min-height: 380px;
  isolation: isolate;
  box-shadow: var(--shadow-md);
}
.industry-card__img {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  z-index: -2;
  filter: saturate(1.05);
  transition: transform var(--duration-slow) var(--ease-out);
}
.industry-card:hover .industry-card__img { transform: scale(1.04); }
.industry-card::before {
  content: '';
  position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(16, 16, 16,0.20) 0%, rgba(16, 16, 16,0.78) 80%, rgba(16, 16, 16,0.95) 100%);
  z-index: -1;
}
.industry-card__body {
  position: relative;
  padding: var(--space-12) var(--space-8) var(--space-8);
  margin-top: 240px;
  color: var(--color-fg);
}
.industry-card__body p {
  font-size: var(--text-base);
  line-height: var(--leading-body);
  color: rgba(255,255,255,0.9);
  margin: 0;
}
.industry-card__body strong { color: var(--color-primary); font-weight: 700; }

/* ── Presencia internacional (dark) ─────────────────────────── */

.presence {
  position: relative;
  overflow: hidden;
}
.presence::before {
  content: '';
  position: absolute; inset: 0;
  background:
    radial-gradient(ellipse at 30% 30%, rgba(6,182,212,0.10) 0%, transparent 60%),
    radial-gradient(ellipse at 80% 80%, rgba(220,38,38,0.10) 0%, transparent 60%);
  pointer-events: none;
}
.presence__head {
  text-align: center;
  max-width: 720px;
  margin: 0 auto var(--space-8);
}
.presence__head .section-title { margin-top: var(--space-3); }
.presence__head .section-lede { margin-top: var(--space-4); }
/* (.presence__grid retire : la section est passee en mise en page "globe
   heros" avec .presence__stage, plus de colonne laterale) */

/* Globe wrapper */
.presence__globe-wrap {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-6);
}
.presence__globe {
  width: 100%;
  /* Doit rester synchronise avec GLOBE_MAX dans index.html (calcul des
     positions des etiquettes) */
  max-width: 660px;
  aspect-ratio: 1;
  position: relative;
  border-radius: 50%;
  /* soft red glow halo to integrate with brand */
  box-shadow:
    0 0 80px rgba(220, 38, 38, 0.18),
    inset 0 0 60px rgba(6, 182, 212, 0.06);
}
.presence__globe canvas { display: block; border-radius: 50%; }

/* Tooltip styling */
.globe-tooltip {
  background: rgba(23, 23, 23, 0.95);
  backdrop-filter: blur(12px);
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-md);
  padding: 10px 14px;
  color: var(--color-fg);
  font: 600 var(--text-sm)/1.3 var(--font-sans);
  pointer-events: none;
  box-shadow: var(--shadow-lg);
  white-space: nowrap;
}
.globe-tooltip__country { display: block; }
.globe-tooltip__meta {
  display: block;
  margin-top: 4px;
  font: 500 11px/1 var(--font-mono);
  letter-spacing: 0.08em;
  color: var(--color-muted);
  text-transform: uppercase;
}

/* ── PRESENCIA v3 — globe heros + cartes dans son espace ──────────── */
.presence__stage {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--space-8);
}
.presence__stage .presence__globe-wrap { width: 100%; }

/* Mobile / tablette : tout s'empile, le globe reste centre. */
.presence__float,
.presence__fallback {
  background: rgba(248, 250, 252, 0.03);
  border: 1px solid rgba(248, 250, 252, 0.10);
  border-radius: var(--radius-lg);
  padding: var(--space-5) var(--space-6);
}

@media (min-width: 1080px) {
  /* Desktop : les cartes occupent les coins vides du carre qui englobe le
     cercle du globe. Le globe reste seul au centre, sans colonne laterale. */
  .presence__stage { display: block; min-height: 660px; }
  /* .presence__stage en prefixe : sans lui, .highlight (defini plus loin dans
     ce fichier, meme specificite) reprend la main et casse le position:absolute */
  .presence__stage .presence__float {
    position: absolute;
    width: clamp(230px, 21vw, 290px);
    margin: 0;
    z-index: 3;
    backdrop-filter: blur(6px);
  }
  /* Les 3 cartes encadrent le globe en triangle, dans les coins vides du
     carre qui englobe le cercle. */
  .presence__stage .presence__float--hub       { top: 0;    left: 0; }
  .presence__stage .presence__float--expanding { top: 0;    right: 0; }
  .presence__stage .presence__float--sectorial { bottom: 0; left: 0; }
  /* La liste "Operación activa" est portee par les etiquettes du globe */
  .presence.has-globe-pins .presence__fallback { display: none; }
  .presence__stage .presence__fallback {
    position: absolute; bottom: 0; right: 0;
    width: clamp(230px, 21vw, 290px);
    margin: 0;
  }
}

/* ── Etiquettes ancrees aux points du globe ───────────────────────── */
/* Calque au-dessus du canvas : positions calculees en JS (projection de la
   camera), voir updatePins dans index.html. */
.globe-pins {
  position: absolute;
  inset: 0;
  overflow: hidden;
  pointer-events: none;   /* ne bloque ni le drag ni les tooltips du globe */
  z-index: 2;
  opacity: 0;             /* revele au premier calcul de position valide */
  transition: opacity 400ms var(--ease-out);
}
.globe-pins.is-ready { opacity: 1; }
.globe-pin {
  position: absolute;
  top: 0; left: 0;
  width: 0; height: 0;
  pointer-events: none;
  will-change: transform;
}
.globe-pin__chip {
  position: absolute;
  top: 0;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  white-space: nowrap;
  padding: 5px 10px;
  border-radius: 999px;
  background: rgba(16, 16, 16, 0.82);
  border: 1px solid rgba(248, 250, 252, 0.16);
  font: 600 12px/1 var(--font-sans);
  color: var(--color-fg);
  transition: opacity 260ms var(--ease-out);
}
/* --pin-dy : ecart vertical applique par l'anti-collision (voir updatePins) */
.globe-pin--right .globe-pin__chip { left: 16px;  transform: translateY(calc(-50% + var(--pin-dy, 0px))); }
.globe-pin--left  .globe-pin__chip { right: 16px; transform: translateY(calc(-50% + var(--pin-dy, 0px))); flex-direction: row-reverse; }
.globe-pin__dot {
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--color-primary);
  box-shadow: 0 0 8px var(--color-primary);
  flex: 0 0 auto;
}
.globe-pin__meta {
  font: 500 10px/1 var(--font-mono);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-muted);
}
.globe-pin--hq .globe-pin__chip {
  border-color: rgba(220, 38, 38, 0.55);
  background: rgba(16, 16, 16, 0.9);
}
.globe-pin--hub .globe-pin__dot {
  background: var(--color-zerotrust);
  box-shadow: 0 0 8px var(--color-zerotrust);
}
/* Point passe derriere le globe */
.globe-pin.is-behind .globe-pin__chip { opacity: 0; }
@media (max-width: 1079px) {
  /* Hors mise en page "globe heros" : la liste porte l'information */
  .globe-pin { display: none; }
}
@media (prefers-reduced-motion: reduce) {
  .globe-pin__chip { transition: none; }
}

.presence__legend {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-3) var(--space-6);
  margin-top: var(--space-2);
}
.presence__legend-item {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--text-xs);
  color: var(--color-muted);
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.presence__legend-dot {
  width: 10px; height: 10px;
  border-radius: 999px;
  display: inline-block;
}
.presence__legend-dot--active    { background: var(--color-primary); box-shadow: 0 0 10px var(--color-primary); }
.presence__legend-dot--expanding { background: var(--color-csirt);   box-shadow: 0 0 10px var(--color-csirt); border: 1px dashed var(--color-fg); }
.presence__legend-dot--hub       { background: var(--color-zerotrust); box-shadow: 0 0 10px var(--color-zerotrust); }

/* PRESENCIA — SOC dashboard panel v2
   Glass treatment + status indicators + terminal-style sub-labels */
.presence__panel {
  display: grid;
  gap: var(--space-5);
}
.presence__group .presence__sub-label { margin-top: 0; }

.presence__sub-label {
  display: flex;
  align-items: center;
  gap: 8px;
  font: 600 11px/1 var(--font-mono);
  color: rgba(203, 213, 225, 0.95);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  margin: var(--space-6) 0 var(--space-3);
  padding-bottom: var(--space-3);
  border-bottom: 1px solid rgba(255, 255, 255, 0.05);
}
.presence__sub-prompt {
  color: rgba(34, 211, 238, 0.85);
  font-weight: 700;
}
.presence__sub-count {
  margin-left: auto;
  color: rgba(148, 163, 184, 0.65);
  letter-spacing: 0.06em;
  font-weight: 500;
}

.country-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
  gap: 6px;
}
.country {
  display: grid;
  grid-template-columns: 10px 1fr auto;
  align-items: center;
  gap: var(--space-3);
  padding: 10px 14px;
  background: rgba(23, 23, 23, 0.55);
  border: 1px solid rgba(255, 255, 255, 0.05);
  border-radius: 8px;
  font-size: var(--text-sm);
  font-weight: 600;
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  /* Liquid Glass refraction */
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.04),
    inset 0 -1px 0 rgba(0, 0, 0, 0.20);
  transition: border-color 240ms var(--ease-out), background 240ms var(--ease-out), transform 240ms var(--ease-out);
}
.country:hover {
  border-color: rgba(220, 38, 38, 0.35);
  background: rgba(220, 38, 38, 0.04);
  transform: translateX(2px);
}
.country__flag {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--color-primary);
  box-shadow: 0 0 5px rgba(220, 38, 38, 0.30), inset 0 0 2px rgba(255, 255, 255, 0.25);
  flex-shrink: 0;
}
.country__name {
  color: var(--color-fg);
  letter-spacing: -0.005em;
}
.country--expanding {
  background: rgba(23, 23, 23, 0.35);
  border-style: dashed;
  border-color: rgba(6, 182, 212, 0.25);
}
.country--expanding:hover {
  border-color: rgba(6, 182, 212, 0.55);
  background: rgba(6, 182, 212, 0.04);
}
.country--expanding .country__flag {
  background: var(--color-csirt);
  box-shadow: 0 0 5px rgba(6, 182, 212, 0.30), inset 0 0 2px rgba(255, 255, 255, 0.25);
  animation: country-expanding-pulse 2.4s ease-in-out infinite;
}
@keyframes country-expanding-pulse {
  0%, 100% { opacity: 1; transform: scale(1); }
  50%      { opacity: 0.6; transform: scale(0.85); }
}
.country__since {
  font: 700 10px/1 var(--font-mono);
  letter-spacing: 0.08em;
  color: rgba(148, 163, 184, 0.7);
  text-transform: uppercase;
  font-variant-numeric: tabular-nums;
  padding: 4px 7px;
  background: rgba(255, 255, 255, 0.02);
  border: 1px solid rgba(255, 255, 255, 0.05);
  border-radius: 4px;
}
.country--expanding .country__since {
  color: rgba(165, 243, 252, 0.85);
  background: rgba(6, 182, 212, 0.06);
  border-color: rgba(6, 182, 212, 0.20);
}

.presence__highlights {
  display: grid;
  gap: var(--space-3);
  margin-top: var(--space-5);
}
.highlight {
  position: relative;
  background: linear-gradient(180deg, rgba(23, 23, 23, 0.65) 0%, rgba(16, 16, 16, 0.50) 100%);
  border: 1px solid rgba(255, 255, 255, 0.05);
  border-radius: 10px;
  padding: var(--space-5);
  backdrop-filter: blur(12px) saturate(115%);
  -webkit-backdrop-filter: blur(12px) saturate(115%);
  /* Liquid Glass refraction */
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.06),
    inset 0 -1px 0 rgba(0, 0, 0, 0.25),
    0 8px 24px rgba(0, 0, 0, 0.25);
  transition: border-color 280ms var(--ease-out), transform 280ms var(--ease-out);
}
.highlight::before {
  /* Side accent bar */
  content: '';
  position: absolute;
  left: 0; top: 14%; bottom: 14%;
  width: 2px;
  background: var(--color-primary);
  border-radius: 2px;
  box-shadow: 0 0 8px rgba(220, 38, 38, 0.35);
}
.highlight--csirt::before {
  background: var(--color-csirt);
  box-shadow: 0 0 8px rgba(6, 182, 212, 0.35);
}
.highlight:hover {
  border-color: rgba(255, 255, 255, 0.12);
  transform: translateY(-1px);
}
.highlight__label {
  display: flex;
  align-items: center;
  gap: 8px;
  font: 700 10px/1 var(--font-mono);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgba(148, 163, 184, 0.85);
  margin: 0 0 var(--space-3);
}
.highlight__label-marker {
  display: inline-block;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--color-primary);
  box-shadow: 0 0 5px rgba(220, 38, 38, 0.30);
  flex-shrink: 0;
}
.highlight--csirt .highlight__label-marker {
  background: var(--color-csirt);
  box-shadow: 0 0 5px rgba(6, 182, 212, 0.30);
}
.highlight__title {
  font-size: var(--text-xl);
  font-weight: 700;
  margin: 0 0 var(--space-2);
  letter-spacing: -0.01em;
}
.highlight__text {
  margin: 0;
  color: var(--color-muted);
  font-size: var(--text-sm);
}

/* ── Prácticas grid (light) ─────────────────────────────────── */

.practices__grid {
  display: grid;
  gap: var(--space-4);
}
@media (min-width: 720px) {
  .practices__grid { grid-template-columns: repeat(2, 1fr); gap: var(--space-5); }
}
/* Desktop: 5 columnas compactas (1 card por práctica = mismo ancho) */
@media (min-width: 1100px) {
  .practices__grid { grid-template-columns: repeat(5, 1fr); gap: var(--space-3); }
  .practices__grid .practice { padding: var(--space-6) var(--space-5); gap: var(--space-3); }
  .practices__grid .practice__title { font-size: var(--text-base); line-height: 1.25; }
  .practices__grid .practice__desc { font-size: var(--text-sm); line-height: 1.4; }
  .practices__grid .practice__chips { gap: 4px; }
  .practices__grid .practice__chip { font-size: 9.5px; padding: 4px 7px; }
}
.practice {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  background: var(--color-surface-light);
  border: 1px solid var(--color-border-light);
  border-radius: var(--radius-lg);
  padding: var(--space-8);
  text-decoration: none;
  color: inherit;
  transition: all var(--duration-normal) var(--ease-out);
}
.practice:hover {
  border-color: var(--color-primary);
  transform: translateY(-2px);
  box-shadow: var(--shadow-md);
  color: inherit;
}
.practice__icon-wrap {
  width: 48px; height: 48px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-md);
  background: rgba(220,38,38,0.08);
  color: var(--color-primary);
}
.practice__icon-wrap .icon { width: 24px; height: 24px; }
.practice__title {
  font-size: var(--text-xl);
  font-weight: 700;
  letter-spacing: -0.01em;
  margin: 0;
  line-height: 1.25;
}
.practice__desc {
  font-size: var(--text-sm);
  color: var(--color-muted-light);
  margin: 0;
  flex: 1;
}
.practice__chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: var(--space-2);
}
.practice__chip {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.04em;
  padding: 4px 10px;
  border-radius: var(--radius-full);
  background: rgba(220,38,38,0.06);
  color: var(--color-primary);
  border: 1px solid rgba(220,38,38,0.15);
}
.practice__more {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--color-primary);
  margin-top: var(--space-2);
}
.practice__more .icon { width: 16px; height: 16px; transition: transform var(--duration-fast) var(--ease-out); }
.practice:hover .practice__more .icon { transform: translateX(3px); }

/* ── La Liga ASHA (home) : portrait detoure + contenu ──────────────
   La couleur par card vient de --p (mapping data-persona plus bas).

   .practices__grid--met a ete SUPPRIMEE le 2026-08-12, pas laissee morte : ses
   trois declarations forcaient la grille a trois colonnes pour loger six
   cartes, or la capitana est sortie de la grille et il n'en reste que cinq.
   Le variant n'existe plus dans aucun HTML. La seule regle qui servait encore
   etait sa marge basse, reportee ci-dessous sur le variant qui l'a remplacee. */
.practices__grid--fronts { margin-bottom: var(--space-10); }
.practice[data-persona]:hover { border-color: var(--p, var(--color-primary)); }

/* Portrait du heros en tete de card : cadrage buste (tete -> mains),
   grand format, aura radiale a sa couleur */
.practice__hero {
  height: 280px;
  overflow: hidden;
  /* Etait --radius-sm (6 px) a l'interieur d'une carte a --radius-lg (16 px) :
     l'image coupait droit la ou la carte courbait encore, et le decrochement de
     courbure se voyait dans les deux coins hauts. On prend le rayon de la carte
     moins son trait de 1 px, qui est le rayon interieur exact. */
  border-radius: calc(var(--radius-lg) - 1px) calc(var(--radius-lg) - 1px) 0 0;
  /* colle le portrait aux bords de la card (padding theming: space-8 / space-6) */
  margin: calc(var(--space-8) * -1) calc(var(--space-6) * -1) var(--space-2);
}
.practice__hero img {
  width: 100%;
  height: 100%;
  display: block;
  object-fit: cover;
  object-position: center top;
  background: radial-gradient(70% 80% at 50% 38%,
    color-mix(in srgb, var(--p, var(--color-primary)) 24%, transparent) 0%,
    transparent 75%);
  filter: drop-shadow(0 10px 24px rgba(0, 0, 0, 0.45));
  transition: transform var(--duration-slow) var(--ease-out);
}
.practice--card:hover .practice__hero img { transform: scale(1.04); }
/* le numero passe en filigrane derriere le portrait */
.practice--card { text-align: left; }
.practice--card .practice__num { position: absolute; top: var(--space-4); right: var(--space-5); }

/* The 4th & 5th card spanning full width on 3-col layout */
@media (min-width: 1024px) {
  .practice--span-2 { grid-column: span 1; }
}

/* ── Servicios detallados accordion (light) ─────────────────── */

.services {
  background: var(--color-bg-light);
}
.services__list {
  display: grid;
  gap: var(--space-4);
}
.service-group {
  background: var(--color-surface-light);
  border: 1px solid var(--color-border-light);
  border-radius: var(--radius-lg);
  overflow: hidden;
  transition: border-color var(--duration-fast) var(--ease-out);
}
.service-group[open] { border-color: var(--color-primary); }
.service-group summary {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  padding: var(--space-6) var(--space-8);
  cursor: pointer;
  list-style: none;
  font-weight: 700;
  font-size: var(--text-lg);
}
.service-group summary::-webkit-details-marker { display: none; }
.service-group summary:hover { background: rgba(0,0,0,0.02); }
.service-group__icon {
  width: 40px; height: 40px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-md);
  background: rgba(220,38,38,0.08);
  color: var(--color-primary);
  flex-shrink: 0;
}
.service-group__icon .icon { width: 22px; height: 22px; }
.service-group__title {
  flex: 1;
  margin: 0;
}
.service-group__chev {
  width: 22px; height: 22px;
  color: var(--color-muted-light);
  transition: transform var(--duration-normal) var(--ease-out);
}
.service-group[open] .service-group__chev { transform: rotate(180deg); }
.service-group__body {
  padding: 0 var(--space-8) var(--space-8) var(--space-8);
  display: grid;
  gap: var(--space-4);
}
@media (min-width: 720px) {
  .service-group__body { grid-template-columns: repeat(2, 1fr); }
}
.service-item {
  padding: var(--space-4);
  border-left: 2px solid var(--color-border-light);
  padding-left: var(--space-4);
}
.service-item h4 {
  font-size: var(--text-base);
  font-weight: 700;
  letter-spacing: -0.01em;
  margin: 0 0 6px;
  color: var(--color-fg-light);
}
.service-item ul {
  margin: 0;
  padding-left: 18px;
  font-size: var(--text-sm);
  color: var(--color-muted-light);
}
.service-item li { margin-bottom: 2px; }

/* ── Alianzas estratégicas (dark) ───────────────────────────── */

.alliances__head {
  text-align: center;
  max-width: 720px;
  margin: 0 auto var(--space-12);
}

/* ── Bande de destacados (motif CrowdStrike, 2026-08-11) ─────── */
/* Nomme .destacado et non .highlight : .highlight existe deja (ligne ~1600, barre rouge en ::before) et polluait le panneau. Panneau unique divise en trois liens : kicker rouge, titre gras, fleche qui
   glisse au survol. Sur mobile les colonnes deviennent des lignes. */
.destacados { padding: var(--space-10) 0 0; }
.destacados__panel {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  background: rgba(23, 23, 23, 0.85);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  overflow: hidden;
}
.destacado {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  padding: var(--space-7) var(--space-7) var(--space-6);
  text-decoration: none;
  transition: background var(--duration-normal) var(--ease-out);
}
.destacado + .destacado { border-left: 1px solid var(--color-border); }
.destacado:hover { background: rgba(220, 38, 38, 0.06); }
.destacado__kicker {
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--color-danger-soft);
}
.destacado__title {
  font-weight: 700;
  font-size: var(--text-base);
  line-height: 1.4;
  color: var(--color-fg);
  max-width: 34ch;
}
.destacado__arrow {
  margin-top: auto;
  font-size: var(--text-lg);
  color: var(--color-primary);
  transition: transform var(--duration-normal) var(--ease-out);
}
.destacado:hover .destacado__arrow { transform: translateX(6px); }
@media (max-width: 900px) {
  .destacados__panel { grid-template-columns: 1fr; }
  .destacado + .destacado { border-left: 0; border-top: 1px solid var(--color-border); }
}
.alliances__tier {
  margin-bottom: var(--space-12);
}
.alliances__tier:last-child { margin-bottom: 0; }
.alliances__tier-label {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  font-size: var(--text-xs);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--color-muted);
  margin-bottom: var(--space-6);
}
.alliances__tier-label::before,
.alliances__tier-label::after {
  content: '';
  flex: 1;
  height: 1px;
  background: var(--color-border);
}
.alliances__grid {
  display: grid;
  gap: var(--space-3);
  grid-template-columns: repeat(2, 1fr);
}
@media (min-width: 540px) { .alliances__grid { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 900px) { .alliances__grid { grid-template-columns: repeat(7, 1fr); } }
.alliance {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 18px 12px;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  font-size: var(--text-sm);
  font-weight: 700;
  letter-spacing: 0.02em;
  color: var(--color-fg);
  text-align: center;
  transition: all var(--duration-normal) var(--ease-out);
}
.alliance:hover {
  border-color: var(--color-primary);
  color: var(--color-primary);
  transform: translateY(-1px);
}

/* Partner certification levels */
.alliances__levels {
  margin-top: var(--space-12);
  padding-top: var(--space-8);
  border-top: 1px solid var(--color-border);
}
.partner-levels {
  list-style: none;
  margin: var(--space-6) 0 0;
  padding: 0;
  display: grid;
  gap: var(--space-3);
  grid-template-columns: 1fr;
}
@media (min-width: 720px)  { .partner-levels { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1100px) { .partner-levels { grid-template-columns: repeat(5, 1fr); } }
.alliances__coverage {
  margin: var(--space-6) auto 0;
  max-width: 760px;
  text-align: center;
  font-size: 15px;
  line-height: 1.5;
  color: var(--color-muted);
}
.alliances__coverage-stat {
  font: 800 1.15em/1 var(--font-mono);
  color: var(--color-primary);
  margin-right: 4px;
}

/* ── Casos de éxito ─────────────────────────────────────────────── */
.cases__head { text-align: center; max-width: 720px; margin: 0 auto var(--space-12); }

/* Un cas par LIGNE pleine largeur (2026-08-11, remplace deux cartes cote a
   cote) : identite et titre a gauche, chiffres puis recit a droite. Les deux
   cas n'ont pas le meme nombre de mesures reelles ; en ligne, cette asymetrie
   se lit comme deux histoires differentes et non comme une carte a moitie
   vide, ce qui evite d'avoir a la meubler avec de faux chiffres. */
.cases__rows { display: flex; flex-direction: column; gap: var(--space-6); }
.case-row {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-6);
  padding: var(--space-8);
  background: rgba(248, 250, 252, 0.03);
  border: 1px solid rgba(248, 250, 252, 0.10);
  border-radius: var(--radius-lg);
}
@media (min-width: 900px) {
  .case-row {
    grid-template-columns: minmax(0, 0.8fr) minmax(0, 1.2fr);
    gap: clamp(32px, 4vw, 64px);
    align-items: start;
  }
}
.case-row__eyebrow {
  display: flex; align-items: center; gap: 8px;
  font: 600 12px/1 var(--font-mono);
  letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--color-muted);
  margin: 0 0 var(--space-3);
}
.case-row__marker {
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--color-primary);
  box-shadow: 0 0 10px rgba(220, 38, 38, 0.6);
  flex: 0 0 auto;
}
.case-row__title {
  font-size: clamp(22px, 2.7vw, 32px);
  line-height: 1.15;
  color: var(--color-fg);
  margin: 0;
}
.case-row__main { display: flex; flex-direction: column; gap: var(--space-6); }
.case-row__metrics {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--space-5) var(--space-4);
  padding-bottom: var(--space-6);
  border-bottom: 1px solid rgba(248, 250, 252, 0.10);
}
@media (min-width: 700px) { .case-row__metrics { grid-template-columns: repeat(4, 1fr); } }
/* Un seul chiffre dur : il occupe la ligne et grossit, au lieu d'etre noye
   dans une grille a trous. */
.case-row__metrics--single { grid-template-columns: 1fr; }
.case-metric--lead .case-metric__num { font-size: clamp(32px, 4.4vw, 46px); }
.case-metric--lead .case-metric__label { max-width: 42ch; }
.case-row__story { display: flex; flex-direction: column; gap: var(--space-4); }

.case-metric { display: flex; flex-direction: column; gap: 6px; }
.case-metric__num {
  font: 800 clamp(20px, 3vw, 28px)/1 var(--font-mono);
  color: var(--color-primary);
  letter-spacing: -0.01em;
}
.case-metric__unit { font-size: 0.5em; font-weight: 600; margin-left: 3px; color: var(--color-fg); }
.case-metric__label { font-size: 12px; line-height: 1.3; color: var(--color-muted); }
.case-flow { display: flex; gap: var(--space-4); align-items: flex-start; }
.case-flow p { margin: 0; font-size: 14px; line-height: 1.5; color: rgba(248, 250, 252, 0.78); }
.case-flow__tag {
  flex: 0 0 auto;
  font: 600 10px/1 var(--font-mono);
  letter-spacing: 0.12em; text-transform: uppercase;
  padding: 5px 8px; border-radius: var(--radius-sm);
  margin-top: 2px;
}
.case-flow__tag--before { color: var(--color-muted); border: 1px solid rgba(248, 250, 252, 0.16); }
/* Vert = signal "contenido/OK", cohérent avec l'état safe de la escena ¿Cómo lo hacemos? */
.case-flow__tag--after  { color: #22C55E; border: 1px solid rgba(34, 197, 94, 0.4); background: rgba(34, 197, 94, 0.08); }

/* ── Acompañamiento (grille de services) ────────────────────────── */
.support__head { text-align: center; max-width: 720px; margin: 0 auto var(--space-12); }
.support-grid {
  list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: 1fr; gap: var(--space-3);
}
@media (min-width: 640px)  { .support-grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1000px) { .support-grid { grid-template-columns: repeat(3, 1fr); } }
.support-item {
  display: flex; align-items: center; gap: var(--space-3);
  padding: var(--space-4) var(--space-5);
  background: rgba(248, 250, 252, 0.03);
  border: 1px solid rgba(248, 250, 252, 0.10);
  border-radius: var(--radius-md);
  font-size: 15px; color: var(--color-fg);
}
.support-item .icon { flex: 0 0 auto; width: 18px; height: 18px; color: var(--color-primary); }

/* ── Liderazgo ──────────────────────────────────────────────────── */
.leadership {
  list-style: none; margin: 0 auto; padding: 0;
  display: grid; grid-template-columns: 1fr; gap: var(--space-4);
  max-width: 760px;
}
@media (min-width: 640px) { .leadership { grid-template-columns: repeat(2, 1fr); } }
.leader-card {
  display: flex; align-items: center; gap: var(--space-4);
  padding: var(--space-5) var(--space-6);
  background: rgba(248, 250, 252, 0.03);
  border: 1px solid rgba(248, 250, 252, 0.10);
  border-radius: var(--radius-lg);
}
.leader-card__avatar {
  flex: 0 0 auto;
  width: 52px; height: 52px; border-radius: 50%;
  display: grid; place-items: center;
  font: 700 16px/1 var(--font-mono);
  letter-spacing: 0.04em;
  color: var(--color-fg);
  background: rgba(220, 38, 38, 0.14);
  border: 1px solid rgba(220, 38, 38, 0.4);
}
.leader-card__name { margin: 0; font-size: 18px; color: var(--color-fg); }
.leader-card__role { margin: 2px 0 0; font-size: 14px; color: var(--color-muted); }
/* Plaques de certification : logo blanc HD + badge niveau code metal.
   Metaux neutres (or / argent) + rouge ASHA pour Elite — les couleurs
   persona restent reservees aux heros. */
.partner-level {
  --metal: rgba(220, 38, 38, 0.85);
  position: relative;
  display: grid;
  grid-template-rows: auto 1fr auto;
  justify-items: center;
  gap: var(--space-3);
  padding: var(--space-5) var(--space-4) var(--space-4);
  border-radius: var(--radius-md);
  border: 1px solid var(--color-border-strong);
  background: linear-gradient(180deg, rgba(255,255,255,0.04), rgba(255,255,255,0));
  overflow: hidden;
  transition: transform var(--duration-normal) var(--ease-out),
              border-color var(--duration-normal) var(--ease-out),
              box-shadow var(--duration-normal) var(--ease-out);
}
.partner-level::before {
  /* filet metal en tete de plaque */
  content: '';
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 2px;
  background: linear-gradient(90deg, transparent, var(--metal), transparent);
}
.partner-level:hover {
  transform: translateY(-3px);
  border-color: color-mix(in srgb, var(--metal) 55%, transparent);
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.35);
}
.partner-level__tag {
  display: inline-block;
  width: max-content;
  font: 700 10px/1 var(--font-mono);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  padding: 5px 10px;
  border-radius: var(--radius-full);
  color: var(--metal);
  background: color-mix(in srgb, var(--metal) 12%, transparent);
  border: 1px solid color-mix(in srgb, var(--metal) 45%, transparent);
}
.partner-level__logo {
  display: block;
  max-width: 82%;
  max-height: 44px;
  width: auto;
  height: auto;
  align-self: center;
  filter: brightness(0) invert(1);
  opacity: 0.92;
}
.partner-level__note {
  font-size: var(--text-xs);
  color: var(--color-muted);
  text-align: center;
  line-height: 1.35;
}
.partner-level--elite    { --metal: #DC2626; }                /* rouge ASHA */
.partner-level--platinum { --metal: #C9D4E3; }                /* argent */
.partner-level--gold     { --metal: #D4A94F; }                /* or */

/* ── Clientes (light) ───────────────────────────────────────── */

.clients__head {
  text-align: center;
  margin-bottom: var(--space-12);
}
.clients__title {
  font-size: clamp(var(--text-3xl), 4vw, var(--text-4xl));
}
.clients__sub {
  color: var(--color-muted-light);
  font-size: var(--text-lg);
  margin-top: var(--space-2);
}
.clients__grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--space-2);
  align-items: center;
  justify-items: center;
}
@media (min-width: 540px) { .clients__grid { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 720px) { .clients__grid { grid-template-columns: repeat(4, 1fr); } }
@media (min-width: 1024px) { .clients__grid { grid-template-columns: repeat(7, 1fr); } }
.client-logo {
  width: 100%;
  aspect-ratio: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-4);
  border-radius: var(--radius-md);
  transition: all var(--duration-normal) var(--ease-out);
}
.client-logo img {
  max-width: 100%;
  max-height: 80%;
  object-fit: contain;
  filter: grayscale(100%) opacity(0.55);
  transition: filter var(--duration-normal) var(--ease-out);
}
.client-logo:hover {
  background: rgba(220,38,38,0.04);
}
.client-logo:hover img {
  filter: grayscale(0%) opacity(1);
}

.clients__more {
  margin-top: var(--space-12);
  padding-top: var(--space-8);
  border-top: 1px solid var(--color-border-light);
  text-align: center;
}
.clients__more-label {
  font: 600 var(--text-xs)/1 var(--font-mono);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--color-muted-light);
  margin: 0 0 var(--space-6);
}
.client-names {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-2) var(--space-3);
  max-width: 900px;
  margin-inline: auto;
}
.client-names li {
  font-weight: 500;
  font-size: var(--text-sm);
  color: var(--color-fg-light);
  padding: 6px 14px;
  border-radius: var(--radius-full);
  background: var(--color-surface-light);
  border: 1px solid var(--color-border-light);
}

/* ── Final CTA (dark) ───────────────────────────────────────── */

.final-cta {
  position: relative;
  background: var(--color-surface);
  overflow: hidden;
}
.final-cta::before {
  content: '';
  position: absolute; inset: 0;
  background:
    radial-gradient(ellipse 60% 50% at 50% 0%, rgba(220,38,38,0.18) 0%, transparent 65%),
    linear-gradient(rgba(220,38,38,0.04) 1px, transparent 1px),
    linear-gradient(90deg, rgba(220,38,38,0.04) 1px, transparent 1px);
  background-size: auto, 64px 64px, 64px 64px;
  pointer-events: none;
  mask-image: radial-gradient(ellipse at center, black 0%, transparent 80%);
  -webkit-mask-image: radial-gradient(ellipse at center, black 0%, transparent 80%);
}
.final-cta__inner {
  position: relative;
  text-align: center;
  max-width: 760px;
  margin: 0 auto;
  padding-block: var(--space-24);
}
.final-cta__title {
  font-size: clamp(var(--text-3xl), 4vw, var(--text-5xl));
  line-height: 1.1;
}
.final-cta__title .accent {
  color: var(--color-primary);
  font-weight: 800;
}
.final-cta__actions {
  display: inline-flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  justify-content: center;
  margin-top: var(--space-8);
}

/* ── Footer (dark) ──────────────────────────────────────────── */

.site-footer {
  background: var(--color-bg);
  border-top: 1px solid var(--color-border);
  padding-block: var(--space-16) 0;
}
.site-footer__grid {
  display: grid;
  gap: var(--space-12);
}
@media (min-width: 720px) {
  .site-footer__grid { grid-template-columns: 1.4fr 1fr 1fr 1.2fr; gap: var(--space-12); }
}
.site-footer__col h3 {
  font-size: var(--text-sm);
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--color-muted);
  margin: 0 0 var(--space-4);
}
.site-footer__brand-text {
  font-size: var(--text-sm);
  color: var(--color-muted);
  line-height: var(--leading-body);
  margin: var(--space-4) 0;
  max-width: 320px;
}
.site-footer__logo {
  height: 44px;
  width: auto;
  border-radius: 4px;
}
.site-footer__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 8px;
}
.site-footer__list a {
  font-size: var(--text-sm);
  color: var(--color-fg);
  opacity: 0.8;
  transition: all var(--duration-fast) var(--ease-out);
}
.site-footer__list a:hover { opacity: 1; color: var(--color-primary); }

.social-icons { display: flex; gap: var(--space-2); margin-top: var(--space-4); }
.social-icon {
  width: 36px; height: 36px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--color-border);
  border-radius: 50%;
  color: var(--color-fg);
  transition: all var(--duration-fast) var(--ease-out);
}
.social-icon:hover {
  border-color: var(--color-primary);
  color: var(--color-primary);
}
.social-icon .icon { width: 16px; height: 16px; }

.site-footer__bottom {
  margin-top: var(--space-16);
  padding-block: var(--space-6);
  border-top: 1px solid var(--color-border);
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-4);
  font-size: var(--text-xs);
  color: var(--color-muted);
}
.site-footer__bottom a { color: var(--color-muted); }
.site-footer__bottom a:hover { color: var(--color-primary); }

/* LATAM map mini in footer */
.footer-map {
  position: relative;
  border-radius: var(--radius-md);
  overflow: hidden;
  background: var(--color-surface);
  padding: var(--space-2);
}
.footer-map img { width: 100%; height: auto; opacity: 0.85; }

/* ── Mobile menu drawer ─────────────────────────────────────── */

.mobile-menu {
  position: fixed;
  inset: 0;
  z-index: var(--z-modal);
  background: rgba(16, 16, 16, 0.98);
  backdrop-filter: blur(20px) saturate(150%);
  -webkit-backdrop-filter: blur(20px) saturate(150%);
  display: flex;
  flex-direction: column;
  opacity: 0;
  visibility: hidden;
  transform: translateY(-12px);
  transition: opacity var(--duration-normal) var(--ease-out),
              visibility var(--duration-normal) var(--ease-out),
              transform var(--duration-normal) var(--ease-out);
}
.mobile-menu.is-open {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
}
@media (min-width: 1024px) {
  .mobile-menu { display: none; }
}

.mobile-menu__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-4) var(--container-px);
  height: var(--header-h);
  border-bottom: 1px solid var(--color-border);
  flex-shrink: 0;
}
.mobile-menu__close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px; height: 40px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: transparent;
  color: var(--color-fg);
}
.mobile-menu__close .icon { width: 20px; height: 20px; }

.mobile-menu__inner {
  flex: 1;
  overflow-y: auto;
  padding: var(--space-8) var(--container-px) var(--space-4);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.mobile-menu__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 2px;
}
.mobile-menu__link {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 14px 4px;
  font-size: var(--text-2xl);
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--color-fg);
  border-bottom: 1px solid var(--color-border);
}
.mobile-menu__link.is-active { color: var(--color-primary); }
.mobile-menu__link .icon { width: 18px; height: 18px; opacity: 0.5; }

.mobile-submenu {
  list-style: none;
  margin: 0;
  padding: 8px 0 12px var(--space-4);
  display: grid;
  gap: 4px;
  border-bottom: 1px solid var(--color-border);
}
.mobile-submenu a {
  display: block;
  padding: 8px 4px;
  font-size: var(--text-base);
  color: var(--color-muted);
}
.mobile-submenu a:hover { color: var(--color-primary); }

.mobile-menu__cta {
  margin-top: auto;
  padding: var(--space-6) var(--container-px) calc(var(--space-6) + env(safe-area-inset-bottom, 0px));
  display: grid;
  gap: var(--space-3);
  border-top: 1px solid var(--color-border);
  background: rgba(16, 16, 16,0.6);
}
.mobile-menu__cta .btn { justify-content: center; padding: 16px 24px; font-size: var(--text-base); }

/* When menu is open, lock body scroll */
body.menu-open { overflow: hidden; }

/* Hide header CTAs on mobile to leave room for the hamburger only */
@media (max-width: 1023px) {
  .site-header__cta .btn { display: none; }
}

/* ── Compact page hero (inner pages) ─────────────────────────── */

.page-hero {
  position: relative;
  padding: clamp(72px, 10vw, 120px) 0 clamp(40px, 6vw, 64px);
  background: var(--color-bg);
  overflow: hidden;
  text-align: center;
}
.page-hero::before {
  content: '';
  position: absolute; inset: 0;
  background:
    radial-gradient(ellipse 80% 60% at center top, rgba(220,38,38,0.12) 0%, transparent 60%),
    linear-gradient(rgba(220,38,38,0.04) 1px, transparent 1px),
    linear-gradient(90deg, rgba(220,38,38,0.04) 1px, transparent 1px);
  background-size: auto, 64px 64px, 64px 64px;
  mask-image: radial-gradient(ellipse at top center, black 0%, transparent 70%);
  -webkit-mask-image: radial-gradient(ellipse at top center, black 0%, transparent 70%);
  pointer-events: none;
}
.page-hero__inner {
  position: relative;
  max-width: 920px;
  margin: 0 auto;
}
.page-hero__eyebrow {
  display: inline-block;
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--color-primary);
  margin-bottom: var(--space-4);
}
.page-hero__title {
  font-size: clamp(var(--text-3xl), 4.5vw, var(--text-5xl));
  line-height: 1.1;
  letter-spacing: -0.02em;
  font-weight: 800;
}
/* Accent — solid brand red (gradient text removido, banned por DS) */
.page-hero__title .accent {
  color: var(--color-primary);
}
.page-hero__sub {
  margin: var(--space-4) auto 0;
  color: var(--color-muted);
  font-size: var(--text-lg);
  max-width: 720px;
}

/* ── Page hero: La Liga ASHA variant (Phase C6) ─────────────── */
.page-hero--league {
  text-align: left;
  padding: clamp(120px, 14vw, 184px) 0 clamp(80px, 10vw, 120px);
  min-height: clamp(500px, 70vh, 720px);
  min-height: 70dvh;          /* iOS Safari fix */
  display: flex;
  align-items: center;
  isolation: isolate;
  overflow: hidden;
}
.page-hero--league::before { display: none; }

.page-hero__bg {
  position: absolute; inset: 0;
  z-index: 0;
  pointer-events: none;
}
.page-hero__bg-img {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  object-position: center 30%;
  opacity: 0.55;
  filter: saturate(1.05) contrast(1.05);
}
.page-hero__bg-grad {
  position: absolute; inset: 0;
  background:
    /* gentle fade to the section bg at the bottom so the hero blends into the next section */
    linear-gradient(180deg, transparent 0%, transparent 60%, var(--color-bg) 100%),
    /* warm/cool persona-tinted radials anchoring the corners */
    radial-gradient(ellipse 60% 70% at 92% 8%,  rgba( 6, 182, 212, 0.10), transparent 60%),
    radial-gradient(ellipse 70% 80% at 8%  92%, rgba(220,  38,  38, 0.14), transparent 60%);
}
.page-hero__bg-grid {
  position: absolute; inset: 0;
  background-image:
    linear-gradient(rgba(255,255,255,0.04) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255,255,255,0.04) 1px, transparent 1px);
  background-size: 64px 64px;
  mask-image: radial-gradient(ellipse at center, black 30%, transparent 80%);
  -webkit-mask-image: radial-gradient(ellipse at center, black 30%, transparent 80%);
  opacity: 0.4;
}

.page-hero--league .page-hero__inner {
  /* Match the header's container behavior exactly so the H1 left edge aligns
     with the logo above. The base .page-hero__inner ships a tighter max-width
     (920px) that would offset the column; override to full container width. */
  max-width: var(--container-max);
  margin-inline: auto;
  position: relative;
  z-index: 2;
}
/* Constrain readable width on text elements so they wrap nicely while their
   left edge stays anchored to the container's left padding (= logo X). */
.page-hero--league .page-hero__title,
.page-hero--league .page-hero__lede,
.page-hero--league .liga-constellation,
.page-hero--league .page-hero__actions {
  max-width: 880px;
}
.page-hero--league .page-hero__eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.18em;
  padding: 8px 14px;
  border-radius: var(--radius-full);
  background: rgba(220,38,38,0.10);
  border: 1px solid rgba(220,38,38,0.30);
  color: var(--color-danger-soft);
}
.page-hero__eyebrow-dot {
  width: 8px; height: 8px;
  background: var(--color-primary);
  border-radius: 50%;
  box-shadow: 0 0 10px var(--color-primary);
  animation: pulse 2.4s ease-in-out infinite;
}

.page-hero--league .page-hero__title {
  /* One step below the home hero: this is a secondary page, not the landing.
     Same family/weight as home, slightly tighter clamp. */
  font-size: clamp(var(--text-4xl), 5vw, 60px);
  line-height: 1.05;
  letter-spacing: -0.03em;
  font-weight: 800;
  margin: var(--space-6) 0 var(--space-6);
  color: var(--color-fg);
  text-shadow:
    0 0 32px rgba(255,255,255,0.18),
    0 0 6px rgba(220,38,38,0.35),
    0 2px 18px rgba(0,0,0,0.45);
}

/* ── La Liga · Hero theatrical entry (Phase P1-4) ─────────────── */

/* Slow drifting radial blob layer that adds breath to the hero bg.
   Uses persona-tinted blobs so the eye registers "6 frentes" subconsciously. */
.page-hero__bg-drift,
.hero__drift {
  position: absolute; inset: 0;
  background:
    radial-gradient(circle 380px at 8%  88%, rgba(220, 38, 38, 0.22), transparent 60%),
    radial-gradient(circle 320px at 92% 18%, rgba(  6,182,212, 0.18), transparent 60%),
    radial-gradient(circle 280px at 65% 92%, rgba( 34,197, 94, 0.16), transparent 60%),
    radial-gradient(circle 240px at 30% 12%, rgba(168, 85,247, 0.14), transparent 60%);
  filter: blur(8px);
  opacity: 0.85;
  mix-blend-mode: screen;
  animation: liga-drift 26s ease-in-out infinite alternate;
  pointer-events: none;
}
@keyframes liga-drift {
  0%   { transform: translate3d(0, 0, 0)        scale(1);    }
  50%  { transform: translate3d(-2%, 1.5%, 0)   scale(1.04); }
  100% { transform: translate3d(2%, -1.5%, 0)   scale(1.02); }
}

/* SOC-style corner tickers — minimal, monospace, mostly atmosphere */
.page-hero__ticker {
  position: absolute;
  z-index: 1;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: rgba(248, 250, 252, 0.55);
  padding: 8px 12px;
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: var(--radius-full);
  background: rgba(16, 16, 16, 0.45);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  opacity: 0;
  animation: liga-ticker-fade 800ms var(--ease-out) 200ms forwards;
}
.page-hero__ticker--tl { top: 96px;  left: 24px; }
.page-hero__ticker--br { bottom: 24px; right: 24px; }
.page-hero__ticker-dot {
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--color-primary);
  box-shadow: 0 0 8px var(--color-primary);
  animation: pulse 2.4s ease-in-out infinite;
}
.page-hero__ticker-dot--cyan {
  background: var(--color-csirt);
  box-shadow: 0 0 8px var(--color-csirt);
}
@keyframes liga-ticker-fade { to { opacity: 1; } }
@media (max-width: 768px) {
  .page-hero__ticker { display: none; }
}

/* The constellation: 6 wired persona nodes acting as a quick TOC + visual signature */
.liga-constellation {
  position: relative;
  margin: var(--space-6) 0 var(--space-8);
  display: flex;
  flex-wrap: wrap;
  gap: 18px 28px;
  align-items: center;
}
.liga-constellation__wire {
  position: absolute;
  inset: 50% 0 auto 0;
  width: 100%;
  height: 2px;
  transform: translateY(-50%);
  pointer-events: none;
  overflow: visible;
  z-index: 0;
}
.liga-constellation__wire path {
  fill: none;
  stroke: rgba(255, 255, 255, 0.12);
  stroke-width: 1.2;
  stroke-dasharray: 600;
  stroke-dashoffset: 600;
  animation: liga-wire-draw 1400ms cubic-bezier(0.16, 1, 0.3, 1) 200ms forwards;
}
@keyframes liga-wire-draw { to { stroke-dashoffset: 0; } }

.liga-constellation__node {
  position: relative;
  z-index: 1;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 9px 16px 9px 14px;
  border-radius: var(--radius-full);
  background: rgba(16, 16, 16, 0.7);
  border: 1px solid var(--persona-stroke, rgba(255, 255, 255, 0.10));
  color: var(--color-fg);
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.10em;
  text-decoration: none;
  text-transform: uppercase;
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  opacity: 0;
  transform: translateY(8px);
  animation: liga-node-in 520ms cubic-bezier(0.16, 1, 0.3, 1) forwards;
  transition: transform var(--duration-normal) var(--ease-out),
              border-color var(--duration-normal) var(--ease-out),
              box-shadow var(--duration-normal) var(--ease-out);
}
.liga-constellation__node:nth-child(2) { animation-delay: 420ms; }
.liga-constellation__node:nth-child(3) { animation-delay: 520ms; }
.liga-constellation__node:nth-child(4) { animation-delay: 620ms; }
.liga-constellation__node:nth-child(5) { animation-delay: 720ms; }
.liga-constellation__node:nth-child(6) { animation-delay: 820ms; }
.liga-constellation__node:nth-child(7) { animation-delay: 920ms; }
@keyframes liga-node-in {
  to { opacity: 1; transform: translateY(0); }
}
.liga-constellation__node:hover,
.liga-constellation__node:focus-visible {
  transform: translateY(-2px);
  border-color: var(--persona-color, var(--color-fg));
  box-shadow: 0 0 0 1px var(--persona-color, var(--color-fg)) inset,
              0 8px 24px -8px var(--persona-color, rgba(255,255,255,0.3));
  outline: none;
}
.liga-constellation__dot {
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--persona-color, var(--color-fg));
  box-shadow: 0 0 10px var(--persona-color, var(--color-fg));
}
.liga-constellation__label { line-height: 1; }

/* Per-persona color tokens — drive the dot color, hover border, glow */
.liga-constellation__node[data-persona="ngsoc"]     { --persona-color: var(--color-ngsoc);     --persona-stroke: rgba(226,232,240,0.18); }
.liga-constellation__node[data-persona="csirt"]     { --persona-color: var(--color-csirt);     --persona-stroke: rgba(  6,182,212,0.30); }
.liga-constellation__node[data-persona="ctem"]      { --persona-color: var(--color-ctem);      --persona-stroke: rgba(249,115, 22,0.30); }
.liga-constellation__node[data-persona="zerotrust"] { --persona-color: var(--color-zerotrust); --persona-stroke: rgba(168, 85,247,0.30); }
.liga-constellation__node[data-persona="grc"]       { --persona-color: var(--color-grc);       --persona-stroke: rgba( 34,197, 94,0.30); }
.liga-constellation__node[data-persona="asha"]      { --persona-color: var(--color-primary);   --persona-stroke: rgba(220, 38, 38,0.32); }

@media (max-width: 640px) {
  .liga-constellation { gap: 10px 12px; }
  .liga-constellation__node { padding: 7px 12px 7px 10px; font-size: 11px; }
  .liga-constellation__wire { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .page-hero__bg-drift,
  .hero__drift { animation: none; }
  .liga-constellation__wire path { stroke-dashoffset: 0; animation: none; }
  .liga-constellation__node { opacity: 1; transform: none; animation: none; }
  .page-hero__ticker { opacity: 1; animation: none; }
}

.page-hero__lede {
  font-size: var(--text-lg);
  line-height: 1.6;
  color: var(--color-muted);
  margin: 0 0 var(--space-8);
  max-width: 56ch;
}

.page-hero__actions {
  display: inline-flex;
  flex-wrap: wrap;
  gap: var(--space-3);
}

/* ── Breadcrumb ──────────────────────────────────────────────── */

.breadcrumb-wrap {
  background: var(--color-bg);
  border-bottom: 1px solid var(--color-border);
}
.breadcrumb {
  list-style: none;
  margin: 0;
  padding: var(--space-3) 0;
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  font-size: var(--text-xs);
  color: var(--color-muted);
  letter-spacing: 0.06em;
}
.breadcrumb a { color: var(--color-muted); }
.breadcrumb a:hover { color: var(--color-primary); }
.breadcrumb li:not(:last-child)::after {
  content: '/';
  margin-left: 6px;
  opacity: 0.4;
}
.breadcrumb li:last-child {
  color: var(--color-fg);
  font-weight: 600;
}

/* ── Persona deep dive ───────────────────────────────────────── */

.persona-deep {
  padding-block: var(--space-16);
  position: relative;
}
.persona-deep + .persona-deep {
  border-top: 1px solid var(--color-border);
}
.persona-deep__grid {
  display: grid;
  gap: var(--space-12);
  align-items: center;
}
@media (min-width: 900px) {
  .persona-deep__grid { grid-template-columns: 1fr 1.4fr; gap: var(--space-16); }
  .persona-deep--reverse .persona-deep__grid > :first-child { order: 2; }
  .persona-deep--reverse .persona-deep__grid > :last-child  { order: 1; }
}
/* Pas de plateau noir ici, et c'est deliberе : les six blocs de metodologia
   portent tous .persona-deep__media--video, qui retire cadre, fond, bordure et
   rayon en !important pour laisser les personnages FLOTTER derriere une aura
   radiale de leur couleur. Verifie sur les 6 : aucun n'utilise ce cadre.
   Les valeurs qui suivent ne servent donc que de repli si un persona revenait
   un jour a une image encadree. */
.persona-deep__media {
  position: relative;
  border-radius: var(--radius-lg);
  overflow: hidden;
  background: var(--color-surface);
  aspect-ratio: 3 / 4;
  max-width: 460px;
  margin-inline: auto;
  border: 1px solid var(--color-border);
}
/* (regla "GRC media bigger" retirada 2026-07-02 : las 6 animaciones v2
   comparten el mismo formato 3:4, GRC vuelve al tamaño estándar) */
.persona-deep__media img {
  width: 100%; height: 100%;
  object-fit: cover;
  object-position: center top;
}
.persona-deep__media::after {
  content: '';
  position: absolute; inset: 0;
  background: linear-gradient(180deg, transparent 50%, rgba(16, 16, 16,0.7) 100%);
  pointer-events: none;
}
.persona-deep__role {
  font-size: var(--text-xs);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  font-weight: 700;
  margin-bottom: var(--space-3);
  color: var(--color-primary);
}
.persona-deep__name {
  font-size: clamp(var(--text-3xl), 4vw, var(--text-5xl));
  line-height: 1;
  font-weight: 800;
  letter-spacing: -0.02em;
  margin: 0 0 var(--space-4);
}
.persona-deep__desc {
  font-size: var(--text-lg);
  color: var(--color-muted);
  margin-bottom: var(--space-6);
}
.persona-deep__bullets {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 12px;
}
.persona-deep__bullets li {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  font-size: var(--text-base);
  color: var(--color-fg);
}
.persona-deep__bullets li .icon {
  width: 18px; height: 18px;
  color: var(--color-primary);
  flex-shrink: 0;
  margin-top: 4px;
}
/* Servicios técnicos — popover flotante glass (progressive disclosure) */
.persona-deep__services {
  position: relative;
  margin-top: var(--space-5);
  padding-top: var(--space-5);
  border-top: 1px dashed rgba(148, 163, 184, 0.18);
}

/* Summary = toggle button — chip cyan inline */
.persona-deep__services-toggle {
  list-style: none;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 10px 16px;
  border: 1px solid rgba(6, 182, 212, 0.30);
  border-radius: var(--radius-full);
  background: rgba(6, 182, 212, 0.06);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  user-select: none;
  transition: background 240ms var(--ease-out), border-color 240ms var(--ease-out), transform 240ms var(--ease-out);
  /* Liquid Glass inset */
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.06);
}
.persona-deep__services-toggle::-webkit-details-marker,
.persona-deep__services-toggle::marker { display: none; content: ''; }
.persona-deep__services-toggle:hover {
  background: rgba(6, 182, 212, 0.12);
  border-color: rgba(6, 182, 212, 0.55);
  transform: translateY(-1px);
}
.persona-deep__services-toggle:active {
  transform: translateY(0);
}
.persona-deep__services-toggle:focus-visible {
  outline: 2px solid var(--color-csirt);
  outline-offset: 3px;
}
.persona-deep__services-label {
  font: 700 11.5px/1 var(--font-mono);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: rgba(165, 243, 252, 0.92);
}
.persona-deep__services-count {
  font: 700 10px/1 var(--font-mono);
  letter-spacing: 0.04em;
  color: rgb(165, 243, 252);
  background: rgba(6, 182, 212, 0.22);
  padding: 3px 8px;
  border-radius: 999px;
  border: 1px solid rgba(6, 182, 212, 0.40);
  font-variant-numeric: tabular-nums;
}
.persona-deep__services-chevron {
  width: 12px; height: 12px;
  color: rgba(165, 243, 252, 0.75);
  transition: transform 280ms var(--ease-out);
  flex-shrink: 0;
}
details[open] > .persona-deep__services-toggle .persona-deep__services-chevron {
  transform: rotate(90deg);
}
details[open] > .persona-deep__services-toggle {
  background: rgba(6, 182, 212, 0.16);
  border-color: rgba(6, 182, 212, 0.65);
}

/* Panel — popover flotante glass que aparece sobre el contenido */
.persona-deep__services-panel {
  /* mobile : accordeon en flux (ne recouvre plus rien) */
  position: static;
  z-index: 40;
  width: 100%;
  margin-top: 12px;
  padding: var(--space-5) var(--space-6);
  background: linear-gradient(180deg, rgba(23, 23, 23, 0.78) 0%, rgba(16, 16, 16, 0.70) 100%);
  border: 1px solid rgba(6, 182, 212, 0.22);
  border-radius: 14px;
  backdrop-filter: blur(18px) saturate(120%);
  -webkit-backdrop-filter: blur(18px) saturate(120%);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.06),
    inset 0 -1px 0 rgba(0, 0, 0, 0.25),
    0 18px 44px rgba(0, 0, 0, 0.45),
    0 0 28px rgba(6, 182, 212, 0.10);
  animation: services-bubble-in 320ms cubic-bezier(0.16, 1, 0.3, 1) backwards;
}
/* Flecha del popover apuntando al toggle */
.persona-deep__services-panel::before {
  content: '';
  position: absolute;
  top: -7px;
  left: 28px;
  width: 12px;
  height: 12px;
  background: rgba(23, 23, 23, 0.78);
  border-left: 1px solid rgba(6, 182, 212, 0.22);
  border-top: 1px solid rgba(6, 182, 212, 0.22);
  transform: rotate(45deg);
  backdrop-filter: blur(18px);
  -webkit-backdrop-filter: blur(18px);
}
@keyframes services-bubble-in {
  from { opacity: 0; transform: translateY(-6px) scale(0.98); }
  to   { opacity: 1; transform: translateY(0) scale(1); }
}

/* Desktop : le panneau se deploie EN OVERLAY sur la carte du heros
   correspondant (cote animation), centre verticalement — il ne recouvre
   plus jamais le heros suivant */
@media (min-width: 900px) {
  .persona-deep { position: relative; }
  .persona-deep__services { position: static; }
  .persona-deep__services-panel {
    position: absolute;
    top: 50%;
    left: 0;
    width: 40%;
    max-height: 94%;
    overflow-y: auto;
    margin-top: 0;
    transform: translateY(-50%);
    animation-name: services-bubble-in-center;
  }
  .persona-deep--reverse .persona-deep__services-panel { left: auto; right: 0; }
  .persona-deep__services-panel::before { display: none; }
  @keyframes services-bubble-in-center {
    from { opacity: 0; transform: translateY(calc(-50% - 10px)) scale(0.98); }
    to   { opacity: 1; transform: translateY(-50%) scale(1); }
  }
}
@media (prefers-reduced-motion: reduce) {
  .persona-deep__services-panel { animation: none; }
  .persona-deep__services-chevron { transition: none; }
}

.persona-deep__services-list {
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--space-3);
}
.persona-deep__service {
  display: grid;
  grid-template-columns: 160px 1fr;
  gap: var(--space-4);
  align-items: baseline;
  padding-bottom: var(--space-3);
  border-bottom: 1px solid rgba(255, 255, 255, 0.04);
}
.persona-deep__service:last-child { border-bottom: 0; padding-bottom: 0; }
.persona-deep__service dt {
  font: 700 11.5px/1.3 var(--font-mono);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-fg);
  margin: 0;
}
.persona-deep__service dd {
  margin: 0;
  font-size: var(--text-sm);
  line-height: 1.5;
  color: rgba(203, 213, 225, 0.88);
}
@media (max-width: 720px) {
  .persona-deep__services-panel { padding: var(--space-4); }
  .persona-deep__service { grid-template-columns: 1fr; gap: 4px; }
  .persona-deep__service dt { font-size: 10.5px; }
}

.persona-deep__chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: var(--space-6);
}
.persona-deep__chip {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.06em;
  padding: 6px 12px;
  border-radius: var(--radius-full);
  border: 1px solid var(--color-border-strong);
  color: var(--color-fg);
}

/* Persona-specific accents */
.persona-deep[data-persona="zerotrust"] .persona-deep__role { color: var(--color-zerotrust); }
.persona-deep[data-persona="zerotrust"] .persona-deep__bullets .icon { color: var(--color-zerotrust); }
.persona-deep[data-persona="zerotrust"] .persona-deep__media { border-color: rgba(168,85,247,0.4); box-shadow: var(--glow-zerotrust); }

.persona-deep[data-persona="ngsoc"] .persona-deep__role { color: var(--color-ngsoc); }
.persona-deep[data-persona="ngsoc"] .persona-deep__bullets .icon { color: var(--color-ngsoc); }
.persona-deep[data-persona="ngsoc"] .persona-deep__media { border-color: rgba(226,232,240,0.3); box-shadow: var(--glow-ngsoc); }

.persona-deep[data-persona="asha"] .persona-deep__role { color: var(--color-primary); }
.persona-deep[data-persona="asha"] .persona-deep__bullets .icon { color: var(--color-primary); }
.persona-deep[data-persona="asha"] .persona-deep__media { border-color: rgba(220,38,38,0.4); box-shadow: var(--glow-primary); }

.persona-deep[data-persona="csirt"] .persona-deep__role { color: var(--color-csirt); }
.persona-deep[data-persona="csirt"] .persona-deep__bullets .icon { color: var(--color-csirt); }
.persona-deep[data-persona="csirt"] .persona-deep__media { border-color: rgba(6,182,212,0.4); box-shadow: var(--glow-csirt); }

.persona-deep[data-persona="ctem"] .persona-deep__role { color: var(--color-ctem); }
.persona-deep[data-persona="ctem"] .persona-deep__bullets .icon { color: var(--color-ctem); }
.persona-deep[data-persona="ctem"] .persona-deep__media { border-color: rgba(249,115,22,0.4); box-shadow: var(--glow-ctem); }

.persona-deep[data-persona="grc"] .persona-deep__role { color: var(--color-grc); }
.persona-deep[data-persona="grc"] .persona-deep__bullets .icon { color: var(--color-grc); }
.persona-deep[data-persona="grc"] .persona-deep__media { border-color: rgba(34,197,94,0.4); box-shadow: var(--glow-grc); }

/* ── Persona media · video integration ─────────────────────────── */

/* When the media slot holds a video, drop the box: no surface, no border,
   no rounded frame, no gradient overlay. The hero floats freely over the
   page background, surrounded by a soft persona-tinted aura.
   The <img> still provides intrinsic dimensions for the 3/4 box. */
.persona-deep__media--video {
  isolation: isolate;
  background: transparent !important;
  border: none !important;
  border-radius: 0 !important;
  box-shadow: none !important;
  overflow: visible;
}
.persona-deep__media--video::after { display: none; }
.persona-deep__media--video::before {
  /* persona-color radial aura — replaces the box glow */
  content: '';
  position: absolute;
  inset: 5%;
  background: radial-gradient(60% 55% at 50% 60%, var(--persona-aura, transparent) 0%, transparent 70%);
  filter: blur(40px);
  z-index: -1;
  pointer-events: none;
  opacity: 0.85;
}
/* Static poster (only kept for personas still using <video> like GRC) */
.persona-deep__media--video img:not(.persona-deep__media__anim) {
  position: relative;
  z-index: 0;
  opacity: 0;
  transition: opacity var(--duration-slow) var(--ease-out);
}
/* Animated WebP with true alpha — replaces the <video> for transparent personas */
.persona-deep__media__anim {
  position: relative;
  z-index: 1;
  width: 100%;
  height: auto;
  display: block;
  object-fit: contain;
}
.persona-deep__media video {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: contain;
  object-position: center;
  display: block;
  z-index: 1;
  background: transparent;
}

/* Persona aura colors (used by ::before above) */
.persona-deep[data-persona="zerotrust"] .persona-deep__media--video { --persona-aura: rgba(168, 85, 247, 0.45); }
.persona-deep[data-persona="ngsoc"]     .persona-deep__media--video { --persona-aura: rgba(226, 232, 240, 0.25); }
.persona-deep[data-persona="asha"]      .persona-deep__media--video { --persona-aura: rgba(220,  38,  38, 0.45); }
.persona-deep[data-persona="csirt"]     .persona-deep__media--video { --persona-aura: rgba(  6, 182, 212, 0.45); }
.persona-deep[data-persona="ctem"]      .persona-deep__media--video { --persona-aura: rgba(249, 115,  22, 0.45); }
.persona-deep[data-persona="grc"]       .persona-deep__media--video { --persona-aura: rgba( 34, 197,  94, 0.45); }

/* "Ver el caso" lightbox trigger — sits over the gradient, persona-tinted */
.persona-deep__media__play {
  position: absolute;
  z-index: 3;
  right: var(--space-4);
  bottom: var(--space-4);
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: 10px 16px 10px 12px;
  border-radius: var(--radius-full);
  border: 1px solid rgba(255,255,255,0.25);
  background: rgba(16, 16, 16,0.55);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  color: var(--color-fg);
  font: 600 12px/1 var(--font-sans);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  cursor: pointer;
  transition: transform var(--duration-normal) var(--ease-out),
              background var(--duration-normal) var(--ease-out),
              border-color var(--duration-normal) var(--ease-out);
}
.persona-deep__media__play:hover,
.persona-deep__media__play:focus-visible {
  transform: translateY(-2px);
  background: rgba(16, 16, 16,0.75);
  border-color: rgba(255,255,255,0.45);
  outline: none;
}
.persona-deep__media__play .icon {
  width: 14px; height: 14px;
}
/* persona-tinted dot on the play badge */
.persona-deep[data-persona="asha"]  .persona-deep__media__play::before,
.persona-deep[data-persona="ngsoc"] .persona-deep__media__play::before,
.persona-deep[data-persona="grc"]   .persona-deep__media__play::before,
.persona-deep[data-persona="csirt"] .persona-deep__media__play::before,
.persona-deep[data-persona="ctem"]  .persona-deep__media__play::before,
.persona-deep[data-persona="zerotrust"] .persona-deep__media__play::before {
  content: '';
  width: 8px; height: 8px;
  border-radius: 999px;
  background: currentColor;
  box-shadow: 0 0 12px currentColor;
  animation: persona-pulse 2s var(--ease-out) infinite;
}
.persona-deep[data-persona="asha"]      .persona-deep__media__play::before { color: var(--color-primary); }
.persona-deep[data-persona="ngsoc"]     .persona-deep__media__play::before { color: var(--color-ngsoc); }
.persona-deep[data-persona="grc"]       .persona-deep__media__play::before { color: var(--color-grc); }
.persona-deep[data-persona="csirt"]     .persona-deep__media__play::before { color: var(--color-csirt); }
.persona-deep[data-persona="ctem"]      .persona-deep__media__play::before { color: var(--color-ctem); }
.persona-deep[data-persona="zerotrust"] .persona-deep__media__play::before { color: var(--color-zerotrust); }

@keyframes persona-pulse {
  0%, 100% { opacity: 1;   transform: scale(1); }
  50%      { opacity: 0.4; transform: scale(0.8); }
}

/* Soft hover-lift on video media (desktop only) */
@media (hover: hover) and (min-width: 900px) {
  .persona-deep__media--video {
    transition: transform var(--duration-slow) var(--ease-out),
                box-shadow var(--duration-slow) var(--ease-out);
  }
  .persona-deep__media--video:hover {
    transform: translateY(-4px) scale(1.01);
  }
}

/* Scroll-triggered reveal — applied to every persona-deep */
.persona-deep {
  opacity: 0;
  transform: translateY(28px);
  transition: opacity 700ms var(--ease-out), transform 700ms var(--ease-out);
}
.persona-deep.is-visible {
  opacity: 1;
  transform: none;
}

/* Video lightbox ─────────────────────────────────────────── */

.video-lightbox[hidden] { display: none; }
.video-lightbox {
  position: fixed;
  inset: 0;
  z-index: var(--z-modal);
  display: grid;
  place-items: center;
  padding: var(--space-6);
  background: rgba(9, 9, 9, 0.85);
  backdrop-filter: blur(16px) saturate(140%);
  -webkit-backdrop-filter: blur(16px) saturate(140%);
  opacity: 0;
  transition: opacity var(--duration-normal) var(--ease-out);
}
.video-lightbox.is-open { opacity: 1; }
.video-lightbox__frame {
  position: relative;
  width: min(1100px, 100%);
  aspect-ratio: 16 / 9;
  border-radius: var(--radius-lg);
  overflow: hidden;
  background: #000;
  box-shadow: 0 32px 80px rgba(0,0,0,0.6), 0 0 0 1px rgba(255,255,255,0.08);
  transform: translateY(24px) scale(0.97);
  transition: transform 420ms var(--ease-out);
}
.video-lightbox.is-open .video-lightbox__frame { transform: none; }
.video-lightbox__video {
  width: 100%; height: 100%;
  display: block;
  background: #000;
}
.video-lightbox__caption {
  position: absolute;
  left: 0; right: 0; top: 0;
  padding: var(--space-6) calc(var(--space-12) + 28px) var(--space-8) var(--space-6);
  color: var(--color-fg);
  font: 700 var(--text-lg)/1.2 var(--font-sans);
  pointer-events: none;
  letter-spacing: -0.01em;
  background: linear-gradient(180deg, rgba(9, 9, 9,0.75), rgba(9, 9, 9,0));
}
.video-lightbox__caption span {
  display: block;
  font: 600 11px/1 var(--font-mono);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--color-muted);
  margin-bottom: 6px;
}
.video-lightbox__close {
  position: absolute;
  top: var(--space-4);
  right: var(--space-4);
  width: 44px; height: 44px;
  display: grid;
  place-items: center;
  border-radius: var(--radius-full);
  border: 1px solid rgba(255,255,255,0.25);
  background: rgba(16, 16, 16,0.6);
  color: var(--color-fg);
  cursor: pointer;
  transition: background var(--duration-fast) var(--ease-out),
              border-color var(--duration-fast) var(--ease-out);
}
.video-lightbox__close:hover,
.video-lightbox__close:focus-visible {
  background: rgba(16, 16, 16,0.9);
  border-color: rgba(255,255,255,0.5);
  outline: none;
}
.video-lightbox__close .icon { width: 22px; height: 22px; }

@media (max-width: 640px) {
  .video-lightbox { padding: var(--space-3); }
  .video-lightbox__frame { aspect-ratio: 9 / 16; max-height: 90vh; width: auto; }
}

/* Reduced motion — no scroll reveal, no pulse, no hover lift, no lightbox transition */
@media (prefers-reduced-motion: reduce) {
  .persona-deep { opacity: 1; transform: none; transition: none; }
  .persona-deep__media__play::before { animation: none; }
  .persona-deep__media--video:hover { transform: none; }
  .video-lightbox,
  .video-lightbox__frame { transition: none; }
}

/* ── Feature grid (CSIRT functions, framework cards on light) ── */

.feature-grid {
  display: grid;
  gap: var(--space-6);
  grid-template-columns: 1fr;
}
@media (min-width: 720px)  { .feature-grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1024px) { .feature-grid { grid-template-columns: repeat(3, 1fr); } }
.feature-card {
  background: var(--color-surface-light);
  border: 1px solid var(--color-border-light);
  border-radius: var(--radius-lg);
  padding: var(--space-8);
  transition: all var(--duration-normal) var(--ease-out);
}
.feature-card:hover {
  border-color: var(--color-primary);
  transform: translateY(-2px);
  box-shadow: var(--shadow-md);
}
.feature-card__icon {
  width: 48px; height: 48px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-md);
  background: rgba(220,38,38,0.08);
  color: var(--color-primary);
  margin-bottom: var(--space-4);
}
.feature-card__icon .icon { width: 24px; height: 24px; }
.feature-card h3 {
  font-size: var(--text-xl);
  font-weight: 700;
  letter-spacing: -0.01em;
  margin: 0 0 var(--space-2);
  color: var(--color-fg-light);
}
.feature-card p {
  font-size: var(--text-base);
  color: var(--color-muted-light);
  margin: 0;
  line-height: 1.55;
}

/* ── Phase cards (numbered, dark) ────────────────────────────── */

.phase-grid {
  display: grid;
  gap: var(--space-4);
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
}
.phase-card {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: var(--space-6);
  transition: all var(--duration-normal) var(--ease-out);
}
.phase-card:hover {
  border-color: rgba(220,38,38,0.4);
  transform: translateY(-2px);
}
.phase-card__num {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 40px; height: 40px;
  padding: 0 8px;
  background: linear-gradient(135deg, var(--color-primary) 0%, #FB7185 100%);
  color: var(--color-fg);
  font-weight: 800;
  border-radius: var(--radius-md);
  font-family: var(--font-mono);
  font-size: var(--text-base);
  margin-bottom: var(--space-3);
  letter-spacing: 0;
}
.phase-card h3 {
  font-size: var(--text-lg);
  font-weight: 700;
  margin: 0 0 6px;
  letter-spacing: -0.01em;
}
.phase-card p {
  font-size: var(--text-sm);
  color: var(--color-muted);
  margin: 0;
  line-height: 1.55;
}

/* ── Prose (long-form text) ──────────────────────────────────── */

.prose {
  max-width: 760px;
  margin: 0 auto;
}
.prose h2 {
  margin-top: var(--space-12);
  margin-bottom: var(--space-3);
  font-size: var(--text-2xl);
  letter-spacing: -0.01em;
}
.prose h2:first-child { margin-top: 0; }
.prose h3 {
  margin-top: var(--space-6);
  margin-bottom: var(--space-2);
  font-size: var(--text-lg);
  color: var(--color-primary);
}
.prose p {
  font-size: var(--text-base);
  color: var(--color-muted-light);
  margin: 0 0 var(--space-4);
  line-height: var(--leading-body);
}
.prose blockquote {
  margin: 0 0 var(--space-4);
  padding-left: var(--space-4);
  border-left: 2px solid var(--color-primary);
  font-style: italic;
  color: var(--color-fg-light);
}
.prose ul {
  margin: 0 0 var(--space-4);
  padding-left: 1.4em;
  color: var(--color-muted-light);
  font-size: var(--text-base);
}
.prose ul li { margin-bottom: var(--space-2); line-height: var(--leading-body); }

/* ════════════════════════════════════════════════════════════════
   ENHANCEMENT LAYER v2 — Futurist / Tech / Cyber direction
   Adds polish without modifying base rules above.
   ════════════════════════════════════════════════════════════════ */

/* ── Liga ASHA: HUD corner brackets + persona accent top bar ──── */
.persona {
  --persona-color: var(--color-primary);
}
.persona[data-persona="zerotrust"] { --persona-color: var(--color-zerotrust); }
.persona[data-persona="ngsoc"]     { --persona-color: var(--color-ngsoc); }
.persona[data-persona="csirt"]     { --persona-color: var(--color-csirt); }
.persona[data-persona="ctem"]      { --persona-color: var(--color-ctem); }
.persona[data-persona="grc"]       { --persona-color: var(--color-grc); }

.persona::before {
  content: '';
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 2px;
  background: linear-gradient(90deg, transparent, var(--persona-color), transparent);
  z-index: 3;
  opacity: 0;
  transition: opacity var(--duration-normal) var(--ease-out);
}
.persona:hover::before { opacity: 1; }

.persona__body {
  background: linear-gradient(180deg, transparent 0%, rgba(16, 16, 16,0.85) 60%, rgba(16, 16, 16,0.97) 100%);
  padding: var(--space-6) var(--space-4) var(--space-4);
  transition: background var(--duration-normal) var(--ease-out);
}
.persona__name {
  font-family: var(--font-mono);
  letter-spacing: 0.18em;
  text-shadow: 0 0 16px color-mix(in srgb, var(--persona-color) 60%, transparent);
}

/* HUD corner brackets — only visible on hover */
.persona .persona__body::before,
.persona .persona__body::after {
  content: '';
  position: absolute;
  width: 14px; height: 14px;
  border: 1.5px solid var(--persona-color);
  opacity: 0;
  transition: opacity var(--duration-normal) var(--ease-out), transform var(--duration-normal) var(--ease-out);
}
.persona .persona__body::before {
  top: 8px; left: 8px;
  border-right: none; border-bottom: none;
  transform: translate(4px, 4px);
}
.persona .persona__body::after {
  bottom: 8px; right: 8px;
  border-left: none; border-top: none;
  transform: translate(-4px, -4px);
}
.persona:hover .persona__body::before,
.persona:hover .persona__body::after { opacity: 0.85; transform: translate(0,0); }

/* Persona scan line on hover */
.persona__img {
  position: relative;
  z-index: 0;
}
.persona__scanline {
  position: absolute;
  left: 0; right: 0; top: -10%;
  height: 30%;
  background: linear-gradient(180deg,
    transparent 0%,
    color-mix(in srgb, var(--persona-color) 25%, transparent) 49%,
    color-mix(in srgb, var(--persona-color) 95%, white 5%) 50%,
    color-mix(in srgb, var(--persona-color) 25%, transparent) 51%,
    transparent 100%);
  mix-blend-mode: screen;
  pointer-events: none;
  z-index: 2;
  opacity: 0;
  transform: translateY(0);
  transition: opacity var(--duration-fast) var(--ease-out);
}
.persona:hover .persona__scanline {
  opacity: 0.9;
  animation: persona-scan 1.6s ease-in-out infinite;
}
@keyframes persona-scan {
  0%   { transform: translateY(-30%); }
  100% { transform: translateY(330%); }
}

/* ── How: HUD overlay on image + tinted promise icons ────────── */
.how__media {
  position: relative;
  isolation: isolate;
}
.how__media::before {
  content: '';
  position: absolute; inset: 0;
  background:
    linear-gradient(135deg, transparent 0%, transparent 70%, rgba(220,38,38,0.18) 100%),
    repeating-linear-gradient(0deg, transparent 0 6px, rgba(255,255,255,0.025) 6px 7px);
  border-radius: inherit;
  z-index: 1;
  pointer-events: none;
  mix-blend-mode: screen;
}
.how__media::after {
  content: '';
  position: absolute;
  top: 12px; right: 12px;
  width: 40px; height: 40px;
  border-top: 2px solid var(--color-primary);
  border-right: 2px solid var(--color-primary);
  z-index: 2;
  opacity: 0.75;
}
.promise {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: 14px 18px;
  background: rgba(220,38,38,0.04);
  border: 1px solid rgba(220,38,38,0.18);
  border-radius: var(--radius-md);
  font-size: var(--text-base);
  font-weight: 600;
  color: var(--color-fg-light);
  transition: all var(--duration-normal) var(--ease-out);
}
.promise .icon {
  width: 22px; height: 22px;
  flex-shrink: 0;
  color: var(--color-primary);
  filter: drop-shadow(0 0 6px rgba(220,38,38,0.5));
}
.promise:hover {
  background: rgba(220,38,38,0.08);
  border-color: var(--color-primary);
  transform: translateX(4px);
}
.promises {
  list-style: none;
  margin: var(--space-6) 0 0;
  padding: 0;
  display: grid;
  gap: var(--space-2);
}

/* ── Diff metrics: bigger numbers + persona-tinted frameworks ── */
.metric__num {
  font-family: var(--font-mono);
  font-weight: 800;
  letter-spacing: -0.02em;
  color: var(--color-fg);
  text-shadow: 0 0 30px rgba(220,38,38,0.25);
}
.framework {
  transition: all var(--duration-fast) var(--ease-out);
  background: rgba(255,255,255,0.03);
  border: 1px solid rgba(255,255,255,0.08);
  cursor: default;
}
.framework:hover {
  border-color: var(--color-primary);
  background: rgba(220,38,38,0.10);
  color: var(--color-fg);
  transform: translateY(-2px);
  box-shadow: 0 0 18px rgba(220,38,38,0.2);
}
.framework .icon {
  filter: drop-shadow(0 0 4px rgba(220,38,38,0.6));
}

/* ── Industries: tech overlay + sector dots colored ──────────── */
.industry-card::after {
  content: '';
  position: absolute;
  bottom: 12px; left: 12px;
  width: 36px; height: 36px;
  border-bottom: 2px solid var(--color-primary);
  border-left: 2px solid var(--color-primary);
  z-index: 2;
  opacity: 0.6;
  transition: opacity var(--duration-normal) var(--ease-out);
}
.industry-card:hover::after { opacity: 1; }
.industries__sector .dot {
  background: var(--color-primary);
  box-shadow: 0 0 8px var(--color-primary);
}
.industries__sector--secondary .dot {
  background: var(--color-csirt);
  box-shadow: 0 0 8px var(--color-csirt);
}

/* ── Practices: corner brackets + persona-color rotation ─────── */
.practice {
  isolation: isolate;
  overflow: hidden;
}
/* Tinte persona pilote par data-persona (remplace l'ancien mapping
   posicional nth-child, fragile des qu'on reordonne les cards) */
.practice[data-persona="csirt"]     { --p: var(--color-csirt); }
.practice[data-persona="ctem"]      { --p: var(--color-ctem); }
.practice[data-persona="ngsoc"]     { --p: var(--color-ngsoc); }
.practice[data-persona="zerotrust"] { --p: var(--color-zerotrust); }
.practice[data-persona="grc"]       { --p: var(--color-grc); }
.practice[data-persona="asha"]      { --p: var(--color-primary); }
.practice::before {
  content: '';
  position: absolute;
  top: 0; left: 0;
  width: 0;
  height: 3px;
  background: var(--p, var(--color-primary));
  transition: width var(--duration-slow) var(--ease-out);
  z-index: 2;
}
.practice:hover::before { width: 100%; }
.practice:hover {
  border-color: var(--p, var(--color-primary));
  box-shadow: 0 0 0 1px var(--p, var(--color-primary)), 0 16px 32px rgba(0,0,0,0.10);
}
.practice:hover .practice__icon-wrap {
  background: color-mix(in srgb, var(--p, var(--color-primary)) 15%, transparent);
  color: var(--p, var(--color-primary));
  box-shadow: 0 0 24px color-mix(in srgb, var(--p, var(--color-primary)) 40%, transparent);
}
.practice__icon-wrap {
  transition: all var(--duration-normal) var(--ease-out);
}
.practice__chip {
  transition: all var(--duration-fast) var(--ease-out);
}
.practice:hover .practice__chip {
  background: color-mix(in srgb, var(--p, var(--color-primary)) 8%, transparent);
  border-color: color-mix(in srgb, var(--p, var(--color-primary)) 25%, transparent);
  color: var(--p, var(--color-primary));
}

/* ── Services accordion: chevron animation + group glow ──────── */
.service-group {
  transition: border-color var(--duration-normal) var(--ease-out);
}
.service-group__chev {
  width: 18px; height: 18px;
  transition: transform var(--duration-normal) var(--ease-out);
  color: var(--color-muted-light);
}
.service-group[open] > summary .service-group__chev {
  transform: rotate(180deg);
  color: var(--color-primary);
}
.service-group:hover summary .service-group__icon {
  background: rgba(220,38,38,0.12);
  box-shadow: 0 0 16px rgba(220,38,38,0.3);
}
.service-group__icon {
  transition: all var(--duration-normal) var(--ease-out);
}

/* ── Alianzas: tier badge glow per level + hover ─────────────── */
.alliance {
  transition: all var(--duration-fast) var(--ease-out);
  cursor: default;
}
.alliance:hover {
  background: rgba(220,38,38,0.12);
  border-color: var(--color-primary);
  color: var(--color-fg);
  transform: translateY(-2px);
  box-shadow: 0 0 20px rgba(220,38,38,0.25);
}
.partner-level {
  transition: all var(--duration-normal) var(--ease-out);
}
.partner-level:hover {
  transform: translateY(-3px);
  box-shadow: 0 12px 32px rgba(0,0,0,0.4);
}
.partner-level--elite     { box-shadow: 0 0 24px rgba(220,38,38,0.20); }
.partner-level--platinum  { box-shadow: 0 0 24px rgba(168,85,247,0.20); }
.partner-level--gold      { box-shadow: 0 0 24px rgba(249,115,22,0.20); }
.partner-level--elite .partner-level__tag {
  text-shadow: 0 0 8px rgba(220,38,38,0.35);
}
.partner-level--platinum .partner-level__tag {
  text-shadow: 0 0 8px rgba(168,85,247,0.35);
}
.partner-level--gold .partner-level__tag {
  text-shadow: 0 0 8px rgba(249,115,22,0.35);
}

/* ── Clients: silver hover + name pill polish ────────────────── */
.client-logo {
  transition: all var(--duration-normal) var(--ease-out);
}
.client-logo img {
  filter: grayscale(100%) brightness(0.7) opacity(0.7);
  transition: filter var(--duration-normal) var(--ease-out), transform var(--duration-normal) var(--ease-out);
}
.client-logo:hover img {
  filter: grayscale(0%) brightness(1) opacity(1);
  transform: scale(1.05);
}
.client-names li {
  transition: all var(--duration-fast) var(--ease-out);
}
.client-names li:hover {
  border-color: var(--color-primary);
  color: var(--color-primary);
  transform: translateY(-1px);
}

/* ── Final CTA: gradient border + corner accents ─────────────── */
.final-cta {
  position: relative;
  isolation: isolate;
  overflow: hidden;
}
.final-cta::before {
  content: '';
  position: absolute; inset: 0;
  background:
    radial-gradient(ellipse at 30% 50%, rgba(220,38,38,0.18), transparent 60%),
    radial-gradient(ellipse at 70% 50%, rgba(6,182,212,0.10), transparent 60%);
  pointer-events: none;
  z-index: -1;
}
.final-cta__inner {
  position: relative;
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-xl);
  padding: clamp(40px, 6vw, 72px);
  background:
    linear-gradient(135deg, rgba(23, 23, 23,0.6), rgba(16, 16, 16,0.6));
  backdrop-filter: blur(8px);
  text-align: center;
  overflow: hidden;
}
.final-cta__inner::before,
.final-cta__inner::after {
  content: '';
  position: absolute;
  width: 60px; height: 60px;
  border: 2px solid var(--color-primary);
  opacity: 0.6;
}
.final-cta__inner::before {
  top: 16px; left: 16px;
  border-right: none; border-bottom: none;
}
.final-cta__inner::after {
  bottom: 16px; right: 16px;
  border-left: none; border-top: none;
}
.final-cta__title .accent {
  color: var(--color-primary);
  font-weight: 800;
}

/* ── Footer: top accent line + link hover ────────────────────── */
.site-footer {
  position: relative;
  border-top: 1px solid var(--color-border-strong);
}
.site-footer::before {
  content: '';
  position: absolute;
  top: -1px; left: 50%;
  transform: translateX(-50%);
  width: 240px; height: 2px;
  background: linear-gradient(90deg, transparent, var(--color-primary), transparent);
  box-shadow: 0 0 16px rgba(220,38,38,0.25);
}
.site-footer__list a {
  position: relative;
  transition: color var(--duration-fast) var(--ease-out);
}
.site-footer__list a::after {
  content: '';
  position: absolute;
  left: 0; bottom: -2px;
  width: 0; height: 1px;
  background: var(--color-primary);
  transition: width var(--duration-normal) var(--ease-out);
}
.site-footer__list a:hover::after { width: 100%; }
.site-footer__list a:hover { color: var(--color-primary); }
.social-icon {
  transition: all var(--duration-fast) var(--ease-out);
}
.social-icon:hover {
  color: var(--color-primary);
  transform: translateY(-2px);
  filter: drop-shadow(0 0 8px rgba(220,38,38,0.6));
}

/* ── Equal-height card enforcement (proportions) ─────────────── */
.practices__grid,
.alliances__grid {
  align-items: stretch;
}
.practices__grid > .practice {
  height: 100%;
}

/* ── Reveal initial states (so SR animations don't FOUC) ─────── */
@media (prefers-reduced-motion: no-preference) {
  /* Nothing forced — GSAP handles via .from() */
}

/* ════════════════════════════════════════════════════════════════
   SCENE « ¿Cómo lo hacemos? » — la capitana seule.
   La machine a etats (attack / rescue / safe) et ses calques d'ambiance ont
   ete retires le 2026-08-11 : il ne reste que la video et sa propre animation.
   ════════════════════════════════════════════════════════════════ */

.scene-hacked {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  /* min-height 100vh retire le 2026-08-11 au soir : il servait quand la section
     n'avait qu'une grille a deux colonnes a caler sur l'ecran. Depuis la
     refonte en blocs empiles, c'est le contenu qui donne la hauteur, et le
     plancher plein ecran ne faisait que l'allonger. Padding resserre au passage,
     la section passait de 1024 a 1549 px. */
  background: var(--color-bg);
  padding: clamp(80px, 8vw, 112px) 0;
}


/* Removed harsh shake — felt too aggressive */


/* Code rain */


/* Ligne d'en-tete : elle nomme le cadre (plan CCIIIAR, objectif operationnel)
   pour qu'on ne lise pas la sequence comme un incident en direct. */


/* Alert badge */


/* ── Resolution verte : logs de restauration + badge [OK] ─────────
   L'ecran passe au vert quand la capitana a repousse l'attaque. */


/* renforce la lueur verte du fond a l'etat safe */


/* Inner layout — DEMO MUCH BIGGER */
.scene-hacked__inner {
  position: relative;
  z-index: 3;
  display: grid;
  gap: var(--space-12);
  align-items: center;
}
@media (min-width: 900px) {
  .scene-hacked__inner {
    /* .scene-hacked__inner n'est plus utilise depuis la refonte du
       2026-08-11 au soir : la section suit le modele de « Nuestro
       diferenciador », en-tete centre puis blocs pleine largeur, sans grille a
       deux colonnes. Regle conservee au cas ou le markup y reviendrait. */
    grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr);
    gap: clamp(32px, 4vw, 72px);
  }
}

.scene-hacked__hero-wrap {
  position: relative;
  display: grid;
  place-items: center;
  /* 3/4 = le ratio EXACT de la source (1248 x 1664). Le bloc desktop imposait
     4/5 : object-fit: contain letterboxait alors la video et laissait 12 px de
     fond de chaque cote, ce qui dessinait le rectangle visible autour de la
     capitana. Un seul ratio partout, celui du fichier. */
  aspect-ratio: 3/4;
  /* Un seul plafond, valable a TOUTES les largeurs : le clamp etait reserve au
     bloc >= 1024px et la regle de base autorisait 720 px, donc entre 768 et
     1023 la video montait a 720 x 960. min(360px, 100%) la borne partout et la
     laisse remplir le conteneur sur mobile, ou 360 depasserait. */
  /* « Moyenne taille » demandee par Gabriel : 400 px au plafond, soit 533 de
     haut au ratio 3:4 de la source. */
  max-width: min(400px, 100%);
  margin-inline: auto;
  /* Plus de cadre depuis le passage a l'animation « geste seul » en ALPHA : le
     cadre servait a assumer le rectangle du mp4 au fond cuit, qui n'etait pas
     rigoureusement celui de la section. La video etant maintenant transparente,
     il n'y a plus de rectangle a assumer, la capitana flotte sur le fond. */
}
@media (min-width: 1024px) {
  /* Reduite le 2026-08-11 au soir, demande de Gabriel. Le « max-width: none »
     laissait le wrap remplir sa colonne de 1,3fr, soit 722 px, et le couple
     aspect-ratio 4/5 + min-height 640 le poussait a 962 px de haut : la
     capitana ecrasait la section et creusait un vide en face du texte, plus
     court. Plafond de largeur retabli, min-height retire, le ratio suffit. */
  /* Plus d'override de largeur ici : le plafond min(360px, 100%) de la regle de
     base vaut a toutes les largeurs. La video est simplement centree, au milieu
     d'un bloc pleine largeur, comme le globe de « Presencia ». */
}
.scene-hacked__hero {
  position: relative;
  z-index: 2;
  width: 100%;
  height: 100%;
  object-fit: contain;
  /* Plus d'effet d'apparition (2026-08-11) : elle etait masquee puis revelee
     en fondu + scale + filtre par la machine a etats. Elle est simplement la,
     et seule sa propre animation joue. */
}


/* Botón replay discreto — círculo en esquina del wrap */
.scene-hacked__replay {
  position: absolute;
  right: 12px;
  bottom: 12px;
  width: 38px;
  height: 38px;
  z-index: 6;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: rgba(16, 16, 16, 0.55);
  border: 1px solid rgba(165, 243, 252, 0.25);
  color: rgba(165, 243, 252, 0.7);
  cursor: pointer;
  backdrop-filter: blur(6px);
  opacity: 0.55;
  transition: opacity 240ms var(--ease-out), background 240ms var(--ease-out), border-color 240ms var(--ease-out), color 240ms var(--ease-out), transform 240ms var(--ease-out);
}
.scene-hacked__replay:hover,
.scene-hacked__replay:focus-visible {
  opacity: 1;
  background: rgba(6, 182, 212, 0.15);
  border-color: rgba(6, 182, 212, 0.55);
  color: var(--color-csirt-soft);
  transform: scale(1.08);
  outline: none;
}
.scene-hacked__replay svg { width: 18px; height: 18px; }
.scene-hacked__replay:active { transform: scale(0.95); }

/* L'aura prend la couleur de l'etat : elle restait rouge alors que l'etat safe
   est vert, ce qui faisait jurer les deux teintes autour du personnage. */


/* Copy */
.scene-hacked__copy {
  color: var(--color-fg);
}
.scene-hacked__eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 8px 14px;
  border-radius: var(--radius-full);
  background: rgba(220,38,38,0.10);
  border: 1px solid rgba(220,38,38,0.30);
  color: var(--color-danger-soft);
  font: 600 12px/1 var(--font-mono);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  margin-bottom: var(--space-6);
}
.scene-hacked__eyebrow .pulse {
  width: 8px; height: 8px;
  background: var(--color-primary);
  border-radius: 50%;
  box-shadow: 0 0 8px var(--color-primary);
  animation: pulse 2.4s ease-in-out infinite;
}

.scene-hacked__title {
  font-family: var(--font-sans);
  font-size: clamp(36px, 5vw, 64px);
  font-weight: 800;
  line-height: 1.05;
  letter-spacing: -0.02em;
  margin: 0 0 var(--space-6);
  color: var(--color-fg);
  text-shadow:
    0 0 32px rgba(255,255,255,0.18),
    0 0 6px rgba(220,38,38,0.35);
}
.scene-hacked__title-line {
  display: block;
}
.scene-hacked__title-attack {
  color: #EF4444;
  text-shadow: 0 0 16px rgba(239,68,68,0.6);
  font-style: italic;
  position: relative;
}
.scene-hacked__title-safe {
  color: var(--color-primary);
  font-weight: 800;
}

.scene-hacked__lede {
  font-size: var(--text-lg);
  line-height: 1.6;
  color: var(--color-muted);
  margin: 0 0 var(--space-6);
  max-width: 56ch;
}

.scene-hacked__status {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 10px 16px;
  border-radius: var(--radius-full);
  background: rgba(34,197,94,0.10);
  border: 1px solid rgba(34,197,94,0.40);
  color: var(--color-success);
  font: 700 12px/1 var(--font-mono);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  margin-bottom: var(--space-6);
  opacity: 0;
  transform: translateY(8px);
  transition: opacity 400ms, transform 400ms;
}
.scene-hacked__status .icon { width: 18px; height: 18px; filter: drop-shadow(0 0 6px rgba(34,197,94,0.6)); }


.scene-hacked__replay {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}
.scene-hacked__replay .icon { width: 18px; height: 18px; }

@media (prefers-reduced-motion: reduce) {


  .scene-hacked__hero { opacity: 1; transform: none; }

  .scene-hacked__status { opacity: 1; transform: none; }
}

/* ════════════════════════════════════════════════════════════════
   DNA v3 — REFERENCES_ANALYSIS execution
   8 distilled patterns applied to homepage sections.
   ════════════════════════════════════════════════════════════════ */

/* ── DNA-1 · Hero accent word + chips + floating fragments ──── */

.hero__title-accent {
  display: inline-block;
  color: var(--color-primary);
  font-weight: 800;
  font-style: normal;
  text-shadow: 0 0 32px rgba(220,38,38,0.35);
}

/* Anti-FOUC : le hero n'est pre-cache QUE si JS est actif (classe .js posee
   en synchrone dans le <head>) ; GSAP revele ensuite via fromTo. Sans JS,
   tout reste visible. */
html.js .hero__eyebrow,
html.js .hero__title > span,
html.js .hero__subtitle,
html.js .hero__actions,
html.js .hero__trust,
html.js .hero__scroll { opacity: 0; }
/* LES HEROS DE PAGE PASSENT SOUS LE MEME GATE — 2026-08-21.
   La home cachait ses elements avant l'animation, les pages interieures non :
   leur hero s'affichait entier puis se re-animait, ce qui produit le flash que
   ce gate existe precisement pour eviter. Meme cause, meme remede.
   Ce gate n'est SUR que parce que page-hero-reveal.js retire la classe « js »
   quand GSAP manque, et qu'il porte un filet a 2 s. Sans ces deux garde-fous,
   ces regles pourraient rendre un hero definitivement invisible. */
html.js .page-hero--league .page-hero__eyebrow,
html.js .page-hero--league .page-hero__title > span,
html.js .page-hero--league .page-hero__lede,
html.js .page-hero--league .page-hero__actions,
html.js .page-hero--league .liga-constellation { opacity: 0; }
@media (prefers-reduced-motion: reduce) {
  /* La preference coupe l'animation : le gate n'a plus de raison d'etre et
     laisserait un hero vide. */
  html.js .page-hero--league .page-hero__eyebrow,
  html.js .page-hero--league .page-hero__title > span,
  html.js .page-hero--league .page-hero__lede,
  html.js .page-hero--league .page-hero__actions,
  html.js .page-hero--league .liga-constellation { opacity: 1; }
}
.hero__chips {
  list-style: none;
  margin: var(--space-6) 0 var(--space-8);
  padding: 0;
  display: inline-flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-3);
}
.hero__chip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 8px 14px;
  background: rgba(23, 23, 23,0.55);
  border: 1px solid rgba(255,255,255,0.10);
  border-radius: var(--radius-full);
  backdrop-filter: blur(8px);
  font: 600 11px/1 var(--font-mono);
  color: var(--color-fg);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  transition: all var(--duration-fast) var(--ease-out);
}
.hero__chip:hover {
  border-color: var(--color-primary);
  background: rgba(220,38,38,0.12);
}
.hero__chip-dot {
  width: 6px; height: 6px;
  border-radius: 999px;
  background: var(--color-primary);
  box-shadow: 0 0 6px rgba(220,38,38,0.40);
}

.btn-pill {
  border-radius: var(--radius-full) !important;
  padding-left: 28px !important;
  padding-right: 28px !important;
}

/* DNA-1 — refined scroll indicator (mono "scroll to explore" + arrow) */
.hero__scroll {
  flex-direction: row !important;
  bottom: 32px !important;
  right: 32px !important;
  left: auto !important;
  transform: none !important;
  gap: 10px !important;
}
.hero__scroll-text {
  font: 600 11px/1 var(--font-mono);
  letter-spacing: 0.18em;
  text-transform: uppercase;
}
.hero__scroll-arrow {
  width: 12px; height: 16px;
  animation: scroll-arrow-bounce 1.8s ease-in-out infinite;
  color: var(--color-primary);
}
@keyframes scroll-arrow-bounce {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(4px); }
}
@media (max-width: 700px) {
  .hero__scroll { display: none; }
}

/* ── DNA-2 · Editorial stats (no containers) ─────────────────── */

.metrics--editorial {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0;
  border-top: 1px solid var(--color-border);
  border-bottom: 1px solid var(--color-border);
}
.metrics--editorial .metric {
  background: transparent !important;
  border: none !important;
  border-radius: 0 !important;
  padding: var(--space-8) var(--space-6);
  margin: 0;
  position: relative;
}
.metrics--editorial .metric:nth-child(odd) { border-right: 1px solid var(--color-border); }
.metrics--editorial .metric:nth-child(-n+2) { border-bottom: 1px solid var(--color-border); }
.metrics--editorial .metric:hover { transform: none; box-shadow: none; }
.metrics--editorial .metric__num {
  font-family: var(--font-mono) !important;
  font-size: clamp(64px, 9vw, 112px) !important;
  font-weight: 800 !important;
  letter-spacing: -0.04em !important;
  line-height: 0.95 !important;
  color: #fff !important;
  background: none !important;
  -webkit-text-fill-color: #fff !important;
  text-shadow: 0 0 32px rgba(220,38,38,0.35) !important;
  margin: 0 0 var(--space-3);
}
.metrics--editorial .metric__num .unit {
  font-size: 0.55em;
  color: var(--color-primary);
  margin-left: 4px;
  -webkit-text-fill-color: var(--color-primary) !important;
}
.metrics--editorial .metric__label {
  font: 600 11px/1.4 var(--font-mono);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--color-muted);
  margin: 0;
  max-width: 22ch;
}
@media (max-width: 700px) {
  .metrics--editorial { grid-template-columns: 1fr; }
  .metrics--editorial .metric { border-right: none !important; border-bottom: 1px solid var(--color-border) !important; }
  .metrics--editorial .metric:last-child { border-bottom: none !important; }
}

/* ── DNA-3 · Liga ASHA asymmetric (1 captain + 5 satellites) ── */

@media (min-width: 900px) {
  .liga__grid--asym {
    grid-template-columns: 1fr 1fr !important;
    grid-template-rows: 1fr 1fr;
    gap: var(--space-6) !important;
  }
  .persona--captain {
    grid-row: 1 / 3;
    grid-column: 1;
  }
  .liga__grid--asym .persona:not(.persona--captain) {
    aspect-ratio: auto;
  }
  /* Right side: 5 satellites in 3+2 pattern */
  .liga__grid--asym {
    display: grid !important;
    grid-template-columns: 1.2fr 1fr 1fr 1fr !important;
    grid-template-rows: 1fr 1fr;
  }
  .persona--captain { grid-column: 1; grid-row: 1 / 3; }
  /* Auto-place rest sequentially in right 3 columns */
}

.persona--captain {
  position: relative;
}
.persona--captain .persona__body {
  padding: var(--space-8) var(--space-6);
  background: linear-gradient(180deg, transparent 0%, rgba(16, 16, 16,0.92) 50%, rgba(16, 16, 16,0.99) 100%);
}
.persona--captain .persona__name {
  font-size: clamp(28px, 3vw, 40px);
  font-family: var(--font-sans);
  font-weight: 800;
  letter-spacing: -0.02em;
  text-transform: none;
  margin-bottom: var(--space-2);
  color: var(--color-primary);
  text-shadow: 0 0 18px rgba(220,38,38,0.35);
}
.persona--captain .persona__role {
  font-size: var(--text-sm);
  text-transform: none;
  letter-spacing: 0;
  color: var(--color-fg);
  font-weight: 500;
  max-width: 32ch;
}
.persona__captain-tag {
  display: inline-block;
  font: 700 10px/1 var(--font-mono);
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--color-primary);
  background: rgba(220,38,38,0.12);
  border: 1px solid rgba(220,38,38,0.40);
  padding: 6px 10px;
  border-radius: var(--radius-full);
  margin-bottom: var(--space-3);
  text-shadow: 0 0 6px rgba(220,38,38,0.30);
}

/* ── DNA-4 · Practices numbered glass cards ─────────────────── */

.practice {
  /* Aligne le 2026-08-11 sur .pillar : meme corps navy opaque derriere le texte,
     pour que les six cartes de heros et les trois cartes de Nuestro
     diferenciador soient la meme carte. Remplace un degrade de blanc a 4 %
     translucide, qui laissait le fond de section traverser.
     Le backdrop-filter: blur(8px) est retire par la meme occasion. C'est le
     meme flou que .pillar avait deja abandonne, commentaire d'epoque a l'appui :
     « el blur era el culpable del freeze al entrar la sección ». Il tournait
     encore ici sur SIX cartes en meme temps. */
  background: rgba(23, 23, 23, 0.85) !important;
  border-color: rgba(255,255,255,0.08) !important;
  position: relative;
}
.practice__num {
  position: absolute;
  top: var(--space-6);
  right: var(--space-6);
  font: 800 32px/1 var(--font-mono);
  color: rgba(255,255,255,0.10);
  letter-spacing: -0.02em;
  transition: all var(--duration-normal) var(--ease-out);
  z-index: 2;
}
.practice:hover .practice__num {
  color: var(--p, var(--color-primary));
  text-shadow: 0 0 16px color-mix(in srgb, var(--p, var(--color-primary)) 60%, transparent);
}
.practice__title { color: var(--color-fg) !important; }
.practice__desc { color: rgba(248,250,252,0.65) !important; }
.practice__chip {
  background: rgba(255,255,255,0.04) !important;
  border-color: rgba(255,255,255,0.10) !important;
  color: var(--color-fg) !important;
}
.practice__more {
  color: var(--color-fg) !important;
}
/* Also flip the section to dark since glass cards live better on dark */
#practicas.section--light {
  background: var(--color-bg);
  color: var(--color-fg);
}
#practicas .section-title { color: var(--color-fg); }
#practicas .section-lede  { color: var(--color-muted) !important; }

/* HUD corners on practice cards */
.practice::after {
  content: '';
  position: absolute;
  bottom: 12px; left: 12px;
  width: 16px; height: 16px;
  border-bottom: 1.5px solid var(--p, var(--color-primary));
  border-left: 1.5px solid var(--p, var(--color-primary));
  opacity: 0;
  transform: translate(-4px, 4px);
  transition: all var(--duration-normal) var(--ease-out);
}
.practice:hover::after {
  opacity: 0.8;
  transform: translate(0, 0);
}

/* ── DNA-5 · Marquee continuo logos ─────────────────────────── */

.marquee {
  position: relative;
  width: 100%;
  overflow: hidden;
  mask-image: linear-gradient(90deg, transparent 0%, #000 6%, #000 94%, transparent 100%);
  -webkit-mask-image: linear-gradient(90deg, transparent 0%, #000 6%, #000 94%, transparent 100%);
}
.marquee__track {
  display: flex;
  gap: var(--space-4);
  width: max-content;
  animation: marquee-scroll 50s linear infinite;
}
.marquee--right .marquee__track { animation-direction: normal; }
.marquee--left  .marquee__track { animation-direction: reverse; }
.marquee--clients .marquee__track { animation-duration: 70s; gap: var(--space-6); }
.marquee:hover .marquee__track { animation-play-state: paused; }
@keyframes marquee-scroll {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}
.marquee .alliance-card {
  flex-shrink: 0;
  width: 240px;
  height: 88px;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 var(--space-4);
}
.marquee .alliance-card[data-brand="darkivore"] { width: 180px; }
.marquee--clients .client-logo {
  flex-shrink: 0;
  width: 160px;
  height: 100px;
  background: var(--color-surface-light);
  border-radius: var(--radius-md);
  border: 1px solid var(--color-border-light);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-4);
}
.marquee--clients .client-logo img {
  max-width: 100%;
  max-height: 60%;
  filter: grayscale(100%) brightness(0.5);
  transition: filter var(--duration-normal) var(--ease-out);
}
.marquee--clients .client-logo:hover img {
  filter: grayscale(0) brightness(1);
}
@media (prefers-reduced-motion: reduce) {
  .marquee__track { animation: none; }
}

/* ── DNA-7 · Background grid + radial mask refinement ───────── */

.section--dark:not(.hero):not(.scene-hacked):not(.final-cta--poster) {
  position: relative;
}
.section--dark:not(.hero):not(.scene-hacked):not(.final-cta--poster)::before {
  content: '';
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(rgba(220,38,38,0.04) 1px, transparent 1px),
    linear-gradient(90deg, rgba(220,38,38,0.04) 1px, transparent 1px);
  background-size: 64px 64px;
  mask-image: radial-gradient(ellipse 70% 60% at center, black 20%, transparent 75%);
  -webkit-mask-image: radial-gradient(ellipse 70% 60% at center, black 20%, transparent 75%);
  pointer-events: none;
  z-index: 0;
  opacity: 0.6;
}
.section--dark > .container { position: relative; z-index: 1; }

/* ── DNA-8 · Final CTA poster manifesto ─────────────────────── */

.final-cta--poster {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  padding: clamp(96px, 14vw, 184px) 0;
  min-height: 70vh;
  display: flex;
  align-items: center;
}
.final-cta__bg-img {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  /* nouvelle composition sur navy, groupe ancre en bas -> personne coupe */
  object-position: center bottom;
  /* Remonte de 0,42 a 0,58 le 2026-08-12, avec le passage au noir. Cause :
     l'affiche ne contribuait qu'a ~4 % du pixel final (0,42 sous un voile a
     0,90), et sur navy c'est l'ECART DE TEINTE entre le voile bleu et les tons
     de peau et de costume qui la faisait exister. Un voile neutre sur du noir
     ne laisse que la clarte, et a 4 % il n'en reste rien : les six personnages
     avaient disparu. Le voile descend en meme temps, ci-dessous. */
  opacity: 0.58;
  z-index: 0;
  filter: saturate(0.95);
}
.final-cta__bg-grad {
  position: absolute; inset: 0;
  z-index: 1;
  background:
    /* Voile descendu de 0,85/0,92 a 0,74/0,82 pour rendre l'affiche visible.
       Le bas reste opaque (--color-bg), c'est ce qui ancre le groupe. */
    linear-gradient(180deg, rgba(16, 16, 16,0.74) 0%, rgba(16, 16, 16,0.82) 50%, var(--color-bg) 100%),
    radial-gradient(ellipse at 80% 20%, rgba(220,38,38,0.25), transparent 55%),
    radial-gradient(ellipse at 20% 80%, rgba(6,182,212,0.12), transparent 55%);
}
.final-cta__bg-grid {
  position: absolute; inset: 0;
  z-index: 2;
  background-image:
    linear-gradient(rgba(255,255,255,0.04) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255,255,255,0.04) 1px, transparent 1px);
  background-size: 64px 64px;
  mask-image: radial-gradient(ellipse at center, black 30%, transparent 80%);
  -webkit-mask-image: radial-gradient(ellipse at center, black 30%, transparent 80%);
}
.final-cta--poster .final-cta__inner {
  position: relative;
  z-index: 5;
  max-width: 920px;
  text-align: center;
  margin-inline: auto;
  padding: 0 var(--space-8);
}

.final-cta--poster .final-cta__eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 8px 16px;
  border-radius: var(--radius-full);
  background: rgba(220,38,38,0.10);
  border: 1px solid rgba(220,38,38,0.30);
  font: 600 11px/1 var(--font-mono);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--color-danger-soft);
  margin-bottom: var(--space-6);
}
.final-cta--poster .final-cta__eyebrow .pulse {
  width: 8px; height: 8px;
  background: var(--color-primary);
  border-radius: 50%;
  box-shadow: 0 0 10px var(--color-primary);
  animation: pulse 2.4s ease-in-out infinite;
}
.final-cta__eyebrow-prefix {
  color: var(--color-success);
}

.final-cta--poster .final-cta__title {
  font-family: var(--font-sans);
  font-size: clamp(36px, 5vw, 56px);
  font-weight: 800;
  line-height: 1.06;
  letter-spacing: -0.02em;
  color: var(--color-fg);
  margin: 0 0 var(--space-6);
  max-width: 18ch;
  margin-inline: auto;
}
/* Accent: color sólido brand-red, sin gradient text ni shimmer */
.final-cta__accent {
  color: var(--color-primary);
  font-style: normal;
  font-weight: 800;
}
.final-cta--poster .final-cta__lede {
  font-size: var(--text-lg);
  color: var(--color-muted);
  max-width: 56ch;
  margin: 0 auto var(--space-8);
  line-height: 1.55;
}
.final-cta--poster .final-cta__actions {
  display: inline-flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: var(--space-5);
  margin-bottom: var(--space-10);
}

/* Primary CTA destaca con tamaño */
.final-cta__btn-primary {
  font-size: var(--text-base);
  padding: 14px 28px;
}

/* Secondary como text link con flecha (no segundo button) — clear hierarchy */
.final-cta__link {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font: 600 14px/1 var(--font-sans);
  letter-spacing: 0;
  color: rgba(241, 245, 249, 0.85);
  text-decoration: none;
  padding: 8px 4px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.15);
  transition: color 200ms var(--ease-out), border-color 200ms var(--ease-out), transform 200ms var(--ease-out);
}
.final-cta__link:hover {
  color: var(--color-fg);
  border-color: rgba(255, 255, 255, 0.5);
  transform: translateX(3px);
}
.final-cta__link .icon { width: 14px; height: 14px; }

/* Corner brackets giant */
.final-cta__corner {
  position: absolute;
  width: clamp(40px, 6vw, 72px);
  height: clamp(40px, 6vw, 72px);
  z-index: 4;
  border-color: var(--color-primary);
  opacity: 0.6;
  filter: drop-shadow(0 0 12px rgba(220,38,38,0.4));
}
.final-cta__corner--tl { top: 24px; left: 24px; border-top: 2px solid; border-left: 2px solid; }
.final-cta__corner--tr { top: 24px; right: 24px; border-top: 2px solid; border-right: 2px solid; }
.final-cta__corner--bl { bottom: 24px; left: 24px; border-bottom: 2px solid; border-left: 2px solid; }
.final-cta__corner--br { bottom: 24px; right: 24px; border-bottom: 2px solid; border-right: 2px solid; }

/* Meta line — trust signals subtle bajo el CTA */
.final-cta__meta {
  display: inline-flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: var(--space-3);
  font: 600 11px/1.5 var(--font-mono);
  letter-spacing: 0.10em;
  color: rgba(203, 213, 225, 0.7);
  text-transform: uppercase;
}
.final-cta__meta-item {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.final-cta__meta-dot {
  width: 6px; height: 6px;
  border-radius: 50%;
  background: rgb(34, 197, 94);
  box-shadow: 0 0 5px rgba(34, 197, 94, 0.35);
  animation: hero-panel-pulse 2s ease-in-out infinite;
}
.final-cta__meta-sep {
  color: rgba(148, 163, 184, 0.35);
}

/* ════════════════════════════════════════════════════════════════
   v4 — User feedback fixes (post-DNA pass)
   ════════════════════════════════════════════════════════════════ */

/* ── #1 · Logo treatment (PNG transparent, fits header) ─────── */

.site-header__logo {
  height: 40px !important;
  width: auto !important;
  background: transparent !important;
  filter: drop-shadow(0 0 8px rgba(220,38,38,0.25));
}
.site-footer__logo {
  height: 56px;
  width: auto;
  background: transparent;
  filter: drop-shadow(0 0 8px rgba(220,38,38,0.25));
}

/* ── #2 · Hero bg image + smaller title ─────────────────────── */

.hero {
  /* Hauteur calculee (2026-08-11) : on veut voir un LISERE de la bande blanche,
     pas les logos. Les logos commencent a ~34 px du haut de la bande, donc on
     vise ~20 px de depassement, et il doit rester constant quelle que soit la
     hauteur d'ecran : hero = ecran - entete (73 px) - liseré (20 px).
     Un plancher evite que le hero devienne minuscule sur ecran tres court.
     Double declaration : vh en repli, svh pour ignorer la barre d'URL mobile. */
  min-height: max(560px, calc(100vh - 93px)) !important;
  min-height: max(560px, calc(100svh - 93px)) !important;
}
.hero__bg-img {
  position: absolute;
  inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  object-position: right center;
  z-index: 0;
  /* Plus de mix-blend-mode ni de hue-rotate : le visuel est le sujet du hero,
     pas une texture d'appoint. Il est cadre a droite pour que l'embleme reste
     visible quand la largeur se reduit.
     Opacite et filtre alignes (2026-08-11) sur .page-hero__bg-img, le visuel de
     fond des heros de nosotros et metodologia : meme 0,55 et meme
     saturate/contrast. C'est ce qui rend les trois heros coherents, et c'est
     aussi ce qui laisse la grille et les halos exister par-dessus, alors qu'une
     image opaque les ecrasait. */
  opacity: 0.55;
  filter: saturate(1.05) contrast(1.05);
}
/* Les halos partagent leur declaration avec .page-hero__bg-drift, qui vit dans
   un conteneur .page-hero__bg en z-index 0. Ici ce conteneur n'existe pas, donc
   la couche a besoin de son propre etage : au-dessus du visuel (0) et de la
   grille (1), sous le fondu bas (2) et sous le contenu (5). */
.hero__drift {
  z-index: 1;
}
/* Voile lateral : rend un plancher sombre a la colonne de texte, que le circuit
   imprime de la banniere concurrencait. Il s'eteint avant 62 % de la largeur,
   donc le bouclier garde son eclat intact. Pas d'opacite sur la couche mais un
   degrade a alpha variable, pour que la transition soit progressive et qu'aucune
   arete ne se voie. */
.hero__scrim {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background: linear-gradient(
    to right,
    rgba(16, 16, 16, 0.78) 0%,
    rgba(16, 16, 16, 0.62) 26%,
    rgba(16, 16, 16, 0.28) 46%,
    transparent 62%
  );
}
@media (max-width: 900px) {
  /* En colonne unique le texte occupe toute la largeur : le voile devient
     vertical et couvre le haut, la ou vivent l'eyebrow, le titre et le lede. */
  .hero__scrim {
    background: linear-gradient(
      to bottom,
      rgba(16, 16, 16, 0.72) 0%,
      rgba(16, 16, 16, 0.58) 55%,
      rgba(16, 16, 16, 0.30) 100%
    );
  }
}
@media (prefers-reduced-motion: reduce) {
  .hero__bg-img { animation: none; }
}
/* Vignette removed — text legibility is now via text-shadow on title (fix #1) */
.hero__vignette { display: none !important; }
.hero__title {
  /* BORNE PAR LA HAUTEUR AUTANT QUE PAR LA LARGEUR — 2026-08-22.
     Gabriel, sur Mac : « le titre etait trop grand par rapport a l'ecran ».
     La taille ne dependait que de la largeur : des 1 281 px de large, on etait
     au plafond de 82 px, quelle que soit la HAUTEUR disponible. Or un portable
     est large et bas. Mesure sur les hauteurs utiles reelles d'un MacBook :
     a 1280x650 le bloc du hero finit a 651 px pour 650 px d'ecran, il remplit
     donc l'ecran au pixel pres, sans respiration, avec un titre de 82 px.
     min(6.4vw, 11vh) prend la plus contraignante des deux dimensions : 71 px a
     650 px de haut, 77 px a 700, et le plafond de 82 px des 745 px de haut.
     Les grands ecrans ne changent pas d'un pixel. */
  font-size: clamp(40px, min(6.4vw, 11vh), 82px) !important;
  line-height: 1.02 !important;
  letter-spacing: -0.02em;
  max-width: 15ch;
  margin-inline: auto;
}
.hero__subtitle {
  font-size: clamp(15px, 1.4vw, 18px) !important;
  max-width: 640px;
}

/* ── #5 · Practices: bigger icons + persona-color tint ──────── */

.practice {
  padding: var(--space-8) var(--space-6) var(--space-6) !important;
}
.practice__icon-wrap {
  width: 80px !important;
  height: 80px !important;
  background: color-mix(in srgb, var(--p, var(--color-primary)) 12%, transparent) !important;
  border: 1px solid color-mix(in srgb, var(--p, var(--color-primary)) 30%, transparent);
  color: var(--p, var(--color-primary)) !important;
  margin-bottom: var(--space-4);
}
.practice__icon-wrap .icon {
  width: 40px !important;
  height: 40px !important;
  filter: drop-shadow(0 0 8px color-mix(in srgb, var(--p, var(--color-primary)) 60%, transparent));
}
.practice__num {
  font-size: 56px !important;
  color: rgba(255,255,255,0.06) !important;
}
.practice:hover .practice__icon-wrap {
  background: color-mix(in srgb, var(--p, var(--color-primary)) 25%, transparent) !important;
  box-shadow: 0 0 32px color-mix(in srgb, var(--p, var(--color-primary)) 50%, transparent);
}
.practice:hover .practice__icon-wrap .icon {
  filter: drop-shadow(0 0 16px color-mix(in srgb, var(--p, var(--color-primary)) 90%, transparent));
}
.practice__title {
  font-size: var(--text-xl) !important;
  letter-spacing: -0.01em !important;
}

/* ── #6 · Clients marquee — 2 lines, BIG logos ──────────────── */

/* Espaciar ligeramente las dos filas */
.clients .marquee--clients + .marquee--clients { margin-top: var(--space-4); }

.marquee--clients .client-logo {
  background: transparent !important;
  border: none !important;
  width: 280px !important;
  height: 140px !important;
  padding: var(--space-3) var(--space-5) !important;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}
.marquee--clients .client-logo img {
  max-width: 100% !important;
  max-height: 100% !important;
  width: auto !important;
  height: auto !important;
  /* logos du CV en tons de gris varies -> normalises en blanc uniforme
     pour rester lisibles sur le fond navy */
  filter: brightness(0) invert(1);
  opacity: 0.78;
  transition: all var(--duration-normal) var(--ease-out);
}
.marquee--clients .client-logo:hover img {
  filter: brightness(0) invert(1);
  opacity: 1;
  transform: scale(1.05);
}
@media (max-width: 720px) {
  .marquee--clients .client-logo { width: 200px !important; height: 100px !important; }
}
/* Make light client section bg dark to match */
.clients.section--light {
  background: var(--color-bg) !important;
}
.clients__title { color: var(--color-fg) !important; }
.clients__sub { color: var(--color-muted) !important; }
.clients__more {
  border-top-color: var(--color-border) !important;
}
.clients__more-label { color: var(--color-muted) !important; }
.client-names li {
  background: rgba(255,255,255,0.03) !important;
  border-color: rgba(255,255,255,0.08) !important;
  color: var(--color-fg) !important;
}

/* ── #7 · Partner-level cards proportions ───────────────────── */

.partner-level {
  min-height: 132px;
  padding: var(--space-6) !important;
  gap: var(--space-3) !important;
}
.partner-level__tag {
  font-size: 11px !important;
  padding: 6px 12px !important;
  letter-spacing: 0.2em !important;
}
.partner-level__brand {
  font-size: var(--text-2xl) !important;
  margin-top: 4px;
}
.partner-level__note {
  font-size: var(--text-sm) !important;
  line-height: 1.5;
  color: var(--color-muted) !important;
}

/* ── #8 · DNA polish on remaining sections ──────────────────── */

/* HOW section — better visual rhythm */
.how__media {
  border-radius: var(--radius-xl);
  overflow: hidden;
  position: relative;
}
.how__media::before {
  background:
    linear-gradient(135deg, transparent 0%, transparent 60%, rgba(220,38,38,0.25) 100%),
    repeating-linear-gradient(0deg, transparent 0 6px, rgba(255,255,255,0.025) 6px 7px) !important;
}
.how__text .eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 6px 14px;
  border-radius: var(--radius-full);
  background: rgba(220,38,38,0.10);
  border: 1px solid rgba(220,38,38,0.30);
  color: #DC2626 !important;
  font: 600 11px/1 var(--font-mono);
  letter-spacing: 0.18em;
  text-transform: uppercase;
}
.how__text .eyebrow::before {
  content: '>';
  color: var(--color-primary);
  font-weight: 700;
}

/* DIFERENCIADOR — accent the title strong */
.diff__title .accent {
  color: var(--color-primary) !important;
  font-weight: 800;
  font-style: italic;
}
.diff__copy p strong {
  color: var(--color-fg);
  background: linear-gradient(120deg, transparent 60%, rgba(220,38,38,0.20) 60%);
  padding: 0 4px;
}
.diff .eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 6px 14px;
  border-radius: var(--radius-full);
  background: rgba(220,38,38,0.10);
  border: 1px solid rgba(220,38,38,0.30);
  color: var(--color-danger-soft) !important;
  font: 600 11px/1 var(--font-mono);
  letter-spacing: 0.18em;
  text-transform: uppercase;
}
.diff .eyebrow::before {
  content: '>';
  color: var(--color-primary);
  font-weight: 700;
}

/* INDUSTRIES — halo cyan (anti-AI-purple, aligné sur la marque CSIRT).
   2026-08-12 : la classe .section--light de cette section était un MENSONGE de
   balisage. Le getComputedStyle rendait #101010 côté navy, pas #F8FAFC : ce
   bloc-ci l'écrasait par un linear-gradient opaque en !important. Le HTML
   annonçait donc une bande claire et le navigateur peignait une bande sombre.
   Le linear-gradient opaque et le !important sont retirés, le sol vient
   désormais de data-sol="1" ; il ne reste ici que les deux halos cyan, qui
   sont transparents et se posent par-dessus. Le sélecteur perd .section--light
   pour ne plus dépendre d'une classe qui n'a plus lieu d'être sur la balise. */
/* LES CYANS EN DUR DE CE BLOC SONT PASSES EN color-mix — 2026-09-04.
   Ils etaient ecrits rgba(6,182,212,...) et rgba(34,211,238,...), donc ils
   n'auraient PAS suivi le passage au bleu editorial : la section se serait
   retrouvee avec des halos et des filets cyan autour d'une pastille bleue.
   Ecrits sur la variable, ils suivent. Meme alpha, meme geometrie, rien
   d'autre ne change. */
.industries {
  background-image:
    radial-gradient(ellipse 90% 50% at 50% 0%, color-mix(in srgb, var(--color-csirt) 10%, transparent), transparent 55%),
    radial-gradient(ellipse 70% 50% at 50% 100%, color-mix(in srgb, var(--color-csirt-soft) 8%, transparent), transparent 55%);
  color: var(--color-fg);
  position: relative;
  overflow: hidden;
}
.industries::before {
  /* Subtle hex grid pattern as background motif */
  content: '';
  position: absolute;
  inset: 0;
  background-image:
    repeating-linear-gradient(60deg, transparent 0 64px, color-mix(in srgb, var(--color-csirt) 4%, transparent) 64px 65px),
    repeating-linear-gradient(-60deg, transparent 0 64px, color-mix(in srgb, var(--color-csirt) 4%, transparent) 64px 65px),
    repeating-linear-gradient(0deg, transparent 0 64px, color-mix(in srgb, var(--color-csirt) 4%, transparent) 64px 65px);
  mask-image: radial-gradient(ellipse 80% 70% at center, black 30%, transparent 80%);
  -webkit-mask-image: radial-gradient(ellipse 80% 70% at center, black 30%, transparent 80%);
  pointer-events: none;
  opacity: 0.6;
}
.industries .container { position: relative; z-index: 2; }
.industries .section-title { color: var(--color-fg); }
.industries__sector {
  background: color-mix(in srgb, var(--color-csirt) 6%, transparent);
  border-color: color-mix(in srgb, var(--color-csirt) 25%, transparent) !important;
  color: var(--color-fg) !important;
}
.industries__sector .dot {
  background: var(--color-csirt) !important;
  box-shadow: 0 0 8px color-mix(in srgb, var(--color-csirt) 35%, transparent);
}
.industries__sector--secondary .dot {
  background: rgba(226, 232, 240, 0.9) !important;
  box-shadow: 0 0 8px rgba(226, 232, 240, 0.4);
}
.industries .eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 6px 14px;
  border-radius: var(--radius-full);
  background: color-mix(in srgb, var(--color-csirt) 12%, transparent);
  border: 1px solid color-mix(in srgb, var(--color-csirt) 30%, transparent);
  /* Etait rgb(165,243,252), cyan-200 EN DUR : il n'aurait pas suivi le passage
     au bleu.
     ATTENTION, CETTE DECLARATION EST MORTE, et c'est le piege 2 du repo :
     .industries .eyebrow est redeclaree ligne ~14563 avec `color:
     var(--color-fg) !important`, donc le libelle de cette pastille est BLANC
     et l'a toujours ete. Le blanc sur un fond de 14 % de bleu compose rend
     18,24:1 sur sol-0, 15,45 sur sol-1 et 13,39 sur sol-2 : il n'y a rien a
     corriger la-bas.
     La valeur est quand meme mise au systeme plutot qu'a un cyan en dur : si
     la regle du bas disparait un jour, le repli sera bleu et non cyan. */
  color: var(--color-csirt-soft) !important;
  font: 600 11px/1 var(--font-mono);
  letter-spacing: 0.18em;
  text-transform: uppercase;
}
.industries .eyebrow::before {
  content: '>';
  color: var(--color-csirt);
  font-weight: 700;
}
/* Cadre remis dans le systeme le 2026-08-11. Ce bloc habillait la carte en
   --color-csirt, la couleur de la persona CSIRT, sur une section qui n'est pas
   cette persona : le design system reserve les six couleurs de persona a leur
   persona. C'etait aussi la seule carte de la page a porter une bordure coloree,
   et a 0,20 elle etait deux fois et demie plus visible que le blanc 0,08 des
   autres. Bordure et survol alignes sur .pillar, donc sur le rouge unique.
   La couleur cyan des libelles dans .industry-card__body est conservee : le
   texte cyan est une convention du site (.pillar__stat), c'est le CADRE qui
   sortait du systeme, pas la typo. */
.industry-card {
  background: var(--color-surface) !important;
  border: 1px solid var(--color-border) !important;
}
.industry-card:hover {
  border-color: rgba(220, 38, 38, 0.55) !important;
  box-shadow: 0 16px 40px rgba(0,0,0,0.40), 0 0 32px rgba(220, 38, 38, 0.18);
}
.industry-card__body p {
  color: rgba(255,255,255,0.85) !important;
}
.industry-card__body strong {
  /* Etait rgb(34,211,238), cyan-400 EN DUR — le dernier cyan de la section a
     avoir survecu au passage au bleu du 2026-09-04. Trouve a l'oeil sur une
     capture (le titre etait bleu, ce texte turquoise), puis confirme par la
     mesure du style calcule : #60A5FA pour le titre, #22D3EE ici.
     CONTRASTE MESURE SUR LES PIXELS RENDUS, et non sur le CSS, parce que ce
     texte est pose sur une PHOTO : le fond a ete capture texte masque, et ses
     3 612 pixels donnent une luminance de 0,0066 a 0,0085, le voile de la
     carte ecrasant l'image presque au noir. Sur le 90e centile, le pire cas
     realiste : cyan 10,03:1, bleu clair 7,13:1, bleu PLEIN 3,79:1.
     C'est donc la variante claire qu'il faut ici, et surtout pas le ton
     plein. */
  color: var(--color-csirt-soft) !important;
}

/* SERVICES (accordion) — make dark with mono prefixes */
.services.section--light {
  background: var(--color-bg) !important;
  color: var(--color-fg);
}
.services .section-title { color: var(--color-fg); }
.services .section-lede { color: var(--color-muted) !important; }
.services .eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 6px 14px;
  border-radius: var(--radius-full);
  background: rgba(220,38,38,0.10);
  border: 1px solid rgba(220,38,38,0.30);
  color: var(--color-danger-soft) !important;
  font: 600 11px/1 var(--font-mono);
  letter-spacing: 0.18em;
  text-transform: uppercase;
}
.services .eyebrow::before {
  content: '>';
  color: var(--color-primary);
  font-weight: 700;
}
.service-group {
  background: rgba(255,255,255,0.03);
  border: 1px solid var(--color-border) !important;
  border-radius: var(--radius-md);
  margin-bottom: var(--space-3);
}
.service-group summary {
  color: var(--color-fg);
  padding: var(--space-5) var(--space-6);
}
.service-group__title {
  color: var(--color-fg) !important;
  font-size: var(--text-lg) !important;
}
.service-group__body {
  background: rgba(255,255,255,0.02);
  border-top: 1px solid var(--color-border);
  padding: var(--space-6);
}
.service-item h4 {
  color: var(--color-primary) !important;
  font-family: var(--font-mono) !important;
  font-size: 13px !important;
  letter-spacing: 0.14em !important;
  text-transform: uppercase;
  margin-bottom: var(--space-3) !important;
}
.service-item h4::before {
  content: '> ';
  color: var(--color-success);
}
.service-item ul {
  color: var(--color-muted) !important;
}
.service-item ul li { color: rgba(248,250,252,0.7) !important; }

/* HOW section — LIGHT BREATHING ROOM (contrast island between dark sections) */
.how.section--light {
  background:
    radial-gradient(ellipse 80% 50% at 50% 0%, rgba(220,38,38,0.06), transparent 60%),
    linear-gradient(180deg, #FFFFFF 0%, #F8FAFC 100%) !important;
  color: var(--color-fg-light);
  position: relative;
  overflow: hidden;
}
.how.section--light::before {
  /* Top diagonal divider — visual transition from previous dark section */
  content: '';
  position: absolute;
  top: -1px;
  left: 0; right: 0;
  height: 60px;
  background: var(--color-bg);
  clip-path: polygon(0 0, 100% 0, 100% 100%, 0 30%);
  z-index: 1;
}
.how.section--light::after {
  /* Bottom diagonal divider */
  content: '';
  position: absolute;
  bottom: -1px;
  left: 0; right: 0;
  height: 60px;
  background: var(--color-bg);
  clip-path: polygon(0 70%, 100% 100%, 100% 100%, 0 100%);
  z-index: 1;
}
.how .container { position: relative; z-index: 2; }
.how .section-title { color: var(--color-fg-light); }
.how__text p { color: var(--color-muted-light) !important; }
.how__text p strong {
  color: var(--color-fg-light) !important;
  background: linear-gradient(120deg, transparent 60%, rgba(220,38,38,0.20) 60%);
  padding: 0 4px;
}
.how__text .eyebrow {
  color: var(--color-primary) !important;
  background: rgba(220,38,38,0.08);
  border: 1px solid rgba(220,38,38,0.20);
}
.how__media {
  /* Rayon aligne sur les cartes du site (16 px). C'etait le meme ecart a 24 px
     que celui corrige sur .industry-card. Pas de plateau noir : ce cadre porte
     une PHOTO opaque qui le remplit, son fond ne se voit jamais.
     Attention, c'est CETTE regle qui gagne : .how__media est declaree quatre
     fois dans ce fichier. */
  border-radius: var(--radius-lg);
  overflow: hidden;
  position: relative;
  box-shadow:
    0 32px 64px -16px rgba(16, 16, 16,0.25),
    0 0 0 1px rgba(220,38,38,0.10);
}
.how__media img {
  transition: transform 1.2s cubic-bezier(0.4, 0, 0.2, 1);
}
.how__media:hover img { transform: scale(1.03); }
/* Orphan global .promise overrides removed (DNA-9). They pinned every .promise
   card to a low-contrast red and used !important, blocking the scene-hacked
   theme styling at .promises--scene below from applying. */

/* ── Footer bootlog terminal (SOC-grade dmesg style) ────────── */
.site-footer__bootlog {
  position: relative;
  margin-top: var(--space-12);
  margin-bottom: var(--space-4);
  padding: var(--space-4) var(--space-6);
  border: 1px solid rgba(255, 255, 255, 0.05);
  border-radius: 10px;
  background: linear-gradient(180deg, rgba(23, 23, 23, 0.55) 0%, rgba(16, 16, 16, 0.40) 100%);
  backdrop-filter: blur(12px) saturate(115%);
  -webkit-backdrop-filter: blur(12px) saturate(115%);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.05),
    inset 0 -1px 0 rgba(0, 0, 0, 0.25);
  font: 500 11.5px/1.5 var(--font-mono);
  letter-spacing: 0.02em;
  color: rgba(203, 213, 225, 0.85);
  overflow: hidden;
}

/* Session prompt header */
.site-footer__bootlog-head {
  padding-bottom: var(--space-2);
  margin-bottom: var(--space-3);
  border-bottom: 1px solid rgba(255, 255, 255, 0.05);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.site-footer__bootlog-prompt { color: rgb(110, 231, 183); font-weight: 600; }
.site-footer__bootlog-sep    { color: rgba(255, 255, 255, 0.35); }
.site-footer__bootlog-path   { color: rgb(165, 243, 252); font-weight: 600; }
.site-footer__bootlog-dollar { color: rgba(255, 255, 255, 0.55); margin: 0 6px; font-weight: 600; }
.site-footer__bootlog-cmd    { color: rgba(241, 245, 249, 0.92); }

/* Service status list */
.site-footer__bootlog-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0;
}
.site-footer__bootlog-list li {
  display: grid;
  grid-template-columns: 78px 8px 1fr auto 52px;
  align-items: center;
  gap: var(--space-3);
  padding: 4px 0;
}
.site-footer__bootlog-time {
  color: rgba(148, 163, 184, 0.55);
  font-variant-numeric: tabular-nums;
  font-weight: 600;
}
.site-footer__bootlog-dot {
  width: 6px; height: 6px;
  border-radius: 50%;
  background: rgb(34, 197, 94);
  box-shadow: 0 0 5px rgba(34, 197, 94, 0.35);
}
.site-footer__bootlog-name {
  color: rgba(241, 245, 249, 0.95);
  font-weight: 600;
  letter-spacing: 0;
}
.site-footer__bootlog-desc {
  color: rgba(148, 163, 184, 0.85);
  text-align: right;
  letter-spacing: 0;
}
.site-footer__bootlog-ok {
  color: rgb(110, 231, 183);
  font-weight: 700;
  letter-spacing: 0.04em;
  text-align: right;
}

@media (max-width: 720px) {
  .site-footer__bootlog { padding: var(--space-3) var(--space-4); font-size: 10.5px; }
  .site-footer__bootlog-list li {
    grid-template-columns: 60px 6px 1fr auto;
    gap: var(--space-2);
  }
  .site-footer__bootlog-desc { display: none; }
}

/* ── Alliance logo cards (Phase C2) ──────────────────────────── */

.visually-hidden {
  position: absolute !important;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0,0,0,0);
  white-space: nowrap; border: 0;
}

.alliance-card {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 88px;
  padding: var(--space-4) var(--space-5);
  background: linear-gradient(180deg, rgba(255,255,255,0.04), rgba(255,255,255,0.01));
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  transition: all var(--duration-normal) var(--ease-out);
  cursor: default;
  isolation: isolate;
  overflow: hidden;
}
.alliance-card::before {
  content: '';
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 1px;
  background: linear-gradient(90deg, transparent, var(--color-primary), transparent);
  opacity: 0;
  transition: opacity var(--duration-normal) var(--ease-out);
}
.alliance-card:hover {
  border-color: var(--color-primary);
  background: linear-gradient(180deg, rgba(220,38,38,0.10), rgba(220,38,38,0.02));
  transform: translateY(-3px);
  box-shadow: 0 12px 24px rgba(0,0,0,0.30), 0 0 24px rgba(220,38,38,0.18);
}
.alliance-card:hover::before { opacity: 1; }

.alliance-card__name {
  font-family: var(--font-mono);
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.10em;
  color: var(--color-fg);
  text-align: center;
  line-height: 1;
}
.alliance-card[data-brand="crowdstrike"] .alliance-card__name,
.alliance-card[data-brand="proofpoint"]  .alliance-card__name { letter-spacing: 0.06em; }
.alliance-card[data-brand="group-ib"]    .alliance-card__name { letter-spacing: 0.14em; }

.alliance-card__logo {
  max-width: 100%;
  max-height: 48px;
  width: auto;
  height: auto;
  filter: brightness(0) invert(0.85);  /* logos en silver/light gray sobre dark */
  opacity: 0.75;
  transition: filter var(--duration-normal) var(--ease-out), opacity var(--duration-normal) var(--ease-out);
  object-fit: contain;
}
.alliance-card:hover .alliance-card__logo {
  filter: brightness(0) invert(1);
  opacity: 1;
}
/* Darkvore is a tall pictographic logo — needs more vertical room */
.alliance-card[data-brand="darkivore"] .alliance-card__logo { max-height: 64px; }

/* ── Language switcher ───────────────────────────────────────── */
.lang-switch {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 4px 8px;
  border-radius: var(--radius-full);
  border: 1px solid var(--color-border-strong);
  margin-right: var(--space-3);
  font-family: var(--font-mono);
  background: rgba(255, 255, 255, 0.025);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  /* Liquid Glass refraction */
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.07),
    inset 0 -1px 0 rgba(0, 0, 0, 0.10);
}
.lang-switch__btn {
  background: transparent;
  border: 0;
  color: var(--color-muted);
  font: 700 11px/1 var(--font-mono);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  padding: 6px 8px;
  border-radius: var(--radius-full);
  cursor: pointer;
  transition: color var(--duration-fast) var(--ease-out), background var(--duration-fast) var(--ease-out);
}
.lang-switch__btn:hover { color: var(--color-fg); }
.lang-switch__btn.is-active {
  color: var(--color-fg);
  background: rgba(220,38,38,0.18);
  box-shadow: 0 0 12px rgba(220,38,38,0.35);
}
.lang-switch__sep { color: var(--color-muted-soft); font-size: 11px; }
@media (max-width: 900px) {
  .lang-switch { display: none; }
}
.prose ul li strong { color: var(--color-fg-light); }

/* ============================================================
   SITE ENHANCEMENTS — scroll progress bar + split-text reveal
   ============================================================ */

/* (Scroll progress bar removida — el usuario reportó que ralentizaba la página) */

/* ============================================================
   LENIS smooth scroll support
   ============================================================ */
html.lenis, html.lenis body { height: auto; }
.lenis.lenis-smooth { scroll-behavior: auto !important; }
.lenis.lenis-smooth [data-lenis-prevent] { overscroll-behavior: contain; }
.lenis.lenis-stopped { overflow: hidden; }
.lenis.lenis-scrolling iframe { pointer-events: none; }

/* ============================================================
   SCROLL FX — velocity-reactive + multi-layer parallax
   ============================================================ */

/* Parallax: cualquier [data-parallax="X"] se traduce vía --parallax-y */
[data-parallax] {
  will-change: transform;
  transform: translate3d(0, var(--parallax-y, 0px), 0);
  transition: transform 80ms linear;
}

/* Scroll-velocity-reactive cinematic — restaurado al estado "hero perfecto" */
:root {
  --scroll-velocity-abs: 0;
  --scroll-velocity: 0;
}

/* Ancienne teinte du fond du hero (hue-rotate 330deg) retiree le 2026-08-11 :
   elle servait a rougir la photo de cadenas, et rendait l'embleme MAGENTA. La
   regle etait la 3e portant sur .hero__bg-img et gagnait dans la cascade.
   La rotation reactive des fragments flottants part avec eux. */

/* Split-text reveal — palabra por palabra con blur→focus */
[data-split-reveal] .split-word {
  display: inline-block;
  opacity: 0;
  transform: translateY(14px);
  filter: blur(6px);
  transition:
    opacity 600ms cubic-bezier(0.16, 1, 0.3, 1),
    transform 600ms cubic-bezier(0.16, 1, 0.3, 1),
    filter 600ms cubic-bezier(0.16, 1, 0.3, 1);
  transition-delay: calc(var(--i, 0) * 35ms);
  will-change: opacity, transform, filter;
}
[data-split-reveal].is-revealed-words .split-word {
  opacity: 1;
  transform: translateY(0);
  filter: blur(0);
}
@media (prefers-reduced-motion: reduce) {
  [data-split-reveal] .split-word {
    opacity: 1 !important;
    transform: none !important;
    filter: none !important;
    transition: none !important;
  }
}

/* ============================================================
   SCENE-HACKED — fusion: cyber animation + "¿Cómo lo hacemos?" copy
   El contenido derecho NO cambia con los estados — sólo la capa visual.
   ============================================================ */

.scene-hacked__eyebrow {
  display: inline-flex;
  background: rgba(6, 182, 212, 0.08);
  border: 1px solid rgba(6, 182, 212, 0.35);
  color: rgba(165, 243, 252, 0.92);
  padding: 8px 14px;
  border-radius: var(--radius-full);
  font: 600 12px/1 var(--font-mono);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  margin-bottom: var(--space-6);
  box-shadow: 0 0 18px rgba(6,182,212,0.18);
  align-items: center;
  gap: 8px;
}
.scene-hacked__eyebrow .pulse {
  width: 8px; height: 8px;
  background: rgb(34, 211, 238);
  border-radius: 50%;
  box-shadow: 0 0 8px rgba(34, 211, 238, 0.9);
  animation: pulse 2.4s ease-in-out infinite;
}

/* How title inside the scene */
.scene-hacked__title--how {
  font-family: var(--font-sans);
  font-size: clamp(32px, 4.4vw, 52px);
  font-weight: 800;
  line-height: 1.05;
  letter-spacing: -0.02em;
  margin: 0 0 var(--space-5);
  color: var(--color-fg);
  text-shadow:
    0 0 32px rgba(255,255,255,0.15),
    0 0 6px rgba(6, 182, 212, 0.30);
}

/* Promise pills inside the scene copy — informativas (NO interactivas) */
.promises--scene {
  list-style: none;
  padding: 0;
  margin: 0;
  display: grid;
  gap: 10px;
}
.promises--scene .promise {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 18px;
  border: 1px solid rgba(220, 38, 38, 0.42);
  background:
    linear-gradient(180deg, rgba(220, 38, 38, 0.14), rgba(220, 38, 38, 0.06)),
    rgba(23, 23, 23, 0.55);
  border-radius: var(--radius-md);
  color: rgba(248, 250, 252, 0.96);
  font-weight: 600;
  font-size: var(--text-sm);
  cursor: default;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.06),
    0 0 0 1px rgba(220, 38, 38, 0.08),
    0 12px 32px -16px rgba(220, 38, 38, 0.35);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  transition:
    transform var(--duration-normal) var(--ease-out),
    border-color var(--duration-normal) var(--ease-out),
    box-shadow var(--duration-normal) var(--ease-out);
}
.promises--scene .promise:hover {
  transform: translateY(-2px);
  border-color: rgba(220, 38, 38, 0.65);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.08),
    0 0 0 1px rgba(220, 38, 38, 0.18),
    0 18px 40px -16px rgba(220, 38, 38, 0.55);
}
.promises--scene .promise .icon {
  width: 22px; height: 22px;
  color: var(--color-danger-soft);
  filter: drop-shadow(0 0 8px rgba(220, 38, 38, 0.55));
  flex: 0 0 auto;
}

/* ============================================================
   NUESTRO DIFERENCIADOR — 3 pilares + bridge → Liga + frameworks
   Estructura clara: header → 3 columnas → bridge → liga grid → proof
   ============================================================ */

.diferenciador {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  padding: clamp(96px, 12vw, 144px) 0 clamp(112px, 14vw, 160px);
  /* Navy base con leve cyan top + slate bottom (purple removido) */
  background:
    radial-gradient(ellipse 80% 50% at 50% 0%, rgba(6,182,212,0.08), transparent 55%),
    radial-gradient(ellipse 70% 50% at 50% 100%, rgba(148,163,184,0.04), transparent 60%),
    linear-gradient(180deg, #101010 0%, #171717 60%, #101010 100%);
}
.diferenciador::before {
  content: '';
  position: absolute; inset: 0;
  background-image: radial-gradient(rgba(255,255,255,0.04) 1px, transparent 1px);
  background-size: 32px 32px;
  mask-image: radial-gradient(ellipse 70% 60% at center, black 30%, transparent 90%);
  -webkit-mask-image: radial-gradient(ellipse 70% 60% at center, black 30%, transparent 90%);
  pointer-events: none;
  z-index: 0;
}
.diferenciador > .container { position: relative; z-index: 1; }

/* ---- Header ---- */
.diferenciador__head {
  max-width: 760px;
  margin: 0 auto var(--space-12);
  text-align: center;
}
.diferenciador__title {
  font-family: var(--font-sans);
  font-size: clamp(36px, 5vw, 56px);
  font-weight: 800;
  line-height: 1.05;
  letter-spacing: -0.02em;
  margin: var(--space-3) 0 var(--space-4);
  color: var(--color-fg);
}
.diferenciador__title .accent {
  color: var(--color-primary);
  font-weight: 800;
}
.diferenciador__lede {
  font-size: var(--text-lg);
  line-height: 1.6;
  color: var(--color-muted);
  max-width: 560px;
  margin: 0 auto;
}

/* ---- 3 Pilares ---- */
.pillars {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-6);
  margin-bottom: var(--space-16);
}
@media (min-width: 900px) {
  .pillars { grid-template-columns: repeat(3, 1fr); gap: var(--space-6); }
}

.pillar {
  position: relative;
  /* Le padding est passe sur .pillar__body : l'illustration doit toucher les
     bords de la carte, comme sur les cartes produit de CrowdStrike. */
  padding: 0;
  overflow: hidden;              /* clippe l'image aux coins arrondis */
  /* Sólido en vez de glass+blur — el blur era el culpable del freeze al entrar la sección */
  background: rgba(23, 23, 23, 0.85);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  transition: border-color 320ms var(--ease-out), background 320ms var(--ease-out), transform 320ms var(--ease-out);
}
.pillar:hover {
  border-color: rgba(220, 38, 38, 0.55);
  background: rgba(220, 38, 38, 0.06);
  transform: translateY(-4px);
}

/* ── Peau commune des plateaux d'illustration ────────────────── */
/* Le fond noir, le filet de separation et le fondu vers le corps de la carte
   sont declares UNE seule fois pour les deux familles qui en ont besoin :
   .pillar__media (les trois piliers de Nuestro diferenciador) et
   .practice__hero (les six heros de La Liga). Une seule declaration, donc elles
   ne peuvent pas diverger au fil des retouches.
   Seule la GEOMETRIE differe et reste propre a chacune : le pilier est un bloc
   en ratio 4/3, le heros un span de 280 px sorti du padding par marges
   negatives. Le noir est plus sombre que le navy du site (10,14,39) : c'est
   volontaire, il assume le plateau comme un cadre d'image, et la mesure a
   montre que le noir existe deja partout ailleurs sur la page. */
.pillar__media,
.practice__hero {
  position: relative;
  background: var(--color-plate);
  border-bottom: 1px solid var(--color-border);
}
/* Fondu vers le corps de la carte : la bascule image/texte ne doit pas etre une
   arete franche, sinon la carte se lit comme deux blocs colles. La cible du
   degrade est la couleur de corps que les deux familles partagent desormais. */
.pillar__media::after,
.practice__hero::after {
  content: '';
  position: absolute; inset: 0;
  background: linear-gradient(180deg, transparent 55%, rgba(23, 23, 23, 0.85) 100%);
  pointer-events: none;
}

.pillar__media {
  /* Ratio impose en CSS ET width/height sur le <img> : l'emplacement est
     reserve avant le chargement, donc l'image chargee en lazy ne decale rien. */
  aspect-ratio: 4 / 3;
  overflow: hidden;
}
.pillar__media img {
  width: 100%; height: 100%;
  object-fit: cover;
  display: block;
  transition: transform 480ms var(--ease-out);
}
.pillar:hover .pillar__media img {
  transform: scale(1.04);
}
.pillar__body {
  position: relative;            /* ancre .pillar__num sous l'image */
  padding: var(--space-7) var(--space-6) var(--space-6);
}

.pillar__num {
  position: absolute;
  top: var(--space-4);
  right: var(--space-5);
  font: 800 56px/1 var(--font-sans);
  color: rgba(255, 255, 255, 0.06);
  letter-spacing: -0.02em;
  pointer-events: none;
}
/* .pillar__icon (puce rouge de 56 px + SVG de 28 px) retire le 2026-08-11 :
   remplace par .pillar__media. .pillar ne sert que sur la home, verifie, donc
   il n'y a pas d'autre page a casser. */
.pillar__title {
  font-family: var(--font-sans);
  font-size: var(--text-xl);
  font-weight: 700;
  line-height: 1.25;
  margin: 0 0 var(--space-3);
  color: var(--color-fg);
  letter-spacing: -0.01em;
  /* Reserve la place du filigrane .pillar__num, sinon la derniere ligne du titre
     vient buter dedans (« ...certificadas » sur la carte 01). */
  padding-right: 52px;
}
.pillar__title em {
  font-style: italic;
  color: rgba(252, 165, 165, 0.95);
}
.pillar__stat {
  font: 600 12px/1.4 var(--font-mono);
  letter-spacing: 0.10em;
  text-transform: uppercase;
  color: rgba(165, 243, 252, 0.85);
  padding-bottom: var(--space-4);
  margin: 0 0 var(--space-4);
  border-bottom: 1px dashed rgba(148, 163, 184, 0.20);
}
.pillar__stat strong {
  color: var(--color-fg);
  font-weight: 800;
}
.pillar__copy {
  font-size: var(--text-sm);
  line-height: 1.6;
  color: rgba(226, 232, 240, 0.85);
  margin: 0;
}

/* ---- Bridge to Liga ---- */
.liga-bridge {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  max-width: 760px;
  margin: 0 auto var(--space-8);
}
.liga-bridge__line {
  flex: 1;
  height: 1px;
  background: linear-gradient(90deg,
    transparent,
    rgba(6, 182, 212, 0.5) 50%,
    transparent);
}
.liga-bridge__tag {
  font: 600 11px/1 var(--font-mono);
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: rgba(165, 243, 252, 0.85);
  white-space: nowrap;
  padding: 6px 12px;
  border: 1px solid rgba(6, 182, 212, 0.25);
  border-radius: var(--radius-full);
  background: rgba(6, 182, 212, 0.05);
}
@media (max-width: 720px) {
  .liga-bridge__tag { font-size: 10px; letter-spacing: 0.16em; padding: 6px 10px; }
}

.liga-section-head {
  text-align: center;
  margin-bottom: var(--space-10);
}
.eyebrow--liga {
  color: rgba(165, 243, 252, 0.9);
  letter-spacing: 0.26em;
}
.liga-section-head__title {
  font-family: var(--font-sans);
  font-size: clamp(24px, 3vw, 32px);
  font-weight: 700;
  line-height: 1.2;
  margin: var(--space-3) 0 0;
  color: var(--color-fg);
  letter-spacing: -0.01em;
}

/* ---- Proof: frameworks + CTA below the liga grid ---- */
.diferenciador__proof {
  display: grid;
  gap: var(--space-6);
  margin-top: var(--space-16);
  padding-top: var(--space-10);
  border-top: 1px solid var(--color-border);
  text-align: center;
}
.diferenciador__proof .frameworks__label,
.about-frameworks .frameworks__label {
  font: 700 11px/1 var(--font-mono);
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--color-muted);
  margin: 0;
}
.diferenciador__proof .frameworks__grid,
.about-frameworks .frameworks__grid {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 8px;
}
.diferenciador__proof .framework,
.about-frameworks .framework {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font: 600 12px/1 var(--font-mono);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: rgba(241, 245, 249, 0.92);
  padding: 8px 12px;
  border: 1px solid rgba(148, 163, 184, 0.22);
  border-radius: var(--radius-full);
  background: rgba(148, 163, 184, 0.06);
}
.diferenciador__proof .framework .icon,
.about-frameworks .framework .icon {
  width: 14px; height: 14px;
  color: var(--color-success);
}
/* Plus aucun element ne porte cette classe depuis le 2026-08-17 : le bouton
   de #sistema a pris .btn .btn-secondary .btn-pill, comme celui d'alianzas.
   La declaration reste au cas ou une autre page la reprenne. */
.diferenciador__cta {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  margin: var(--space-4) auto 0;
  font: 700 13px/1 var(--font-mono);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--color-fg);
  text-decoration: none;
  padding: 14px 22px;
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-full);
  background: rgba(255,255,255,0.02);
  transition: border-color 240ms, background 240ms, transform 240ms;
}
.diferenciador__cta:hover {
  border-color: var(--color-primary);
  background: rgba(220,38,38,0.10);
  transform: translateX(4px);
}
.diferenciador__cta .icon { width: 18px; height: 18px; }

/* Stagger entrance on pillars and liga grid */
.diferenciador .pillar,
.diferenciador .liga__grid .persona { opacity: 0; transform: translateY(20px); }
.diferenciador.is-in .pillar {
  opacity: 1; transform: translateY(0);
  transition: opacity 600ms cubic-bezier(0.16,1,0.3,1), transform 600ms cubic-bezier(0.16,1,0.3,1);
  transition-delay: var(--d, 0ms);
}
.diferenciador.is-in .pillar:nth-child(1) { --d: 0ms; }
.diferenciador.is-in .pillar:nth-child(2) { --d: 120ms; }
.diferenciador.is-in .pillar:nth-child(3) { --d: 240ms; }

.diferenciador.is-in .liga__grid .persona {
  opacity: 1; transform: translateY(0);
  transition: opacity 600ms cubic-bezier(0.16,1,0.3,1), transform 600ms cubic-bezier(0.16,1,0.3,1);
  transition-delay: var(--d, 0ms);
}
.diferenciador.is-in .liga__grid .persona:nth-child(1) { --d: 0ms; }
.diferenciador.is-in .liga__grid .persona:nth-child(2) { --d: 80ms; }
.diferenciador.is-in .liga__grid .persona:nth-child(3) { --d: 160ms; }
.diferenciador.is-in .liga__grid .persona:nth-child(4) { --d: 240ms; }
.diferenciador.is-in .liga__grid .persona:nth-child(5) { --d: 320ms; }
.diferenciador.is-in .liga__grid .persona:nth-child(6) { --d: 400ms; }

@media (prefers-reduced-motion: reduce) {
  .diferenciador .pillar,
  .diferenciador .liga__grid .persona {
    opacity: 1 !important; transform: none !important; transition: none !important;
  }
}

/* (liga-diff CSS removido — reemplazado por .diferenciador arriba) */

/* ============================================================
   LIGA: 6 cards en 1 línea (mismo tamaño, sin captain especial)
   ============================================================ */
/* ── Ops triad — objetivo operativo NGSOC (1 / 10 / 60 min) ─────────── */
.ops-triad {
  margin: var(--space-12) auto 0;
  max-width: 720px;
  text-align: center;
}
.ops-triad__label {
  font: 600 12px/1.4 var(--font-mono);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--color-muted);
  margin-bottom: var(--space-6);
}
.ops-triad__prompt { color: var(--color-primary); margin-right: 6px; }
.ops-triad__grid {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-4);
  flex-wrap: wrap;
}
.ops-triad__item {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  min-width: 128px;
}
.ops-triad__num {
  font: 800 clamp(40px, 6vw, 60px)/1 var(--font-mono);
  color: var(--color-fg);
  letter-spacing: -0.02em;
}
.ops-triad__unit {
  font-size: 0.34em;
  font-weight: 600;
  color: var(--color-primary);
  margin-left: 4px;
  letter-spacing: 0.04em;
}
.ops-triad__cap {
  font: 600 12px/1 var(--font-mono);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--color-muted);
}
.ops-triad__sep {
  width: 1px;
  height: 44px;
  background: rgba(248, 250, 252, 0.14);
}
@media (max-width: 560px) {
  .ops-triad__sep { display: none; }
  .ops-triad__grid { gap: var(--space-6); }
}

.liga-tag {
  margin: var(--space-12) auto var(--space-6);
  text-align: center;
  font: 600 13px/1.4 var(--font-mono);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgba(165, 243, 252, 0.85);
}
.liga-tag strong {
  color: var(--color-fg);
  font-weight: 800;
}

.liga__grid--row6 {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-4);
  margin-bottom: var(--space-12);
}
@media (min-width: 600px)  { .liga__grid--row6 { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 900px)  { .liga__grid--row6 { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 1200px) { .liga__grid--row6 { grid-template-columns: repeat(6, 1fr); gap: var(--space-3); } }

/* En la fila de 6, las cards van más compactas pero con misma altura */
.liga__grid--row6 .persona {
  aspect-ratio: 3 / 4.6;
  border-radius: var(--radius-lg);
  overflow: hidden;
}
.liga__grid--row6 .persona__img {
  aspect-ratio: auto;
  height: 100%;
  object-fit: cover;
  object-position: center top;
}
.liga__grid--row6 .persona__body {
  padding: var(--space-3) var(--space-3) var(--space-4);
}
.liga__grid--row6 .persona__name {
  font-size: var(--text-base);
  letter-spacing: 0.12em;
  margin: 0 0 4px;
}
.liga__grid--row6 .persona__role {
  font-size: 11px;
  line-height: 1.45;
  letter-spacing: 0.02em;
}
.liga__grid--row6 .persona__role em {
  font-style: normal;
  font-weight: 700;
  color: var(--color-primary);
  text-transform: uppercase;
  letter-spacing: 0.10em;
  font-size: 10px;
  display: block;
  margin-bottom: 4px;
}

/* ============================================================
   TACTILE :active FEEDBACK — physical push on interactive elements
   (cumple Rule 5 de la skill: "On :active use -translate-y-[1px] or scale-[0.98]")
   ============================================================ */
.btn:active,
.btn-primary:active,
.btn-secondary:active,
.btn-pill:active,
.diferenciador__cta:active {
  transform: translateY(1px) scale(0.985);
  transition: transform 80ms cubic-bezier(0.4, 0, 0.2, 1);
}
.persona:active,
.practice:active,
.industry-card:active,
.alliance-card:active,
.client-logo:active,
.country:active,
.framework:active {
  transform: translateY(1px) scale(0.985);
  transition: transform 80ms cubic-bezier(0.4, 0, 0.2, 1);
}
.lang-switch__btn:active,
.main-nav__link:active,
.scene-hacked__replay:active,
.fp-dot:active,
.mobile-menu-toggle:active {
  transform: scale(0.94);
  transition: transform 80ms cubic-bezier(0.4, 0, 0.2, 1);
}
.hero__chip:active {
  transform: scale(0.97);
}
@media (prefers-reduced-motion: reduce) {
  .btn:active, .btn-primary:active, .btn-secondary:active, .btn-pill:active,
  .persona:active, .practice:active, .industry-card:active, .alliance-card:active,
  .client-logo:active, .lang-switch__btn:active, .main-nav__link:active,
  .scene-hacked__replay:active, .hero__chip:active, .country:active,
  .framework:active, .diferenciador__cta:active {
    transform: none !important;
    transition: none !important;
  }
}

/* ============================================================
   FASE 2 — Variaciones dark por sección (anti-monotonía)
   Mantiene identidad cyber dark, agrega ritmo visual entre secciones.
   ============================================================ */

/* Tema DEEP-SLATE: Prácticas y Clientes (más profundo, hint cálido) */
#practicas.section--light {
  background:
    radial-gradient(ellipse 100% 60% at 50% 0%, rgba(220, 38, 38, 0.05), transparent 55%),
    linear-gradient(180deg, #0B0B0B 0%, #101010 50%, #0B0B0B 100%) !important;
  position: relative;
}
#practicas.section--light::before {
  /* Líneas diagonales sutiles 45° — pattern distintivo, no AI */
  content: '';
  position: absolute; inset: 0;
  background-image:
    repeating-linear-gradient(45deg, transparent 0 80px, rgba(255, 255, 255, 0.015) 80px 81px);
  mask-image: radial-gradient(ellipse 90% 80% at center, black 30%, transparent 90%);
  -webkit-mask-image: radial-gradient(ellipse 90% 80% at center, black 30%, transparent 90%);
  pointer-events: none;
  z-index: 0;
}
#practicas.section--light > .container { position: relative; z-index: 1; }

.clients.section--light {
  background:
    radial-gradient(ellipse 90% 60% at 50% 100%, rgba(148, 163, 184, 0.04), transparent 55%),
    linear-gradient(180deg, #0B0B0B 0%, #101010 100%) !important;
}

/* Tema STEEL-BLUE: Alianzas (signal "vendors", azul corporate sutil).
   2026-08-12 : le linear-gradient opaque #171717 -> #1A1A1A et son !important
   sont retirés. Ils bloquaient l'échelle de sols, et surtout ils ne servaient
   à rien : mesuré au getComputedStyle, ce dégradé rendait un sol à 1,000:1 de
   son voisin, donc invisible comme changement de bande. Le sol vient de
   data-sol="1" ; il ne reste ici que le halo argent, transparent. */
#alianzas.section--dark {
  background-image:
    radial-gradient(ellipse 100% 50% at 50% 0%, rgba(148, 163, 184, 0.06), transparent 55%);
  position: relative;
}
/* Override del grid pattern global que aplica a .section--dark — usar uno propio steel */
.section--dark:not(.hero):not(.scene-hacked):not(.final-cta--poster)#alianzas::before {
  background-image:
    linear-gradient(rgba(148, 163, 184, 0.045) 1px, transparent 1px),
    linear-gradient(90deg, rgba(148, 163, 184, 0.045) 1px, transparent 1px);
}

/* Section bridges — divisor sutil entre cambios de theme
   Aplicar solo donde hay transición de color (no a todas) */
.fp-bridge {
  position: relative;
  height: 1px;
  margin: 0;
  background: linear-gradient(90deg,
    transparent 0%,
    rgba(148, 163, 184, 0.10) 30%,
    rgba(148, 163, 184, 0.10) 70%,
    transparent 100%);
}

/* ============================================================
   THEME CLASSES — variaciones dark globales (Metodología + Home)
   ============================================================ */

/* Theme DEEP-SLATE */
.theme-deep-slate {
  background:
    radial-gradient(ellipse 100% 60% at 50% 0%, rgba(220, 38, 38, 0.05), transparent 55%),
    linear-gradient(180deg, #0B0B0B 0%, #101010 50%, #0B0B0B 100%) !important;
  position: relative;
}
.theme-deep-slate::before {
  content: '';
  position: absolute; inset: 0;
  background-image:
    repeating-linear-gradient(45deg, transparent 0 80px, rgba(255, 255, 255, 0.015) 80px 81px);
  mask-image: radial-gradient(ellipse 90% 80% at center, black 30%, transparent 90%);
  -webkit-mask-image: radial-gradient(ellipse 90% 80% at center, black 30%, transparent 90%);
  pointer-events: none;
  z-index: 0;
}
.theme-deep-slate > .container { position: relative; z-index: 1; }

/* ============================================================
   ACREDITACIONES — sección unificada Marcos + Partners + Equipo
   ============================================================ */
.feature-grid--marcos {
  grid-template-columns: 1fr;
  gap: var(--space-5);
  margin-bottom: var(--space-12);
}
@media (min-width: 720px)  { .feature-grid--marcos { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1100px) { .feature-grid--marcos { grid-template-columns: repeat(3, 1fr); } }

.feature-card--framework {
  display: flex;
  flex-direction: column;
  gap: 18px;
  padding: 36px 32px !important;
}
.feature-card--framework .feature-card__icon {
  margin-bottom: 4px;
}
.feature-card--framework h3 {
  margin: 0 !important;
}
.feature-card__quote {
  font-style: italic;
  color: rgba(165, 243, 252, 0.85) !important;
  border-left: 2px solid rgba(6, 182, 212, 0.4);
  padding-left: 16px;
  font-size: var(--text-sm) !important;
  line-height: 1.55 !important;
  margin: 0 !important;
}
.feature-card__bullets {
  margin: 6px 0 0;
  padding: 0 !important;
}
.feature-card__bullets {
  list-style: none;
  padding: 0;
  margin: var(--space-2) 0 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.feature-card__bullets li {
  position: relative;
  padding-left: 16px;
  font: 500 12.5px/1.4 var(--font-mono);
  letter-spacing: 0.02em;
  color: rgba(203, 213, 225, 0.85);
}
.feature-card__bullets li::before {
  content: '›';
  position: absolute;
  left: 0;
  color: rgba(6, 182, 212, 0.6);
  font-weight: 700;
}
.feature-card__bullets li strong {
  color: var(--color-fg);
  font-weight: 700;
}

/* Partner levels strip */
.acreditaciones__partners {
  margin-bottom: var(--space-10);
  padding-top: var(--space-8);
  border-top: 1px solid rgba(255, 255, 255, 0.05);
}
.acreditaciones__partners-label,
.acreditaciones__team-label {
  font: 700 11px/1 var(--font-mono);
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: rgba(148, 163, 184, 0.85);
  text-align: center;
  margin: 0 0 var(--space-4);
}

/* Team certs */
.acreditaciones__team {
  padding-top: var(--space-6);
  border-top: 1px dashed rgba(255, 255, 255, 0.06);
  text-align: center;
  max-width: 720px;
  margin: 0 auto;
}
.acreditaciones__team-text {
  font-size: var(--text-base);
  line-height: 1.6;
  color: rgba(203, 213, 225, 0.85);
  margin: 0;
}
.acreditaciones__team-text strong {
  color: var(--color-fg);
}

/* Theme STEEL — steel-blue corporate */
.theme-steel {
  background:
    radial-gradient(ellipse 100% 50% at 50% 0%, rgba(148, 163, 184, 0.06), transparent 55%),
    linear-gradient(180deg, #171717 0%, #1A1A1A 50%, #171717 100%) !important;
  position: relative;
}
.theme-steel::before {
  content: '';
  position: absolute; inset: 0;
  background-image:
    linear-gradient(rgba(148, 163, 184, 0.045) 1px, transparent 1px),
    linear-gradient(90deg, rgba(148, 163, 184, 0.045) 1px, transparent 1px);
  background-size: 64px 64px;
  mask-image: radial-gradient(ellipse 80% 70% at center, black 30%, transparent 90%);
  -webkit-mask-image: radial-gradient(ellipse 80% 70% at center, black 30%, transparent 90%);
  pointer-events: none;
  z-index: 0;
}
.theme-steel > .container { position: relative; z-index: 1; }

/* ============================================================
   FEATURE-CARD + PROSE overrides cuando viven en dark sections
   ============================================================ */

.section--dark .feature-card,
.theme-deep-slate .feature-card,
.theme-steel .feature-card {
  position: relative;
  background: rgba(23, 23, 23, 0.85);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  overflow: hidden;
  /* Liquid Glass refraction */
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.05),
    inset 0 -1px 0 rgba(0, 0, 0, 0.25);
  transition:
    border-color 320ms var(--ease-out),
    background 320ms var(--ease-out),
    transform 320ms var(--ease-out),
    box-shadow 320ms var(--ease-out);
}
/* Subtle radial glow detrás del icon — aparece en hover */
.section--dark .feature-card::before,
.theme-deep-slate .feature-card::before,
.theme-steel .feature-card::before {
  content: '';
  position: absolute;
  top: -20%; left: -10%;
  width: 60%; height: 60%;
  background: radial-gradient(circle at center, rgba(220, 38, 38, 0.12), transparent 70%);
  opacity: 0;
  transition: opacity 320ms var(--ease-out);
  pointer-events: none;
  z-index: 0;
}
/* HUD corner bracket — bottom-left (mismo patrón que home practices DNA-4) */
.section--dark .feature-card::after,
.theme-deep-slate .feature-card::after,
.theme-steel .feature-card::after {
  content: '';
  position: absolute;
  bottom: 14px; left: 14px;
  width: 18px; height: 18px;
  border-bottom: 1.5px solid var(--color-primary);
  border-left: 1.5px solid var(--color-primary);
  opacity: 0;
  transform: translate(-4px, 4px);
  transition: opacity 320ms var(--ease-out), transform 320ms var(--ease-out);
  pointer-events: none;
  z-index: 1;
}
/* HOVER state — matches home pillars treatment */
.section--dark .feature-card:hover,
.theme-deep-slate .feature-card:hover,
.theme-steel .feature-card:hover {
  border-color: rgba(220, 38, 38, 0.55);
  background: rgba(220, 38, 38, 0.05);
  transform: translateY(-4px);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.08),
    inset 0 -1px 0 rgba(0, 0, 0, 0.25),
    0 20px 48px rgba(0, 0, 0, 0.35),
    0 0 32px rgba(220, 38, 38, 0.18);
}
.section--dark .feature-card:hover::before,
.theme-deep-slate .feature-card:hover::before,
.theme-steel .feature-card:hover::before { opacity: 1; }
.section--dark .feature-card:hover::after,
.theme-deep-slate .feature-card:hover::after,
.theme-steel .feature-card:hover::after {
  opacity: 0.8;
  transform: translate(0, 0);
}
/* Ensure content stays above the bg glow */
.section--dark .feature-card > *,
.theme-deep-slate .feature-card > *,
.theme-steel .feature-card > * { position: relative; z-index: 1; }

/* On hover: icon glow more intensely */
.section--dark .feature-card:hover .feature-card__icon,
.theme-deep-slate .feature-card:hover .feature-card__icon,
.theme-steel .feature-card:hover .feature-card__icon {
  background: rgba(220, 38, 38, 0.20);
  border-color: rgba(220, 38, 38, 0.55);
  box-shadow: 0 0 24px rgba(220, 38, 38, 0.22);
}
.section--dark .feature-card:hover .feature-card__icon .icon,
.theme-deep-slate .feature-card:hover .feature-card__icon .icon,
.theme-steel .feature-card:hover .feature-card__icon .icon {
  filter: drop-shadow(0 0 12px rgba(220, 38, 38, 0.55));
}
.section--dark .feature-card h3,
.theme-deep-slate .feature-card h3,
.theme-steel .feature-card h3 {
  color: var(--color-fg);
}
.section--dark .feature-card p,
.theme-deep-slate .feature-card p,
.theme-steel .feature-card p {
  color: rgba(203, 213, 225, 0.78);
}
.section--dark .feature-card__icon,
.theme-deep-slate .feature-card__icon,
.theme-steel .feature-card__icon {
  background: rgba(220, 38, 38, 0.12);
  border: 1px solid rgba(220, 38, 38, 0.30);
  width: 56px; height: 56px;
}
.section--dark .feature-card__icon .icon,
.theme-deep-slate .feature-card__icon .icon,
.theme-steel .feature-card__icon .icon {
  width: 28px; height: 28px;
  filter: drop-shadow(0 0 6px rgba(220, 38, 38, 0.35));
}

/* PROSE overrides for dark */
.section--dark .prose p,
.theme-deep-slate .prose p,
.theme-steel .prose p {
  color: rgba(203, 213, 225, 0.85);
}
.section--dark .prose p strong,
.theme-deep-slate .prose p strong,
.theme-steel .prose p strong {
  color: var(--color-fg);
}
.section--dark .prose h2,
.theme-deep-slate .prose h2,
.theme-steel .prose h2 {
  color: var(--color-fg);
}
.section--dark .prose h3,
.theme-deep-slate .prose h3,
.theme-steel .prose h3 {
  color: var(--color-csirt);
}
.section--dark .prose blockquote,
.theme-deep-slate .prose blockquote,
.theme-steel .prose blockquote {
  color: rgba(241, 245, 249, 0.95);
  border-left-color: var(--color-primary);
}
.section--dark .prose ul,
.theme-deep-slate .prose ul,
.theme-steel .prose ul {
  color: rgba(203, 213, 225, 0.85);
}
.section--dark .prose ul li strong,
.theme-deep-slate .prose ul li strong,
.theme-steel .prose ul li strong {
  color: var(--color-fg);
}

/* Phase-cards (CSOC SOC core/avanzado) — más glass treatment */
.phase-card {
  background: rgba(23, 23, 23, 0.55) !important;
  border: 1px solid rgba(255, 255, 255, 0.06) !important;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.05),
    inset 0 -1px 0 rgba(0, 0, 0, 0.25);
}
.phase-card:hover {
  background: rgba(23, 23, 23, 0.75) !important;
  border-color: rgba(220, 38, 38, 0.40) !important;
}
.phase-card__num {
  /* Solid red — gradient removed (skill: no gradient text) */
  background: var(--color-primary) !important;
}

/* ═══════════════════════════════════════════════════════════════
   ABOUT PAGE — nosotros.html DS additions
   ═══════════════════════════════════════════════════════════════ */

/* Chip — small inline mono tag (intro chip-row) */
.chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 12px;
  border-radius: 9999px;
  background: rgba(220,38,38,0.08);
  border: 1px solid rgba(220,38,38,0.18);
  font-family: 'JetBrains Mono', monospace;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--color-primary);
}

/* Section head centered variant */
.section-head--center {
  text-align: center;
  align-items: center;
}
.section-head--center .section-lede {
  margin-inline: auto;
}

/* Metric caption (small text under .metric__label) */
.metric__caption {
  margin: var(--space-2) auto 0;
  font-size: var(--text-sm);
  color: var(--color-muted);
  line-height: 1.55;
  max-width: 30ch;
}

/* About-cards grid (6 value-prop cards on nosotros.html) — fresh namespace
   to avoid the legacy .promise pill cascade. */
.about-cards {
  display: grid;
  gap: var(--space-4);
  grid-template-columns: 1fr;
  margin-top: var(--space-8);
  list-style: none;
  padding: 0;
}
@media (min-width: 640px)  { .about-cards { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1024px) { .about-cards { grid-template-columns: repeat(3, 1fr); } }
/* 4-column variant for careers areas */
@media (min-width: 1024px) { .about-cards--4 { grid-template-columns: repeat(4, 1fr); } }

.about-card {
  display: flex !important;
  flex-direction: column !important;
  align-items: flex-start !important;
  gap: var(--space-3);
  padding: var(--space-6);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  color: var(--color-fg) !important;
  font-weight: 400;
  font-size: var(--text-base);
  transition:
    transform var(--duration-normal) var(--ease-out),
    border-color var(--duration-normal) var(--ease-out),
    box-shadow var(--duration-normal) var(--ease-out);
}
.about-card:hover {
  transform: translateY(-3px);
  border-color: rgba(220,38,38,0.42);
  box-shadow:
    0 12px 32px rgba(0,0,0,0.35),
    0 0 24px rgba(220,38,38,0.20);
}
.about-card__icon-wrap {
  display: inline-flex;
  width: 48px; height: 48px;
  border-radius: var(--radius-md);
  align-items: center;
  justify-content: center;
  background: rgba(220,38,38,0.10);
  border: 1px solid rgba(220,38,38,0.22);
  color: var(--color-primary);
}
.about-card__icon-wrap svg {
  width: 24px;
  height: 24px;
  color: var(--color-primary);
  stroke: currentColor;
  fill: none;
}
.about-card__title {
  margin: 0;
  font-size: var(--text-xl);
  font-weight: 700;
  color: var(--color-fg) !important;
  letter-spacing: -0.01em;
  line-height: 1.25;
}
.about-card__desc {
  margin: 0;
  font-size: var(--text-base);
  font-weight: 400;
  color: var(--color-muted) !important;
  line-height: 1.6;
}

/* Essence editorial (etymology) */
.essence-mark {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-2);
  margin: var(--space-10) 0;
  padding: var(--space-8) 0;
  border-top: 1px solid var(--color-border-light);
  border-bottom: 1px solid var(--color-border-light);
}
.essence-mark__word {
  font-family: 'JetBrains Mono', monospace;
  font-size: clamp(72px, 13vw, 152px);
  font-weight: 800;
  line-height: 1;
  letter-spacing: -0.04em;
  color: var(--color-primary);
  text-shadow: 0 0 32px rgba(220,38,38,0.20);
}
.essence-mark__lang {
  font-family: 'JetBrains Mono', monospace;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--color-muted-light);
}
.essence-body p {
  font-size: var(--text-lg);
  line-height: 1.7;
  color: var(--color-fg-light);
  margin-bottom: var(--space-4);
}
.essence-body p:last-child { margin-bottom: 0; }
.essence-body .essence-pull {
  font-size: clamp(24px, 3.2vw, 32px);
  font-weight: 700;
  text-align: center;
  color: var(--color-primary);
  letter-spacing: -0.01em;
  margin: var(--space-6) 0;
  line-height: 1.3;
}

/* Cert strip (light section) */
.cert-strip {
  list-style: none;
  margin: var(--space-8) 0 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--space-3);
}
@media (min-width: 640px)  { .cert-strip { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 1024px) { .cert-strip { grid-template-columns: repeat(5, 1fr); } }

.cert-card {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-4) var(--space-5);
  background: var(--color-surface-light);
  border: 1px solid var(--color-border-light);
  border-radius: var(--radius-md);
  transition:
    transform var(--duration-base) var(--ease-out),
    border-color var(--duration-base) var(--ease-out),
    box-shadow var(--duration-base) var(--ease-out);
}
.cert-card:hover {
  transform: translateY(-2px);
  border-color: var(--color-primary);
  box-shadow: 0 4px 12px rgba(0,0,0,0.08);
}
.cert-card__icon {
  width: 32px; height: 32px;
  color: var(--color-primary);
  flex-shrink: 0;
}
/* sceaux officiels (section claire : art sombre lisible tel quel) */
.cert-card__badge {
  height: 44px;
  width: auto;
  flex-shrink: 0;
}
.cert-card strong {
  display: block;
  font-size: var(--text-base);
  font-weight: 700;
  color: var(--color-fg-light);
  letter-spacing: -0.01em;
  line-height: 1.2;
}
.cert-card span {
  display: block;
  font-family: 'JetBrains Mono', monospace;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--color-muted-light);
  margin-top: 2px;
}

/* Alliances showcase image */
.alliances-image {
  margin-top: var(--space-8);
  text-align: center;
}
.alliances-image img {
  max-width: 100%;
  width: 1100px;
  height: auto;
  margin: 0 auto;
  display: block;
  filter: drop-shadow(0 12px 32px rgba(0,0,0,0.35));
}

/* ═══════════════════════════════════════════════════════════════
   CONTACT PAGE — contacto.html DS additions
   ═══════════════════════════════════════════════════════════════ */

/* RFC 2350 download chips */
.rfc-row {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-3);
  margin-top: var(--space-6);
}
.rfc-chip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 10px 18px;
  border-radius: 9999px;
  background: rgba(220,38,38,0.08);
  border: 1px solid rgba(220,38,38,0.22);
  color: var(--color-primary) !important;
  font-family: 'JetBrains Mono', monospace;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-decoration: none;
  transition:
    background var(--duration-normal) var(--ease-out),
    transform var(--duration-normal) var(--ease-out);
}
.rfc-chip:hover {
  background: rgba(220,38,38,0.14);
  transform: translateY(-2px);
}
.rfc-chip svg { color: var(--color-primary); flex-shrink: 0; }

/* Contact section — slight tint behind the form to separate from brief */
.contact-section {
  position: relative;
  isolation: isolate;
}
.contact-section::before {
  content: '';
  position: absolute; inset: 0;
  background:
    radial-gradient(ellipse 40% 30% at 12% 18%, rgba(220,38,38,0.10), transparent 60%),
    radial-gradient(ellipse 50% 40% at 90% 75%, rgba(6,182,212,0.08), transparent 60%);
  pointer-events: none;
  z-index: -1;
}

/* 2-col grid: contact-info aside + form */
.contact-grid {
  display: grid;
  gap: var(--space-8);
  grid-template-columns: 1fr;
  margin-top: var(--space-8);
  align-items: start;
}
/* LA COLONNE MESURAIT 327 PX DANS UN CONTENEUR DE 280, d'ou 27 px de
   debordement horizontal a 320 px de large. Ce n'est pas la grille qui etait
   trop large : un element de grille a min-width: auto, donc il ne peut pas
   devenir plus etroit que son contenu incompressible — ici l'adresse
   « linkedin.com/company/asha-solution », une chaine sans espace que rien
   n'autorisait a se couper. Les deux moities de la cause, les deux corrigees :
   la grille cesse d'imposer un plancher, et les longues adresses peuvent se
   couper. */
.contact-grid > * { min-width: 0; }
.contact-info__item a,
.contact-info__item strong { overflow-wrap: anywhere; }
@media (min-width: 960px) {
  .contact-grid {
    grid-template-columns: minmax(320px, 0.85fr) 1.4fr;
    gap: var(--space-10);
  }
}

/* CONTACT-INFO aside (CSIRT cyan accents inside, since the form is CSIRT-scoped) */
.contact-info {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  /* Le liseré etait cyan — --color-csirt — parce que ce formulaire est du
     ressort du CSIRT. L'intention se defend mais elle posait la seule touche
     cyan de la page sur son element le plus visible : il prend le rouge de
     marque, comme le reste de la section. */
  border-top: 3px solid var(--color-primary);
  border-radius: var(--radius-lg);
  padding: var(--space-7) var(--space-6);
  color: var(--color-fg) !important;
}
.contact-info__title {
  margin: 0 0 var(--space-2);
  font-size: var(--text-xl);
  font-weight: 700;
  color: var(--color-fg) !important;
  letter-spacing: -0.01em;
}
.contact-info__lede {
  margin: 0 0 var(--space-6);
  font-size: var(--text-sm);
  color: var(--color-muted) !important;
  line-height: 1.6;
}
.contact-info__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}
.contact-info__item {
  display: grid;
  grid-template-columns: 28px 1fr;
  gap: var(--space-3);
  align-items: start;
}
.contact-info__icon {
  color: var(--color-csirt);
  margin-top: 2px;
}
.contact-info__item strong {
  display: block;
  font-size: var(--text-base);
  font-weight: 700;
  color: var(--color-fg) !important;
  line-height: 1.35;
}
.contact-info__item strong a {
  color: var(--color-fg) !important;
  text-decoration: none;
  border-bottom: 1px dashed rgba(255,255,255,0.20);
  transition: color var(--duration-normal) var(--ease-out), border-color var(--duration-normal) var(--ease-out);
}
.contact-info__item strong a:hover {
  color: var(--color-csirt) !important;
  border-color: var(--color-csirt);
}
.contact-info__item span {
  display: block;
  margin-top: 2px;
  font-size: 12.5px;
  color: var(--color-muted) !important;
  line-height: 1.4;
}
.contact-info__countries {
  margin-top: var(--space-7);
  padding-top: var(--space-5);
  border-top: 1px solid var(--color-border);
}
.contact-info__countries .eyebrow {
  display: inline-block;
  margin-bottom: var(--space-2);
}
.contact-info__countries p {
  margin: 0;
  font-size: var(--text-sm);
  color: var(--color-muted) !important;
  line-height: 1.6;
}

/* CSIRT-FORM */
.csirt-form {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: var(--space-7) var(--space-6);
}
.form-section {
  border: none;
  padding: 0;
  margin: 0 0 var(--space-8);
}
.form-section:last-of-type { margin-bottom: var(--space-6); }
.form-section__head {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  margin-bottom: var(--space-5);
  padding: 0;
  font-family: 'JetBrains Mono', monospace;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--color-primary);
}
.form-section__num {
  display: inline-flex;
  width: 24px; height: 24px;
  align-items: center;
  justify-content: center;
  border-radius: 9999px;
  background: rgba(220,38,38,0.14);
  border: 1px solid rgba(220,38,38,0.30);
  color: var(--color-primary);
  font-size: 11px;
  letter-spacing: 0;
}
.form-row {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-4);
  margin-bottom: var(--space-4);
}
@media (min-width: 640px) {
  .form-row { grid-template-columns: 1fr 1fr; gap: var(--space-5); }
}
.form-group {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-bottom: var(--space-4);
}
.form-group:last-child { margin-bottom: 0; }
.form-label {
  font-family: 'JetBrains Mono', monospace;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.10em;
  text-transform: uppercase;
  color: var(--color-muted) !important;
}
.form-input,
.form-select,
.form-textarea {
  font-family: var(--font-sans);
  font-size: var(--text-base);
  color: var(--color-fg) !important;
  background: rgba(16, 16, 16,0.45);
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-md);
  padding: 12px 14px;
  width: 100%;
  outline: none;
  transition:
    border-color var(--duration-normal) var(--ease-out),
    box-shadow var(--duration-normal) var(--ease-out),
    background var(--duration-normal) var(--ease-out);
}
.form-input:hover,
.form-select:hover,
.form-textarea:hover {
  border-color: rgba(255,255,255,0.30);
}
.form-input:focus,
.form-select:focus,
.form-textarea:focus {
  border-color: var(--color-primary);
  box-shadow: 0 0 0 3px rgba(220,38,38,0.18);
  background: rgba(16, 16, 16,0.65);
}
.form-textarea {
  resize: vertical;
  min-height: 96px;
  line-height: 1.5;
}
.form-textarea--mono {
  font-family: 'JetBrains Mono', monospace;
  font-size: 13.5px;
  letter-spacing: 0;
}
.form-select {
  appearance: none;
  -webkit-appearance: none;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%2394A3B8' stroke-width='2'><polyline points='6 9 12 15 18 9'/></svg>");
  background-repeat: no-repeat;
  background-position: right 14px center;
  background-size: 14px;
  padding-right: 38px;
}
.form-file {
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  color: var(--color-muted) !important;
  background: rgba(16, 16, 16,0.45);
  border: 1px dashed var(--color-border-strong);
  border-radius: var(--radius-md);
  padding: 10px 14px;
  width: 100%;
}
.form-file::file-selector-button {
  background: var(--color-primary);
  color: var(--color-fg);
  border: 0;
  padding: 8px 14px;
  border-radius: var(--radius-md);
  font-weight: 600;
  cursor: pointer;
  margin-right: 12px;
  transition: background var(--duration-normal) var(--ease-out);
}
.form-file::file-selector-button:hover { background: var(--color-primary-hover); }

/* Custom checkbox */
.form-checkbox {
  display: grid;
  grid-template-columns: 22px 1fr;
  gap: var(--space-3);
  align-items: start;
  cursor: pointer;
  font-size: var(--text-sm);
  color: var(--color-fg) !important;
  line-height: 1.6;
}
.form-checkbox input[type="checkbox"] {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}
.form-checkbox__box {
  width: 22px; height: 22px;
  border: 1px solid var(--color-border-strong);
  border-radius: 6px;
  background: rgba(16, 16, 16,0.45);
  position: relative;
  margin-top: 1px;
  transition:
    border-color var(--duration-normal) var(--ease-out),
    background var(--duration-normal) var(--ease-out);
}
.form-checkbox__box::after {
  content: '';
  position: absolute;
  left: 6px; top: 2px;
  width: 7px; height: 12px;
  border: solid #fff;
  border-width: 0 2px 2px 0;
  transform: rotate(45deg) scale(0);
  transition: transform var(--duration-normal) var(--ease-out);
}
.form-checkbox input[type="checkbox"]:checked + .form-checkbox__box {
  background: var(--color-primary);
  border-color: var(--color-primary);
}
.form-checkbox input[type="checkbox"]:checked + .form-checkbox__box::after {
  transform: rotate(45deg) scale(1);
}
.form-checkbox input[type="checkbox"]:focus-visible + .form-checkbox__box {
  box-shadow: 0 0 0 3px rgba(220,38,38,0.30);
}
.form-checkbox__label a {
  color: var(--color-primary) !important;
  border-bottom: 1px solid currentColor;
}

.form-note {
  margin: 0 0 var(--space-5);
  font-size: 12.5px;
  font-style: italic;
  color: var(--color-muted) !important;
}
.form-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  margin-top: var(--space-6);
  padding-top: var(--space-5);
  border-top: 1px solid var(--color-border);
}

/* ═══════════════════════════════════════════════════════════════
   SERVICE PAGES — persona-aware system
   Each service page sets <body class="page-service page-service--XXX">
   where XXX is the persona key. The --page-accent CSS var is then
   consumed by .service-* components for accent tints, hovers, glows.
   ═══════════════════════════════════════════════════════════════ */

.page-service { /* base — no persona color yet */ }

.page-service--csirt {
  --page-accent:           #06B6D4;
  --page-accent-tint-08:   rgba(6,182,212,0.08);
  --page-accent-tint-18:   rgba(6,182,212,0.18);
  --page-accent-tint-30:   rgba(6,182,212,0.30);
  --page-accent-tint-45:   rgba(6,182,212,0.45);
}
.page-service--ctem {
  --page-accent:           #F97316;
  --page-accent-tint-08:   rgba(249,115,22,0.08);
  --page-accent-tint-18:   rgba(249,115,22,0.18);
  --page-accent-tint-30:   rgba(249,115,22,0.30);
  --page-accent-tint-45:   rgba(249,115,22,0.45);
}
.page-service--grc {
  --page-accent:           #22C55E;
  --page-accent-tint-08:   rgba(34,197,94,0.08);
  --page-accent-tint-18:   rgba(34,197,94,0.18);
  --page-accent-tint-30:   rgba(34,197,94,0.30);
  --page-accent-tint-45:   rgba(34,197,94,0.45);
}
.page-service--zerotrust {
  --page-accent:           #A855F7;
  --page-accent-tint-08:   rgba(168,85,247,0.08);
  --page-accent-tint-18:   rgba(168,85,247,0.18);
  --page-accent-tint-30:   rgba(168,85,247,0.30);
  --page-accent-tint-45:   rgba(168,85,247,0.45);
}
.page-service--ngsoc {
  --page-accent:           #E2E8F0;
  --page-accent-tint-08:   rgba(226,232,240,0.08);
  --page-accent-tint-18:   rgba(226,232,240,0.18);
  --page-accent-tint-30:   rgba(226,232,240,0.30);
  --page-accent-tint-45:   rgba(226,232,240,0.20);
}
.page-service--asha {
  /* For pages that map to the captain — keeps primary red as accent */
  --page-accent:           #DC2626;
  --page-accent-tint-08:   rgba(220,38,38,0.08);
  --page-accent-tint-18:   rgba(220,38,38,0.18);
  --page-accent-tint-30:   rgba(220,38,38,0.30);
  --page-accent-tint-45:   rgba(220,38,38,0.45);
}

/* Persona-aware hero: shift accent text, eyebrow dot, ticker dot, drift glow */
.page-service .page-hero__title .accent {
  color: var(--page-accent) !important;
}
.page-service .page-hero__eyebrow {
  color: var(--page-accent) !important;
}
.page-service .page-hero__eyebrow-dot {
  background: var(--page-accent) !important;
  box-shadow: 0 0 12px var(--page-accent-tint-45);
}
.page-service .page-hero__ticker-dot {
  background: var(--page-accent) !important;
}
.page-service .page-hero__ticker {
  color: var(--page-accent) !important;
}

/* Persona-aware breadcrumb link */
.page-service .breadcrumb a:hover {
  color: var(--page-accent) !important;
}

/* Persona-aware eyebrow inside content sections */
.page-service .eyebrow {
  color: var(--page-accent) !important;
}

/* ─── Service Brief (Section 01: copy + stat card) ─────────────── */
.service-brief {
  display: grid;
  gap: var(--space-8);
  grid-template-columns: 1fr;
  align-items: start;
}
@media (min-width: 960px) {
  .service-brief {
    grid-template-columns: 1.5fr 1fr;
    gap: var(--space-12);
  }
}
.service-brief__copy .eyebrow {
  display: inline-block;
  margin-bottom: var(--space-3);
}
.service-brief__copy .section-title {
  margin-bottom: var(--space-5);
}
.service-brief__copy p {
  color: var(--color-muted) !important;
  font-size: var(--text-lg);
  line-height: 1.7;
  margin: 0 0 var(--space-4);
}
.service-brief__copy p strong {
  color: var(--color-fg) !important;
  font-weight: 700;
}

/* Stat card (single highlighted number).
   The persona-accent identity is carried by the colored number + glow +
   radial tint; no side stripe needed. */
.service-stat {
  position: relative;
  padding: var(--space-7) var(--space-6);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  isolation: isolate;
  overflow: hidden;
}
.service-stat::before {
  content: '';
  position: absolute; inset: 0;
  background: radial-gradient(circle at 100% 0%, var(--page-accent-tint-08) 0%, transparent 60%);
  z-index: -1;
}
.service-stat__num {
  font-family: 'JetBrains Mono', monospace;
  font-size: clamp(56px, 10vw, 96px);
  font-weight: 800;
  line-height: 1;
  letter-spacing: -0.03em;
  color: var(--page-accent);
  text-shadow: 0 0 24px var(--page-accent-tint-45);
  display: block;
}
.service-stat__num .unit {
  font-size: 0.55em;
  font-weight: 700;
  margin-left: 4px;
}
.service-stat__label {
  margin: var(--space-3) 0 0;
  font-size: var(--text-base);
  color: var(--color-fg) !important;
  line-height: 1.45;
  font-weight: 600;
}
.service-stat__source {
  margin: var(--space-3) 0 0;
  font-family: 'JetBrains Mono', monospace;
  font-size: 11px;
  letter-spacing: 0.10em;
  text-transform: uppercase;
  color: var(--color-muted) !important;
}

/* ─── Service Cards (Section 02: 6-card grid, persona-tinted) ──── */
.service-cards {
  display: grid;
  gap: var(--space-4);
  grid-template-columns: 1fr;
  margin-top: var(--space-8);
}
@media (min-width: 640px)  { .service-cards { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1024px) { .service-cards { grid-template-columns: repeat(3, 1fr); } }

.service-card {
  display: flex !important;
  flex-direction: column !important;
  align-items: flex-start !important;
  gap: var(--space-3);
  padding: var(--space-6);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  color: var(--color-fg) !important;
  position: relative;
  isolation: isolate;
  overflow: hidden;
  transition:
    transform var(--duration-normal) var(--ease-out),
    border-color var(--duration-normal) var(--ease-out),
    box-shadow var(--duration-normal) var(--ease-out);
}
.service-card::before {
  content: '';
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 2px;
  background: var(--page-accent);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform var(--duration-normal) var(--ease-out);
  z-index: 1;
}
.service-card:hover {
  transform: translateY(-3px);
  border-color: var(--page-accent);
  box-shadow:
    0 12px 32px rgba(0,0,0,0.35),
    0 0 24px var(--page-accent-tint-18);
}
.service-card:hover::before {
  transform: scaleX(1);
}
.service-card__icon-wrap {
  display: inline-flex;
  width: 48px; height: 48px;
  border-radius: var(--radius-md);
  align-items: center;
  justify-content: center;
  background: var(--page-accent-tint-08);
  border: 1px solid var(--page-accent-tint-18);
  color: var(--page-accent);
}
.service-card__icon-wrap svg {
  width: 24px;
  height: 24px;
  color: var(--page-accent);
  stroke: currentColor;
  fill: none;
}
.service-card__title {
  margin: 0;
  font-size: var(--text-xl);
  font-weight: 700;
  color: var(--color-fg) !important;
  letter-spacing: -0.01em;
  line-height: 1.25;
}
.service-card__desc {
  margin: 0;
  font-size: var(--text-base);
  font-weight: 400;
  color: var(--color-muted) !important;
  line-height: 1.6;
}

/* ─── Frameworks Strip (Section 03: chips for standards) ────────── */
.frameworks-strip {
  display: grid;
  gap: var(--space-3);
  grid-template-columns: 1fr;
  margin-top: var(--space-7);
}
@media (min-width: 640px)  { .frameworks-strip { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1024px) { .frameworks-strip { grid-template-columns: repeat(4, 1fr); } }

.framework-chip {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-4) var(--space-5);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  transition:
    transform var(--duration-normal) var(--ease-out),
    border-color var(--duration-normal) var(--ease-out);
}
.framework-chip:hover {
  transform: translateY(-2px);
  border-color: var(--page-accent);
}
.framework-chip svg {
  color: var(--page-accent);
  flex-shrink: 0;
  stroke: currentColor;
  fill: none;
}
.framework-chip strong {
  display: block;
  font-size: var(--text-base);
  font-weight: 700;
  color: var(--color-fg) !important;
  letter-spacing: -0.01em;
  line-height: 1.2;
}
.framework-chip span {
  display: block;
  font-family: 'JetBrains Mono', monospace;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.10em;
  text-transform: uppercase;
  color: var(--color-muted) !important;
  margin-top: 3px;
}

/* Service page final-cta — accent uses page persona color */
.page-service .final-cta__title .accent {
  color: var(--page-accent) !important;
}

/* ═══════════════════════════════════════════════════════════════
   LEGAL PAGES — aviso-de-privacidad.html DS additions
   ═══════════════════════════════════════════════════════════════ */

.legal-section {
  padding-block: var(--space-16);
}

.legal-prose {
  max-width: 760px;
  margin: 0 auto;
  color: var(--color-fg);
}
.legal-prose h2 {
  font-size: clamp(20px, 2.2vw, 24px);
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--color-fg) !important;
  margin: var(--space-10) 0 var(--space-3);
  padding-top: var(--space-6);
  border-top: 1px solid var(--color-border);
  line-height: 1.3;
}
.legal-prose h2:first-child {
  margin-top: 0;
  padding-top: 0;
  border-top: none;
}
.legal-prose h3 {
  font-size: var(--text-lg);
  font-weight: 700;
  color: var(--color-fg) !important;
  margin: var(--space-6) 0 var(--space-2);
  letter-spacing: -0.005em;
}
.legal-prose p {
  font-size: var(--text-base);
  line-height: 1.75;
  color: var(--color-muted) !important;
  margin: 0 0 var(--space-4);
  text-align: justify;
}
.legal-prose p strong {
  color: var(--color-fg) !important;
  font-weight: 700;
}
.legal-prose p em {
  font-style: italic;
  color: var(--color-fg) !important;
}
.legal-prose ul {
  list-style: none;
  padding-left: 0;
  margin: var(--space-3) 0 var(--space-5);
}
.legal-prose ul li {
  position: relative;
  padding-left: var(--space-5);
  margin-bottom: var(--space-2);
  font-size: var(--text-base);
  line-height: 1.6;
  color: var(--color-muted);
}
.legal-prose ul li::before {
  content: '';
  position: absolute;
  left: 0; top: 0.65em;
  width: 6px; height: 6px;
  background: var(--color-primary);
  border-radius: 9999px;
}
.legal-prose a {
  color: var(--color-primary);
  border-bottom: 1px dashed currentColor;
  transition: border-color var(--duration-normal) var(--ease-out);
}
.legal-prose a:hover {
  border-bottom-style: solid;
}
.legal-prose__footer {
  margin-top: var(--space-12);
  padding-top: var(--space-5);
  border-top: 1px solid var(--color-border);
  font-family: 'JetBrains Mono', monospace;
  font-size: 11px;
  letter-spacing: 0.10em;
  text-transform: uppercase;
  color: var(--color-muted-light) !important;
  text-align: center;
}

/* Compact legal hero (smaller padding than service hero) */
.page-hero--legal {
  padding: clamp(96px, 11vw, 140px) 0 clamp(64px, 8vw, 96px);
  min-height: auto;
}

/* ─────────────────────────────────────────────────────────────────
   Process Flow — numbered vertical timeline (CSIRT lifecycle).
   Replaces the 6-card grid on the CSIRT service page so each step
   reads as part of a continuous process, not six interchangeable tiles.
   ──────────────────────────────────────────────────────────────── */
.process-flow {
  list-style: none;
  margin: var(--space-10) auto 0;
  padding: 0;
  max-width: 820px;
  display: grid;
  gap: var(--space-8);
  position: relative;
}
.process-flow::before {
  content: '';
  position: absolute;
  left: 32px;
  top: 40px;
  bottom: 40px;
  width: 1px;
  background: linear-gradient(
    180deg,
    transparent 0%,
    var(--page-accent-tint-30) 6%,
    var(--page-accent-tint-30) 94%,
    transparent 100%
  );
  z-index: 0;
}
.process-step {
  display: grid;
  grid-template-columns: 64px 1fr;
  gap: var(--space-6);
  align-items: start;
  position: relative;
  z-index: 1;
}
.process-step__num {
  width: 64px;
  height: 64px;
  display: grid;
  place-items: center;
  font-family: var(--font-mono);
  font-size: 18px;
  font-weight: 700;
  color: var(--page-accent);
  background: var(--color-surface);
  border: 1.5px solid var(--page-accent);
  border-radius: 50%;
  /* The 6px ring of bg colour punches the connector line behind the
     badge so the timeline reads as continuous segments, not crossed. */
  box-shadow:
    0 0 0 6px var(--color-bg),
    0 0 24px var(--page-accent-tint-30);
}
.process-step__body {
  padding-top: 12px;
  min-width: 0;
}
.process-step__title {
  margin: 0 0 var(--space-2);
  font-size: var(--text-xl);
  font-weight: 700;
  color: var(--color-fg);
  letter-spacing: -0.01em;
}
.process-step__desc {
  margin: 0;
  font-size: var(--text-base);
  color: var(--color-muted);
  line-height: 1.55;
}
@media (max-width: 640px) {
  .process-flow::before { left: 24px; top: 32px; bottom: 32px; }
  .process-step { grid-template-columns: 48px 1fr; gap: var(--space-4); }
  .process-step__num {
    width: 48px; height: 48px; font-size: 15px;
    box-shadow: 0 0 0 4px var(--color-bg), 0 0 16px var(--page-accent-tint-30);
  }
  .process-step__body { padding-top: 8px; }
  .process-step__title { font-size: var(--text-lg); }
}

/* ─────────────────────────────────────────────────────────────────
   Capability Rows — full-width numbered editorial rows (GRC).
   Replaces the 6-card grid on the GRC service page. Each capability
   is its own row with a large monospaced number, a thin hairline
   separator and room for the description to breathe horizontally.
   ──────────────────────────────────────────────────────────────── */
.capability-rows {
  list-style: none;
  margin: var(--space-10) 0 0;
  padding: 0;
  display: grid;
  gap: 0;
  border-top: 1px solid var(--color-border);
}
.capability-row {
  display: grid;
  grid-template-columns: 96px 1fr;
  gap: var(--space-6);
  align-items: baseline;
  padding: var(--space-7) 0;
  border-bottom: 1px solid var(--color-border);
  position: relative;
  transition:
    background var(--duration-normal) var(--ease-out),
    padding-left var(--duration-normal) var(--ease-out);
}
.capability-row::before {
  /* thin accent line at the row's leading edge — appears on hover only */
  content: '';
  position: absolute;
  left: 0; top: 50%;
  width: 0; height: 2px;
  background: var(--page-accent);
  transform: translateY(-50%);
  transition: width var(--duration-normal) var(--ease-out);
}
.capability-row:hover {
  background: var(--page-accent-tint-08);
  padding-left: var(--space-4);
}
.capability-row:hover::before {
  width: var(--space-3);
}
.capability-row__num {
  font-family: var(--font-mono);
  font-size: clamp(32px, 5vw, 44px);
  font-weight: 800;
  line-height: 1;
  letter-spacing: -0.02em;
  color: var(--page-accent);
  align-self: start;
  padding-top: 6px;
}
.capability-row__body {
  display: grid;
  gap: var(--space-2);
  max-width: 720px;
  min-width: 0;
}
.capability-row__title {
  margin: 0;
  font-size: var(--text-2xl);
  font-weight: 700;
  color: var(--color-fg);
  letter-spacing: -0.015em;
  line-height: 1.2;
}
.capability-row__desc {
  margin: 0;
  font-size: var(--text-base);
  color: var(--color-muted);
  line-height: 1.55;
}
@media (max-width: 640px) {
  .capability-row {
    grid-template-columns: 56px 1fr;
    gap: var(--space-3);
    padding: var(--space-5) 0;
  }
  .capability-row__num { font-size: 28px; padding-top: 4px; }
  .capability-row__title { font-size: var(--text-xl); }
  .capability-row:hover { padding-left: var(--space-2); }
}

/* ─────────────────────────────────────────────────────────────────
   Stepper — 6 stages in a horizontal cycle (CTEM exposure mgmt).
   Connector line runs through the row of numbered circles. Wraps to
   3×2 on tablet (connector hidden), stacks to vertical rows on mobile.
   ──────────────────────────────────────────────────────────────── */
.stepper {
  list-style: none;
  margin: var(--space-10) 0 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: var(--space-3);
  position: relative;
}
.stepper::before {
  content: '';
  position: absolute;
  left: 8.33%;   /* center of first column (half of 1/6) */
  right: 8.33%;  /* center of last column */
  top: 28px;     /* half of 56px circle */
  height: 1px;
  background: var(--page-accent-tint-30);
  z-index: 0;
}
.stepper__item {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-3);
  text-align: center;
  position: relative;
  z-index: 1;
  padding: 0 var(--space-2);
}
.stepper__num {
  width: 56px; height: 56px;
  border-radius: 50%;
  display: grid; place-items: center;
  background: var(--color-surface);
  border: 1.5px solid var(--page-accent);
  color: var(--page-accent);
  font-family: var(--font-mono);
  font-weight: 700;
  font-size: 16px;
  box-shadow: 0 0 0 6px var(--color-bg);
  transition:
    transform var(--duration-normal) var(--ease-out),
    box-shadow var(--duration-normal) var(--ease-out);
}
.stepper__item:hover .stepper__num {
  transform: scale(1.08);
  box-shadow: 0 0 0 6px var(--color-bg), 0 0 24px var(--page-accent-tint-45);
}
.stepper__body {
  display: grid;
  gap: var(--space-2);
}
.stepper__title {
  margin: 0;
  font-size: var(--text-base);
  font-weight: 700;
  color: var(--color-fg);
  letter-spacing: -0.01em;
  line-height: 1.3;
}
.stepper__desc {
  margin: 0;
  font-size: var(--text-sm);
  color: var(--color-muted);
  line-height: 1.5;
}
@media (max-width: 1024px) {
  .stepper { grid-template-columns: repeat(3, 1fr); gap: var(--space-6) var(--space-4); }
  .stepper::before { display: none; }
}
@media (max-width: 640px) {
  .stepper { grid-template-columns: 1fr; gap: var(--space-5); }
  .stepper__item {
    flex-direction: row;
    align-items: flex-start;
    text-align: left;
    gap: var(--space-4);
    padding: 0;
  }
  .stepper__num { flex-shrink: 0; }
}

/* ─────────────────────────────────────────────────────────────────
   Threat Feed — SOC-alert-feed-styled rows (NGSOC intel).
   Each row reads like a live monitoring channel: pulsing status dot,
   monospace label, then sans-serif body. Avoids the card-grid trap by
   feeling like an operations console.
   ──────────────────────────────────────────────────────────────── */
.threat-feed {
  list-style: none;
  margin: var(--space-10) 0 0;
  padding: 0;
  display: grid;
  gap: var(--space-3);
}
.threat-feed__entry {
  display: grid;
  grid-template-columns: 180px 1fr;
  gap: var(--space-6);
  align-items: start;
  padding: var(--space-5) var(--space-5);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  position: relative;
  transition:
    border-color var(--duration-normal) var(--ease-out),
    background var(--duration-normal) var(--ease-out);
}
.threat-feed__entry:hover {
  border-color: var(--color-border-strong);
  background: var(--page-accent-tint-08);
}
.threat-feed__status {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--page-accent);
  font-weight: 600;
  padding-top: 4px;
}
.threat-feed__status::before {
  content: '';
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--page-accent);
  box-shadow: 0 0 8px var(--page-accent-tint-45);
  animation: feed-pulse 2.4s ease-in-out infinite;
}
@keyframes feed-pulse {
  0%, 100% { opacity: 0.55; }
  50%      { opacity: 1; }
}
.threat-feed__body {
  display: grid;
  gap: var(--space-2);
  min-width: 0;
}
.threat-feed__title {
  margin: 0;
  font-size: var(--text-lg);
  font-weight: 700;
  color: var(--color-fg);
  letter-spacing: -0.01em;
  line-height: 1.25;
}
.threat-feed__desc {
  margin: 0;
  font-size: var(--text-base);
  color: var(--color-muted);
  line-height: 1.55;
}
@media (max-width: 768px) {
  .threat-feed__entry {
    grid-template-columns: 1fr;
    gap: var(--space-2);
    padding: var(--space-4);
  }
  .threat-feed__status { padding-top: 0; }
}

/* ─────────────────────────────────────────────────────────────────
   Fraud Accordion — native <details> rows (ASHA fraud fusion).
   Each capability collapses to a header; click reveals body. Lets us
   present six capabilities without showing six cards at once.
   ──────────────────────────────────────────────────────────────── */
.fraud-accordion {
  list-style: none;
  margin: var(--space-10) 0 0;
  padding: 0;
  display: grid;
  gap: var(--space-3);
}
.fraud-detail {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  overflow: hidden;
  transition: border-color var(--duration-normal) var(--ease-out);
}
.fraud-detail[open] {
  border-color: var(--page-accent);
}
.fraud-detail__summary {
  display: grid;
  grid-template-columns: 56px 1fr 24px;
  align-items: center;
  gap: var(--space-5);
  padding: var(--space-5) var(--space-6);
  cursor: pointer;
  list-style: none;
  transition: background var(--duration-normal) var(--ease-out);
}
.fraud-detail__summary::-webkit-details-marker { display: none; }
.fraud-detail__summary::marker { content: ''; }
.fraud-detail__summary:hover { background: var(--page-accent-tint-08); }
.fraud-detail__num {
  font-family: var(--font-mono);
  font-size: 18px;
  font-weight: 700;
  color: var(--page-accent);
}
.fraud-detail__title {
  margin: 0;
  font-size: var(--text-lg);
  font-weight: 700;
  color: var(--color-fg);
  letter-spacing: -0.01em;
  line-height: 1.3;
}
.fraud-detail__chevron {
  width: 20px; height: 20px;
  color: var(--page-accent);
  transition: transform var(--duration-normal) var(--ease-out);
  justify-self: end;
}
.fraud-detail[open] .fraud-detail__chevron {
  transform: rotate(180deg);
}
.fraud-detail__body {
  padding: 0 var(--space-6) var(--space-6);
  padding-left: calc(56px + var(--space-5) + var(--space-6));
  margin: 0;
  font-size: var(--text-base);
  color: var(--color-muted);
  line-height: 1.6;
}
@media (max-width: 640px) {
  .fraud-detail__summary {
    grid-template-columns: 44px 1fr 20px;
    gap: var(--space-3);
    padding: var(--space-4);
  }
  .fraud-detail__title { font-size: var(--text-base); }
  .fraud-detail__body {
    padding: 0 var(--space-4) var(--space-4);
    padding-left: calc(44px + var(--space-3) + var(--space-4));
    font-size: var(--text-sm);
  }
}

/* ── Harmonisation DS (nosotros) : essence + certifications sur navy ──
   Les deux anciennes sections claires cassaient la direction navy/rouge. */
.section--dark .essence-mark {
  border-top-color: var(--color-border);
  border-bottom-color: var(--color-border);
}
.section--dark .essence-mark__lang { color: var(--color-muted); }
.section--dark .essence-body p { color: var(--color-muted); }
.section--dark .essence-body .essence-pull { color: var(--color-primary); }
.section--dark .essence-body p strong,
.section--dark .essence-body p em { color: var(--color-fg); }
.section--dark .cert-card {
  background: var(--color-surface);
  border-color: var(--color-border-strong);
}
.section--dark .cert-card:hover {
  border-color: var(--color-primary);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.35);
}
.section--dark .cert-card strong { color: var(--color-fg); }
.section--dark .cert-card span { color: var(--color-muted); }
/* sceaux (art sombre) : pastille claire pour rester lisibles sur navy */
.section--dark .cert-card__badge {
  background: rgba(248, 250, 252, 0.92);
  padding: 4px 7px;
  border-radius: var(--radius-sm);
}

/* ═══════════════════════════════════════════════════════════════════
   « Asha agente IA » — carte d'assistant (bas droite)
   Mise en page calquée sur le Falcon Bot de CrowdStrike : carte CLAIRE sur un
   site sombre, ouverte par défaut. Le DOM est injecté par
   assets/js/asha-agent.js, l'emblème animé par assets/js/asha-avatar.js.
   ═══════════════════════════════════════════════════════════════════ */

.aia-card {
  position: fixed;
  right: clamp(12px, 1.6vw, 22px);
  bottom: clamp(12px, 1.6vw, 22px);
  z-index: var(--z-overlay);
  width: min(340px, calc(100vw - 24px));
  display: flex;
  flex-direction: column;
  background: #fff;
  color: var(--color-fg-light);
  border: 1px solid rgba(16, 16, 16, 0.10);
  border-radius: var(--radius-md);
  box-shadow: 0 18px 50px rgba(7, 7, 7, 0.42), 0 2px 8px rgba(7, 7, 7, 0.18);
  /* révélée après le chargement (classe aia-ready sur body) */
  opacity: 0;
  transform: translateY(14px);
  pointer-events: none;
  transition: opacity 380ms var(--ease-out), transform 380ms var(--ease-out);
}
.aia-ready .aia-card { opacity: 1; transform: translateY(0); pointer-events: auto; }
.aia-min .aia-card { opacity: 0; transform: translateY(14px) scale(0.98); pointer-events: none; }

/* ── En-tête ─────────────────────────────────────────────────────── */
.aia-card__head {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 12px 10px 14px;
}
.aia-card__emblem { width: 52px; height: 52px; flex: 0 0 auto; margin: -2px -2px -2px -4px; }
.aia-card__ident { flex: 1; min-width: 0; }
.aia-card__name {
  font-weight: 700;
  font-size: 15px;
  line-height: 1.2;
  color: var(--color-fg-light);
}
.aia-card__role {
  font-size: 12px;
  line-height: 1.2;
  color: var(--color-muted-light);
}
.aia-card__min {
  flex: 0 0 auto;
  width: 28px; height: 28px;
  display: grid; place-items: center;
  border: 0;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--color-muted-light);
  cursor: pointer;
  transition: background var(--duration-fast), color var(--duration-fast);
}
.aia-card__min:hover { background: rgba(16, 16, 16, 0.06); color: var(--color-fg-light); }

/* ── Corps ───────────────────────────────────────────────────────── */
.aia-card__body {
  padding: 0 14px 12px;
  max-height: 46vh;
  overflow-y: auto;
}
.aia-card__welcome {
  margin: 0 0 12px;
  font-size: 13.5px;
  line-height: 1.5;
  color: rgba(16, 16, 16, 0.86);
}
.aia-card__quick { display: flex; flex-wrap: wrap; gap: 8px; }
.aia-card__pill {
  padding: 7px 12px;
  border-radius: var(--radius-sm);
  border: 1px solid rgba(220, 38, 38, 0.45);
  background: #fff;
  color: var(--color-primary);
  font-family: var(--font-sans);
  font-size: 12.5px;
  font-weight: 600;
  text-decoration: none;
  cursor: pointer;
  transition: background var(--duration-fast), border-color var(--duration-fast);
}
.aia-card__pill:hover { background: rgba(220, 38, 38, 0.07); border-color: var(--color-primary); }

/* ── Conversation ────────────────────────────────────────────────── */
.aia-log { display: flex; flex-direction: column; gap: 8px; }
.aia-msg {
  max-width: 92%;
  padding: 9px 11px;
  border-radius: var(--radius-sm);
  font-size: 13.5px;
  line-height: 1.5;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}
.aia-msg--user {
  align-self: flex-end;
  background: var(--color-primary);
  color: #fff;
}
.aia-msg--ai {
  align-self: flex-start;
  background: rgba(16, 16, 16, 0.05);
  color: rgba(16, 16, 16, 0.92);
}
.aia-msg.is-typing { color: var(--color-muted-light); font-style: italic; }
.aia-msg__link {
  display: inline-block;
  margin-top: 5px;
  color: var(--color-primary);
  font-weight: 600;
  text-decoration: underline;
}

/* ── Saisie ──────────────────────────────────────────────────────── */
.aia-card__form {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 12px;
  border-top: 1px solid rgba(16, 16, 16, 0.10);
}
.aia-card__input {
  flex: 1;
  min-width: 0;
  height: 38px;
  padding: 0 12px;
  border-radius: var(--radius-sm);
  border: 1px solid rgba(16, 16, 16, 0.16);
  background: #fff;
  color: var(--color-fg-light);
  font-family: var(--font-sans);
  font-size: 13.5px;
}
.aia-card__input::placeholder { color: rgba(71, 85, 105, 0.75); }
.aia-card__input:focus {
  outline: none;
  border-color: var(--color-primary);
  box-shadow: 0 0 0 3px rgba(220, 38, 38, 0.12);
}
.aia-card__send {
  flex: 0 0 auto;
  width: 38px; height: 38px;
  display: grid; place-items: center;
  border: 0;
  border-radius: var(--radius-sm);
  background: var(--color-primary);
  color: #fff;
  cursor: pointer;
  transition: background var(--duration-fast);
}
.aia-card__send:hover:not(:disabled) { background: var(--color-primary-hover); }
.aia-card__send:disabled { opacity: 0.55; cursor: not-allowed; }

/* ── Mention légale ──────────────────────────────────────────────── */
.aia-card__fine {
  margin: 0;
  padding: 0 14px 12px;
  font-size: 10.5px;
  line-height: 1.45;
  color: var(--color-muted-light);
}
.aia-card__privacy { color: var(--color-muted-light); text-decoration: underline; }
.aia-card__privacy:hover { color: var(--color-primary); }

/* ── Bouton de réouverture (carte réduite) ───────────────────────── */
/* Bouton reduit : plus de pastille navy ni de bordure, l'embleme anime flotte
   seul (2026-08-11). Il est aussi plus grand que la pastille precedente. */
.aia-reopen {
  position: fixed;
  right: clamp(10px, 1.4vw, 18px);
  bottom: clamp(10px, 1.4vw, 18px);
  z-index: var(--z-overlay);
  width: 92px; height: 92px;
  display: grid; place-items: center;
  padding: 0;
  border: 0;
  background: transparent;
  cursor: pointer;
  opacity: 0;
  pointer-events: none;
  transition: opacity 300ms var(--ease-out), transform var(--duration-fast) var(--ease-out);
}
.aia-min.aia-ready .aia-reopen { opacity: 1; pointer-events: auto; }
.aia-reopen:hover { transform: translateY(-2px); }
.aia-reopen__emblem { width: 100%; height: 100%; }
/* .aia-live = l'embleme anime, deplace entre l'en-tete de la carte et le bouton
   reduit par asha-agent.js. Il remplit son hote, quel qu'il soit. */
.aia-live { width: 100%; height: 100%; }

@media (max-width: 700px) {
  /* LES DEUX MARGES SONT POSEES, LA LARGEUR EN DECOULE — 2026-09-07.
     Gabriel : « la fenetre de ASHA agente IA depasse du cote gauche, il faut
     qu'elle rentre et qu'elle ait une marge comme a droite ».
     Avant : `right` fixe et `width: calc(100vw - 20px)`. La marge de gauche
     n'etait donc pas choisie, elle etait le reste d'une soustraction — mesuree
     a 11-12 px quand celle de droite en faisait 15-16. Un ecart de 4 px, mais
     visible parce que la carte est large et que l'oeil compare les deux bords.
     En posant `left` et `right` a la meme valeur et en laissant la largeur
     s'ajuster, les deux marges sont egales par construction, a toute largeur
     d'ecran. */
  .aia-card {
    left: clamp(12px, 1.6vw, 22px);
    width: auto;
  }
  .aia-card__body { max-height: 38vh; }
}
@media print {
  .aia-card, .aia-reopen { display: none !important; }
}
@media (prefers-reduced-motion: reduce) {
  .aia-card, .aia-reopen { transition: none; }
}

/* ═══════════════════════════════════════════════════════════════════
   Bandeau de confiance — logos clients, pleine largeur, juste sous le hero
   Casse volontairement le container (aucun .container) : ca se lit comme un
   bandeau de preuve et non comme une section de contenu. Les logos sources
   sont deja en monochrome sombre sur transparent : sur fond clair ils
   sortent naturellement, sans recoloration (marques deposees).
   Defilement : reutilise .marquee / .marquee__track deja eprouves sur le
   site (masque de fondu sur les bords, pause au survol, coupe si
   prefers-reduced-motion). Le jeu de 16 logos est duplique dans le HTML,
   la keyframe translate de 0 a -50 %.
   ═══════════════════════════════════════════════════════════════════ */
.trustband {
  background: var(--color-bg-light);
  padding: clamp(20px, 2.6vw, 34px) 0;
}
/* SUR TELEPHONE ELLE RESPIRE PLUS — 2026-09-07, demande de Gabriel :
   « augmente la taille de la bande blanche qui est juste apres la hero avec
   ces logos ». Le `clamp` ci-dessus la calait sur sa borne basse des que
   l'ecran descendait sous 770 px de large : 20 px de rembourrage, soit une
   bande de 72 px pour des logos de 32. Elle passait pour un filet plutot que
   pour une bande. 30 px de rembourrage la portent a 92 px, et les logos
   gagnent la meme proportion. */
@media (max-width: 760px) {
  .trustband { padding: 30px 0; }
  /* La taille des logos est posee en fin de feuille : voir le commentaire
     la-bas, elle doit passer APRES la regle d'origine. */
}
/* VITESSE — 110 s a l origine, portee a 85 s le 2026-09-06 a la demande de
   Gabriel (« augmenter un peu la vitesse a laquelle les logos defilent »).

   LA MESURE, parce que le commentaire d origine estimait mal la piste : elle
   fait 5247 px pour 30 logos, mais l animation ne translate que de -50 %,
   donc la COURSE reelle est de 2624 px, pas 5000.
     110 s -> 23,9 px/s   (l origine : un logo mettait dix secondes a parcourir
                           sa propre largeur, ce qui se lit comme un arret)
      85 s -> 30,9 px/s   (+29 %, retenu)
   Le pas suivant serait 75 s (35,0 px/s, +47 %) si c'est encore trop lent.
   Le garde-fou n'a pas bouge : la bande reste plus calme que le hero
   au-dessus, et elle se met toujours en pause au survol. */
.trustband .marquee__track {
  animation-duration: 85s;
  align-items: center;
  gap: clamp(30px, 4.2vw, 68px);
}
.trustband__row { list-style: none; margin: 0; padding: 0; }
.trustband__item {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
}
/* Calibrage par poids optique : les logos larges (Profuturo 6.8, Copa 5.9,
   Coppel et Banorte 4.9) sont plus bas, les logos carres (C5 1.0, Banxico 1.7,
   HDI 1.6) plus hauts, sinon la ligne parait desequilibree a hauteur egale. */
.trustband__item img {
  height: clamp(24px, 2.7vw, 38px);      /* ratio moyen (INE, Sura, AMIS...) */
  width: auto;
  max-width: 100%;
  object-fit: contain;
  filter: grayscale(100%);
  /* 0.72 : en monochrome, plus bas rendait les logos fantomatiques ; ils
     doivent se lire comme une preuve, pas comme un filigrane. */
  opacity: 0.72;
  transition: opacity var(--duration-normal) var(--ease-out);
}
.trustband__item--wide img { height: clamp(19px, 2.1vw, 30px); }
.trustband__item--sq   img { height: clamp(32px, 3.7vw, 50px); }
.trustband__item:hover img { opacity: 1; }

/* Sceaux de certification du hero : une seule plaque claire au lieu de trois
   pastilles separees, sur le meme fond que le bandeau de confiance
   (--color-bg-light). Les sceaux ISO/ATR sont des marques officielles livrees
   avec un fond blanc incruste (aucune transparence) : ils ne peuvent ni etre
   poses sur le navy ni etre recolorises. On harmonise donc par la surface. */
/* Ligne de certifications en texte. Elle remplace .hero__trust-seals, la plaque
   claire qui portait les trois sceaux : illisibles a 34 px par construction, et
   posant un bloc blanc a 20 px au-dessus du bandeau blanc des clients.
   Meme registre que le ticker de nosotros.html : mono, majuscules espacees,
   discret. Pas de fond, donc plus rien ne concurrence le bandeau. */
.hero__trust-line {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(226, 232, 240, 0.72);
}
.hero__trust-seals {
  display: inline-flex;
  align-items: center;
  gap: 16px;
  padding: 8px 15px;
  border-radius: var(--radius-md);
  background: var(--color-bg-light);
  border: 1px solid rgba(248, 250, 252, 0.18);
}
.hero__trust-seals .hero__trust-badge {
  padding: 0;
  background: none;
  border: 0;
  border-radius: 0;
}
.hero__trust-seals .hero__trust-badge img { height: 34px; }

/* Calibrage optique de la plaque de marques officielles : a hauteur egale, un
   sceau circulaire (ISO, ratio 1.0) parait minuscule a cote d'un logotype
   large (NIST et MITRE, ratio 3.7). Trois tailles. */
.hero__trust-badge--seal img { height: 34px !important; }
.hero__trust-badge--mid  img { height: 30px !important; }
.hero__trust-badge--wide img { height: 22px !important; }
.hero__trust-badge img { width: auto; }
/* Separateur : certifications a gauche, standards et marcos a droite */
.hero__trust-sep {
  width: 1px;
  align-self: stretch;
  margin: 2px 4px;
  background: rgba(16, 16, 16, 0.16);
}
@media (max-width: 700px) {
  .hero__trust-seals { flex-wrap: wrap; gap: 12px; }
  .hero__trust-sep { display: none; }
}

/* Logos des marcos de referencia (bloc « Marcos de referencia y estándares »).
   Section sur fond navy : les fichiers sont sombres sur transparent, donc on
   les passe en blanc (brightness(0) invert(1)). Le monochrome est le
   traitement standard et admis pour ces marques ; on ne leur invente jamais
   une couleur. Calibrage optique comme ailleurs. */
.frameworks__logos {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  /* Valeur generique, qui sert les pages AUTRES que nosotros. L'ecart de la
     section « Certificaciones » se regle plus bas, dans la declaration
     .page-nosotros #certificaciones : elle est plus specifique et gagne. */
  gap: clamp(24px, 3.2vw, 52px);
  margin-bottom: var(--space-6);
}
.framework-logo img {
  height: 26px;
  width: auto;
  filter: brightness(0) invert(1);
  opacity: 0.7;
  transition: opacity var(--duration-normal) var(--ease-out);
}
.framework-logo--wide img { height: 21px; }
.framework-logo--tall img { height: 30px; }
.framework-logo:hover img { opacity: 1; }


/* Plaque des sceaux desormais dans le flux du hero (a la place des chips) :
   plus de filet separateur ni de centrage, elle s'aligne a gauche comme le
   reste de la colonne. */
.hero__trust--inline {
  padding-top: 0;
  border-top: 0;
  margin-inline: 0;
  /* de l'air avant les boutons, sinon la plaque est collee au CTA rouge */
  margin-bottom: var(--space-6);
  justify-content: flex-start;
  max-width: none;
}

/* Ecrans peu hauts (1366x768, 1280x800...) : on resserre uniquement le padding,
   jamais la taille du titre, pour que le bandeau affleure la aussi. */
@media (min-width: 1024px) and (max-height: 830px) {
  .hero { padding-top: 44px !important; padding-bottom: 14px !important; }
}

/* Hero en petit ecran : l'image est cadree a droite, donc en portrait le
   recadrage « cover » amene l'embleme pile derriere le titre, et « ataques
   sofisticados » se retrouvait en rouge sur rouge, illisible. On recentre un
   peu et on met le visuel en retrait : il reste present comme ambiance, le
   texte redevient lisible. */
@media (max-width: 900px) {
  .hero__bg-img {
    object-position: 68% center;
    /* Recalibre le 2026-08-11 : ce 0,42 avait ete choisi quand l'image de fond
       etait OPAQUE, il retirait alors 58 %. Depuis que la base est passee a 0,55
       pour s'aligner sur les heros de nosotros/metodologia, 0,42 ne retirait
       presque plus rien et « ataques » se retrouvait a nouveau en rouge sur
       l'arche rouge du cadenas. On garde le meme retrait RELATIF. */
    opacity: 0.3;
  }
}

/* ── En-tete editorial (motif Palo Alto, 2026-08-11) ─────────── */
/* Titre a gauche sur deux lignes dont la seconde en accent, lien fleche a
   droite aligne sur la ligne de base. Le modificateur se pose PAR-DESSUS les
   en-tetes existants (.cases__head, .alliances__head) et neutralise leur
   centrage : une seule classe a retirer pour revenir en arriere.
   Ce bloc vit en FIN de fichier, obligatoirement : .cases__head et
   .alliances__head redefinissent text-align/max-width/margin plus bas dans le
   fichier, et a specificite egale c'est la derniere declaration qui gagne. */
.section-head--split {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--space-8);
  text-align: left;
  max-width: none;
  margin: 0 0 var(--space-12);
}
.section-head--split .section-lede {
  max-width: 640px;
  margin-left: 0;
}
/* L'ECHELLE PARTICULIERE EST RETIREE le 2026-08-18. Elle donnait a ce seul
   titre 66,2 px quand les sept autres de la home font 47,5, et une graisse de
   800 contre 700 — un titre sur huit qui ne suivait pas.
   Elle datait d'un moment ou ce bloc avait un traitement editorial a lui, calque
   sur les ~72 px de Palo Alto ; le reste du site a depuis converge sur
   clamp(26px, 3,3vw, 48px). On retire au lieu de recopier les bonnes valeurs :
   l'heritage donne le meme resultat sans un second endroit a maintenir.
   Cette classe n'a qu'un porteur dans tout le site, ce titre. */
.section-title .accent { color: var(--color-primary); }
.section-cta {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  flex-shrink: 0;
  /* La ligne de base du lien tombe sur celle du titre, comme chez Palo Alto :
     le lede sous le titre fait ~2 lignes, on compense pour rester a hauteur
     du bloc titre sans script. */
  margin-bottom: 6px;
  font-weight: 700;
  font-size: var(--text-base);
  color: var(--color-fg);
  text-decoration: none;
  white-space: nowrap;
}
.section-cta .icon {
  width: 20px; height: 20px;
  transition: transform var(--duration-normal) var(--ease-out);
}
.section-cta:hover { color: var(--color-primary); }
.section-cta:hover .icon { transform: translateX(4px); }
@media (max-width: 900px) {
  /* En colonne : le lien passe sous le lede, aligne a gauche. */
  .section-head--split { flex-direction: column; align-items: flex-start; }
  .section-cta { margin-bottom: 0; }
}

/* ── ¿Como lo hacemos? : layout Palo Alto (2026-08-11) ───────── */
/* Reference paloaltonetworks.fr/#why : titre editorial pleine largeur avec
   accent, puis kicker + declaration a gauche et anneaux de stats a droite.
   La capitana reste au centre, flanquee du message et des preuves.
   En fin de fichier pour la meme raison que .section-head--split : les regles
   historiques de .scene-hacked__* se redeclarent en cours de fichier. */
/* Pas de plafond de ligne ajoute sur .scene-hacked__lede malgre la colonne
   passee de 555 a 729 px : mesure faite, elle rend 61 caracteres par ligne, en
   plein dans la fourchette lisible. Le 56ch deja pose plus haut dans le fichier
   vaut 738 px avec cette police, il ne mord donc pas sur la colonne. */
.how-stats {
  /* Rangee centree sous la capitana : elle opere, les trois temps chiffrent son
     objectif, les deux forment une unite. Etait dans la colonne de texte tant
     que la section avait deux colonnes. */
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: flex-start;
  gap: clamp(20px, 4vw, 72px);
  margin-top: clamp(48px, 5vw, 72px);
  padding-top: clamp(32px, 3.4vw, 48px);
  border-top: 1px solid var(--color-border);
}
.how-stats__label {
  /* flex-basis 100 % : il occupe sa propre ligne au-dessus des trois anneaux.
     Centre comme tout le bloc depuis la refonte. */
  flex-basis: 100%;
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.14em;
  line-height: 1.5;
  text-transform: uppercase;
  color: var(--color-muted);
  margin: 0;
  text-align: center;
}
.ring-stat { text-align: center; flex: 0 1 auto; }
/* L'ARC SE DESSINE — 2026-08-21. Meme mecanique que .case-ring, et pour la
   meme raison : la transition vit sur le CONTENEUR, qui porte --fill, jamais
   sur l'enfant qui porte le degrade conique — pose sur l'enfant, elle n'a rien
   a interpoler.
   Ces trois cadrans etaient les seuls anneaux du site a s'afficher deja
   pleins : les anneaux des casos se dessinaient depuis le 14/08, ceux du
   1-10-60 non. Deux anneaux de meme facture, deux comportements, c'etait
   l'incoherence la plus visible du site.
   La duree monte a 1100 ms, contre 900 pour les casos : ici l'arc du premier
   cadran ne fait que 2 % du tour, et c'est justement l'argument — il lui faut
   le temps d'etre vu partir et s'arreter presque aussitot. */
.ring-stat { transition: --fill 1600ms var(--ease-out); }
@media (prefers-reduced-motion: reduce) {
  .ring-stat { transition: none; }
}
.ring-stat__dial-wrap {
  position: relative;
  display: block;
  width: clamp(104px, 7.4vw, 128px);
  aspect-ratio: 1;
  margin: 0 auto var(--space-3);
}
/* L'anneau est un conic-gradient evide par un masque radial : --fill donne le
   pourcentage d'arc rouge (50 -> demi-anneau, 100 -> plein), le reste en blanc
   discret, depart a 220deg comme la reference (la breche en haut a gauche). */
.ring-stat__dial {
  position: absolute; inset: 0;
  border-radius: 50%;
  background: conic-gradient(from 220deg,
    var(--color-primary) calc(var(--fill, 100) * 1%),
    rgba(248, 250, 252, 0.16) 0);
  /* Epaisseur de l'anneau reduite avec son diametre, pour garder la meme
     proportion visuelle qu'a 152 px. */
  -webkit-mask: radial-gradient(closest-side, transparent calc(100% - 11px), #000 calc(100% - 10px));
          mask: radial-gradient(closest-side, transparent calc(100% - 11px), #000 calc(100% - 10px));
}
.ring-stat__num {
  position: absolute; inset: 0;
  display: flex;
  /* flex-wrap indispensable : sans lui align-content n'a aucun effet et la
     ligne se colle au debut de l'axe, ce qui plaquait les chiffres en HAUT de
     l'anneau au lieu du centre. wrap + align-content: center centre la ligne,
     align-items: baseline aligne « min » sur la ligne de base du chiffre. */
  flex-wrap: wrap;
  align-content: center;
  align-items: baseline;
  justify-content: center;
  gap: 3px;
  line-height: 1;
  color: var(--color-fg);
}
.ring-stat__val {
  font-weight: 800;
  /* Reduit : a l'ancienne taille « 60min » depassait du cercle interieur, qui
     ne fait que le diametre moins deux fois l'epaisseur de l'anneau. */
  font-size: clamp(23px, 1.8vw, 30px);
  letter-spacing: -0.02em;
}
/* « min » en petit a cote du chiffre, comme le bandeau 1-10-60 deja present
   plus bas dans la page : meme lecture typographique aux deux endroits. */
.ring-stat__unit {
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: lowercase;
  color: var(--color-muted);
}
.ring-stat__sub {
  color: var(--color-primary);
  font-size: var(--text-base);
  font-weight: 700;
  letter-spacing: 0.02em;
  margin: 0;
}
.ring-stat__cap {
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--color-muted);
  line-height: 1.6;
  margin: 0;
}

/* Anneaux du 1-10-60 sur petit ecran. En flex, la largeur de chaque item est
   dictee par son plus large enfant, ici le libelle « investigación » a 108 px :
   3 x 106 + 2 x 18 depassait les 335 px disponibles en 375 px de viewport et le
   troisieme anneau tombait a la ligne (2 + 1, disgracieux).
   La grille a trois colonnes egales rend la contrainte independante du contenu :
   chaque item prend un tiers, le libelle se coupe si besoin. */
@media (max-width: 560px) {
  .how-stats {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 12px;
  }
  .how-stats__label { grid-column: 1 / -1; }
  .ring-stat__dial-wrap { width: min(88px, 100%); }
  /* Epaisseur du trait reduite avec le diametre, sinon l'anneau parait lourd. */
  .ring-stat__dial {
    -webkit-mask: radial-gradient(closest-side, transparent calc(100% - 9px), #000 calc(100% - 8px));
            mask: radial-gradient(closest-side, transparent calc(100% - 9px), #000 calc(100% - 8px));
  }
  .ring-stat__val { font-size: 21px; }
  .ring-stat__unit { font-size: 10px; }
  .ring-stat__sub { font-size: 13px; }
}

/* ── ¿Como lo hacemos? : en-tete centre (2026-08-11 au soir) ──── */
/* Calque sur .diferenciador__head, a la demande de Gabriel : cette section
   etait la seule de la home a poser son titre a droite d'une grille a deux
   colonnes. Memes valeurs que le modele pour que les deux en-tetes soient
   interchangeables a l'oeil. */
.how__head {
  max-width: 860px;
  margin: 0 auto var(--space-10);
  text-align: center;
}
.how__title {
  font-family: var(--font-sans);
  font-size: clamp(36px, 5vw, 56px);
  font-weight: 800;
  line-height: 1.05;
  letter-spacing: -0.02em;
  /* Plus de marge basse dans l'en-tete : il n'y a plus de lede en dessous. */
  margin: var(--space-3) 0 0;
  color: var(--color-fg);
}
.how__title .accent { color: var(--color-primary); font-weight: 800; }
/* .how__lede supprime : l'en-tete centre ne porte plus que l'eyebrow et le
   titre, les deux paragraphes vivent dans la colonne de droite avec les
   promesas, comme avant. */

/* Corps de la section, motif crowdstrike.com : le visuel a gauche, trois blocs
   de texte a droite. La reference les separe par de simples FILETS, sans cartes
   bordees, et c'est sa force : on la suit.
   0.85fr / 1.15fr : le texte porte plus de matiere que le visuel, il prend donc
   la colonne large. */
.how__body {
  display: grid;
  gap: clamp(40px, 5vw, 80px);
  align-items: center;
  position: relative;
  z-index: 3;
}
@media (min-width: 1024px) {
  .how__body { grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr); }
}
.how__visual { min-width: 0; }

/* Colonne de droite : les deux ledes puis les quatre promesas en 2 x 2, format
   d'origine rendu le 2026-08-11 au soir sur demande de Gabriel. Les classes
   .how-list / .how-item (trois blocs a gros titre, motif CrowdStrike) sont
   supprimees et non laissees mortes. */
.how__copy { min-width: 0; }
/* Echelle du texte montee le 2026-08-12 sur la reference crowdstrike.com « The
   Future of Security Starts Here », mesuree sur la capture 1920 : lede de
   section a 20 px, corps des items a 20 px, titres d'items a 40 px. Nos valeurs
   etaient de 18 px pour les ledes et surtout 14 px FIXES pour les promesas,
   nettement en dessous. Le titre de section reste a 56 px, deja au-dessus des
   48 px de la reference. */
.how__copy .scene-hacked__lede {
  font-size: clamp(18px, 1.45vw, 22px);
  line-height: 1.55;
}
.how__copy .promises--scene .promise {
  font-size: clamp(15px, 1.2vw, 19px);
  line-height: 1.45;
  padding: clamp(16px, 1.5vw, 22px) clamp(18px, 1.6vw, 24px);
  gap: clamp(12px, 1.1vw, 16px);
}
.how__copy .promises--scene .promise .icon {
  width: clamp(22px, 1.7vw, 26px);
  height: clamp(22px, 1.7vw, 26px);
}
.how__copy .promises--scene { gap: clamp(12px, 1.2vw, 18px); }
.how__copy .scene-hacked__lede:first-child { margin-top: 0; }
.promises--scene { margin-top: var(--space-7); }

/* ══════════════════════════════════════════════════════════════════════════
   EL PROBLEMA — la tension, ajoutee le 2026-08-12 (master prompt §10)
   ══════════════════════════════════════════════════════════════════════════
   Trois partis pris, tous mesurables sur la page :

   1. L'en-tete monte a 880 px au lieu des 760 px de .section-head, pour un
      titre de 52 caracteres. Rendu mesure a 880 px sur neuf largeurs : deux
      lignes de 1920 a 600 px, trois a 430, quatre a 320. Entre 1024 et 768 px
      la seconde ligne ne porte que « herramientas. », et c'est tres bien : le
      mot accentue tombe seul, ce qui est la chute cherchee. Un orphelin qui
      genererait, c'est un mot court et non signifiant (« de », « un ») isole,
      et il n'y en a a aucune largeur.

   2. Les six symptomes ne sont PAS des cartes. Une carte bordee sur quatre
      cotes est un objet ferme, fini, et le propos de la section est justement
      que rien n'est ferme ni fini. Un filet a gauche et rien d'autre : le
      fragment reste ouvert vers la droite.

   3. La bascule finale tire son emphase de son ISOLEMENT, pas de sa taille.
      Elle est a peine plus grande que le titre de section (64 contre 56 px de
      plafond) mais elle a une section a elle seule, un filet au-dessus et
      quatre-vingt-seize pixels de vide autour. Un titre deux fois plus gros
      aurait ecrase le titre de section, qui est le titre de la page.
*/
.problema__head { max-width: 880px; }

.symptoms {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(20px, 2vw, 32px) clamp(24px, 2.4vw, 44px);
  margin: 0;
  padding: 0;
  list-style: none;
}
/* Deux colonnes puis une seule. Bornes choisies pour que six items ne laissent
   jamais d'orphelin : 3x2 puis 2x3 puis 1x6. */
@media (max-width: 1100px) {
  .symptoms { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 640px) {
  .symptoms { grid-template-columns: minmax(0, 1fr); }
}

.symptom {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: start;
  gap: clamp(12px, 1.2vw, 18px);
  padding: clamp(4px, 0.6vw, 8px) 0 clamp(4px, 0.6vw, 8px) clamp(16px, 1.6vw, 24px);
  border-left: 2px solid rgba(220, 38, 38, 0.28);
  transition: border-color var(--duration-normal) var(--ease-out);
}
.symptom:hover { border-left-color: var(--color-primary); }

.symptom__idx {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: 500;
  letter-spacing: 0.08em;
  color: rgba(220, 38, 38, 0.75);
  /* Aligne la ligne de base du numero sur celle de la premiere ligne de texte.
     Sans ce decalage le numero flottait 3 px trop haut, le mono et le sans
     n'ayant pas la meme hauteur d'x. */
  padding-top: 0.28em;
}

.symptom__text {
  margin: 0;
  font-size: clamp(15px, 1.15vw, 18px);
  line-height: 1.5;
  color: var(--color-muted);
}

.problema__turn {
  margin-top: clamp(56px, 6vw, 96px);
  padding-top: clamp(28px, 3vw, 44px);
  border-top: 1px solid var(--color-border);
  text-align: center;
}
.problema__turn-label {
  margin: 0 0 clamp(12px, 1.2vw, 18px);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--color-muted);
}
.problema__turn-prompt { color: var(--color-primary); margin-right: 0.4em; }
.problema__turn-text {
  margin: 0;
  font-size: clamp(var(--text-3xl), 4.4vw, 64px);
  font-weight: 800;
  line-height: 1.05;
  letter-spacing: -0.02em;
}

/* ══════════════════════════════════════════════════════════════════════════
   EL SISTEMA DE DEFENSA — le diagramme, ajoute le 2026-08-12 (§11)
   ══════════════════════════════════════════════════════════════════════════
   Le parti pris qui fait tout tenir : le connecteur n'est PAS centre.

   Un diagramme hierarchique met d'ordinaire son trait au milieu. Ici les
   strates sont des bandes pleine largeur dont le contenu commence a gauche :
   un trait central aurait flotte dans le vide entre deux textes, sans relier
   quoi que ce soit visuellement. Le trait descend donc dans la colonne des
   numeros, chaque numero se posant dessus comme un noeud sur une ligne de vie.
   C'est le motif d'un schema d'architecture, et il a deux avantages concrets :
   il survit tel quel au passage en colonne sur mobile, et il donne aux sept
   niveaux une continuite que sept cartes empilees n'auraient pas eue.

   La hierarchie ne vient pas de la taille des bandes mais de leur traitement :
   sommet et chute encadres, commandement en rouge, socle en retrait. Trois
   bandes de socle volontairement plus discretes que les quatre autres, sinon
   le diagramme se lisait comme une liste de sept elements egaux.
*/
.defense-system__head { max-width: 900px; }

.layers {
  position: relative;
  --layers-rail: clamp(26px, 2.4vw, 34px);   /* axe du trait, depuis le bord */
}
/* La ligne de vie. Elle s'arrete a la premiere et a la derniere bande pour ne
   pas depasser dans le vide au-dessus du sommet ni sous la chute. */
.layers::before {
  content: '';
  position: absolute;
  left: var(--layers-rail);
  top: clamp(22px, 2vw, 30px);
  bottom: clamp(22px, 2vw, 30px);
  width: 1px;
  background: linear-gradient(
    to bottom,
    rgba(220, 38, 38, 0.5),
    rgba(255, 255, 255, 0.14) 22%,
    rgba(255, 255, 255, 0.14) 78%,
    rgba(220, 38, 38, 0.5)
  );
  pointer-events: none;
}

.layer {
  position: relative;
  display: grid;
  grid-template-columns: calc(var(--layers-rail) * 2) minmax(0, 1fr);
  align-items: center;
  gap: clamp(12px, 1.4vw, 20px);
  padding: clamp(14px, 1.5vw, 20px) clamp(16px, 1.6vw, 24px) clamp(14px, 1.5vw, 20px) 0;
}
.layer + .layer { margin-top: clamp(6px, 0.7vw, 10px); }

/* Le noeud : le numero est opaque et centre sur l'axe, il coupe donc la ligne
   proprement au lieu de se superposer a elle. */
.layer__idx {
  position: relative;
  z-index: 1;
  justify-self: center;
  padding: 6px 0;
  background: var(--color-bg);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: 500;
  letter-spacing: 0.06em;
  color: var(--color-muted);
  text-align: center;
}

.layer__body { min-width: 0; }
.layer__name {
  margin: 0;
  font-size: clamp(17px, 1.5vw, 22px);
  font-weight: 700;
  letter-spacing: -0.01em;
  line-height: 1.25;
}
.layer__note {
  margin: 4px 0 0;
  font-size: clamp(13px, 1vw, 15px);
  line-height: 1.5;
  color: var(--color-muted);
}
.layer__label {
  margin: 0 0 clamp(12px, 1.2vw, 16px);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--color-muted);
}

/* ── Encadrements : TOUJOURS sur le contenu, jamais sur la bande ─────────
   Corrige a la capture du 2026-08-12. Premiere version : la bande « La
   Capitana » portait un filet gauche rouge de 2 px et les bandes 01 et 07 un
   cadre complet. Trois defauts se voyaient d'un coup a 1440 px : le filet
   rouge tombait a 34 px de la ligne de vie, donc deux verticales rouges
   paralleles et desalignees ; les cadres de 01 et 07 englobaient l'axe alors
   que les autres bandes le laissaient dehors ; et la hierarchie se lisait donc
   selon trois grammaires differentes.
   Regle retenue : l'axe et ses noeuds a gauche, le contenu et son traitement a
   droite, sans jamais se croiser. La hierarchie d'une strate s'exprime SUR
   l'axe par la couleur de son numero, et a droite par le fond de son contenu. */
/* Le padding vertical passe au contenu : sans cette remise a zero il s'ajoute
   a celui de .layer et ces trois bandes deviennent une fois et demie plus
   hautes que celles du socle, ce qui fausse la hierarchie qu'on cherche. */
.layer--crown,
.layer--outcome,
.layer--command { padding-block: 0; }
.layer--crown .layer__body,
.layer--outcome .layer__body,
.layer--command .layer__body {
  border-radius: var(--radius-md);
  padding: clamp(13px, 1.4vw, 19px) clamp(18px, 1.8vw, 26px);
}
.layer--crown .layer__body,
.layer--outcome .layer__body {
  border: 1px solid var(--color-border-strong);
  background: rgba(255, 255, 255, 0.02);
}
.layer--crown .layer__name { font-size: clamp(19px, 1.8vw, 26px); }
.layer--crown .layer__idx { color: rgba(248, 250, 252, 0.72); }

.layer--outcome .layer__body {
  border-color: rgba(220, 38, 38, 0.45);
  background: rgba(220, 38, 38, 0.05);
}
.layer--outcome .layer__name { color: var(--color-primary); }
.layer--outcome .layer__idx { color: var(--color-primary); }

/* Commandement : pas de filet, seulement un fond qui s'eteint vers la droite.
   Le rouge du nom et celui du noeud suffisent — il n'y a qu'un chef, on n'a pas
   besoin de trois signaux pour le dire. */
.layer--command .layer__body {
  background: linear-gradient(90deg, rgba(220, 38, 38, 0.12), transparent 72%);
}
.layer--command .layer__name { color: var(--color-primary); }
.layer--command .layer__idx { color: var(--color-primary); }

/* ── Socle : en retrait, pour que sept bandes ne fassent pas une liste ─── */
.layer--base { padding-block: clamp(10px, 1.1vw, 14px); }
.layer--base .layer__name {
  font-size: clamp(15px, 1.25vw, 18px);
  font-weight: 600;
  color: rgba(248, 250, 252, 0.88);
}

/* ── Les cinq frentes ───────────────────────────────────────────────────── */
.fronts {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: clamp(8px, 0.9vw, 14px);
  margin: 0;
  padding: 0;
  list-style: none;
}
.front {
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding: clamp(10px, 1.1vw, 15px) clamp(10px, 1.1vw, 16px);
  border: 1px solid var(--color-border);
  border-top: 2px solid var(--persona, var(--color-muted));
  border-radius: var(--radius-sm);
  background: var(--color-surface);
  transition: border-color var(--duration-normal) var(--ease-out),
              transform var(--duration-normal) var(--ease-out);
}
.front:hover {
  transform: translateY(-2px);
  border-color: var(--persona, var(--color-border-strong));
}
.front__name {
  font-size: clamp(13px, 1.1vw, 16px);
  font-weight: 700;
  line-height: 1.2;
  color: var(--persona, var(--color-fg));
}
.front__verb {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--color-muted);
}
/* Chaque pastille EST son persona : c'est le contexte que le design system
   autorise pour ces cinq couleurs. Elles ne sortent pas de cette liste. */
.front[data-persona="ctem"]      { --persona: var(--color-ctem); }
.front[data-persona="ngsoc"]     { --persona: var(--color-ngsoc); }
.front[data-persona="csirt"]     { --persona: var(--color-csirt); }
.front[data-persona="zerotrust"] { --persona: var(--color-zerotrust); }
.front[data-persona="grc"]       { --persona: var(--color-grc); }

/* ── Recomposition. Les frentes passent a 3 puis 2 colonnes ; les bandes
      gardent leur structure numero + contenu, qui tient jusqu'a 320 px. ─── */
@media (max-width: 900px) {
  .fronts { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@media (max-width: 560px) {
  .fronts { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .layers { --layers-rail: 22px; }
  .layer { gap: 10px; }
}

/* ══════════════════════════════════════════════════════════════════════════
   LA LIGA — le commandement sorti de la grille, 2026-08-12 (§3, §5, §12)
   ══════════════════════════════════════════════════════════════════════════
   La capitana etait la sixieme carte d'une grille de six : meme largeur, meme
   hauteur, meme traitement que les frentes qu'elle orchestre. La page
   contredisait le discours. Elle passe en bandeau horizontal pleine largeur
   AU-DESSUS de la grille.

   Les cinq frentes n'ont eu besoin d'aucune regle de colonnes : la classe de
   base .practices__grid passe deja a cinq colonnes au-dela de 1100 px, et
   c'etait le variant --met qui la forcait a trois pour loger six cartes. Le
   retirer suffit, et cinq colonnes alignees rappellent la strate 03 du
   diagramme juste au-dessus. On ajoute seulement un palier a trois colonnes
   entre 860 et 1099 px, sans quoi cinq cartes en deux colonnes donnaient trois
   rangees dont une orpheline.
*/
/* MODIFICATEUR AUJOURD'HUI INEMPLOYE — note du 2026-08-14.
   .practice--command mettait la carte de La Capitana en banniere pleine
   largeur, portrait a gauche et corps a droite. Depuis que les six cartes
   sont « misma talla » dans .practices__grid--six, la classe est retiree du
   HTML : plus aucune page ne la porte. Les regles restent, elles decrivent
   une banniere qui fonctionne, mais ne rien y changer en croyant agir sur la
   home. Le signal de rang de la Capitana passe desormais par la regle de
   bordure en fin de fichier. */
.practice--command {
  display: grid;
  grid-template-columns: clamp(190px, 21vw, 300px) minmax(0, 1fr);
  align-items: center;
  gap: clamp(18px, 2.2vw, 40px);
  margin-bottom: clamp(14px, 1.6vw, 24px);
  border-color: rgba(220, 38, 38, 0.35);
}
.practice--command:hover { border-color: var(--color-primary); }
.practice--command .practice__hero {
  height: clamp(210px, 23vw, 300px);
  margin: 0;
}
.practice__command-body {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: clamp(8px, 0.9vw, 14px);
  min-width: 0;
}
.practice__rank {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--color-primary);
}
.practice--command .practice__title {
  font-size: clamp(20px, 2vw, 30px);
  line-height: 1.15;
}
.practice--command .practice__desc {
  max-width: 62ch;   /* la mesure de lecture, pas la largeur du bloc */
  font-size: clamp(14px, 1.1vw, 17px);
}
.practice--command .practice__chips { justify-content: flex-start; }

/* Sous 720 px le bandeau s'empile : le portrait passe au-dessus du texte,
   comme les cartes de la grille. */
@media (max-width: 719px) {
  .practice--command {
    grid-template-columns: minmax(0, 1fr);
    gap: var(--space-4);
  }
  .practice--command .practice__hero { height: 240px; }
}

@media (min-width: 860px) and (max-width: 1099px) {
  .practices__grid--fronts { grid-template-columns: repeat(3, 1fr); }
}

/* ══════════════════════════════════════════════════════════════════════════
   DE LA ESTRATEGIA A LA OPERACIÓN — ajoutee le 2026-08-12 (§15)
   ══════════════════════════════════════════════════════════════════════════
   Les quatre capacites sont numerotees et separees par de simples filets, sans
   cartes : la section qui les suit (les cas) et celle qui les precede (la Liga)
   sont deja tres cartonnees, en ajouter une troisieme grille de cartes aurait
   donne trois murs de rectangles a la file.

   La frise en six temps est une seule ligne horizontale avec six noeuds. Le
   trait est un fond de la LISTE et non une bordure des items, pour qu'il ne se
   coupe pas entre les etapes. En dessous de 900 px elle bascule en colonne, le
   trait passant a la verticale : c'est le meme dispositif que la ligne de vie
   du diagramme, ce qui fait que les deux schemas de la page se lisent pareil.
*/
.operacion__head { max-width: 840px; }

.caps {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: clamp(20px, 2.2vw, 40px);
  margin: 0 0 clamp(48px, 5vw, 80px);
  padding: 0;
  list-style: none;
}
@media (max-width: 1024px) { .caps { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 560px)  { .caps { grid-template-columns: minmax(0, 1fr); } }

.cap {
  padding-top: clamp(14px, 1.4vw, 20px);
  border-top: 1px solid var(--color-border-strong);
}
.cap__idx {
  display: block;
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: 500;
  letter-spacing: 0.08em;
  color: var(--color-primary);
}
.cap__title {
  margin: clamp(8px, 0.9vw, 12px) 0 clamp(6px, 0.7vw, 10px);
  font-size: clamp(17px, 1.5vw, 22px);
  font-weight: 700;
  letter-spacing: -0.01em;
}
.cap__text {
  margin: 0;
  font-size: clamp(14px, 1.05vw, 16px);
  line-height: 1.55;
  color: var(--color-muted);
}

/* ── La frise ───────────────────────────────────────────────────────────── */
.flow__label {
  margin: 0 0 clamp(18px, 1.8vw, 26px);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--color-muted);
}
.flow__prompt { color: var(--color-primary); margin-right: 0.4em; }

.flow__steps {
  position: relative;
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: clamp(8px, 1vw, 16px);
  margin: 0;
  padding: 0;
  list-style: none;
  counter-reset: none;
}
/* Le trait appartient a la liste, pas aux items : une bordure par item se
   serait interrompue a chaque gouttiere. Il s'arrete au centre du premier et du
   dernier noeud, calcule depuis la largeur d'une colonne. */
.flow__steps::before {
  content: '';
  position: absolute;
  top: 5px;
  left: calc(100% / 12);
  right: calc(100% / 12);
  height: 1px;
  background: linear-gradient(90deg,
    var(--color-primary),
    rgba(255, 255, 255, 0.16) 30%,
    rgba(255, 255, 255, 0.16) 70%,
    var(--color-primary));
}
.flow__step {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(10px, 1vw, 16px);
  font-size: clamp(13px, 1.05vw, 16px);
  font-weight: 600;
  text-align: center;
  color: var(--color-fg);
}
.flow__dot {
  width: 11px;
  height: 11px;
  border-radius: var(--radius-full);
  background: var(--color-bg);
  border: 2px solid var(--color-primary);
}
/* Les quatre etapes du milieu en noeuds neutres : le rouge marque l'entree et
   la sortie du cycle, pas chacun de ses temps. */
.flow__step:not(:first-child):not(:last-child) .flow__dot {
  border-color: rgba(255, 255, 255, 0.28);
}

@media (max-width: 900px) {
  .flow__steps {
    grid-template-columns: minmax(0, 1fr);
    gap: clamp(14px, 2vw, 20px);
  }
  .flow__steps::before {
    top: 6px;
    bottom: 6px;
    left: 5px;
    right: auto;
    width: 1px;
    height: auto;
    background: linear-gradient(180deg,
      var(--color-primary),
      rgba(255, 255, 255, 0.16) 30%,
      rgba(255, 255, 255, 0.16) 70%,
      var(--color-primary));
  }
  .flow__step {
    flex-direction: row;
    align-items: center;
    gap: clamp(14px, 2vw, 20px);
    text-align: left;
  }
}

/* ══════════════════════════════════════════════════════════════════════════
   ¿QUÉ NECESITA RESOLVER? — les solutions par le besoin, 2026-08-12 (§12, §30)
   ══════════════════════════════════════════════════════════════════════════
   Ces cartes doivent se distinguer au premier coup d'oeil des trading cards de
   la Liga qui les suivent, sinon le visiteur croit voir deux fois la meme
   grille. Trois differences volontaires : pas de portrait, une etiquette de
   methodologie en tete au lieu d'un numero, et un fond de surface plein la ou
   les cartes de la Liga posent leur personnage sur le plateau noir.

   L'ordre de lecture dans la carte porte l'argument du §3 : le BESOIN en gros,
   la methodologie en petit au-dessus comme une reponse, et l'action en bas.
   La couleur persona ne teinte que l'etiquette et le filet superieur — le titre
   reste blanc, parce que c'est le probleme du client qu'on met en avant, pas
   notre nomenclature.
*/
.needs__grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(14px, 1.4vw, 22px);
  margin: 0;
  padding: 0;
  list-style: none;
}
@media (max-width: 1024px) { .needs__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 620px)  { .needs__grid { grid-template-columns: minmax(0, 1fr); } }

.need { display: flex; }
.need__link {
  display: flex;
  flex-direction: column;
  gap: clamp(8px, 0.9vw, 12px);
  width: 100%;
  padding: clamp(20px, 2vw, 30px) clamp(20px, 2vw, 28px);
  border: 1px solid var(--color-border);
  border-top: 2px solid var(--persona, var(--color-primary));
  border-radius: var(--radius-md);
  background: var(--color-surface);
  color: inherit;
  text-decoration: none;
  transition: border-color var(--duration-normal) var(--ease-out),
              transform var(--duration-normal) var(--ease-out),
              background var(--duration-normal) var(--ease-out);
}
.need__link:hover {
  transform: translateY(-3px);
  border-color: var(--persona, var(--color-primary));
  background: var(--color-surface-elev);
}
.need__method {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--persona, var(--color-primary));
}
.need__title {
  margin: 0;
  font-size: clamp(18px, 1.6vw, 24px);
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: -0.01em;
}
.need__text {
  margin: 0;
  flex: 1;
  font-size: clamp(14px, 1.05vw, 16px);
  line-height: 1.55;
  color: var(--color-muted);
}
.need__cta {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-top: clamp(6px, 0.7vw, 10px);
  font-size: clamp(13px, 1vw, 15px);
  font-weight: 600;
  color: var(--color-fg);
}
.need__cta .icon {
  width: 16px;
  height: 16px;
  transition: transform var(--duration-fast) var(--ease-out);
}
.need__link:hover .need__cta { color: var(--persona, var(--color-primary)); }
.need__link:hover .need__cta .icon { transform: translateX(3px); }

.need[data-persona="ngsoc"]     { --persona: var(--color-ngsoc); }
.need[data-persona="ctem"]      { --persona: var(--color-ctem); }
.need[data-persona="csirt"]     { --persona: var(--color-csirt); }
.need[data-persona="zerotrust"] { --persona: var(--color-zerotrust); }
.need[data-persona="grc"]       { --persona: var(--color-grc); }
.need[data-persona="asha"]      { --persona: var(--color-primary); }

/* Vague 2 (§8) : la ligne de support du hero, sous le sous-titre. Corps plus
   petit et couleur attenuee — c'est la phrase qui explique, pas celle qui
   frappe, et elle ne doit pas concurrencer « Los que rebasan las herramientas
   convencionales » juste au-dessus. */
.hero__support {
  max-width: 58ch;
  margin: clamp(10px, 1vw, 16px) 0 0;
  font-size: clamp(14px, 1.05vw, 17px);
  line-height: 1.55;
  color: var(--color-muted);
}

/* Le septieme symptome (§10 de la vague 2 : la pression reglementaire) fait
   passer la grille de six a sept, et sept est un nombre ingrat : en trois
   colonnes il laisse un orphelin. On ouvre donc un palier a quatre colonnes
   au-dela de 1400 px, ou 4 + 3 se repartit proprement. En dessous l'orphelin
   est assume : ce sont des fragments de texte a filet, pas des cartes, et une
   place vide y est nettement moins visible. */
@media (min-width: 1400px) {
  .symptoms { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

/* ==================================================================
   METODOLOGIA — systeme de contraste par bandes  (2026-08-12)
   Ajoute en FIN de fichier : plusieurs selecteurs de ce fichier sont
   declares jusqu'a quatre fois et, a specificite egale, la derniere
   declaration gagne. Les classes .method* sont neuves : aucune collision
   avec .persona-deep* (que cette page n'utilise plus).

   Doctrine complete et ratios mesures :
     design-system/asha-solution/CONTRASTE.md

   Trois regles portent tout le systeme :
   1. L'ENCRE SUIT LE SOL IMMEDIAT, pas la section. Un aplat clair pose dans
      une bande sombre reprend les encres de fond clair.
   2. La couleur persona pure est une couleur d'APLAT et de FILET. En TEXTE
      elle n'est utilisee que dans la variante conforme au sol (-ink / -lift).
   3. Deux bandes voisines ne partagent jamais leur sol. L'alternance est
      claire / sombre, jamais sombre / sombre : mesure, #101010 contre
      #05070D ne vaut que 1,06:1, donc --color-plate ne peut PAS servir de
      bande contrastante, seulement de creux imbrique.
   ================================================================== */

/* ------------------------------------------------------------------
   1. MENU SECONDAIRE DE PAGE  (.subnav)
   Empile sous le header : top = --header-h. Le fond reste navy quelle que
   soit la bande dessous, sinon la barre clignoterait a chaque frontiere.
   ------------------------------------------------------------------ */

.subnav {
  position: sticky;
  top: var(--header-h);
  /* sous le header (100) mais au-dessus du contenu et des aplats */
  z-index: 90;
  background: rgba(16, 16, 16, 0.94);
  backdrop-filter: saturate(160%) blur(12px);
  -webkit-backdrop-filter: saturate(160%) blur(12px);
  border-bottom: 1px solid var(--color-border);
  /* la barre garde une hauteur stable : le soulignement actif est pose en
     inset, il ne pousse rien */
  height: var(--subnav-h);
}
.subnav__inner {
  position: relative;
  height: 100%;
}
/* La piste defilante. overflow-x auto seulement quand c'est necessaire ;
   les masques de bord ci-dessous annoncent qu'il reste du contenu, pour ne
   jamais tronquer en silence. */
.subnav__track {
  height: 100%;
  display: flex;
  align-items: stretch;
  gap: clamp(2px, 0.6vw, 10px);
  margin: 0;
  padding: 0;
  list-style: none;
  overflow-x: auto;
  overflow-y: hidden;
  scroll-snap-type: x proximity;
  scrollbar-width: none;
  -ms-overflow-style: none;
  overscroll-behavior-x: contain;
  /* le clavier doit pouvoir defiler la piste */
  scroll-behavior: smooth;
}
.subnav__track::-webkit-scrollbar { display: none; }

.subnav__item { flex: 0 0 auto; scroll-snap-align: center; }

.subnav__link {
  position: relative;
  display: flex;
  align-items: center;
  gap: 8px;
  height: 100%;
  /* 44px de haut minimum garanti par --subnav-h (54/60) */
  padding-inline: clamp(8px, 1vw, 16px);
  color: var(--color-muted);
  font-size: clamp(12px, 0.85vw, 13.5px);
  font-weight: 600;
  letter-spacing: 0.02em;
  white-space: nowrap;
  transition: color var(--duration-fast) var(--ease-out);
}
.subnav__link .icon {
  width: 17px;
  height: 17px;
  flex-shrink: 0;
  color: var(--color-muted);
  opacity: 0.75;
  transition: color var(--duration-fast) var(--ease-out),
              opacity var(--duration-fast) var(--ease-out);
}
/* Le role ("Proteger", "Detectar"...) : deuxieme ligne de sens, coupee des
   que la place manque. Ce n'est pas de la troncature muette, c'est un niveau
   d'information secondaire qui s'efface avant le libelle. */
.subnav__role {
  font: 600 10px/1 var(--font-mono);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--color-muted);
  opacity: 0.55;
  padding-left: 8px;
  margin-left: 2px;
  border-left: 1px solid var(--color-border-strong);
}
/* Le soulignement : 3e signal de l'etat actif. Pose en absolu pour ne pas
   deplacer le texte quand il apparait. */
.subnav__link::after {
  content: '';
  position: absolute;
  left: clamp(8px, 1vw, 16px);
  right: clamp(8px, 1vw, 16px);
  bottom: 0;
  height: 3px;
  border-radius: 2px 2px 0 0;
  background: var(--persona, var(--color-primary));
  transform: scaleX(0);
  transform-origin: 50% 100%;
  transition: transform var(--duration-normal) var(--ease-out);
}
.subnav__link:hover { color: var(--color-fg); }
.subnav__link:hover .icon { opacity: 1; color: var(--persona-lift, var(--persona)); }
.subnav__link:hover::after { transform: scaleX(0.4); }

/* Etat actif : TROIS signaux simultanes, comme sur la reference.
   1. texte blanc en gras  2. icone dans la couleur persona  3. filet epais */
.subnav__link.is-active {
  color: var(--color-fg);
  font-weight: 700;
}
.subnav__link.is-active .icon {
  color: var(--persona-lift, var(--persona));
  opacity: 1;
  /* halo tres discret, il aide l'argent et le violet a decoller du navy */
  filter: drop-shadow(0 0 6px color-mix(in srgb, var(--persona-lift, var(--persona)) 45%, transparent));
}
.subnav__link.is-active::after { transform: scaleX(1); }
.subnav__link.is-active .subnav__role {
  color: var(--persona-lift, var(--persona));
  opacity: 0.9;
}
.subnav__link:focus-visible {
  outline: 2px solid var(--persona-lift, var(--color-ring));
  outline-offset: -3px;
  border-radius: 4px;
}

/* Masques de bord : n'apparaissent que si la piste deborde reellement,
   pilotes par les classes posees depuis method-nav.js. */
.subnav__inner::before,
.subnav__inner::after {
  content: '';
  position: absolute;
  top: 0;
  bottom: 0;
  width: 40px;
  pointer-events: none;
  opacity: 0;
  transition: opacity var(--duration-normal) var(--ease-out);
  z-index: 2;
}
.subnav__inner::before {
  left: 0;
  background: linear-gradient(90deg, rgba(16, 16, 16,0.98) 0%, rgba(16, 16, 16,0) 100%);
}
.subnav__inner::after {
  right: 0;
  background: linear-gradient(270deg, rgba(16, 16, 16,0.98) 0%, rgba(16, 16, 16,0) 100%);
}
.subnav.has-scroll-start .subnav__inner::before { opacity: 1; }
.subnav.has-scroll-end   .subnav__inner::after  { opacity: 1; }

/* Au-dela de 1180 px les six entrees tiennent sans defilement : on centre. */
@media (min-width: 1180px) {
  .subnav__track { justify-content: center; overflow-x: visible; }
}
/* Le role disparait avant le libelle. */
@media (max-width: 1319px) {
  .subnav__role { display: none; }
}
/* Sous 420 px l'icone seule ne suffirait pas (nav-label-icon) : on garde le
   libelle et on assume le defilement horizontal, annonce par les masques. */
@media (max-width: 420px) {
  .subnav__link { gap: 6px; padding-inline: 10px; }
  .subnav__link .icon { width: 15px; height: 15px; }
}
@media (prefers-reduced-motion: reduce) {
  .subnav__track { scroll-behavior: auto; }
  .subnav__link::after { transition: none; }
}

/* Les ancres doivent se poser SOUS les deux barres collantes.
   UNE seule compensation, sur les cibles : scroll-padding-top sur la racine
   PLUS scroll-margin-top sur la cible s'additionnent (mesure : 288 px de
   decalage au lieu de 144). On garde scroll-margin-top, qui ne depend pas de
   :has() et se comporte donc pareil sur tous les navigateurs. */
.method,
#liga-deep-title,
#acreditaciones,
#acompanamiento,
#contacto {
  scroll-margin-top: calc(var(--header-h) + var(--subnav-h) + 12px);
}

/* TOUTE SECTION D'ANCRE, ET PLUS UNE LISTE D'IDENTIFIANTS. La regle ci-dessus
   ne couvrait que les cibles de metodologia ; celles de la home et de nosotros
   avaient un scroll-margin de 0, si bien qu'un clic dans le sous-menu posait la
   section sous les barres collantes et coupait son surtitre — 52 px a 1440,
   jusqu'a 72 px a 768, mesures sur les quatorze ancres des deux pages.
   Tenir une liste d'ids est precisement ce qui a produit ce defaut : le
   selecteur vise donc toute section portant un id. La propriete ne fait rien
   tant qu'on ne defile pas vers la cible, l'elargir ne coute donc rien.
   PAS DE SUPPLEMENT DE 12 PX ICI : le padding-top de la section — 96 px a 1440,
   64 a 768 — donne deja l'air au-dessus du surtitre. En ajouter reviendrait a
   compter deux fois le meme espace et poserait le surtitre plus bas que lorsque
   le lecteur arrive en defilant. */
main > section[id] {
  scroll-margin-top: calc(var(--header-h) + var(--subnav-h, 0px));
}


/* ------------------------------------------------------------------
   2. LES SIX BANDES  (.method)
   Chaque methodologie est une <section> pleine largeur avec son propre sol.
   Les variables --band-* et --plate-* sont les seules choses que les deux
   variantes de bande redefinissent : tout le reste du composant s'y adosse.
   ------------------------------------------------------------------ */

.method {
  position: relative;
  isolation: isolate;
  background: var(--band-bg);
  color: var(--band-fg);
  padding-block: clamp(56px, 7vw, 104px);
  overflow: clip;
}

/* Bande SOMBRE : encre persona = variante -lift (texte sur navy),
   aplat inverse = clair. */
.method--dark {
  --band-bg: var(--color-bg);
  --band-fg: var(--color-fg);
  --band-muted: var(--color-muted);
  --band-rule: rgba(255, 255, 255, 0.12);
  --band-rule-soft: rgba(255, 255, 255, 0.07);
  --ink: var(--persona-lift);
  /* #F8FAFC et pas #F1F5F9 : les variantes -ink sont calculees contre
     #F8FAFC exactement. Sur un aplat un cran plus sombre, les six encres
     tombaient a 4,31-4,35:1, sous le seuil AA. Mesure, corrigee. */
  --plate-bg: var(--color-bg-light);
  --plate-fg: var(--color-fg-light);
  --plate-muted: var(--color-muted-light);
  --plate-rule: rgba(16, 16, 16, 0.12);
  --plate-ink: var(--persona-ink);   /* l'aplat est CLAIR : encre de fond clair */
}
/* Bande CLAIRE : encre persona = variante -ink (texte sur #F8FAFC),
   aplat inverse = navy. */
.method--light {
  --band-bg: var(--color-bg-light);
  --band-fg: var(--color-fg-light);
  --band-muted: var(--color-muted-light);
  --band-rule: var(--color-border-light);
  --band-rule-soft: rgba(16, 16, 16, 0.08);
  --ink: var(--persona-ink);
  --plate-bg: var(--color-bg);
  --plate-fg: var(--color-fg);
  --plate-muted: var(--color-muted);
  --plate-rule: rgba(255, 255, 255, 0.12);
  --plate-ink: var(--persona-lift);  /* l'aplat est SOMBRE : encre de navy */
}

/* Couleurs par persona. --persona = couleur pure (aplats, filets, auras).
   --persona-ink / -lift = les deux seules encres autorisees en texte. */
.method[data-persona="asha"],      .subnav__link[data-persona="asha"]      { --persona: var(--color-primary);   --persona-ink: var(--color-primary-ink);   --persona-lift: var(--color-primary-lift); --persona-on: var(--color-fg); }
.method[data-persona="ctem"],      .subnav__link[data-persona="ctem"]      { --persona: var(--color-ctem);      --persona-ink: var(--color-ctem-ink);      --persona-lift: var(--color-ctem);      --persona-on: var(--color-fg-light); }
.method[data-persona="ngsoc"],     .subnav__link[data-persona="ngsoc"]     { --persona: var(--color-ngsoc);     --persona-ink: var(--color-ngsoc-ink);     --persona-lift: var(--color-ngsoc);     --persona-on: var(--color-fg-light); }
.method[data-persona="csirt"],     .subnav__link[data-persona="csirt"]     { --persona: var(--color-csirt);     --persona-ink: var(--color-csirt-ink);     --persona-lift: var(--color-csirt);     --persona-on: var(--color-fg-light); }
.method[data-persona="zerotrust"], .subnav__link[data-persona="zerotrust"] { --persona: var(--color-zerotrust); --persona-ink: var(--color-zerotrust-ink); --persona-lift: var(--color-zerotrust); --persona-on: var(--color-fg-light); }
.method[data-persona="grc"],       .subnav__link[data-persona="grc"]       { --persona: var(--color-grc);       --persona-ink: var(--color-grc-ink);       --persona-lift: var(--color-grc);       --persona-on: var(--color-fg-light); }

/* Signature chromatique de la bande : un filet epais en haut, dans la
   couleur pure. Volontairement PAS de lavis degrade : le contraste doit venir
   de la couleur et de l'inversion, un halo pose sur du papier ne fait que le
   salir. Il ne subsiste donc qu'un halo de BANDE SOMBRE, et pour une raison
   mesuree : contre le navy les six figures ne valent que 1,49 a 2,60:1, elles
   ont besoin d'etre decollees du fond. Sur papier elles valent 6,99 a 12,98:1
   et n'ont besoin de rien. */
.method::before {
  content: '';
  position: absolute;
  inset-inline: 0;
  top: 0;
  height: 4px;
  background: var(--persona);
  z-index: 2;
}
.method--dark::after {
  content: '';
  position: absolute;
  z-index: 0;
  top: -8%;
  width: min(50vw, 720px);
  aspect-ratio: 1;
  border-radius: 50%;
  background: radial-gradient(circle at center,
              color-mix(in srgb, var(--persona) 18%, transparent) 0%,
              transparent 66%);
  pointer-events: none;
  opacity: 0.8;
}
.method--dark.method--media-start::after { left: -14vw; }
.method--dark.method--media-end::after   { right: -14vw; }

.method > .container { position: relative; z-index: 1; }

/* --- 2a. Le bandeau de titre, pleine largeur --------------------- */

.method__head {
  display: grid;
  grid-template-columns: auto 1fr;
  align-items: end;
  gap: clamp(16px, 2.5vw, 32px);
  padding-bottom: clamp(16px, 2vw, 24px);
  border-bottom: 2px solid var(--persona);
  margin-bottom: clamp(32px, 4vw, 56px);
}
/* Le numero d'ordre : un APLAT plein de la couleur persona, pas un chiffre
   fantome. C'est le bloc de couleur saturee de la bande, et le seul endroit ou
   la couleur pure porte du texte — d'ou --persona-on, calcule pour ca :
   navy sur argent 15,42 · cyan 7,83 · vert 8,34 · orange 6,78 · violet 4,80,
   et blanc sur rouge 4,62 (le rouge est le seul assez sombre pour renverser
   la regle). Reperage editorial, jamais une metrique. */
.method__index {
  display: grid;
  place-items: center;
  min-width: clamp(64px, 8vw, 108px);
  padding: clamp(10px, 1.2vw, 18px) clamp(12px, 1.4vw, 20px);
  border-radius: var(--radius-md);
  background: var(--persona);
  color: var(--persona-on);
  font: 800 clamp(30px, 4vw, 54px)/0.9 var(--font-mono);
  letter-spacing: -0.04em;
  font-variant-numeric: tabular-nums;
  align-self: end;
}
.method__head-text { min-width: 0; }
/* La ligne a tres large interlettrage : c'est ICI qu'elle vit, en mono et en
   petit corps. A 76 px un tracking de 0,2em dechirerait le mot et
   deborderait a 320 px — mesure, "ZEROTRUST" y gagnerait 126 px. */
.method__role {
  margin: 0 0 clamp(6px, 0.8vw, 12px);
  font: 700 clamp(10px, 0.8vw, 12px)/1.2 var(--font-mono);
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--ink);
}
.method__name {
  margin: 0;
  font-size: clamp(30px, 5.2vw, 68px);
  font-weight: 800;
  line-height: 0.95;
  letter-spacing: 0.005em;   /* les capitales demandent un peu d'air, pas 0,2em */
  text-transform: uppercase;
  color: var(--band-fg);
  overflow-wrap: break-word;
}

/* --- 2b. Le corps : deux colonnes, personnage et contenu -------- */

.method__body {
  display: grid;
  gap: clamp(28px, 4vw, 64px);
  align-items: start;
}
@media (min-width: 920px) {
  .method__body {
    /* colonne etroite = le personnage, colonne large = le contenu */
    grid-template-columns: minmax(230px, 0.72fr) minmax(0, 1.28fr);
    /* les deux colonnes se centrent l'une sur l'autre : la figure fait
       480 px de haut, la colonne de contenu entre 380 et 620 px selon le
       nombre de points, les caler en haut laissait un vide sous la plus
       courte des deux. */
    align-items: center;
  }
  /* L'alternance : le personnage passe a droite une section sur deux.
     PLACEMENT EXPLICITE, pas `order` : avec order, les items changent de
     place mais les PISTES restent ou elles sont, et le texte heritait de la
     piste etroite (mesure : 456 px au lieu de 806 a 1440). On inverse donc
     le gabarit ET on place chaque item.
     L'ordre du DOM ne bouge pas : contenu d'abord au clavier et au lecteur
     d'ecran, le personnage est une illustration. */
  .method--media-end .method__body {
    grid-template-columns: minmax(0, 1.28fr) minmax(230px, 0.72fr);
  }
  .method--media-end .method__media   { grid-column: 2; grid-row: 1; }
  .method--media-end .method__content { grid-column: 1; grid-row: 1; }
}

.method__media {
  position: relative;
  margin: 0;
  /* pas d'align-self ici : il ecraserait le align-items:center de la grille
     et decalait les deux colonnes de 116 px a 1024. */
}
.method__media img {
  width: 100%;
  max-width: 380px;
  height: auto;
  display: block;
  margin-inline: auto;
}
/* Aura persona derriere le personnage. Sur navy elle est INDISPENSABLE :
   mesure, les six figures sont sombres (luminance moyenne 0,027 a 0,094) et ne
   valent que 1,49 a 2,60:1 contre le navy — sans aura elles s'y noient.
   Sur papier elles valent 6,99 a 12,98:1 : l'aura n'y sert a rien et se voit
   comme un cerne colore sur le blanc. Elle est donc reservee aux bandes
   sombres, et les bandes claires ne gardent que le socle. */
.method--dark .method__media::before {
  content: '';
  position: absolute;
  inset: 4% 2% 6%;
  z-index: -1;
  border-radius: 50%;
  background: radial-gradient(58% 52% at 50% 58%,
              color-mix(in srgb, var(--persona) 55%, transparent) 0%,
              transparent 70%);
  filter: blur(38px);
  pointer-events: none;
}
/* Socle : une ellipse qui pose la figure au sol au lieu de la laisser
   flotter sans ancrage. */
.method__media::after {
  content: '';
  position: absolute;
  left: 50%;
  bottom: 2%;
  translate: -50% 0;
  width: 58%;
  height: 14px;
  border-radius: 50%;
  background: radial-gradient(ellipse at center,
              color-mix(in srgb, var(--persona) 42%, transparent) 0%,
              transparent 72%);
  filter: blur(7px);
  pointer-events: none;
}

.method__content { min-width: 0; }

.method__desc {
  margin: 0 0 clamp(20px, 2.4vw, 28px);
  max-width: 62ch;
  font-size: clamp(16px, 1.15vw, 19px);
  line-height: 1.6;
  color: var(--band-muted);
}
/* Le point de bascule : sur fond clair, --color-muted-light vaut 7,24:1,
   sur navy --color-muted vaut 7,41:1. Les deux passent AAA en grand corps
   et AA en corps courant. */

.method__points {
  margin: 0 0 clamp(24px, 3vw, 36px);
  padding: 0;
  list-style: none;
  display: grid;
  gap: 14px;
  max-width: 68ch;
}
.method__points li {
  display: grid;
  grid-template-columns: 22px 1fr;
  gap: 12px;
  align-items: start;
  font-size: clamp(14.5px, 1vw, 16px);
  line-height: 1.55;
  color: var(--band-fg);
}
.method__points .icon {
  width: 18px;
  height: 18px;
  margin-top: 3px;
  color: var(--ink);
}

/* --- 2c. L'APLAT INVERSE : le choc local ------------------------ */
/* C'est le geste que la reference utilise et que l'alternance de bandes
   seule ne donne pas : dans une bande sombre un aplat clair a texte
   sombre, et dans une bande claire un aplat navy a texte clair. Chaque
   section porte donc les DEUX valeurs, jamais une seule. */

.method__proof {
  background: var(--plate-bg);
  color: var(--plate-fg);
  border: 1px solid var(--plate-rule);
  border-radius: var(--radius-lg);
  padding: clamp(20px, 2.2vw, 28px);
  box-shadow: var(--shadow-md);
}
.method--light .method__proof { box-shadow: var(--shadow-lg); }

.method__proof-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px 16px;
  padding-bottom: 16px;
  margin-bottom: 18px;
  border-bottom: 1px solid var(--plate-rule);
}
/* Le chiffre : un seul par section, et c'est une donnee reelle (le nombre de
   services catalogues), pas un ornement. Label en petites capitales. */
.method__proof-figure {
  font: 800 clamp(30px, 3.2vw, 44px)/0.85 var(--font-mono);
  letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;
  color: var(--plate-ink);
  margin: 0;
}
.method__proof-label {
  flex: 0 1 auto;
  max-width: 13ch;
  font: 700 10.5px/1.35 var(--font-mono);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--plate-muted);
  margin: 0;
}
/* Les cadres de reference vivent DANS l'aplat : ce sont des preuves, elles
   appartiennent a la colonne de preuve, pas au sol de la bande. Elles
   remplissent aussi la moitie droite de la ligne, qui sonnait creuse. */
.method__proof .method__chips {
  margin: 0 0 0 auto;
  justify-content: flex-end;
}
.method__proof .method__chip {
  border-color: color-mix(in srgb, var(--plate-ink) 40%, var(--plate-rule));
  color: var(--plate-fg);
  background: color-mix(in srgb, var(--plate-ink) 8%, transparent);
}
@media (max-width: 640px) {
  .method__proof .method__chips { margin-left: 0; justify-content: flex-start; }
  .method__proof-label { max-width: none; }
}

.method__services {
  margin: 0;
  padding: 0;
  display: grid;
  gap: 14px;
}
.method__service {
  display: grid;
  grid-template-columns: minmax(120px, 172px) 1fr;
  gap: 6px 20px;
  align-items: baseline;
  padding-bottom: 14px;
  border-bottom: 1px solid var(--plate-rule);
}
.method__service:last-child { border-bottom: 0; padding-bottom: 0; }
.method__service dt {
  margin: 0;
  font: 700 11.5px/1.35 var(--font-mono);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--plate-ink);
}
.method__service dd {
  margin: 0;
  font-size: 14px;
  line-height: 1.55;
  color: var(--plate-muted);
}
@media (max-width: 720px) {
  .method__service { grid-template-columns: 1fr; gap: 4px; }
}

/* Le depliage. Reste un <details> : six sections x 3 a 6 services
   deployes feraient une page de mur de texte. Le chiffre et les cadres
   restent visibles, seul le detail se replie. */
.method__disclose { margin-top: 4px; }
.method__disclose-toggle {
  list-style: none;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  min-height: 44px;
  padding: 10px 18px;
  border-radius: var(--radius-full);
  /* Bordure remontee de 45 % a 80 % de l'encre : mesure sur les six aplats,
     45 % ne donnait que 1,81 a 2,07:1 contre l'aplat, sous le seuil de 3:1 des
     elements d'interface. A 80 % on releve 3,13 a 3,65:1 sur aplat clair et
     3,47 a 9,99:1 sur aplat sombre. */
  border: 1px solid color-mix(in srgb, var(--plate-ink) 80%, transparent);
  /* PAS de remplissage teinte. Mesure du 2026-08-12 : la teinte de 10 % de
     l'encre assombrissait l'aplat clair de #F8FAFC a #F5E5E7 environ, et les
     six encres -ink tombaient de 4,52-4,62:1 a 3,95-4,01:1, sous le seuil AA.
     Sur aplat sombre le violet tombait de 4,80 a 4,36:1. Les variantes -ink et
     -lift sont calculees contre l'aplat EXACT : toute teinte les casse. */
  background: transparent;
  color: var(--plate-ink);
  font: 700 11.5px/1 var(--font-mono);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  user-select: none;
  transition: background var(--duration-normal) var(--ease-out),
              border-color var(--duration-normal) var(--ease-out);
}
.method__disclose-toggle::-webkit-details-marker,
.method__disclose-toggle::marker { display: none; content: ''; }
.method__disclose-toggle:hover {
  /* Le survol ne peut pas teinter le fond sous le texte sans casser le ratio.
     Il epaissit donc le signal par la bordure pleine seule. */
  background: transparent;
  border-color: var(--plate-ink);
}
.method__disclose-toggle:focus-visible {
  outline: 2px solid var(--plate-ink);
  outline-offset: 3px;
}
.method__disclose-chevron {
  width: 12px; height: 12px;
  flex-shrink: 0;
  transition: transform var(--duration-normal) var(--ease-out);
}
.method__disclose[open] > .method__disclose-toggle .method__disclose-chevron {
  transform: rotate(90deg);
}
.method__disclose-panel { padding-top: 18px; }
@media (prefers-reduced-motion: reduce) {
  .method__disclose-chevron { transition: none; }
}

/* --- 2d. Cadres de reference (chips) --------------------------- */
/* Sur la bande, pas dans l'aplat : ils appartiennent au sol de la bande. */
.method__chips {
  display: flex;
  flex-wrap: wrap;
  gap: 7px;
  margin-top: clamp(20px, 2.4vw, 28px);
}
.method__chip {
  font: 600 11.5px/1 var(--font-sans);
  letter-spacing: 0.05em;
  padding: 8px 13px;
  border-radius: var(--radius-full);
  border: 1px solid color-mix(in srgb, var(--ink) 42%, var(--band-rule));
  color: var(--band-fg);
  background: color-mix(in srgb, var(--persona) 8%, transparent);
}

/* --- 2e. Reveal ------------------------------------------------- */
/* Regle du systeme : dans un groupe on n'anime QUE transform, jamais
   l'opacite. Si l'observateur ne se declenche pas, le contenu reste
   visible. Le filet de securite vit dans method-nav.js. */
.method__body > *,
.method__index,
.method__head-text {
  transition: transform 620ms var(--ease-out);
}
.method.is-pending .method__media   { transform: translateY(26px); }
.method.is-pending .method__content { transform: translateY(26px); }
.method.is-pending .method__head-text { transform: translateY(14px); }
/* LE NUMERO DE LA BANDE AUSSI — 2026-08-21. L'audit exhaustif l'a trouve :
   « 01 » a « 06 » restaient immobiles a cote d'un titre qui glissait, sur les
   six bandes. Un chiffre fixe pose contre un texte qui bouge se remarque plus
   qu'une bande entierement statique. */
.method.is-pending .method__index { transform: translateY(14px); }
.method.is-pending .method__content { transition-delay: 90ms; }
@media (prefers-reduced-motion: reduce) {
  .method__body > *, .method__index, .method__head-text { transition: none; }
  .method.is-pending .method__media,
  .method.is-pending .method__content,
  .method.is-pending .method__index,
  .method.is-pending .method__head-text { transform: none; }
}

/* --- 2f. Petites largeurs ------------------------------------- */
@media (max-width: 919px) {
  /* Le personnage passe au-dessus du texte et se reduit : sous 920 px il
     doit rester un signe d'identite, pas manger le premier ecran. */
  .method__media img { max-width: min(300px, 62vw); }
  .method__head { grid-template-columns: 1fr; gap: 12px; align-items: start; }
  /* L'aplat ne doit PAS s'etirer sur toute la largeur quand la tete passe en
     une colonne, et surtout pas heriter d'une opacite : c'etait un reste du
     chiffre fantome de la premiere version, il delavait le rouge en rose a
     1,3:1 sous le blanc. */
  .method__index {
    justify-self: start;
    min-width: 72px;
    font-size: clamp(30px, 8vw, 44px);
  }
}
@media (max-width: 560px) {
  .method__media img { max-width: min(240px, 66vw); }
  .method__proof { padding: 18px 16px; border-radius: var(--radius-md); }
  .method__chips { gap: 6px; }
  .method__chip { font-size: 11px; padding: 7px 11px; }
}

/* Le halo de bande est purement decoratif : il disparait quand l'ecran est
   trop etroit pour qu'il ait un sens, et il ne doit jamais creer de
   debordement horizontal. */
@media (max-width: 700px) {
  .method::after { width: 120vw; left: -10vw; right: auto; top: -6%; opacity: 0.4; }
}

/* --- 2g. Intro de la liste ------------------------------------- */
.liga-intro { padding-bottom: clamp(32px, 4vw, 56px); }


/* ══════════════════════════════════════════════════════════════════════════
   ÉCHELLE DE SOLS — application aux bandes de la page d'accueil
   Ajout du 2026-08-12. Doctrine et ratios : css/tokens.css.
   ══════════════════════════════════════════════════════════════════════════
   Mesure de départ, relevée au getComputedStyle sur les quatorze bandes de
   index.html : DOUZE d'entre elles rendaient exactement #101010, soit un
   ratio de 1,000:1 entre voisines. Le défaut « ça manque de contraste et de
   rythme » n'était donc pas une impression, c'était une absence de sols.

   Le sol se déclare par l'attribut data-sol sur la <section>. Le nombre est
   le niveau de l'échelle ; il ne dit rien de la couleur du texte, qui reste
   commandée par .section--dark / .section--light.

   Spécificité : deux sélecteurs par niveau. Le premier, main > section[…],
   vaut 0,1,2 et bat les règles de section à une classe (.hero, .trustband,
   .scene-hacked, .final-cta, .diferenciador). Le second ajoute .section pour
   monter à 0,2,2 et battre .section--dark / .section--light, qui valent 0,2,0.
   C'est mesuré par getComputedStyle, pas déduit.

   background-color et non background : les halos radiaux de marque déjà posés
   par .hero, .diferenciador, #alianzas et .industries survivent au-dessus du
   nouveau sol au lieu d'être effacés.                                       */

main > section[data-sol="0"],
main > section.section[data-sol="0"] { background-color: var(--sol-0); }

main > section[data-sol="1"],
main > section.section[data-sol="1"] { background-color: var(--sol-1); }

main > section[data-sol="2"],
main > section.section[data-sol="2"] { background-color: var(--sol-2); }

/* La seule bande sur sol clair est .trustband, qui ne porte PAS la classe
   .section : le second selecteur de la paire serait mort, il est retire. */
main > section[data-sol="clair"] { background-color: var(--sol-clair); }

/* Le muted éclairci devient l'encre courante dès sol-2 : --color-muted y vaut
   4,45:1 sur ce sol, sous le seuil de 4,5. On redéfinit la variable sur la
   section elle-même : toute règle qui écrit var(--color-muted) dans le
   sous-arbre suit automatiquement, sans qu'il faille les recenser une à une.
   Les plaques CLAIRES imbriquées ne sont pas touchées, elles utilisent
   --color-muted-light, une autre variable. */
main > section[data-sol="2"] { --color-muted: var(--color-muted-lift); }

/* ── Conséquence directe des deux régimes sur l'eyebrow et l'accent ────────
   C'est la partie que la seule pose des sols ne suffisait pas à régler, et la
   mesure est sans appel. Rouge en TEXTE, par sol :

                        sol-0   sol-1   sol-2   sol-clair
     #DC2626             3,94    3,03    2,36     4,62
     #EF4444 (lift)      5,05    3,89    3,04     3,60

   Pour un eyebrow de 12 px en gras — qui n'est PAS du texte large, le seuil
   de 3:1 ne commence qu'à 18,66 px en gras — le seuil est 4,5. Aucune des
   deux variantes ne l'atteint sur sol-1 ni sur sol-2.

   La doctrine donne la sortie sans inventer de couleur : à partir de sol-1 on
   quitte le régime texte pour le régime APLAT. L'eyebrow devient donc une
   PASTILLE rouge pleine à texte blanc, mesurée à 4,62:1. Elle est aussi ce
   que le client demande — de la couleur en aplat — et elle rend visible, à
   l'œil, la frontière entre les deux régimes de la page.                   */

main > section[data-sol="1"] > .container .eyebrow,
main > section[data-sol="2"] > .container .eyebrow {
  color: var(--color-fg);
  background: var(--color-primary);
  padding: 5px 12px 4px;
  border-radius: var(--radius-full);
  /* 12 px reste le corps du token. Le seuil de 4,5 est atteint à 4,62:1 SANS
     marge : ne pas descendre ce corps, ne pas éclaircir cet aplat. */
  font-size: var(--text-xs);
}

/* Accent de titre sur sol-1 : à 56 px on est en texte large, seuil 3:1. Le
   rouge de base n'y vaut que 3,03:1, la variante lift 3,89:1. C'est donc la
   lift, et elle seule, qui est admise sur ce sol. */
/* Un seul selecteur suffit : data-split-reveal decoupe le titre en
   span.split-word A L'INTERIEUR du span.accent, la couleur y descend donc par
   heritage. Le selecteur .split-word.accent, qui aurait supposé la classe sur
   le meme element, ne matchait rien — verifie par querySelectorAll. */
/* ══════════════════════════════════════════════════════════════════════════
   UN SEUL ROUGE DE TITRE, DEUX VALEURS SELON LE SOL      2026-08-22
   ══════════════════════════════════════════════════════════════════════════
   Gabriel : « le rouge de "a la capacidad operada" n'est pas le bon rouge, mets
   le bon rouge dans tous les titres comme dans "nuestro modelo" ».

   CE QUE LA MESURE A MONTRE. Les accents de titre de la home portaient SIX
   couleurs differentes : #DC2626 (hero), #EF4444 (problema), #F87171 (versus,
   operacion, presencia), #B01E1E (sistema), du cyan #67E8F9 (soluciones,
   industrias) et du vert #22C55E (casos). Chacune etait mesuree pour son fond,
   donc defendable seule — mais mises bout a bout elles ne donnaient plus une
   marque, elles donnaient une collection.

   POURQUOI LE ROUGE DEMANDE NE PEUT PAS ALLER PARTOUT. Le rouge de « nuestro
   modelo » est #B01E1E, et cette section est la seule sur FOND CLAIR. Mesure du
   meme rouge sur les sols sombres : 2,34:1 sur le sol 2, 2,68:1 sur le sol 1,
   pour un seuil de 3:1. Il y serait illisible. Ce n'est pas un rouge de marque,
   c'est un rouge de fond clair.

   LA REGLE RETENUE. Sur fond clair, le rouge profond #B01E1E que Gabriel
   designe (6,58:1). Sur fond sombre, #DC2626 — LE rouge ASHA du design system,
   celui du hero, le plus proche du profond parmi ceux qui restent lisibles :
   3,33:1 sur le sol 2, 3,81:1 sur le sol 1, 4,35:1 sur le noir pur.
   Le seuil applicable est 3:1 et non 4,5:1 : ces titres ont ete mesures entre
   32 et 48 px pour un poids de 700 a 800, donc du grand texte au sens WCAG. La
   marge la plus faible est de 11 %.

   Les accents cyan et vert des titres disparaissent : le design system dit une
   seule tension rouge, et les couleurs persona restent scopees a leur persona.
   Le CTA final « azul » garde son cyan, et c'est volontaire : son poster est
   bleu, un accent rouge y serait une couleur de plus et non une de moins.
   ══════════════════════════════════════════════════════════════════════════ */
main > section[data-sol="1"] .section-title .accent,
main > section[data-sol="1"] .section-title .accent .split-word {
  color: var(--color-primary);
}

/* Accent de titre sur sol-2 : la lift n'y vaut que 3,04:1 pour un seuil de
   3:1, soit 1,3 % de marge — trop peu pour être tenu comme conforme à
   l'antialiasing près. Ces sections passent donc au titre MONOCHROME, ce qui
   est exactement la règle de la fiche 08 : quand un bloc de tuiles colorées
   porte la couleur de la section, le titre n'en porte aucune. */
main > section[data-sol="2"] .section-title .accent {
  /* ROUGE ET NON PLUS BLANC — 2026-08-14, demande de Gabriel : « utilise bien
     le rouge dans les titres, certains ne l'ont pas ». Quatre des huit accents
     de la home sortaient blancs, et c'était cette règle.
     Sa raison d'origine tenait : --color-primary-lift ne vaut que 3,04:1 sur
     sol-2 pour un seuil de 3, soit 1,3 % de marge, trop peu pour être tenu
     pour conforme à l'antialiasing près. Mais la variante SOFT (#F87171) y
     mesure 5,82:1. Le choix n'était donc pas « rouge ou lisible », c'était
     « quel rouge » — et personne ne l'avait posé comme ça.
     La règle de la fiche 08 (un titre sans couleur quand la section porte déjà
     un bloc de tuiles colorées) est écartée ici : Gabriel a tranché pour la
     constance du rouge d'un titre à l'autre.
     2026-08-22 : la soft (#F87171) mesurait 5,82:1, largement au-dessus du
     seuil, mais c'etait un TROISIEME rouge. Retour au rouge de marque, 3,33:1
     sur ce sol pour un seuil de 3:1 en grand texte. */
  color: var(--color-primary);
}


/* ══════════════════════════════════════════════════════════════════════════
   ÉTAPE B — travail par section sur la nouvelle échelle
   ══════════════════════════════════════════════════════════════════════════ */

/* ── 03 · DESTACADOS — sol-2 ───────────────────────────────────────────────
   Ce que la section doit FAIRE : offrir trois portes vers les preuves les plus
   fortes de la page, juste après le mur de logos clients, parcourables en cinq
   secondes et manifestement cliquables.

   Fiche retenue : le panneau divisé existant est conservé — trois entrées de
   même rang tombent juste dans une grille de trois — et on lui greffe le
   MÉCANISME de la fiche 08 : sur ce sol, la couleur n'est plus du texte, elle
   est un aplat. Le kicker devient une pastille rouge pleine à texte blanc
   (4,62:1 mesuré), la flèche un disque rouge plein à glyphe blanc, et un filet
   épais de 3 px coiffe chaque carte.

   Ce qu'on NE fait pas, et pourquoi : colorer les trois cartes chacune dans
   une couleur persona. Ces trois entrées ne SONT pas des personas — ce sont un
   cas client, un panorama de menaces et une alliance. Le design system réserve
   les six couleurs à ce qu'elles désignent ; les employer en décor les userait.
   Les trois portes sont donc rouges, et c'est leur kicker qui les distingue.

   Le panneau passe à sol-1 pour se détacher de son propre sol : 1,281:1
   mesuré, au-dessus du seuil de bande de 1,25.                              */

main > section[data-sol] .destacados__panel {
  background: var(--sol-1);
  border-color: var(--color-border-strong);
}
.destacado { padding-top: calc(var(--space-7) + 3px); }
/* Le filet : posé en absolu pour ne pas déplacer le contenu, et arrêté aux
   bords de chaque carte pour que trois filets se lisent comme trois portes. */
.destacado::before {
  content: '';
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 3px;
  background: var(--color-primary);
}
.destacado:hover { background: rgba(220, 38, 38, 0.10); }

.destacado__kicker {
  /* Blanc sur #DC2626 = 4,62:1. Le corps monte de 12 à 13 px : le seuil de 4,5
     est atteint sans marge, autant ne pas y ajouter la fatigue d'un petit
     corps. */
  align-self: flex-start;
  color: var(--color-fg);
  background: var(--color-primary);
  padding: 4px 10px 3px;
  border-radius: var(--radius-full);
  font-size: 13px;
  letter-spacing: 0.10em;
}

/* La flèche : un disque plein. En texte rouge sur la carte elle mesurait
   3,51:1 pour un seuil de 4,5 — un échec. En aplat, le glyphe blanc dessus
   vaut 4,62:1, et la cible passe de 18 px de glyphe à 32 px de disque. */
.destacado__arrow {
  margin-top: auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px; height: 32px;
  border-radius: var(--radius-full);
  background: var(--color-primary);
  color: var(--color-fg);
  font-size: var(--text-base);
  line-height: 1;
}


/* ── 04 · PROBLEMA — sol-1 ─────────────────────────────────────────────────
   Ce que la section doit FAIRE : installer la tension. Sept symptômes que le
   visiteur reconnaît, puis une bascule qui les retourne en problème adressable.

   Sept éléments ne tombent juste dans aucune grille de trois — ils y
   laisseraient un orphelin. La grille de deux colonnes existante les répartit
   en 4 + 3, ce qui se lit ; elle est conservée.

   Ce qui change vient de la doctrine des deux régimes : le numéro d'ordre
   était en rouge à 75 % d'opacité, soit #AD272B sur ce sol, mesuré à 2,16:1
   pour un seuil de 4,5. Il devient une PASTILLE carrée rouge pleine à chiffre
   blanc — 4,62:1. C'est le troisième traitement du chiffre de la fiche 08, à
   petite échelle : le chiffre ne se pose plus sur le fond, il devient un bloc. */

/* Re-scope du 2026-08-12 : ces deux regles etaient liees a data-sol="1" parce
   que #problema y etait. Le deplacement de #soluciones a impose d'echanger les
   sols de .destacados et #problema pour eviter deux bandes voisines identiques,
   et #problema est passe au sol-2. Elles portent de la GEOMETRIE (pastille du
   numero, filet gauche du symptome), pas seulement de la couleur : liees a un
   sol elles auraient disparu. Elles sont donc scopees a la section, ou .symptom
   n'existe de toute facon nulle part ailleurs. */
#problema .symptom__idx {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 26px;
  padding: 3px 5px;
  border-radius: var(--radius-sm);
  background: var(--color-primary);
  color: var(--color-fg);
  font-weight: 700;
  /* Le décalage de ligne de base n'a plus lieu d'être : le chiffre est centré
     dans sa pastille, ce n'est plus lui qu'on aligne mais la pastille. */
  padding-top: 3px;
}
#problema .symptom { border-left-color: rgba(220, 38, 38, 0.45); }

/* Le glyphe « > » de la bascule : le rouge y valait 3,03:1 et sa variante lift
   3,89:1, tous deux sous 4,5. --color-danger-soft #FCA5A5, déjà dans les
   tokens, mesure 7,71:1 sur ce sol. C'est l'encre de la FAMILLE rouge sur les
   sols éclaircis, quand un aplat serait trop lourd pour un seul caractère. */
/* La bascule de problema vit sur sol-1 et nulle part ailleurs : la variante
   sol-2 etait defensive et morte. */
/* Re-scope du 2026-08-12, meme cause que les deux regles .symptom juste
   au-dessus : #problema est passe du sol-1 au sol-2, cette regle liee au
   sol-1 avait donc cesse de s'appliquer et le chevron etait retombe a
   3,33:1. Scopee a la section, ou .problema__turn-prompt n'existe de toute
   facon nulle part ailleurs. */
#problema .problema__turn-prompt { color: var(--color-danger-soft); }


/* ── 06 · SISTEMA — sol-1 ──────────────────────────────────────────────────
   Ce que la section doit FAIRE : montrer que les capacités s'articulent, et
   pas seulement qu'elles coexistent. Sept niveaux, quatre groupes visuels.

   C'est ici que la demande du client — beaucoup de couleur, notamment en fond
   de carte — rencontre exactement la doctrine. Les cinq frentes portaient leur
   couleur persona en TEXTE : mesuré sur ce sol, le violet tombait à 3,70:1 et
   n'était plus conforme. Sur sol-1 on est en régime APLAT : les cinq tuiles
   deviennent des aplats pleins de leur couleur, et le texte se pose dessus.

   Sa couleur ne se choisit pas, elle se mesure. Texte NAVY sur les cinq :
   cyan 7,83 · vert 8,34 · orange 6,78 · argent 15,42 · violet 4,80. Le violet
   est le cas qui obligeait à mesurer un par un : il PARAÎT assez sombre pour
   porter du blanc et ne l'est pas (3,78:1, échec). Cinq tuiles, cinq textes
   navy — et le rouge ASHA reste le seul aplat de la palette à porter du blanc,
   ce qui en fait la couleur du commandement et non d'un frente.            */

main > section[data-sol="1"] .front {
  background: var(--persona);
  border-color: var(--persona);
  border-top-width: 1px;
}
main > section[data-sol="1"] .front__name,
main > section[data-sol="1"] .front__verb {
  color: var(--color-fg-light);
}
main > section[data-sol="1"] .front__verb { opacity: 0.78; }
main > section[data-sol="1"] .front:hover {
  transform: translateY(-2px);
  border-color: var(--color-fg);
}

/* Le commandement et la chute portaient leur nom en ROUGE. Sur ce sol c'est
   intenable, et le piège est le clamp : .layer__name est en
   clamp(17px, 1.5vw, 22px). À 1440 px il rend 21,6 px, donc du texte large au
   seuil de 3:1, où --color-primary-lift passe avec 3,89:1. Mais en dessous de
   1024 px le clamp descend au plancher de 17 px — et 17 px en gras n'est PLUS
   du texte large, la frontière étant à 18,66 px. Le seuil remonte à 4,5 et la
   même couleur échoue à 3,80-3,89:1. Vérifié sur sept largeurs : conforme à
   1920, 1440 et 1280, en échec à 1024, 768, 430, 375 et 320.
   La sortie n'est pas une couleur plus claire, c'est la doctrine : sur sol-1 on
   est en régime aplat, le rouge n'a pas à être du texte. Les deux noms passent
   en blanc plein (13,98:1) et l'identité rouge est portée par la pastille
   d'aplat de .layer__idx, juste à côté, qui la dit déjà. */
main > section[data-sol="1"] .layer--command .layer__name,
main > section[data-sol="1"] .layer--outcome .layer__name { color: var(--color-fg); }
main > section[data-sol="1"] .layer--command .layer__idx,
main > section[data-sol="1"] .layer__idx {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 24px;
  padding: 2px 4px;
  border-radius: var(--radius-sm);
  background: rgba(248, 250, 252, 0.10);
  color: var(--color-fg);
}
main > section[data-sol="1"] .layer--command .layer__idx {
  background: var(--color-primary);
  color: var(--color-fg);
}


/* ── 07 · OPERACIÓN — sol-2 — FICHE 08 ─────────────────────────────────────
   Ce que la section doit FAIRE : établir qu'ASHA ne s'arrête pas à la
   recommandation. L'argument a besoin, EN FACE de lui, des moyens qui le
   rendent crédible — sans quoi il reste une promesse.

   Fiche 08, « argument à gauche, tuiles pleines à droite ». Elle est marquée
   prête, et ses conditions d'emploi tombent juste ici : ses quatre tuiles
   veulent des éléments d'UNE MÊME FAMILLE, et les quatre capacités le sont
   — ce sont les quatre maillons d'une seule chaîne d'exécution. Quatre
   éléments dans une grille 2 × 2 tombent exactement juste.

   Longueurs des quatre paragraphes, mesurées : 150, 141, 137 et 131
   caractères. L'écart maximal est de 19 caractères sur 150, soit 12,7 % : la
   fiche 04 impose des longueurs comparables pour que l'alignement ne révèle
   pas de vides inégaux, et c'est vérifié.

   CE QUI EST MÉLANGÉ, et d'où ça vient :
     · fiche 08 — la composition à deux colonnes (argument borné à gauche,
       bloc compact de tuiles à droite) et surtout son mécanisme central :
       le chiffre, ou ici la capacité, ne se pose pas sur un fond, elle
       DEVIENT le fond. Quatre tuiles forment une masse, pas quatre lignes.
     · fiche 08 encore — le titre de section reste monochrome, parce que le
       bloc de tuiles porte déjà toute la couleur. C'est la règle du sol-2
       posée plus haut, et les deux se rejoignent.
     · fiche 04 — la règle des longueurs comparables, vérifiée ci-dessus.

   CE QUI N'EST PAS REPRIS de la fiche 08, et pourquoi : ses DEUX titres de
   même corps séparés par un eyebrow. Il faudrait un second titre, et nous n'en
   avons pas de validé pour cette section. En inventer un serait combler un
   trou par de la donnée fabriquée.                                          */

.operacion__split {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: clamp(32px, 4vw, 64px);
  margin-bottom: clamp(48px, 5vw, 80px);
}
@media (min-width: 1024px) {
  .operacion__split {
    /* L'argument prend la colonne étroite de lecture, le bloc de tuiles la
       large. La fiche borne l'argument à ~510 px sur un viewport de 1920 ;
       ici la colonne est proportionnelle et le max-width ci-dessous fait la
       borne, pour que le texte ne s'étire jamais vers les tuiles. */
    grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr);
    align-items: start;
  }
}
.operacion__split > .operacion__head {
  max-width: 520px;
  margin-bottom: 0;
  text-align: left;
}
.operacion__split .caps { margin-bottom: 0; }

/* Le bloc de tuiles : 2 × 2, gouttière serrée pour qu'il pèse comme une masse
   et non comme quatre cartes éparses. */
main > section[data-sol="2"] .caps {
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(12px, 1.2vw, 20px);
}
@media (max-width: 620px) {
  /* La fiche le dit : passer en colonne unique détruit l'effet de masse. On
     tient donc le 2 × 2 le plus longtemps possible, et on ne l'abandonne qu'en
     dessous de 480 px, où deux tuiles côte à côte ne portent plus leur texte. */
  main > section[data-sol="2"] .caps { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 479px) {
  main > section[data-sol="2"] .caps { grid-template-columns: minmax(0, 1fr); }
}

main > section[data-sol="2"] .cap {
  padding: clamp(18px, 1.8vw, 26px) clamp(18px, 1.8vw, 24px);
  border-top: 0;
  border-radius: var(--radius-md);
  /* L'aplat de marque, avec le même très léger éclaircissement en haut à
     gauche que la référence. Les deux bornes du dégradé portent du blanc :
     #DC2626 à 4,62:1 et #B91C1C à 6,18:1. */
  background: linear-gradient(150deg, var(--color-primary) 0%, var(--color-primary-hover) 100%);
  color: var(--color-fg);
}
main > section[data-sol="2"] .cap__idx {
  color: var(--color-fg);
  opacity: 0.72;
}
main > section[data-sol="2"] .cap__title { color: var(--color-fg); }
/* Le paragraphe ne peut PAS rester sur --color-muted : #94A3B8 sur cet aplat
   rouge ne vaut que 1,60:1. Il passe en blanc plein, 4,62:1. */
main > section[data-sol="2"] .cap__text { color: var(--color-fg); }

/* Le glyphe « > » de la frise : rouge sur sol-2 il valait 2,36:1. */
main > section[data-sol="2"] .flow__prompt { color: var(--color-danger-soft); }


/* ── 08 · SOLUCIONES — sol-1 — FICHE 08 (aplats) + FICHE 09 (carte) ────────
   Ce que la section doit FAIRE : partir du problème du visiteur et non de
   notre organisation interne. Six besoins, formulés comme un CISO les
   formulerait, chacun nommant ENSUITE la méthodologie qui y répond.

   Six éléments dans une grille de trois tombent exactement juste : 3 + 3, pas
   d'orphelin. C'est le seul endroit de la page où le compte le permet.

   C'est ici que la demande du client — beaucoup de couleur, en fond de carte,
   des tuiles en aplat plein — trouve son emplacement le plus légitime de toute
   la page, pour une raison qui n'est pas esthétique : chacune de ces six
   cartes PORTE DÉJÀ son data-persona. La couleur n'y est pas un décor, elle
   désigne. Ailleurs sur la page il aurait fallu attribuer des couleurs
   persona à des blocs qui n'en sont pas.

   CE QUI EST MÉLANGÉ, et d'où ça vient :
     · fiche 08 — le mécanisme d'aplat : la couleur n'est jamais du texte,
       elle est le fond, et le texte se pose dessus. C'est ce qui rend le
       violet et le rouge utilisables ici alors qu'en texte sur ce sol ils
       échouent (3,70:1 et 3,03:1).
     · fiche 09 — la STRUCTURE de la carte : étiquette de méthode, titre,
       texte, puis un CTA propre à la carte. La fiche 09 est faite pour un
       fond clair et pour deux CTA par carte ; on ne garde que sa structure à
       CTA unique, ce que son index note comme utilisable dès maintenant.

   La couleur du texte ne se choisit pas, elle se mesure, aplat par aplat :
     cyan 7,83 · vert 8,34 · orange 6,78 · argent 15,42 · violet 4,80 en NAVY
     rouge 4,62 en BLANC — seul cas de la palette.
   Le violet est le piège : il paraît assez sombre pour porter du blanc et ne
   l'est pas (3,78:1). C'est pour lui qu'il fallait mesurer un par un.        */

/* RE-SCOPE DU 2026-08-14 — la troisieme fois que ce couplage mord.
   Ces regles portent l'IDENTITE des cartes persona (l'aplat et son encre),
   pas une adaptation au sol. Elles etaient liees a data-sol="1" parce que
   #soluciones y etait ; l'insertion de la bande de comparaison juste avant
   fait passer la section au sol-2, et toutes auraient cesse de s'appliquer :
   six aplats persona et leur encre disparus d'un coup.
   Meme cause que .symptom et .problema__turn-prompt les 12 et 13 aout.
   REGLE : une declaration qui porte de la GEOMETRIE ou de l'IDENTITE ne doit
   jamais dependre du sol. Seules les couleurs qui s'ADAPTENT au sol le peuvent.
   Scope a la section : .need n'existe nulle part ailleurs. */
#soluciones .need__link {
  background: var(--persona);
  border-color: var(--persona);
  border-top-width: 1px;
  color: var(--on-persona);
}
#soluciones .need__method,
#soluciones .need__title,
#soluciones .need__text,
#soluciones .need__cta { color: var(--on-persona); }
/* L'étiquette de méthode et le texte reculent par l'opacité et non par une
   couleur plus pâle : une couleur plus pâle sur un aplat clair perdrait son
   ratio, l'opacité sur la même encre reste calculable. 0,82 sur navy contre
   cyan donne encore 6,0:1 au plus serré des cinq aplats clairs. */
#soluciones .need__method { opacity: 0.82; }
#soluciones .need__text   { opacity: 0.88; }
#soluciones .need__link:hover {
  background: var(--persona);
  border-color: var(--on-persona);
}
#soluciones .need__link:hover .need__cta { color: var(--on-persona); }

/* Encre portée par chaque aplat. Cinq navy, un blanc. */
.need[data-persona="ngsoc"],
.need[data-persona="ctem"],
.need[data-persona="csirt"],
.need[data-persona="zerotrust"],
.need[data-persona="grc"]  { --on-persona: var(--color-fg-light); }
.need[data-persona="asha"] { --on-persona: var(--color-fg); }


/* ── 09 · LIGA — sol-0 ─────────────────────────────────────────────────────
   Ce que la section doit FAIRE : dire ce qui nous distingue et le prouver, puis
   présenter les six personnages qui l'incarnent.

   Elle RESTE sur sol-0, et ce n'est pas un choix de rythme : le CSS des auras
   persona porte déjà la mesure — « sur navy elle est INDISPENSABLE », la figure
   de chaque héros ne valant que 2,2:1 contre le fond. Éclaircir le sol sous les
   six portraits aurait effacé ce qui les détache. Contrainte dure, comme
   scene-hacked, pour une raison différente.

   FICHE 04, ce qui en est pris et ce qui est ÉCARTÉ.
   Écarté : sa grille de trois cartes de preuve. Ses conditions d'emploi
   demandent « exactement trois chiffres du même niveau d'impact » et « qui
   tiennent tous sur une ligne ». Nos trois piliers portent « 12+ años »,
   « 5 países » et « Infraestructura crítica » : le troisième n'est pas un
   chiffre. Le trio serait boiteux, ce que la fiche nomme précisément comme son
   mauvais cas. Aucun chiffre n'a été inventé pour le combler.
   Pris : son quatrième usage de la couleur dans un titre — une PHRASE ENTIÈRE
   colorée pour marquer le basculement du constat à la proposition. La thèse
   existait déjà en deux temps dans le lede, elle n'était simplement pas
   composée : « Tres pilares definen nuestra propuesta » est le constat, « La
   Capitana con cinco frentes de defensa los hacen realidad cada día » est la
   proposition. Aucun mot n'est ajouté ni retiré.
   Mesure : à 18 px en corps normal le seuil est 4,5. Le rouge de base vaut
   3,94:1 sur sol-0 et échoue ; --color-primary-lift vaut 5,05:1.            */

.diferenciador__lede .accent { color: var(--color-primary-lift); }

/* Le filigrane 01/02/03 des piliers valait 1,16:1 — neuf occurrences d'un
   chiffre que personne ne peut lire. Deux sorties possibles : l'assumer comme
   pure décoration, ou en faire un repère. Il devient un repère : un aplat rouge
   à chiffre blanc, 4,62:1. Il tient dans les 52 px que .pillar__title réserve
   déjà à droite, donc la ligne du titre ne bouge pas. */
.pillar__num {
  position: absolute;
  top: var(--space-4);
  right: var(--space-5);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px; height: 40px;
  border-radius: var(--radius-sm);
  background: var(--color-primary);
  font: 700 15px/1 var(--font-mono);
  letter-spacing: 0.04em;
  color: var(--color-fg);
  pointer-events: none;
}

/* Le rang du commandement : rouge à 12 px sur la carte il valait 3,73:1.
   --color-primary-lift y mesure 4,78:1 (la carte est #171717, un cran plus
   claire que sol-0, d'où 4,78 et non 5,05). */
.practice--command .practice__rank { color: var(--color-primary-lift); }


/* ── 05 · SCENE-HACKED — sol-0, contrainte dure ────────────────────────────
   Le sol ne bouge pas : le repli MP4 de la Capitana a son fond CUIT à
   (9,14,39), à un niveau de (10,14,39). Sur tout autre sol la vidéo
   apparaîtrait dans un rectangle visible. C'est la contrainte la plus dure de
   la page, et elle vient d'un asset, pas d'un choix.
   Seul défaut de contraste relevé ici : le libellé des trois cadrans, rouge à
   16 px, 3,94:1 pour un seuil de 4,5. */
.ring-stat__sub { color: var(--color-primary-lift); }


/* ── 10 · ALIANZAS — sol-1 ─────────────────────────────────────────────────
   Deux échecs de contraste, tous deux du rouge en petit texte sur le nouveau
   sol, tous deux réglés par le régime aplat.

   Le « 95 % » de couverture : 17,3 px en gras. Ce N'EST PAS du texte large —
   le seuil de 3:1 ne commence qu'à 18,66 px en gras — donc le seuil est 4,5 et
   le rouge n'y valait que 3,03:1. Il devient une pastille rouge à texte blanc,
   4,62:1. Le chiffre y gagne aussi le poids qu'il mérite dans la phrase.     */
.alliances__coverage-stat {
  display: inline-block;
  padding: 3px 9px 2px;
  border-radius: var(--radius-full);
  background: var(--color-primary);
  color: var(--color-fg);
  font-size: 1em;
}

/* Les trois niveaux de partenariat passent tous en aplat, pas seulement celui
   qui échouait : « Elite » en rouge valait 3,22:1. Encre mesurée par métal —
   navy sur or 8,68:1, navy sur argent 12,68:1, blanc sur rouge 4,62:1. Le
   rouge est encore une fois le seul des trois à porter du blanc. */
.partner-level__tag {
  color: var(--metal-on, var(--color-fg-light));
  background: var(--metal);
  border-color: var(--metal);
}
.partner-level--elite    { --metal-on: var(--color-fg); }
.partner-level--platinum { --metal-on: var(--color-fg-light); }
.partner-level--gold     { --metal-on: var(--color-fg-light); }
/* Les halos de texte devenaient des bavures sur un aplat plein. */
.partner-level--elite .partner-level__tag,
.partner-level--platinum .partner-level__tag,
.partner-level--gold .partner-level__tag { text-shadow: none; }


/* ── 11 · CASOS DE ÉXITO — sol-2 — FICHE 08, 3e traitement du chiffre ──────
   Ce que la section doit FAIRE : prouver par deux cas réels, chiffres à
   l'appui, que les résultats existent en production.

   Les chiffres étaient du texte rouge : mesuré sur ce sol, 2,16:1 pour un
   seuil de 3 même à 46 px. Aucune variante rouge ne remonte au-dessus (la
   lift plafonne à 3,04:1 sur sol-2). Le régime aplat est donc la seule sortie,
   et c'est exactement le TROISIÈME traitement du chiffre relevé dans la
   bibliothèque : « blanc et centré dans une tuile de couleur pleine — le
   chiffre devient le bloc ». Sa vertu, écrite dans l'index : la couleur n'y
   est jamais du texte, ce qui en fait la manière la plus sûre d'employer le
   rouge ASHA en volume.

   Ce qui est ADAPTÉ de la fiche : elle décrit une grille 2 × 2. Ici les quatre
   métriques occupent la colonne droite d'une ligne de cas, où quatre tuiles
   côte à côte forment déjà la masse colorée unique que la fiche recherche —
   elles passent en 2 × 2 sous 700 px. Le second cas n'a qu'un chiffre dur, et
   il n'en aura pas quatre pour faire joli : sa tuile unique garde le même
   traitement, le grand format en moins.                                     */

main > section[data-sol="2"] .case-metric {
  gap: 4px;
  padding: clamp(14px, 1.4vw, 20px) clamp(12px, 1.2vw, 18px);
  border-radius: var(--radius-md);
  background: linear-gradient(150deg, var(--color-primary) 0%, var(--color-primary-hover) 100%);
}
main > section[data-sol="2"] .case-metric__num,
main > section[data-sol="2"] .case-metric__unit { color: var(--color-fg); }
/* Le libellé ne peut pas rester sur --color-muted : 1,60:1 sur cet aplat.
   Blanc plein, 4,62:1, et il ne descend pas sous 12 px. */
main > section[data-sol="2"] .case-metric__label { color: var(--color-fg); opacity: 0.92; }
main > section[data-sol="2"] .case-row__metrics { border-bottom: 0; }

/* L'étiquette « Después » : vert sur son propre voile vert, 4,04:1 pour un
   seuil de 4,5. En aplat vert plein avec du texte navy elle monte à 8,34:1 —
   et le vert reste, ce qui était le sens du signal. */
main > section[data-sol="2"] .case-flow__tag--after {
  color: var(--color-fg-light);
  background: var(--color-grc);
  border-color: var(--color-grc);
}


/* ── 12 · INDUSTRIAS — sol-1 ───────────────────────────────────────────────
   Exception à la pastille rouge des sols éclaircis. Cet eyebrow est cyan
   depuis l'origine parce que la section est alignée sur la marque CSIRT, et le
   cyan en texte vaut 6,03:1 sur ce sol : il n'a aucun besoin d'un aplat. La
   règle générale l'aurait posé sur du rouge, où il tombait à 3,87:1. */
main > section[data-sol="1"] > .container .industries__head .eyebrow,
main > section[data-sol="1"] .industries__head .eyebrow {
  background: rgba(6, 182, 212, 0.12);
  color: var(--color-csirt-soft);
}


/* ── 13 · PRESENCIA — sol-2 ────────────────────────────────────────────────
   Le globe est en fond transparent (backgroundColor rgba(0,0,0,0) dans son
   initialisation), il vit donc sur n'importe quel sol sans retouche.
   Trois gris de la section étaient calculés en opacité sur le navy et perdent
   leur ratio dès qu'on éclaircit le sol : ils passent tous à l'encre pleine. */
main > section[data-sol="2"] .presence__sub-count { color: var(--color-muted-lift); }
main > section[data-sol="2"] .country__since      { color: var(--color-muted-lift); }
main > section[data-sol="2"] .highlight__label    { color: var(--color-muted-lift); }


/* ── 14 · CONTACTO — sol-0 ─────────────────────────────────────────────────
   L'affiche de la Liga et son voile navy à 85-92 % font que cette bande rend
   déjà du navy quel que soit le fond déclaré : la mettre sur sol-0 aligne le
   déclaré sur le rendu, et la page se referme sur le sol où elle s'est ouverte.
   Le séparateur « · » de la ligne de méta valait 1,91:1. */
.final-cta__meta-sep { color: var(--color-muted); }
/* La cible du CTA secondaire mesurait 125 x 31 px. Le seuil est 44. */
.final-cta__link { padding: 14px 4px; }


/* Le numero d'ordre des six cartes de la Liga : meme defaut que .pillar__num,
   rgba(255,255,255,0.06) mesure a 1,16:1 pour un seuil de 3 a 56 px. Six
   occurrences de plus.
   Ici la sortie n'est PAS un aplat, parce que la section est sur sol-0 : c'est
   le seul sol de la page ou presque toute la palette parle en TEXTE, et 56 px
   en 800 est du texte large, seuil 3:1. Ratios mesures sur la carte (#171717) :
     argent 14,60 · vert 7,90 · cyan 7,41 · orange 6,42 · violet 4,55
     rouge #DC2626 3,73 — conforme aussi, le seuil etant 3 et non 4,5.
   Le numero prend donc la couleur de son persona. C'est ce que faisait deja le
   survol : l'etat au repos rejoint l'etat au survol au lieu de le contredire.
   !important parce que la declaration de la ligne 4865 en porte un ; sans lui
   cette regle serait morte malgre sa position en fin de fichier. */
.practice__num { color: var(--p, var(--color-primary-lift)) !important; }
/* Le survol ne peut plus se signaler par la couleur, elle est deja la : il
   passe par le halo seul. */
.practice:hover .practice__num {
  text-shadow: 0 0 16px color-mix(in srgb, var(--p, var(--color-primary)) 60%, transparent);
}


/* ══════════════════════════════════════════════════════════════════════════
   DÉFAUTS TROUVÉS EN CHEMIN SUR LES AUTRES PAGES — 2026-08-12
   ══════════════════════════════════════════════════════════════════════════
   Ils ne viennent pas de l'échelle de sols : la mesure de contraste passée sur
   les six pages du site les a simplement mis au jour. Presque tous sont la
   MÊME faute que celle nommée par la correction de l'eyebrow — du rouge
   --color-primary employé comme TEXTE en petit corps sur fond sombre, où il
   plafonne à 3,94:1 pour un seuil de 4,5 — et dans trois cas un voile rouge
   sous ce texte rouge, qui fait encore descendre le ratio.
   Sélecteurs relevés sur le DOM rendu, pas devinés.                         */

/* nosotros — les puces de certification. Rouge 11 px sur son propre voile
   rouge à 8 % : 3,78:1. Elles deviennent des aplats à texte blanc, 4,62:1.  */
.chip {
  background: var(--color-primary);
  border-color: var(--color-primary);
  color: var(--color-fg);
}

/* contacto et bolsa-de-trabajo — le numéro d'étape du formulaire. Rouge 11 px
   sur voile rouge à 14 % : 3,40:1. Même sortie en aplat, 4,62:1. */
.form-section__num {
  background: var(--color-primary);
  border-color: var(--color-primary);
  color: var(--color-fg);
}

/* Le libellé d'étape, à côté de ce numéro. Rouge 12 px sur la plaque
   --color-surface #171717 : 3,70:1. Il reste du texte — la plaque est assez
   sombre pour que --color-primary-lift y mesure 4,74:1. */
.form-section__head > span:not(.form-section__num) { color: var(--color-primary-lift); }

/* Le lien vers l'avis de confidentialité dans la case à cocher : rouge 14 px
   sur la même plaque, 3,70:1. !important obligatoire : la déclaration de la
   ligne 7002 en porte un, et sans lui cette règle-ci était MORTE malgré sa
   position en fin de fichier. Vérifié par remesure, pas supposé. */
.form-checkbox__label a { color: var(--color-primary-lift) !important; }

/* contacto — la ligne « Consulta y descarga nuestro RFC ». Rouge 12 px sur son
   voile : 3,78:1. */
.rfc-chip span { color: var(--color-primary-lift); }

/* aviso-de-privacidad — les URL en clair dans le corps du texte. Rouge 16 px
   sur navy : 3,94:1. Ce sont les seuls liens de la page. */
.legal-prose a { color: var(--color-primary-lift); }

/* nosotros — DÉFAUT LE PLUS GRAVE trouvé en chemin, et ce n'est pas du rouge :
   le premier paragraphe de « No somos un proveedor más » rend
   --color-muted-light #475569 sur le navy, soit 2,51:1. C'est du corps de
   texte à 18 px, donc illisible, sur une page principale.
   Cause exacte : la règle .how__text p pose l'encre de fond CLAIR en
   !important sans condition de bande. Elle a été écrite pour
   .how.section--light, mais sur nosotros le bloc .how__text vit dans une
   <section class="section section--dark"> — l'encre claire tombe donc sur un
   fond sombre. La règle est scindée par bande ; --color-muted sur navy vaut
   7,41:1 et le strong en blanc plein 18,16:1. */
.section--dark .how__text p { color: var(--color-muted) !important; }
/* Pas de regle pour le <strong> de ce paragraphe, et c'est une TROUVAILLE, pas
   un oubli : le <p> porte data-i18n="about.who_p1", et i18n.js remplace
   textContent — le <strong>ASHA Solution</strong> ecrit dans le source est donc
   DETRUIT au chargement du bundle. Verifie par querySelectorAll sur la page
   rendue : zero occurrence. C'est le piege numero un du repo, encore en place
   sur nosotros.html. Le corriger demande de sortir le strong du noeud traduit,
   ce qui touche la chaine i18n : signale, pas fait ici. */


/* ── Cibles tactiles des commandes principales ─────────────────────────────
   Mesure sur sept largeurs de 1920 a 320 px, sur les commandes du contenu
   (les liens en ligne d'un paragraphe et ceux du pied de page relevent d'une
   autre regle, WCAG 2.5.8 les exemptant). Trois etaient sous le seuil de 44 :
     .final-cta__link      161 x 43  — a un pixel, et c'est moi qui l'ai amene
                                       la en passant son padding a 14 px
     .section-cta          256 x 26  — deux occurrences, prealable
     .scene-hacked__replay  38 x 38  — prealable
   Aucune n'est corrigee en changeant un corps de texte : seule la boite
   grandit, la ligne de base et la composition ne bougent pas. */
.final-cta__link { padding: 15px 4px; }
.section-cta { min-height: 44px; }
.scene-hacked__replay { width: 44px; height: 44px; }


/* ── Finitions mesurees apres la pose des sols ─────────────────────────────*/

/* Les logos partenaires sont un filtre plat brightness(0) invert(0.85), donc un
   gris ~#D9D9D9 pose a 75 % d'opacite. Ils avaient ete calibres sur sol-0 :
   mesure, ils y valaient 7,45:1 contre leur plaque. En montant la bande sur
   sol-1, la plaque s'eclaircit de #1A1A1A a #313131 et le meme reglage tombe a
   5,89:1 — les logos palissent. L'opacite passe a 88 %, ce qui redonne 7,49:1,
   soit exactement le rendu d'avant. Ce ne sont pas du texte, aucun seuil WCAG
   ne s'applique ; c'est la LISIBILITE qu'on restitue, a la mesure. */
main > section[data-sol="1"] .alliance-card__logo { opacity: 0.88; }

/* Le second cas n'a qu'un chiffre : sa tuile occupait toute la colonne droite
   et se lisait comme un bandeau, pas comme une tuile. Elle se dimensionne
   desormais sur son contenu — le libelle est deja borne a 42ch — donc elle
   garde le poids d'une tuile sans devenir une bande. */
main > section[data-sol="2"] .case-row__metrics--single {
  grid-template-columns: minmax(0, max-content);
}

/* Le titre d'industrias tombait en quatre lignes dont une portant le seul mot
   « en » : mesure a 1440 px, la colonne de titre ne faisait que 1fr contre
   1,4fr pour la liste de secteurs, soit 458 px pour un display de 56 px. Les
   proportions s'inversent — le titre est l'element de la paire qui a besoin de
   largeur, la liste de secteurs est faite de pastilles qui se replient toutes
   seules. */
@media (min-width: 900px) {
  .industries__head { grid-template-columns: 1.35fr 1fr; }
}


/* ══════════════════════════════════════════════════════════════════════════
   OPERACIÓN — la frise dans la colonne de l'argument, 2026-08-12
   ══════════════════════════════════════════════════════════════════════════
   Le probleme mesure : sur la composition de la fiche 08, l'en-tete de gauche
   fait 251 px de haut et le bloc de tuiles 443 px. Il restait donc 192 px de
   vide sous l'argument, et la fiche comble ce vide par un SECOND titre de meme
   corps que nous n'avons pas.

   La frise « El recorrido completo » existait deja, pleine largeur sous les
   deux colonnes. Elle entre ici dans la grille en colonne 1 rangee 2, et les
   tuiles s'etendent sur les deux rangees. La frise passe alors en VERTICAL,
   exactement comme elle le fait deja sous 900 px : c'est le meme dispositif de
   trait continu que la ligne de vie du diagramme de #sistema, donc les deux
   schemas de la page continuent de se lire pareil.

   Pourquoi c'est mieux qu'un remplissage : la frise dit le parcours, les tuiles
   disent les moyens de ce parcours. Les mettre face a face fait de la section
   une seule phrase au lieu de deux blocs empiles.                            */

@media (min-width: 1024px) {
  .operacion__split {
    /* Rangee 1 a la hauteur de l'en-tete, rangee 2 prend le reste. Les tuiles
       traversent les deux : c'est elles qui fixent la hauteur totale. */
    grid-template-rows: auto 1fr;
    row-gap: clamp(28px, 3vw, 44px);
  }
  .operacion__split > .operacion__head { grid-column: 1; grid-row: 1; }
  .operacion__split > .caps            {
    grid-column: 2;
    grid-row: 1 / span 2;
    /* Mesure : la colonne de l'argument (en-tete + frise) fait 499 a 578 px de
       haut selon la largeur, le bloc de tuiles 408 a 443 px. Sans etirement le
       vide changeait simplement de cote, de 84 a 170 px sous les tuiles. On
       etire donc les deux rangees de tuiles a parts egales : les deux colonnes
       se ferment a la meme hauteur, et les 42 a 85 px gagnes par tuile
       tombent en marge basse DANS l'aplat rouge, ce qui epaissit la masse au
       lieu de creuser un trou. */
    align-self: stretch;
    grid-template-rows: repeat(2, minmax(0, 1fr));
  }
  .operacion__split > .flow            { grid-column: 1; grid-row: 2; align-self: end; }

  /* Verticale : la colonne fait ~520 px, six etapes a l'horizontale y
     tiendraient a 13 px de corps, sous le plancher de lisibilite. */
  .operacion__split > .flow .flow__steps {
    grid-template-columns: minmax(0, 1fr);
    gap: clamp(12px, 1.2vw, 18px);
  }
  .operacion__split > .flow .flow__steps::before {
    top: 6px;
    bottom: 6px;
    left: 5px;
    right: auto;
    width: 1px;
    height: auto;
    background: linear-gradient(180deg,
      var(--color-primary),
      rgba(255, 255, 255, 0.16) 30%,
      rgba(255, 255, 255, 0.16) 70%,
      var(--color-primary));
  }
  .operacion__split > .flow .flow__step {
    flex-direction: row;
    align-items: center;
    gap: clamp(14px, 1.4vw, 20px);
    text-align: left;
  }
  .operacion__split > .flow .flow__label { margin-bottom: clamp(14px, 1.4vw, 20px); }
}


/* ══════════════════════════════════════════════════════════════════════════
   ROUGES RECALIBRÉS APRÈS LE PASSAGE AU NOIR — 2026-08-12, seconde passe
   ══════════════════════════════════════════════════════════════════════════
   Deux causes distinctes, et la seconde est de mon fait :

   1. Le sol descend au noir pur, ce qui AMÉLIORE le rouge (#DC2626 passe de
      3,94 à 4,35:1 sur le sol de marque). Amélioré mais toujours sous 4,5 : il
      manquait 0,15. Le rouge de base reste donc exclu du texte, partout.

   2. --color-surface est passé de #0F172A à #2B2B2B, et c'est une HAUSSE de
      clarté volontaire : la carte doit se détacher au-dessus des trois sols,
      comme chez la référence dont les cartes (#161616) sont plus claires que
      leur sol (#000000). Conséquence non voulue : les règles de la passe
      précédente qui posaient --color-primary-lift sur cette plaque avaient été
      mesurées à 4,74:1 contre #171717. Sur #2B2B2B elles tombent à 3,76:1.
      Elles étaient justes quand elles ont été écrites ; c'est mon changement de
      plaque qui les a cassées, pas une erreur de leur auteur.

   D'où le troisième cran, --color-primary-soft #F87171, et la règle simple :

     texte rouge PETIT (< 24 px)  · sur sol-0 ou sol-1 → -lift  (5,58 / 4,90)
                                  · sur sol-2 ou plus clair → -soft (5,82 / 5,12)
     texte rouge GRAND (≥ 24 px)  · -lift partout        (5,58 → 3,12)
     rouge en APLAT               · --color-primary, texte blanc dessus, 4,62:1

   Sélecteurs relevés sur le DOM rendu des six pages, chacun avec le ratio
   mesuré avant correction.                                                  */

/* Le lien de navigation actif. Rouge 14 px sur le verre du header composité
   sur le noir, plus son propre voile rouge à 8 % : 3,83:1. Le verre reste
   assez sombre pour que -lift suffise, 4,90:1. */
.main-nav__link:hover,
.main-nav__link.is-active { color: var(--color-primary-lift); }

/* Le CTA du pied de page, présent sur les SIX pages : rouge 14 px sur le noir,
   4,35:1. Le !important est obligatoire, la déclaration d'origine en porte un. */
.site-footer__contact-cta { color: var(--color-primary-lift) !important; }

/* Les accents de titre en gros corps. Seuil 3 et non 4,5, mais l'affiche du CTA
   final pose son titre sur un voile clair où le rouge de base ne vaut plus que
   2,93:1. -lift y remonte à 3,76:1. */
.final-cta__accent,
.final-cta__title .accent,
.page-hero__title .accent { color: var(--color-primary-lift); }

/* ── Les quatre règles rendues fausses par la hausse de --color-surface ─────
   Toutes portaient -lift, mesuré 4,74:1 sur l'ancienne plaque #171717, tombé à
   3,76:1 sur #2B2B2B. Elles passent au cran suivant : 5,12:1. */
.form-section__head > span:not(.form-section__num) { color: var(--color-primary-soft); }
.form-checkbox__label a { color: var(--color-primary-soft) !important; }
.rfc-chip span { color: var(--color-primary-soft); }
.contact-info__countries .eyebrow { color: var(--color-primary-soft); }


/* ══════════════════════════════════════════════════════════════════════════
   LA PLAQUE TEINTÉE — recette unique, 2026-08-12
   ══════════════════════════════════════════════════════════════════════════
   Demande de Gabriel : « je voudrais que tous les boutons de couleurs soient
   traités de la même manière que ces boutons », capture à l'appui — les quatre
   promesas de ¿Cómo lo hacemos?. La référence est donc NOTRE PROPRE SITE, il
   n'y a rien à transposer, seulement à généraliser.

   ÉTAT DES LIEUX MESURÉ SUR LE DOM DES SIX PAGES. Trois familles cohabitaient :
     A. la plaque teintée, déjà la bonne recette, mais avec SIX alphas de fond
        différents (0,06 · 0,08 · 0,10 · 0,12 · 0,14 · 0,18) et HUIT alphas de
        bordure (0,20 → 0,55). Personne n'aurait pu deviner laquelle est la
        bonne : aucune ne l'était, il n'y avait pas de recette.
     B. l'aplat plein : pastilles, chiffres, tags. Une partie venait de la passe
        de contraste, où l'aplat servait à sauver du rouge illisible en texte.
     C. les boutons d'ACTION, .btn et compagnie.

   LA RECETTE, reprise à l'identique de .promises--scene .promise :
     fond      accent 14 % → 6 % en dégradé vertical, sur rgba(23,23,23,0.55)
     bordure   1 px, accent 42 %
     texte     blanc à 96 %
     ombres    liseré interne blanc 6 %, halo externe accent 8 %, portée 35 %
     icône     accent éclairci, avec sa lueur

   MESURE, blanc sur la plaque, les six accents × les trois sols :
     rouge 17,0 / 15,7 / 14,8 · violet 16,3 / 15,0 / 14,0 · orange 15,7 / 14,3 /
     13,4 · cyan 15,4 / 14,0 / 13,1 · vert 15,2 / 13,8 / 12,9 · argent 13,5 /
     12,1 / 11,2. La plaque est donc PLUS SÛRE que l'aplat plein qu'elle
     remplace, où le texte blanc plafonnait à 4,62:1 sur le rouge.

   L'ARGENT EST LE SEUL CAS PARTICULIER, et c'est la mesure qui l'impose : un
   accent clair au même alpha donne une plaque bien plus claire. À 14 % l'argent
   produit #2B2B2C sur sol-0, c'est-à-dire --color-surface #2B2B2B au pixel
   près : la plaque cesse de se lire comme une plaque et devient une carte
   ordinaire. Ses alphas sont donc divisés par deux, 7 % et 24 %.

   CE QUE LA RECETTE NE TOUCHE PAS, volontairement : ni le rayon, ni le
   remplissage, ni la taille de texte, ni l'affichage. C'est un TRAITEMENT de
   surface, pas une géométrie. Les pastilles rondes restent rondes, les pilules
   restent des pilules.

   TROIS FAMILLES EXCLUES, et pourquoi :
     · .btn — le CTA primaire. Un aplat rouge plein est ce qui en fait le point
       d'action de la page ; en plaque teintée il ne serait plus primaire, il
       aurait le même poids qu'un label. À dire à Gabriel, pas à trancher seul.
     · .need et .cap — les cartes pleine couleur de Soluciones et Operación,
       demandées explicitement (« des cards full couleurs comme palo alto »).
       Ce sont des cartes de contenu, pas des boutons.
     · .skip-link, le widget de l'assistant, et le chrome de navigation
       (.main-nav__link, .lang-switch__btn) : systèmes à part.            */

.eyebrow,
main > section[data-sol="1"] > .container .eyebrow,
main > section[data-sol="2"] > .container .eyebrow,
main > section[data-sol="1"] > .container .industries__head .eyebrow,
main > section[data-sol="1"] .industries__head .eyebrow,
.hero__eyebrow, .page-hero__eyebrow, .final-cta__eyebrow,
.symptom__idx, .layer__idx, .pillar__num,
/* .method__index RETIRE de cette liste le 2026-08-14. Les grands numeraux 01
   a 06 des bandes de metodologia ont DEJA leur propre remplissage, et il est
   persona : `background: var(--persona)` avec `color: var(--persona-on)` a la
   l.9457. La recette de plaque leur imposait par-dessus un --plq rouge, d'ou
   un cadre rouge autour du 06 sur une bande verte — vu par Gabriel en
   capture.
   C'est la DEUXIEME fois aujourd'hui que cette liste capture un element qui
   portait deja sa couleur : .practice__num ce matin, .method__index ce soir.
   Avant d'y ajouter un selecteur, verifier qu'il n'a pas deja un fond. */
/* .practice__num RETIRE de cette liste le 2026-08-14. Les grands chiffres
   01 a 06 des six cartes de heros n'ont JAMAIS eu de fond : ce sont des
   numeraux colores par persona, poses en absolu dans le coin de la carte.
   La recette leur mettait un degrade rouge et une bordure a 42 % : c'est le
   « cuadro rojo encima de cada numero » signale par Gabriel.
   Une contre-regle existait, mais scopee #liga — section supprimee le
   2026-08-14 quand les cartes ont rejoint #sistema. Elle est donc morte,
   et le cadre est revenu. On corrige la cause, pas le symptome. */
.form-section__num, .chip, .rfc-chip, .partner-level__tag,
.destacado__kicker, .destacado__arrow, .alliances__coverage-stat,
.about-card__icon-wrap, .feature-card__icon, .leader-card__avatar,
.case-flow__tag, .framework, .industries__sector, .country__since,
.front {
  --plq: var(--color-primary);
  --plq-fond-haut: 14%;
  --plq-fond-bas: 6%;
  --plq-bord: 42%;
  border-style: solid;
  border-width: 1px;
  border-color: color-mix(in srgb, var(--plq) var(--plq-bord), transparent);
  background:
    linear-gradient(180deg,
      color-mix(in srgb, var(--plq) var(--plq-fond-haut), transparent),
      color-mix(in srgb, var(--plq) var(--plq-fond-bas), transparent)),
    rgba(23, 23, 23, 0.55);
  color: rgba(248, 250, 252, 0.96);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.06),
    0 0 0 1px color-mix(in srgb, var(--plq) 8%, transparent),
    0 12px 32px -16px color-mix(in srgb, var(--plq) 35%, transparent);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}

/* Les accents autres que le rouge. Chacun garde le sien, la recette ne change
   pas — c'est tout l'intérêt d'avoir sorti l'accent en variable. */
.case-flow__tag              { --plq: var(--color-grc); }
.industries__sector,
.country__since              { --plq: var(--color-csirt); }
.front[data-persona="ctem"]      { --plq: var(--color-ctem); }
.front[data-persona="csirt"]     { --plq: var(--color-csirt); }
.front[data-persona="zerotrust"] { --plq: var(--color-zerotrust); }
.front[data-persona="grc"]       { --plq: var(--color-grc); }

/* L'argent, alphas divisés par deux — voir la mesure ci-dessus. */
.framework,
.front[data-persona="ngsoc"] {
  --plq: var(--color-ngsoc);
  --plq-fond-haut: 7%;
  --plq-fond-bas: 3%;
  --plq-bord: 24%;
}

/* L'icône : l'accent éclairci, avec sa lueur. C'est le seul endroit où la
   couleur reste de la COULEUR et non un aplat, et elle y est légitime : une
   icône n'est pas du texte, son seuil est 3:1 et non 4,5. */
.eyebrow .icon,
.hero__eyebrow .icon, .page-hero__eyebrow .icon, .final-cta__eyebrow .icon,
.chip .icon, .rfc-chip .icon, .framework .icon, .industries__sector .icon,
.about-card__icon-wrap .icon, .feature-card__icon .icon,
.destacado__arrow .icon, .case-flow__tag .icon {
  color: color-mix(in srgb, var(--plq) 62%, #FFFFFF);
  filter: drop-shadow(0 0 8px color-mix(in srgb, var(--plq) 55%, transparent));
}

/* Le survol, pour celles qui sont cliquables. Même geste que la référence :
   deux pixels de lévitation et la bordure qui se resserre. */
a.rfc-chip:hover, a.industries__sector:hover, a.destacado__arrow:hover,
a.front:hover, .front a:hover {
  transform: translateY(-2px);
  border-color: color-mix(in srgb, var(--plq) 65%, transparent);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.08),
    0 0 0 1px color-mix(in srgb, var(--plq) 18%, transparent),
    0 18px 40px -16px color-mix(in srgb, var(--plq) 55%, transparent);
}

/* La référence elle-même repasse par la recette, pour qu'il n'existe plus DEUX
   sources de vérité. Les valeurs sont identiques à celles qu'elle portait en
   dur : rien ne change à l'écran dans ¿Cómo lo hacemos?, seule la provenance
   des nombres change. */
.promises--scene .promise {
  --plq: var(--color-primary);
  border-color: color-mix(in srgb, var(--plq) 42%, transparent);
  background:
    linear-gradient(180deg,
      color-mix(in srgb, var(--plq) 14%, transparent),
      color-mix(in srgb, var(--plq) 6%, transparent)),
    rgba(23, 23, 23, 0.55);
}


/* ── Les six qui perdaient la cascade ──────────────────────────────────────
   Mesuré par getComputedStyle, pas supposé : sur 21 sélecteurs vérifiés, six
   n'avaient reçu que la bordure de la recette, pas le fond. Chacun est battu
   par une règle plus spécifique, et la plus forte atteint (0,3,2). Ma recette
   est à (0,1,0). Quadrupler la classe donnerait (0,4,0) et gagnerait, mais
   rendrait la liste illisible ; !important est le mur documenté de ce fichier,
   et il est ici employé avec la règle battue nommée à chaque ligne.

     .symptom__idx        battu par  main > section[data-sol="1"] .symptom__idx   (0,2,2)
     .layer__idx          battu par  main > section[data-sol="1"] .layer--command .layer__idx  (0,3,2)
     .front               battu par  la règle d'aplat de la passe précédente     (0,2,2)
     .framework           battu par  .diferenciador__proof .framework            (0,2,0)
     .country__since      battu par  .country--expanding .country__since         (0,2,0)
     .feature-card__icon  battu par  .section--dark .feature-card__icon          (0,2,0)
     .industries__sector  bordure seule, battue par sa propre 2e déclaration       */

.symptom__idx, .layer__idx, .front, .framework, .country__since,
.feature-card__icon, .industries__sector {
  border-color: color-mix(in srgb, var(--plq) var(--plq-bord), transparent) !important;
  background:
    linear-gradient(180deg,
      color-mix(in srgb, var(--plq) var(--plq-fond-haut), transparent),
      color-mix(in srgb, var(--plq) var(--plq-fond-bas), transparent)),
    rgba(23, 23, 23, 0.55) !important;
  color: rgba(248, 250, 252, 0.96) !important;
}

/* Les deux enfants de .front. Ils portaient --color-fg-light, l'encre sombre,
   posee quand la tuile etait un aplat CLAIR : sur la plaque teintee, sombre,
   ils tombent a 1,05:1, donc invisibles. Mesure a l'appui, pas une supposition.
   Ils repassent au blanc (le nom) et au muted (le verbe), comme dans la
   reference ou le texte de la plaque est blanc et l'accent est porte par la
   bordure et l'icone. Battus par main > section[data-sol="1"] .front__name
   a (0,2,2), d'ou le !important.
   Mesure apres correction : blanc 15,7:1 sur la plaque rouge, 14,3:1 sur
   l'orange ; muted #94A3B8 6,4 a 7,2:1 selon l'accent. */
main > section[data-sol="1"] .front__name,
.front__name { color: rgba(248, 250, 252, 0.96) !important; }
main > section[data-sol="1"] .front__verb,
.front__verb { color: var(--color-muted) !important; }


/* ══════════════════════════════════════════════════════════════════════════
   « LO QUE NOS HACE ÚNICOS » — la plaque teintée y est ANNULÉE, 2026-08-12
   ══════════════════════════════════════════════════════════════════════════
   Demande de Gabriel : la recette de plaque s'applique partout SAUF dans cette
   section, où les cartes des six super-héros doivent retrouver l'état qu'elles
   avaient juste avant.

   Ce que la recette y avait changé, et c'est là qu'était l'erreur : les quatre
   classes touchées dans #liga sont .eyebrow, .pillar__num, .practice__num et
   .framework. Or .practice__num — les grands chiffres 01 à 06 des cartes de
   héros — n'avait JAMAIS EU DE FOND. C'étaient des numéraux colorés par
   persona, posés à même la carte. La recette leur a mis une boîte qu'ils n'ont
   jamais portée, et c'est ce qui abîmait les cartes.

   Les valeurs ci-dessous ne sont pas reconstituées de mémoire : elles sont
   relevées dans les règles qui précédaient la recette dans ce même fichier,
   avec leur numéro de ligne.                                                */

/* La contre-regle « #liga .practice__num » qui vivait ici est supprimee le
   2026-08-14 : #liga n'existe plus, et la cause est corrigee plus haut. */

/* Les pastilles d'ordre des trois piliers : aplat rouge plein, chiffre blanc.
   Règle d'origine l.10265. */
#liga .pillar__num {
  background: var(--color-primary) !important;
  border: 0 !important;
  border-radius: var(--radius-sm);
  box-shadow: none !important;
  backdrop-filter: none !important;
  -webkit-backdrop-filter: none !important;
  color: var(--color-fg) !important;
}

/* L'eyebrow « NUESTRO DIFERENCIADOR » : du texte rouge éclairci, pas une
   pilule. #liga est au sol-0, où --color-primary-lift mesure 5,58:1. Règle
   d'origine l.90. */
#liga > .container > .diferenciador__head .eyebrow,
#liga .eyebrow {
  background: none !important;
  border: 0 !important;
  box-shadow: none !important;
  backdrop-filter: none !important;
  -webkit-backdrop-filter: none !important;
  color: var(--color-primary-lift) !important;
}

/* Les quatre cartouches de frameworks en bas de section : argent très discret,
   rayon en pilule, et l'icône en VERT de validation et non en accent argent.
   Règle d'origine l.5844 et l.5857. */
#liga .framework {
  background: rgba(148, 163, 184, 0.06) !important;
  border: 1px solid rgba(148, 163, 184, 0.22) !important;
  border-radius: var(--radius-full);
  box-shadow: none !important;
  backdrop-filter: none !important;
  -webkit-backdrop-filter: none !important;
  color: rgba(241, 245, 249, 0.92) !important;
}
#liga .framework .icon {
  color: var(--color-success);
  filter: none;
}


/* ══════════════════════════════════════════════════════════════════════════
   INDUSTRIAS — la ligne des 95 % arrivee d'#alianzas, 2026-08-12
   ══════════════════════════════════════════════════════════════════════════
   Memes valeurs que .alliances__coverage, qu'elle remplace : la phrase n'a pas
   change, seule sa section a change. Elle n'est PAS centree ici, contrairement
   a sa version d'origine : #industrias a un en-tete aligne a gauche
   (.section-head--left), et une phrase centree sous un titre a gauche aurait
   introduit un troisieme axe dans la section.
   La pastille du chiffre passe par la recette de plaque teintee, comme toutes
   les autres pastilles du site.                                             */
.industries__coverage {
  margin: var(--space-7) 0 0;
  max-width: 760px;
  font-size: 15px;
  line-height: 1.5;
  color: var(--color-muted);
}
.industries__coverage-stat {
  display: inline-block;
  padding: 3px 9px 2px;
  border-radius: var(--radius-full);
  font-size: 1em;
  font: 800 1.15em/1 var(--font-mono);
  margin-right: 4px;
  /* la recette de plaque, avec l'accent de marque */
  --plq: var(--color-primary);
  border: 1px solid color-mix(in srgb, var(--plq) 42%, transparent);
  background:
    linear-gradient(180deg,
      color-mix(in srgb, var(--plq) 14%, transparent),
      color-mix(in srgb, var(--plq) 6%, transparent)),
    rgba(23, 23, 23, 0.55);
  color: rgba(248, 250, 252, 0.96);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.06),
    0 0 0 1px color-mix(in srgb, var(--plq) 8%, transparent),
    0 12px 32px -16px color-mix(in srgb, var(--plq) 35%, transparent);
}

/* La liste de secteurs passe de six a DIX entrees. Elle etait en flex libre, ce
   qui tenait a six ; a dix elle doit pouvoir revenir a la ligne proprement et
   ne jamais pousser l'en-tete. Le second rang (--secondary) reste visuellement
   en retrait : ces trois secteurs ne sont pas couverts par le 95 %. */
.industries__sectors {
  flex-wrap: wrap;
  gap: 8px 10px;
}
@media (max-width: 900px) {
  .industries__sectors { justify-content: flex-start; }
}


/* ══════════════════════════════════════════════════════════════════════════
   SOLUCIONES — le héros à côté de chaque méthodologie, 2026-08-12
   ══════════════════════════════════════════════════════════════════════════
   Principe posé par Gabriel : « on doit toujours montrer le héros à côté de
   chaque méthodologie ». Les six visages deviennent le fil qui fait comprendre
   qu'on parle du MÊME objet vu à trois profondeurs, au lieu de trois listes.

   POURQUOI DES BUSTES ET PAS LES DÉCOUPES EXISTANTES. Les six découpes
   heroes/*-cut.webp sont en pied, 800 × 1072. Mesuré : dans une boîte de la
   taille d'une carte, une figure en pied donne une tête de 30 à 35 px, où l'on
   voit « une personne » et non « ce héros-là ». Six bustes ont donc été
   recadrés (440 × 440, tête = 48 % du cadre, 23 à 40 Ko), et le plancher de
   lisibilité a été mesuré sur planche : lisible à 160, 130 et 96 px ; à 72 px
   le visage est une tache ; à 52 px il ne reste qu'une silhouette.
   PLANCHER RETENU : 96 px. Ici on est à 150, donc large.

   TROIS GRAMMAIRES DISTINCTES, c'est la phase 3 du plan :
     · #sistema    buste carré à gauche d'une plaque  → le CYCLE
     · #soluciones figure émergeant du coin bas-droit → le BESOIN
     · #liga       portrait de 280 px en tête de carte → l'INCARNATION
   Réutiliser ici la grammaire de #liga aurait rendu les deux sections
   identiques, ce qui est exactement la redondance qu'on cherche à défaire.

   POIDS : les six bustes sont des fichiers nouveaux (178 Ko au total), mais ils
   ne remplacent rien — les découpes en pied restent utilisées par #liga.      */

.needs__grid .need__link { position: relative; overflow: hidden; }

.need__hero {
  position: absolute;
  right: -14px;
  bottom: -16px;
  width: 150px;
  height: 150px;
  object-fit: contain;
  object-position: bottom right;
  pointer-events: none;
  /* Le buste est une découpe sur transparent : sur un aplat persona clair
     (argent, vert, orange) la figure est sombre et se détache seule ; sur les
     deux aplats foncés (violet, et le rouge s'il revenait) elle a besoin d'un
     souffle. L'ombre portée fait ce travail sans ajouter de forme. */
  filter: drop-shadow(0 6px 18px rgba(0, 0, 0, 0.45));
  transition: transform var(--duration-slow) var(--ease-out);
}
.need__link:hover .need__hero { transform: translateY(-4px) scale(1.03); }

/* Le texte recule pour ne pas passer sous la figure. Mesuré : carte de 428 px
   à 1440 avec 28 px de padding, le texte garde 252 px, soit environ 35 signes
   par ligne — la mesure a été refaite à chaque largeur du harnais. */
.needs__grid .need__text { padding-right: 118px; }
.needs__grid .need__cta  { position: relative; z-index: 1; }

@media (max-width: 560px) {
  /* Une seule colonne : la carte tombe à 335 px et 150 px de figure prendraient
     45 % de sa largeur. Le buste descend à 118 px, ce qui reste TRÈS au-dessus
     du plancher de 96 px mesuré. */
  .need__hero { width: 118px; height: 118px; right: -10px; bottom: -12px; }
  .needs__grid .need__text { padding-right: 92px; }
}

/* ── La carte-passerelle ───────────────────────────────────────────────────
   Elle n'est pas une méthodologie : pas de héros, pas d'aplat persona. Elle
   passe par la plaque teintée, la grammaire du site pour un élément coloré qui
   n'est pas un aplat, avec l'accent de marque. Mesuré sur sol-1 : plaque
   #311818, blanc dessus 15,7:1 ; bordure #681C1C à 1,55:1 du sol.
   Elle est volontairement plus discrète que les cinq aplats (dont la frontière
   contre le sol va de 4,66 à 14,94:1) : c'est une passerelle, pas une offre. */
.need--bridge { --plq: var(--color-primary); }
#soluciones .need--bridge .need__link {
  border: 1px solid color-mix(in srgb, var(--plq) 42%, transparent);
  background:
    linear-gradient(180deg,
      color-mix(in srgb, var(--plq) 14%, transparent),
      color-mix(in srgb, var(--plq) 6%, transparent)),
    rgba(23, 23, 23, 0.55);
  color: rgba(248, 250, 252, 0.96);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.06),
    0 0 0 1px color-mix(in srgb, var(--plq) 8%, transparent),
    0 12px 32px -16px color-mix(in srgb, var(--plq) 35%, transparent);
}
#soluciones .need--bridge .need__title,
#soluciones .need--bridge .need__cta    { color: rgba(248, 250, 252, 0.96); }
#soluciones .need--bridge .need__method { color: var(--color-primary-soft); opacity: 1; }
#soluciones .need--bridge .need__text   { color: var(--color-muted); opacity: 1; }
/* Pas de figure, donc pas de recul du texte. */
.needs__grid .need--bridge .need__text { padding-right: 0; }
#soluciones .need--bridge .need__link:hover {
  background:
    linear-gradient(180deg,
      color-mix(in srgb, var(--plq) 20%, transparent),
      color-mix(in srgb, var(--plq) 10%, transparent)),
    rgba(23, 23, 23, 0.55);
  border-color: color-mix(in srgb, var(--plq) 65%, transparent);
}


/* ══════════════════════════════════════════════════════════════════════════
   SISTEMA — les cinq frentes deviennent des portes, 2026-08-12
   ══════════════════════════════════════════════════════════════════════════
   TROISIÈME GRAMMAIRE, et c'est le point de la phase 3. Les six visages sont
   désormais présents dans trois sections ; s'ils y étaient présentés de la même
   façon, la page se lirait comme trois fois la même liste. D'où :
     · ici        buste carré à gauche, verbe en grand, nom en petit → le CYCLE
     · #soluciones figure émergeant du coin d'un aplat              → le BESOIN
     · #liga      portrait de 280 px en tête de carte                → l'INCARNATION

   LE BUSTE EST À 96 px, ce qui n'est pas un choix esthétique mais le PLANCHER
   mesuré sur planche de contrôle : lisible à 160, 130 et 96 px ; à 72 px le
   visage devient une tache ; à 52 px il ne reste qu'une silhouette. Les plaques
   faisaient 70 px de haut, elles ne pouvaient donc pas porter un héros
   lisible — c'est la plaque qui s'adapte au plancher, pas l'inverse.

   Le verbe passe devant le nom : ce diagramme dit ce que chaque frente FAIT
   dans le cycle, #liga dit qui il EST.                                       */

.fronts {
  grid-template-columns: repeat(auto-fit, minmax(196px, 1fr));
  gap: clamp(10px, 1vw, 16px);
}
.front { padding: 0; }
.front__link {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 8px 14px 8px 8px;
  text-decoration: none;
  color: inherit;
  min-height: 44px;   /* cible tactile */
}
.front__bust {
  width: 96px;
  height: 96px;
  flex: 0 0 96px;
  object-fit: contain;
  object-position: bottom center;
  filter: drop-shadow(0 4px 12px rgba(0, 0, 0, 0.5));
  transition: transform var(--duration-normal) var(--ease-out);
}
.front__link:hover .front__bust { transform: translateY(-3px) scale(1.04); }
.front__body { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
/* Le verbe domine : il porte le cycle. Il reste sous les 18,66 px qui font le
   texte large, donc son seuil est 4,5 — le blanc y vaut 15,7 à 17,6:1 selon
   l'accent de la plaque, très au-dessus. */
.front__verb {
  font-size: clamp(15px, 1.25vw, 19px);
  font-weight: 700;
  letter-spacing: -0.01em;
  line-height: 1.15;
}
.front__name {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
/* Le nom recule dans la hiérarchie mais reste du texte : il passe au muted,
   qui vaut 7,18:1 sur sol-1 et 6,28:1 sur sol-2. */
.front__name { color: var(--color-muted) !important; }
.front__verb { color: rgba(248, 250, 252, 0.96) !important; }

@media (max-width: 560px) {
  .fronts { grid-template-columns: minmax(0, 1fr); }
}


/* ══════════════════════════════════════════════════════════════════════════
   ¿POR QUÉ NADIE MÁS LO RESUELVE? — la comparaison, 2026-08-14
   ══════════════════════════════════════════════════════════════════════════
   Deux colonnes de même largeur et de même hauteur, mais PAS de même poids :
   c'est tout le mécanisme. Celle de gauche est en retrait — bordure neutre,
   tirets, texte muted. Celle de droite est une plaque teintée de marque, avec
   des flèches et des mots en gras. Le lecteur voit lequel des deux modèles est
   le nôtre avant d'avoir lu une ligne.

   POURQUOI PAS DEUX APLATS PLEINS. La fiche 08 réserve l'aplat plein aux
   moments où la couleur doit peser comme une masse. Ici les deux colonnes
   doivent rester lisibles côte à côte et se comparer ligne à ligne : un aplat
   rouge plein écraserait la colonne de gauche et transformerait une comparaison
   en publicité. La plaque suffit, et son blanc mesure 15,7:1.

   Mesures : la colonne de droite sur sol-1 donne une plaque #311818, blanc
   dessus 15,7:1, bordure #681C1C. La colonne de gauche prend --color-surface
   #2B2B2B, frontière 1,301 contre le sol, muted dessus 5,52:1.             */

.versus__head { max-width: 50rem; margin-inline: auto; }

.versus__cols {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(16px, 1.8vw, 28px);
  align-items: stretch;
}

.versus__col {
  padding: clamp(24px, 2.4vw, 36px) clamp(20px, 2.2vw, 32px);
  border-radius: var(--radius-lg);
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
}

/* En retrait : c'est le modèle qu'on n'est pas. */
.versus__col--them {
  background: var(--color-surface);
  border: 1px solid var(--color-border-strong);
}
/* Le nôtre : la plaque de marque. */
.versus__col--us {
  --plq: var(--color-primary);
  border: 1px solid color-mix(in srgb, var(--plq) 42%, transparent);
  background:
    linear-gradient(180deg,
      color-mix(in srgb, var(--plq) 14%, transparent),
      color-mix(in srgb, var(--plq) 6%, transparent)),
    rgba(23, 23, 23, 0.55);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.06),
    0 0 0 1px color-mix(in srgb, var(--plq) 8%, transparent),
    0 12px 32px -16px color-mix(in srgb, var(--plq) 35%, transparent);
}

.versus__tag {
  align-self: flex-start;
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  padding: 6px 14px;
  border-radius: var(--radius-full);
}
.versus__col--them .versus__tag {
  border: 1px solid var(--color-border-strong);
  color: var(--color-muted);
}
/* Le libellé de notre colonne est du rouge en PETIT corps sur une plaque :
   -lift n'y suffirait pas (3,76:1 sur cette plaque), -soft donne 5,12:1. */
.versus__col--us .versus__tag {
  border: 1px solid color-mix(in srgb, var(--color-primary) 55%, transparent);
  color: var(--color-primary-soft);
}

.versus__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: clamp(12px, 1.2vw, 18px);
}
.versus__list li {
  display: flex;
  gap: var(--space-3);
  font-size: clamp(14px, 1.05vw, 16px);
  line-height: 1.5;
  color: var(--color-muted);
}
.versus__list strong { color: var(--color-fg); font-weight: 700; }

.versus__mk {
  flex: 0 0 auto;
  font-family: var(--font-mono);
  line-height: 1.5;
}
/* Le texte est enrobe dans .versus__txt, et ce n'est pas cosmetique : le li est
   un conteneur FLEX, donc son gap de 12 px s'appliquait aussi entre le <strong>
   et le texte qui le suit — ils etaient deux items flex distincts. Resultat
   visible : un espace anormal avant la virgule dans les quatre lignes de la
   colonne de droite. Un seul enfant apres le marqueur, et le gap ne joue plus
   qu'a l'endroit voulu. */
.versus__txt { min-width: 0; }
.versus__col--them .versus__mk { color: var(--color-muted); opacity: 0.6; }
.versus__col--us   .versus__mk { color: var(--color-primary-soft); }

@media (max-width: 47.5rem) {
  /* Une colonne : la comparaison se lit alors de haut en bas, le modèle
     habituel puis le nôtre. L'ordre du DOM est déjà celui-là. */
  .versus__cols { grid-template-columns: minmax(0, 1fr); }
}


/* ══════════════════════════════════════════════════════════════════════════
   L'ORBITE — l'emblème nommé, 2026-08-14
   ══════════════════════════════════════════════════════════════════════════
   La Capitana au centre, cinq frentes autour à 72°. Deux anneaux concentriques,
   un plein et un pointillé, comme la référence. Aucun rayon tracé : les nœuds
   posés sur l'anneau suffisent à dire l'appartenance, et cinq traits partant du
   centre auraient fait un astérisque.

   POSITIONNEMENT PAR left/top, PAS PAR TRANSFORM. C'est une contrainte, pas une
   préférence : le reveal GSAP anime le transform des .front
   (revealGroup('.fronts', '.front', { y: 18 })). Positionner par transform
   aurait fait entrer les deux en conflit, et les nœuds auraient sauté à
   l'origine à chaque apparition. Avec left/top, la position vient de la mise en
   page et l'animation reste libre — elles se composent au lieu de se battre.

   L'angle du nœud i vaut -90° + i × 72°, donc CTEM en haut puis dans le sens
   des aiguilles. L'ordre est celui du CYCLE et non de l'alphabet : anticiper,
   détecter, répondre, protéger, gouverner.

   REPLI SOUS 760 px : l'orbite se défait et redevient la grille de plaques
   d'avant. Mesuré : à 375 px le conteneur ne fait plus que 295 px, le rayon
   tomberait à 100 px et des nœuds de 148 px se chevaucheraient. Et surtout le
   buste passerait sous les 96 px du plancher de lisibilité.              */

@media (min-width: 47.5rem) {
  .orbit {
    --orbit-size: min(560px, 100%);
    /* Rayon 35 % : 196 px à 560, plus 74 de demi-nœud = 270 < 280, le nœud
       reste dans le cercle. La hauteur de nœud descend à 132 et celle du noyau
       à 140 pour dégager le libellé « La Capitana » : mesuré, les deux nœuds du
       bas ont leur centre à y = +159 et leur bord haut à +93, contre +70 pour
       le bas du noyau — 23 px de dégagement là où il n'y en avait que 4. */
    --orbit-r: 35%;
    --onode-w: 148px;
    --onode-h: 132px;
    position: relative;
    width: var(--orbit-size);
    aspect-ratio: 1;
    margin: clamp(8px, 1vw, 20px) auto 0;
  }

  /* Les deux anneaux. Le plein porte la structure, le pointillé la respiration. */
  .orbit::before,
  .orbit::after {
    content: '';
    position: absolute;
    border-radius: var(--radius-full);
    pointer-events: none;
  }
  .orbit::before {
    inset: 12%;
    border: 1px solid var(--color-border-strong);
  }
  .orbit::after {
    inset: 30%;
    border: 1px dashed var(--color-border);
  }

  /* ── Le noyau : La Capitana ─────────────────────────────────────────────
     Elle est nommée en HTML sous le buste, jamais dans l'image. Le halo rouge
     dit que c'est le centre sans avoir besoin d'un aplat, qui aurait écrasé
     les cinq nœuds autour. */
  .orbit__core {
    position: absolute;
    left: 50%;
    top: 50%;
    width: 168px;
    height: 140px;
    margin-left: -84px;
    margin-top: -70px;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: flex-end;
    text-align: center;
  }
  .orbit__core::before {
    content: '';
    position: absolute;
    inset: -6%;
    border-radius: var(--radius-full);
    background: radial-gradient(circle at 50% 42%,
      color-mix(in srgb, var(--color-primary) 30%, transparent) 0%,
      transparent 68%);
    pointer-events: none;
  }
  .orbit__core-bust {
    width: 120px;
    height: 120px;
    object-fit: contain;
    object-position: bottom center;
    filter: drop-shadow(0 6px 18px rgba(0, 0, 0, 0.55));
  }
  .orbit__core-label { display: flex; flex-direction: column; gap: 1px; margin-top: 2px; }
  .orbit__core-name {
    font-family: var(--font-mono);
    font-size: var(--text-sm);
    font-weight: 700;
    letter-spacing: 0.14em;
    /* Rouge en PETIT corps sur le sol-1 de la section : -lift donne 4,90:1,
       le rouge de base seulement 3,81. */
    color: var(--color-primary-lift);
  }
  .orbit__core-role {
    font-size: var(--text-xs);
    color: var(--color-muted);
    letter-spacing: 0.02em;
  }

  /* ── Les cinq nœuds ────────────────────────────────────────────────────
     La position vient d'un calc sur left/top, jamais d'un transform. Les
     cosinus et sinus sont écrits en dur parce que CSS n'a pas trigonométrie
     partout : l'angle du nœud i est -90° + i × 72°.
       i=0  -90°   cos  0.000  sin -1.000
       i=1  -18°   cos  0.951  sin -0.309
       i=2   54°   cos  0.588  sin  0.809
       i=3  126°   cos -0.588  sin  0.809
       i=4  198°   cos -0.951  sin -0.309                                  */
  .orbit__ring {
    display: block;
    position: absolute;
    inset: 0;
    grid-template-columns: none;
    gap: 0;
    margin: 0;
    padding: 0;
  }
  .orbit__ring .front {
    position: absolute;
    width: var(--onode-w);
    min-height: var(--onode-h);
    left: calc(50% + var(--cx) * var(--orbit-r) - var(--onode-w) / 2);
    top:  calc(50% + var(--cy) * var(--orbit-r) - var(--onode-h) / 2);
  }
  .orbit__ring .front[style*="--i: 0"] { --cx:  0.000; --cy: -1.000; }
  .orbit__ring .front[style*="--i: 1"] { --cx:  0.951; --cy: -0.309; }
  .orbit__ring .front[style*="--i: 2"] { --cx:  0.588; --cy:  0.809; }
  .orbit__ring .front[style*="--i: 3"] { --cx: -0.588; --cy:  0.809; }
  .orbit__ring .front[style*="--i: 4"] { --cx: -0.951; --cy: -0.309; }

  /* Le nœud passe en colonne : buste au-dessus, verbe et nom dessous et
     centrés. La grammaire horizontale de la liste ne tiendrait pas dans un
     carré de 148 px. */
  .orbit__ring .front__link {
    flex-direction: column;
    align-items: center;
    gap: 4px;
    padding: 10px 8px 12px;
    text-align: center;
    min-height: var(--tap-min);
  }
  .orbit__ring .front__bust {
    width: 96px;                /* exactement le plancher mesuré */
    height: 96px;
    flex: 0 0 96px;
  }
  .orbit__ring .front__body { align-items: center; }
  .orbit__ring .front__verb { font-size: clamp(14px, 1.15vw, 17px); }

  /* Le label du rang passe au centre : il coiffe l'emblème au lieu de le
     précéder en drapeau. */
  .layer--fronts .layer__label { text-align: center; }
}

/* Sous 760 px, rien à défaire : .orbit et .orbit__ring redeviennent de simples
   div et ul, et la grille de plaques déjà vérifiée reprend la main. Le noyau,
   lui, se replie en une ligne au-dessus de la liste. */
@media (max-width: 47.5rem) {
  .orbit__core {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-3);
    margin-bottom: var(--space-4);
  }
  .orbit__core-bust { width: 72px; height: 72px; object-fit: contain; object-position: bottom center; }
  .orbit__core-label { display: flex; flex-direction: column; }
  .orbit__core-name {
    font-family: var(--font-mono); font-size: var(--text-sm); font-weight: 700;
    letter-spacing: 0.14em; color: var(--color-primary-lift);
  }
  .orbit__core-role { font-size: var(--text-xs); color: var(--color-muted); }
}


/* Les deux points d'appui du hero — 2026-08-14.
   Repris du hero React du DS 1.0. Le troisième (« Gobernado por la Value
   Delivery PMO ») saute : le principe organisateur est La Capitana.
   La puce est un disque de 6 px en rouge éclairci — c'est une forme, pas du
   texte, donc le seuil est 3:1 et non 4,5 ; --color-primary-lift y donne 5,58
   sur le sol de marque, largement au-dessus. */
.hero__points {
  list-style: none;
  margin: clamp(18px, 1.8vw, 26px) 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: clamp(8px, 0.9vw, 12px);
  max-width: 46ch;
}
.hero__points li {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  font-size: clamp(14px, 1.05vw, 16px);
  line-height: 1.5;
  color: var(--color-muted);
}
.hero__points li::before {
  content: '';
  flex: 0 0 auto;
  width: 6px;
  height: 6px;
  border-radius: var(--radius-full);
  background: var(--color-primary-lift);
}


/* ══════════════════════════════════════════════════════════════════════════
   LES SIX CAPACITÉS EN DEUX RANGÉES DE TROIS — 2026-08-14
   ══════════════════════════════════════════════════════════════════════════
   Demande de Gabriel : à la place de la roue, les grandes cartes en deux
   rangées de trois, TOUTES DE MÊME TAILLE.

   Trois colonnes divisent six exactement — aucun orphelin, à aucune largeur.
   C'est la seule division de six qui tienne aussi en 2 et en 1 sans reste.

   « MISMA TALLA » impose de défaire le traitement de bannière de la carte de
   commandement : elle était en deux colonnes, pleine largeur, avec un portrait
   de 300 px et un titre de 30. Elle redevient une carte comme les cinq autres.
   Ce qui la distingue passe entièrement au CONTENU : son libellé de rang
   « Mando · orquestación », sa bordure rouge, et sa première position.

   Tout ce bloc est en fin de fichier et surcharge donc les déclarations
   d'origine à spécificité égale — vérifié par getComputedStyle, pas supposé. */

.practices__grid--six {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-4);
  margin-top: var(--space-5);
}
@media (min-width: 45rem) {
  .practices__grid--six {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--space-5);
    /* « Misma talla » au sens strict : sans ceci, chaque RANGÉE prend la
       hauteur de son contenu et les deux rangées diffèrent — mesuré, 529 px
       contre 509 à 1440. Avec 1fr toutes les rangées prennent la hauteur de la
       plus haute, donc les six cartes sont identiques.
       Volontairement PAS appliqué sous 45rem : en colonne unique il n'y a plus
       de comparaison possible entre cartes voisines, et forcer la hauteur de la
       plus longue ajouterait jusqu'à 120 px de vide sous cinq d'entre elles. */
    grid-auto-rows: 1fr;
  }
}
@media (min-width: 62rem) {
  .practices__grid--six { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-5); }
}




/* Le bloc « Marcos de referencia y estándares » sur nosotros — 2026-08-14.
   Il vient de la home, où il vivait dans .diferenciador__proof. Ce wrapper-là
   portait des marges calibrées pour fermer une section de la home ; ici il
   suit une bande de certifications dans la même section, donc il lui faut
   surtout un séparateur et moins d'air au-dessus.
   Les styles internes (.frameworks__label, .frameworks__logos, .framework-logo,
   .frameworks__grid, .framework) sont déjà chargés : les deux pages partagent
   redesign.css. Rien à dupliquer. */
/* Les deux règles de mise en forme du bloc (label en mono, sceaux en flex
   centré) étaient scopées à .diferenciador__proof, l'enveloppe restée sur la
   home. Sans elles le bloc retombait sur .frameworks__grid l.1168, une grille
   à deux colonnes alignée à gauche : les trois sceaux partaient à ras du bord
   pendant que le label et les logos restaient centrés. .about-frameworks est
   donc ajouté aux DEUX sélecteurs plus haut, pour que le bloc garde exactement
   la présentation qu'il avait sur la home. Il a été déplacé, pas redessiné. */
.about-frameworks {
  /* Même grille à gouttière que .diferenciador__proof (l.5824) : sans elle le
     label collait aux logos. Seules les marges extérieures changent, le bloc
     ne ferme plus une section, il suit une bande dans la même section. */
  display: grid;
  gap: var(--space-6);
  margin-top: clamp(32px, 3.4vw, 56px);
  padding-top: clamp(28px, 3vw, 44px);
  border-top: 1px solid var(--color-border);
  text-align: center;
}
/* Les logos portent déjà leur propre marge basse dans la règle générale ; dans
   une grille à gouttière elle s'ajouterait au gap. */
.about-frameworks .frameworks__logos { margin-bottom: 0; }

/* La sortie de #sistema sur la home, une fois le bloc de preuve parti : le CTA
   reste seul et a besoin de son propre espace. */
.sistema__outro {
  margin-top: clamp(40px, 4vw, 72px);
  text-align: center;
}


/* ══════════════════════════════════════════════════════════════════════════
   LES SIX CARTES DE HÉROS : ALIGNEMENT — 2026-08-14
   ══════════════════════════════════════════════════════════════════════════
   Défaut signalé par Gabriel, puis mesuré : la carte de La Capitana ne
   s'alignait sur aucune des cinq autres. Relevé à 1440 px, en offsetTop
   interne (jamais getBoundingClientRect, qui inclut les transformations des
   reveals) :

       carte              titre   desc   chips   « conocer »   vide dessous
       La Capitana        315     348    427     468           39
       les cinq autres    300     337    435     481           26

   Et l'écart empirait en descendant : 88 px contre 26 sous la Capitana à
   900 px de large. Deux causes distinctes, l'une de structure et l'autre de
   flux :

   1. STRUCTURE. La Capitana enveloppait tout son contenu dans un
      .practice__command-body, héritage de sa mise en page en bannière. Les
      cinq autres posent leurs enfants à plat. Deux gouttières différentes
      (0 contre 12 px) et une enveloppe qui ne s'étirait pas : les lignes ne
      pouvaient pas tomber au même endroit. L'enveloppe est retirée du HTML,
      les six cartes ont désormais exactement la même suite d'enfants.

   2. FLUX. Aucune carte ne calait son lien en bas. Les descriptions ayant des
      longueurs différentes, les six « Conocer al héroe » flottaient à six
      hauteurs. margin-top: auto les pose tous sur la même ligne de base.

   Le rang, lui, n'existait que sur la Capitana et lui coûtait 15 px de décalage
   de titre. Les six le portent maintenant, avec les VERBES DÉJÀ PUBLIÉS sur
   metodologia.html (.subnav__role : Orquestar, Anticipar, Detectar, Responder,
   Proteger, Gobernar). Rien d'inventé, et la rangée dit enfin le cycle.       */

.practices__grid--six .practice__rank {
  color: var(--p, var(--color-primary-lift));
  margin: 0;
}
/* La ligne de base commune des six liens. */
.practices__grid--six .practice__more { margin-top: auto; }


/* La Capitana garde un signal de rang, mais il ne passe plus par la taille :
   « misma talla » était la demande. Une bordure teintée au rouge, reprise de
   l'ancien .practice--command (rgba(220,38,38,0.35), relevée telle quelle), et
   sa première position dans la grille. */
.practices__grid--six .practice[data-persona="asha"] {
  border-color: rgba(220, 38, 38, 0.35);
}
.practices__grid--six .practice[data-persona="asha"]:hover {
  border-color: var(--color-primary);
}


/* Le rang de la carte ASHA, et lui seul, échoue au contraste — mesuré 3,71:1
   pour un seuil de 4,5 à 12 px. Ce n'est pas une surprise, c'est la faute déjà
   nommée trois fois dans ce fichier : --color-primary (#DC2626) employé comme
   TEXTE en petit corps sur fond sombre. Les cinq autres personas passent
   largement (CTEM 6,40 · NGSOC 14,54 · CSIRT 7,38 · ZeroTrust 4,53 · GRC 7,87),
   donc on n'éclaircit pas toute la rangée pour un seul cas : on corrige ce cas.
   Le grand numéral 01 garde --p tel quel : à 56 px son seuil est de 3,0 et il
   mesure 3,71. */
.practices__grid--six .practice[data-persona="asha"] .practice__rank {
  color: var(--color-primary-soft);
}


/* La bande des anneaux, une fois « ¿Cómo lo hacemos? » réduite — 2026-08-14.
   La section gardait le rembourrage d'une section pleine : 112 px en haut et en
   bas à 1440 pour 267 px de contenu, soit 296 px de vide pour 267 px utiles.
   Ça ne se lisait plus comme une bande mais comme un trou. On la resserre à
   peu près de moitié : elle respire encore, mais elle a la hauteur de ce
   qu'elle porte.
   Le fond ne bouge pas : sol-0, la « banda negro » que Gabriel a nommée. Ses
   deux frontières sont mesurées à 1,304:1 avec #soluciones et 1,140:1 avec
   #sistema — cette seconde valeur EST le seuil de bande relevé sur la
   référence, pas un échec. */
.scene-hacked--anillos {
  padding-top: clamp(48px, 4.6vw, 68px);
  padding-bottom: clamp(48px, 4.6vw, 68px);
}
/* .how-stats portait un filet et 120 px de séparation EN HAUT (l.8315 :
   margin-top + padding-top + border-top). Ils séparaient les anneaux du corps
   de la section. Ce corps n'existe plus : le filet flottait tout seul dans le
   vide, avec 135 px de noir au-dessus de lui — vu en capture, pas déduit.
   Il ne reste rien à séparer, donc les trois partent. */
.scene-hacked--anillos .how-stats {
  margin-top: 0;
  padding-top: 0;
  border-top: 0;
}


/* ══════════════════════════════════════════════════════════════════════════
   PRESENCIA : GLOBE À GAUCHE, CARTES À DROITE — 2026-08-14
   ══════════════════════════════════════════════════════════════════════════
   Demande de Gabriel : « le globe plus grand, sur la gauche, le titre pas
   centré mais sur la gauche, et les cards sur la droite ».

   Ce qui bridait le globe n'était pas la place — le conteneur fait 1760 px à
   1920 — mais un plafond de 660 px, écrit DEUX FOIS : max-width ici et
   GLOBE_MAX dans le script inline d'index.html. Le script se dimensionne sur
   Math.min(clientWidth, GLOBE_MAX), donc le plus petit gagne : ne relever
   qu'un des deux ne change rien à l'écran. Les deux passent à 820.

   La scène était un bloc unique où les quatre cartes étaient posées en ABSOLU
   dans les coins du carré englobant le globe. Tout ce positionnement tombe. */

.presence__head {
  text-align: left;
  max-width: 68ch;      /* la mesure de lecture, pas la moitié de la page */
  margin-left: 0;
  margin-right: 0;
}

/* En dessous de deux colonnes, la scène reste l'empilement déjà vérifié. */
/* SEUIL À 1200 PX, ET C'EST UNE MESURE, PAS UN CHIFFRE ROND. Le premier essai
   basculait à 1080 px comme les étiquettes du globe : à cette largeur la colonne
   ne donne que 572 px au globe, soit MOINS que les 660 d'avant. Le but était de
   l'agrandir, pas de le rétrécir sur une plage. La colonne vaut (conteneur −
   gouttière) × 0,595 ; il faut donc au moins 1157 px de conteneur pour rendre
   660. Le seuil a donc été cherché à la mesure, pas au calcul : à 1200 px la
   colonne rend 636 (encore en dessous), à 1280 elle rend 678. C'est 1280.
   Entre 1080 et 1280 on reste en colonne unique, où le globe prend désormais
   jusqu'à 820 px — donc plus grand qu'avant là aussi, et à aucune largeur il
   n'est plus petit qu'il ne l'était. */
@media (min-width: 80rem) {   /* 1280px — seuil mesuré, voir ci-dessus */
  .presence__stage {
    display: grid;
    /* 1,25 / 0,85 : la colonne du globe prend 59,5 % du reste après gouttière.
       À 1440 elle mesure 823 px et le globe prend son plafond de 820 ; à 1280,
       733 px ; à 1080, 623. Sous 1080 on repasse en une colonne, et c'est aussi
       là que les étiquettes du globe s'éteignent. */
    grid-template-columns: minmax(0, 1.25fr) minmax(0, 0.85fr);
    gap: clamp(32px, 3vw, 64px);
    align-items: center;
    min-height: 0;        /* le min-height: 660px de la version en absolu */
  }
  /* Les quatre cartes reviennent dans le flux. */
  .presence__stage .presence__float,
  .presence__stage .presence__fallback {
    position: static;
    width: auto;
    margin: 0;
  }
  .presence__cards {
    display: flex;
    flex-direction: column;
    gap: var(--space-4);
  }
  /* Le globe n'est plus centré dans une pleine largeur : il se cale à gauche
     de sa colonne, sinon il flotte au milieu et le titre ne le rejoint pas. */
  .presence__globe-wrap { align-items: flex-start; }
}

/* En une seule colonne, les cartes s'empilent simplement sous le globe. */
.presence__cards {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  margin-top: var(--space-6);
}

/* Le plafond du globe. Voir l'avertissement plus haut : GLOBE_MAX doit suivre. */
.presence__globe { max-width: 820px; }


/* ══════════════════════════════════════════════════════════════════════════
   PRESENCIA : TROIS CARTES DE MÊME FAMILLE — 2026-08-14
   ══════════════════════════════════════════════════════════════════════════
   Demande de Gabriel : « otras dos cards del mismo estilo que la card en
   desarrollo, con los países de operación activa y el centro de monitoreo ».

   La colonne de droite portait trois formats différents pour trois choses de
   même nature : une liste de pays, un highlight, un autre highlight. Elle en
   porte maintenant UN seul, décliné par la couleur de la légende du globe :
   rouge pour l'actif, cyan pour le développement, violet pour le hub. La même
   pastille que sur le globe, ce qui rend la légende lisible des deux côtés. */

/* « Operación activa » cesse d'être un simple repli. Elle était masquée dès que
   les étiquettes vivaient sur le globe (.has-globe-pins), pour ne pas dire deux
   fois la même chose. Gabriel la veut visible : le globe tourne et ses
   étiquettes passent, la carte, elle, se lit. Elle garde son rôle de repli
   quand il n'y a ni WebGL ni JS — c'est le même bloc. */
/* display: BLOCK, pas flex. La regle d'origine masquait ce bloc (display: none)
   quand les etiquettes vivent sur le globe ; en la neutralisant j'avais ecrit
   flex, et le libelle « > OPERACION ACTIVA [ 5 ] » se retrouvait a COTE de la
   liste au lieu d'etre au-dessus — les cinq pays s'empilaient alors dans une
   colonne etroite. Les deux autres groupes sont en block : celui-ci doit l'etre
   aussi, c'est la condition pour qu'ils soient « exactement du meme style ». */
.presence.has-globe-pins .presence__fallback { display: block; }

/* Le hub : violet, comme la pastille « Centro de monitoreo » de la légende. */
.country--hub {
  background: rgba(23, 23, 23, 0.35);
  border-color: color-mix(in srgb, var(--color-zerotrust) 25%, transparent);
}
.country--hub:hover {
  border-color: color-mix(in srgb, var(--color-zerotrust) 55%, transparent);
  background: color-mix(in srgb, var(--color-zerotrust) 4%, transparent);
}
.country--hub .country__flag {
  background: var(--color-zerotrust);
  box-shadow: 0 0 5px color-mix(in srgb, var(--color-zerotrust) 30%, transparent),
              inset 0 0 2px rgba(255, 255, 255, 0.25);
}
.country--hub .country__since {
  --plq: var(--color-zerotrust);
  color: var(--color-zerotrust-soft, #D8B4FE);
}

/* La note des contrats MSSP, sous la liste du hub. */
.presence__note {
  margin: var(--space-3) 0 0;
  font-size: var(--text-sm);
  line-height: 1.5;
  color: var(--color-muted);
}


/* ══════════════════════════════════════════════════════════════════════════
   TOUS LES EN-TÊTES DE SECTION PASSENT À GAUCHE — 2026-08-14
   ══════════════════════════════════════════════════════════════════════════
   Demande de Gabriel : « las secciones que tienen el titulo en medio, ponerlos
   a la izquierda ». Il l'avait déjà demandé pour #presencia, c'est la même
   règle étendue à tout le site.

   .section-head est la base — 22 en-têtes sur cinq pages en dépendent. Quatre
   sections ont en plus leur propre règle de centrage, écrite avant que la base
   existe ; elles la répètent donc et il faut les prendre aussi, sinon on croit
   avoir tout basculé alors que quatre sections restent centrées. Les rendues
   mortes (.clients__head, .diferenciador__head, .liga__header,
   .liga-section-head, .how__head) ne sont pas touchées : plus aucune page ne
   les porte, les corriger donnerait l'illusion d'un travail fait.

   Le modificateur .section-head--center est retiré du HTML (5 emplois) plutôt
   que neutralisé ici : une classe qui dit « centre » et qui aligne à gauche
   est un piège pour la prochaine passe. La règle CSS reste, elle redeviendra
   vraie si quelqu'un la repose sciemment. */
.section-head,
.presence__head,
.alliances__head,
.cases__head,
.support__head,
.industries__head {
  text-align: left;
  margin-inline-start: 0;
  margin-inline-end: 0;
}
/* Les lèdes de ces en-têtes étaient recentrés par margin-inline: auto. */
.section-head .section-lede,
.presence__head .section-lede,
.alliances__head .section-lede,
.cases__head .section-lede,
.support__head .section-lede,
.industries__head .section-lede {
  margin-inline-start: 0;
  margin-inline-end: 0;
}

/* La surcharge d'accent de #versus qui vivait ici est retirée le 2026-08-14 :
   la section est repassée en sol-1 avec le déplacement demandé par Gabriel,
   et le rouge lui revient par la règle générale l.9909. Une règle qui ne
   matche plus rien est un piège pour la passe suivante, dans un fichier qui
   déclare déjà certains sélecteurs quatre fois. */


/* La section « Nuestra esencia » de nosotros.html était centrée en entier, pas
   seulement son titre : la marque « aša » est un flex centré et la citation
   « Las cosas como deben ser. » porte son propre text-align: center. Aligner le
   seul titre à gauche aurait laissé un bloc à moitié centré, ce qui est pire
   que les deux états francs. Le bloc suit donc son titre. */
.essence-mark { align-items: flex-start; }
.essence-body .essence-pull { text-align: left; }


/* Les trois anneaux grandissent — 2026-08-14, demande de Gabriel.
   Le cadran passe de clamp(104px, 7.4vw, 128px) à clamp(148px, 11vw, 196px),
   soit +53 % au plafond. Trois choses doivent suivre, sinon on obtient un grand
   anneau mal rempli :
     · le chiffre au centre, sinon il flotte dans un disque devenu vide ;
     · l'ÉPAISSEUR du trait — le masque radial creuse un trou à 8 px du bord,
       valeur calibrée pour un cadran de 128 px ; gardée telle quelle sur un
       cadran de 196 px, l'anneau paraîtrait deux fois plus fin ;
     · la gouttière entre les trois, qui doit croître avec eux.
   La bande ne porte plus qu'eux depuis qu'elle a été vidée : elle a la place. */
.scene-hacked--anillos .ring-stat__dial-wrap {
  /* PAS de min(..., 100%) ici, et c'est une erreur que j'ai faite puis mesurée :
     .how-stats est un FLEX dont les .ring-stat sont en flex: 0 1 auto, donc
     leur largeur vient de leur libellé. « 100 % » y valait 100 % du mot
     « investigación », et les trois cadrans prenaient trois tailles
     différentes — 99, 129 et 96 px à 1920. Le cadran se dimensionne donc sur
     le VIEWPORT, avec un plancher assez bas pour que trois cadrans et deux
     gouttières tiennent dans 280 px de zone utile à 320 px de large. */
  width: clamp(84px, 15vw, 196px);
}
.scene-hacked--anillos .ring-stat__dial {
  -webkit-mask: radial-gradient(closest-side, transparent calc(100% - 13px), #000 calc(100% - 12px));
          mask: radial-gradient(closest-side, transparent calc(100% - 13px), #000 calc(100% - 12px));
}
.scene-hacked--anillos .ring-stat__val  { font-size: clamp(34px, 2.7vw, 46px); }
.scene-hacked--anillos .ring-stat__unit { font-size: clamp(14px, 1vw, 17px); }
.scene-hacked--anillos .ring-stat__sub  { font-size: clamp(15px, 1.15vw, 19px); }
/* Ecarte le 2026-08-15 : 96 px au maximum, les trois cadrans se touchaient
   presque sur grand ecran et se lisaient comme un seul objet a trois
   parties, alors que ce sont trois temps distincts. */
/* DEUX VALEURS, ET C'EST TOUT LE POINT. En n'ecrivant qu'un seul gap
   j'ecartais aussi les LIGNES : le libelle « Objetivo operativo del NGSOC »
   occupe sa propre ligne au-dessus des trois cadrans, il se retrouvait donc a
   180 px d'eux sur grand ecran. Le premier nombre est l'ecart vertical, entre
   le libelle et les cadrans ; le second l'ecart horizontal, entre les cadrans. */
.scene-hacked--anillos .how-stats { gap: clamp(6px, 0.7vw, 14px) clamp(40px, 9vw, 180px); }


/* Sous 48rem le clamp est au plancher et le cadran tombe entre 84 et 115 px. Deux choses doivent suivre cette reduction, sinon le trait de
   l'anneau et les chiffres restent calibres pour un cadran de 196 px :
   l'epaisseur du masque et le corps du chiffre. */
@media (max-width: 48rem) {
  .scene-hacked--anillos .how-stats { gap: clamp(10px, 3vw, 20px); }
  .scene-hacked--anillos .ring-stat__dial {
    -webkit-mask: radial-gradient(closest-side, transparent calc(100% - 9px), #000 calc(100% - 8px));
            mask: radial-gradient(closest-side, transparent calc(100% - 9px), #000 calc(100% - 8px));
  }
  .scene-hacked--anillos .ring-stat__val  { font-size: clamp(19px, 5.6vw, 26px); }
  .scene-hacked--anillos .ring-stat__unit { font-size: 10px; }
  .scene-hacked--anillos .ring-stat__sub  { font-size: clamp(12px, 3.4vw, 14px); }
}


/* La surcharge d'accent de #versus est retiree le 2026-08-14 : la bande de
   destacados est devenue le menu secondaire, #versus revient en sol-1, et le
   rouge lui revient par la regle generale l.9909. C'est la deuxieme fois que
   cette surcharge est ecrite puis retiree dans la journee — elle depend du
   sol de la section, donc de son VOISINAGE. Verifier le sol avant de la
   supposer utile. */


/* Le lien de conversion de la bande des anneaux. Il doit se lire comme une
   suite de la promesse chiffrée, pas comme un bouton posé là : donc centré sous
   les trois cadrans, et en secondaire — le primaire rouge sur sol-0 à cette
   position ferait concurrence au CTA final. */
.anillos__cta {
  margin-top: clamp(28px, 3vw, 44px);
  text-align: center;
}


/* Les regles de .practice__num sont devenues MORTES le 2026-08-14 : les grands
   ordinaux ont ete retires des six cartes de heros pour ne laisser qu'une
   numerotation dans #sistema, et cette classe n'existait nulle part ailleurs
   sur le site. Elles ne sont pas supprimees, elles decrivent un traitement qui
   marche et qui redeviendra vrai si les numeros reviennent. Ne pas les modifier
   en croyant agir sur la home : plus rien ne les porte. */


/* La marge droite qui reservait la place des bustes de #soluciones tombe avec
   eux — 2026-08-14. Elle valait 118 px (92 en mobile) et n'existait que pour
   ne pas passer sous l'image. Sans ce retrait, chaque description garderait
   une colonne de vide a droite.
   Les regles de .need__hero (l.11040, l.11056, l.11068) deviennent mortes :
   plus aucune page ne porte cette classe. Elles ne sont pas supprimees, elles
   decrivent un traitement qui marche, mais ne rien y changer en croyant agir
   sur la home. */
.needs__grid .need__text { padding-right: 0; }


/* ══════════════════════════════════════════════════════════════════════════
   ALIANZAS : LA BANDE BLANCHE DE LA HOME — 2026-08-14
   ══════════════════════════════════════════════════════════════════════════
   La section complète est partie sur nosotros.html#alianzas. Il ne reste ici
   que les deux pistes de logos et un bouton, sur fond clair.

   LE FILTRE EST LE POINT CRITIQUE, et il a été mesuré avant d'être écrit. Les
   17 fichiers de logos sont eux-mêmes CLAIRS : luminance moyenne des pixels
   opaques relevée entre 138 et 195 sur 255, treize d'entre eux au-dessus de
   150. Ils sont dessinés pour un fond sombre, et le site les force en plus à
   l'argent par brightness(0) invert(0.85). Posés tels quels sur du blanc, ils
   ne se voient tout simplement pas.
   La parade ne demande AUCUN nouveau fichier : brightness(0) écrase déjà tout
   en noir, il suffit de ne pas inverser. Le poids visuel est calé sur celui de
   la bande de clients juste sous le hero, qui fait le même travail sur le même
   fond (grayscale + opacité 0,72). */
.alliances--band {
  padding-top: clamp(40px, 4vw, 64px);
  padding-bottom: clamp(40px, 4vw, 64px);
}
.alliances--band .alliance-card__logo {
  filter: brightness(0);
  opacity: 0.62;
}
.alliances--band .alliance-card:hover .alliance-card__logo {
  filter: brightness(0);
  opacity: 1;
}
/* La carte perd sa plaque : sur fond clair, un cadre sombre autour de chaque
   logo transformerait une bande calme en damier. */
.alliances--band .alliance-card {
  background: none;
  border: 0;
  box-shadow: none;
}
.alliances--band .alliance-card::before { content: none; }
.alliances--band .alliance-card:hover {
  background: none;
  border: 0;
  transform: none;
}
/* L'étiquette de piste, sur fond clair. */
.alliances--band .alliances__tier-label {
  color: var(--color-muted-light);
}
.alliances--band .alliances__tier + .alliances__tier {
  margin-top: clamp(14px, 1.6vw, 24px);
}
.alliances__band-cta {
  margin-top: clamp(24px, 2.6vw, 40px);
  text-align: center;
}
/* Le bouton secondaire est dessiné pour un fond sombre : bordure et encre
   claires. Sur ce sol il lui faut l'encre de la page claire. */
/* Le bouton de #sistema partage cette regle depuis le 2026-08-17 : Gabriel le
   veut identique a celui d'alianzas, or les memes classes ne suffisaient pas —
   celui-la vivait hors de .alliances--band et gardait donc le .btn-secondary
   dessine pour fond sombre. Un selecteur ajoute, pas une regle jumelle : deux
   regles jumelles divergent des la premiere retouche de l'une. */
.alliances--band .btn-secondary,
.diferenciador__cta-wrap .btn-secondary {
  color: var(--color-fg-light);
  border-color: color-mix(in srgb, var(--color-fg-light) 28%, transparent);
  background: transparent;
}
.alliances--band .btn-secondary:hover,
.diferenciador__cta-wrap .btn-secondary:hover {
  color: var(--color-primary);
  border-color: var(--color-primary);
  background: color-mix(in srgb, var(--color-primary) 6%, transparent);
}


/* ══════════════════════════════════════════════════════════════════════════
   MENU SECONDAIRE DE LA HOME — 2026-08-14
   ══════════════════════════════════════════════════════════════════════════
   Même composant que le sous-menu de metodologia.html (.subnav) : barre
   collante sous le header, piste qui défile avec masques de bord, entrée
   active soulignée. On n'en réécrit rien, on n'ajuste que ce qui diffère.

   TROIS DIFFÉRENCES, et chacune a une raison :
   1. Pas d'icône ni de rôle. Sur metodologia ces deux-là portent les personas ;
      ici les entrées sont des sections, pas des personnages. Sans persona, le
      soulignement actif retombe sur le rouge de marque.
   2. Une pastille pleine en fin de piste, comme dans la référence Palo Alto.
      Elle mène à une AUTRE PAGE : elle est donc exclue du scrollspy et n'est
      jamais « active ».
   3. Le fond suit l'échelle noire de la home, pas le #101010 de metodologia. */

.subnav--home {
  background: color-mix(in srgb, var(--sol-1) 94%, transparent);
  border-bottom: 1px solid var(--color-border);
}
/* Sans persona, l'entrée active se signale au rouge de marque. */
.subnav--home .subnav__link {
  --persona: var(--color-primary);
  --persona-lift: var(--color-primary-lift);
  font-size: clamp(13px, 1.05vw, 15px);
  font-weight: 600;
  letter-spacing: 0.01em;
  white-space: nowrap;
}
/* Les masques de bord sont écrits en dur sur le fond de metodologia : ils
   doivent suivre le nôtre, sinon on voit un rectangle plus clair aux extrémités. */
.subnav--home .subnav__inner::before {
  background: linear-gradient(90deg, var(--sol-1) 0%, color-mix(in srgb, var(--sol-1) 0%, transparent) 100%);
}
.subnav--home .subnav__inner::after {
  background: linear-gradient(270deg, var(--sol-1) 0%, color-mix(in srgb, var(--sol-1) 0%, transparent) 100%);
}

/* La pastille de contact. Elle ne prend pas le soulignement des autres :
   deux signaux d'état sur le même objet se contredisent. */

/* La ligne source des 83 %, sous le lède de #problema. */
.problema__source {
  margin-top: clamp(10px, 1.1vw, 16px);
  /* LA TAILLE PROPRE EST RETIREE — 2026-08-22, releve par Gabriel : « la
     deuxieme phrase a une taille de typo differente ». C'etait exact et
     mesurable : elle portait clamp(14px, 1.05vw, 16px) quand la phrase juste
     au-dessus, de meme classe .section-lede, se rend a var(--text-lg). Deux
     phrases voisines dans le meme bloc, deux tailles, pour rien.
     Elle garde son opacite legerement plus basse : c'est une source citee, elle
     doit rester un cran en retrait, mais en INTENSITE et non en taille. */
  opacity: 0.92;
}

/* En colonne unique la piste ne tient plus centrée : elle défile, et
   margin-inline-start: auto sur la pastille pousserait tout le reste hors
   champ. On la laisse suivre le flux. */


/* ══════════════════════════════════════════════════════════════════════════
   #SOLUCIONES EN PANNEAU MAÎTRE-DÉTAIL — 2026-08-14
   ══════════════════════════════════════════════════════════════════════════
   Six onglets à gauche, un volet à droite. Motif de la référence Palo Alto,
   transposé : chez eux la liste est posée sur une photo pleine largeur, ici
   elle est sur le sol de la section. On ne reprend pas la photo — nous n'avons
   pas d'image de fond à cet endroit, et en inventer une pour imiter la
   référence serait décorer un vide.

   SANS JAVASCRIPT, les six volets s'affichent à la suite : le HTML pose
   hidden sur cinq d'entre eux, sol-panel.js le retire dès qu'il tourne et pose
   .solpanel--vivant. La dégradation montre trop, jamais rien. */

.solpanel__grid {
  display: grid;
  gap: clamp(24px, 3vw, 56px);
}
@media (min-width: 62rem) {
  .solpanel__grid {
    grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr);
    align-items: start;
  }
}

/* ── La liste ─────────────────────────────────────────────────────────── */
.solpanel__list {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.solpanel__tab {
  --p: var(--color-primary);
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 3px;
  width: 100%;
  /* 14px de haut × 2 + le contenu : le rang de 44 px de cible tactile est
     tenu par la hauteur réelle, mesurée, pas par une min-height décorative. */
  padding: 14px clamp(14px, 1.4vw, 20px);
  border: 0;
  border-left: 2px solid transparent;
  border-radius: 0 var(--radius-md) var(--radius-md) 0;
  background: transparent;
  color: var(--color-muted);
  text-align: left;
  cursor: pointer;
  transition: background var(--duration-fast) var(--ease-out),
              border-color var(--duration-fast) var(--ease-out),
              color var(--duration-fast) var(--ease-out);
}
.solpanel__tab-method {
  font: 700 10px/1 var(--font-mono);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--color-muted);
  opacity: 0.7;
}
.solpanel__tab-title {
  font-size: clamp(15px, 1.2vw, 18px);
  font-weight: 600;
  line-height: 1.25;
}
.solpanel__tab:hover {
  background: rgba(248, 250, 252, 0.04);
  color: var(--color-fg);
}
.solpanel__tab.is-active,
.solpanel__tab[aria-selected="true"] {
  border-left-color: var(--p);
  background: color-mix(in srgb, var(--p) 10%, transparent);
  color: var(--color-fg);
}
.solpanel__tab.is-active .solpanel__tab-method,
.solpanel__tab[aria-selected="true"] .solpanel__tab-method {
  color: var(--p);
  opacity: 1;
}
.solpanel__tab:focus-visible {
  outline: 2px solid var(--p);
  outline-offset: -2px;
}

/* ── Le volet ─────────────────────────────────────────────────────────── */
.solpanel__pane {
  --p: var(--color-primary);
  padding: clamp(22px, 2.4vw, 36px);
  border: 1px solid color-mix(in srgb, var(--p) 34%, transparent);
  border-radius: var(--radius-lg);
  background:
    linear-gradient(180deg,
      color-mix(in srgb, var(--p) 12%, transparent),
      color-mix(in srgb, var(--p) 4%, transparent)),
    var(--color-surface);
}
.solpanel__pane-method {
  display: block;
  font: 700 11px/1 var(--font-mono);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--p);
  margin-bottom: var(--space-2);
}
.solpanel__pane-title {
  margin: 0 0 var(--space-3);
  font-size: clamp(22px, 2.1vw, 32px);
  font-weight: 700;
  line-height: 1.2;
  color: var(--color-fg);
}
.solpanel__pane-text {
  margin: 0;
  font-size: clamp(15px, 1.15vw, 17px);
  line-height: 1.6;
  color: var(--color-fg);
  opacity: 0.9;
}
.solpanel__pane-cta {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-top: clamp(18px, 1.8vw, 26px);
  min-height: 44px;
  font-size: clamp(14px, 1.05vw, 16px);
  font-weight: 700;
  color: var(--color-fg);
}
.solpanel__pane-cta .icon {
  width: 16px; height: 16px;
  transition: transform var(--duration-fast) var(--ease-out);
}
.solpanel__pane-cta:hover .icon { transform: translateX(3px); }

/* Le persona colore l'onglet actif et son volet. Les mêmes six variables que
   partout ailleurs — on ne réinvente pas la table.
   RESTAUREE le 2026-08-14 : en retirant le fond d'image des volets, mon
   expression reguliere a mange la moitie droite de chacune de ces lignes et
   laisse une liste de selecteurs ouverte, qui avalait la regle suivante. Le
   volet GRC sortait rouge. Toujours verifier ce qu'une suppression par motif
   emporte AUTOUR de sa cible. */
.solpanel__tab[data-persona="ctem"],      .solpanel__pane[data-persona="ctem"]      { --p: var(--color-ctem); }
.solpanel__tab[data-persona="ngsoc"],     .solpanel__pane[data-persona="ngsoc"]     { --p: var(--color-ngsoc); }
.solpanel__tab[data-persona="csirt"],     .solpanel__pane[data-persona="csirt"]     { --p: var(--color-csirt); }
.solpanel__tab[data-persona="zerotrust"], .solpanel__pane[data-persona="zerotrust"] { --p: var(--color-zerotrust); }
.solpanel__tab[data-persona="grc"],       .solpanel__pane[data-persona="grc"]       { --p: var(--color-grc); }

/* Sous 62rem la liste passe au-dessus du volet, en bandeau qui défile.
   Même DOM, aucun balisage dupliqué. */
@media (max-width: 61.99rem) {
  .solpanel__list {
    flex-direction: row;
    overflow-x: auto;
    scrollbar-width: none;
    gap: 6px;
    padding-bottom: 4px;
  }
  .solpanel__list::-webkit-scrollbar { display: none; }
  .solpanel__tab {
    flex: 0 0 auto;
    border-left: 0;
    border-bottom: 2px solid transparent;
    border-radius: var(--radius-md);
  }
  .solpanel__tab.is-active,
  .solpanel__tab[aria-selected="true"] { border-bottom-color: var(--p); }
  .solpanel__tab-title { white-space: nowrap; }
}


/* La surcharge d'accent de #versus est retiree le 2026-08-14 : la regle
   generale des titres sol-2 passe elle-meme en --color-primary-soft, elle
   dit donc exactement la meme chose. Trois ecritures, trois retraits dans
   la journee pour cette surcharge — cette fois c'est la cause qui a bouge. */



/* ══════════════════════════════════════════════════════════════════════════
   #CASOS-EXITO : DEUX VOLETS, LES CHIFFRES EN DIAGRAMME — 2026-08-14
   ══════════════════════════════════════════════════════════════════════════
   Motif de la référence Palo Alto : un anneau quand le chiffre est une part,
   un grand numéral quand c'est un compte, une phrase forte au-dessus.

   L'ARC EST ANIMABLE PARCE QUE --fill EST DÉCLARÉ. Un conic-gradient ne se
   transitionne pas : le navigateur interpole des images, pas des dégradés.
   @property donne un TYPE à la variable, et une variable typée s'interpole —
   c'est elle qui bouge, le dégradé n'en est que la conséquence. Sans le
   support de @property (navigateurs anciens), --fill saute à sa valeur : pas
   d'animation, pas de casse. */
@property --fill {
  syntax: '<number>';
  /* inherits: TRUE, et ce n'est pas un detail. --fill est pose en style inline
     sur le CONTENEUR (.case-ring, .ring-stat) tandis que le degrade conique vit
     sur l'ENFANT (.case-ring__dial, .ring-stat__dial). Avec inherits: false
     l'enfant ne voit plus la valeur du parent et retombe sur le fallback 0 :
     tous les anneaux se vident. Et comme @property est GLOBAL au document,
     cette erreur ne cassait pas seulement les nouveaux anneaux des casos, elle
     cassait aussi les trois du 1-10-60, qui marchaient depuis des semaines. */
  inherits: true;
  initial-value: 0;
}

/* ── Les deux boutons ─────────────────────────────────────────────────── */
.cases__tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: clamp(26px, 2.8vw, 44px);
}
.cases__tab {
  min-height: 44px;
  padding: 10px clamp(14px, 1.6vw, 22px);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-full);
  background: transparent;
  color: var(--color-muted);
  font-family: var(--font-mono);
  font-size: clamp(11px, 0.95vw, 13px);
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  cursor: pointer;
  transition: color var(--duration-fast) var(--ease-out),
              border-color var(--duration-fast) var(--ease-out),
              background var(--duration-fast) var(--ease-out);
}
/* Le survol allume l'onglet comme toutes les autres pilules du site : filet
   rouge et fond rouge tres dilue. Il etait le seul a s'eclaircir en gris, ce
   qui ne se voyait pas sur ce sol.
   8 % ET NON 14 : l'onglet SELECTIONNE est deja a 14 %, et deux etats a la
   meme valeur auraient rendu impossible de distinguer celui qu'on survole de
   celui qui est ouvert. */
.cases__tab:hover {
  color: var(--color-fg);
  border-color: var(--color-primary);
  background: color-mix(in srgb, var(--color-primary) 8%, transparent);
}
/* LE SURVOL DE CES ONGLETS EST VERT, ET C'EST LA SECTION QUI LE DIT. Gabriel a
   fait passer « casos de exito » au vert : l'etat selectionne y est deja vert
   (regle #casos-exito plus bas). Un survol rouge y aurait introduit la seule
   touche rouge d'une section qui n'en a plus.
   8 % contre 14 % pour l'etat selectionne : les deux etats doivent rester
   distinguables, sinon on ne sait plus lequel est ouvert et lequel est survole. */
#casos-exito .cases__tab:hover:not([aria-selected="true"]):not(.is-active) {
  color: var(--color-fg);
  border-color: var(--color-grc);
  background: color-mix(in srgb, var(--color-grc) 8%, transparent);
}
.cases__tab.is-active,
.cases__tab[aria-selected="true"] {
  color: var(--color-fg);
  border-color: var(--color-primary);
  background: color-mix(in srgb, var(--color-primary) 14%, transparent);
}
.cases__tab:focus-visible { outline: 2px solid var(--color-primary-lift); outline-offset: 2px; }

/* ── Le volet, et son fondu ───────────────────────────────────────────── */
.cases__pane { }
.cases--vivant .cases__pane {
  opacity: 0;
  transform: translateY(10px);
  transition: opacity 380ms var(--ease-out), transform 380ms var(--ease-out);
}
.cases--vivant .cases__pane.is-active { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
  .cases--vivant .cases__pane { transition: none; transform: none; }
}
.cases__pane-title {
  margin: 0 0 clamp(24px, 2.6vw, 40px);
  font-size: clamp(26px, 3.4vw, 46px);
  font-weight: 800;
  line-height: 1.12;
  letter-spacing: -0.02em;
  color: var(--color-fg);
  max-width: 20ch;
}

/* ── Les chiffres ─────────────────────────────────────────────────────── */
.cases__figures {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: clamp(22px, 2.6vw, 44px);
  align-items: start;
  margin-bottom: clamp(28px, 3vw, 48px);
}
.case-fig__num {
  display: block;
  font-size: clamp(38px, 5vw, 68px);
  font-weight: 800;
  line-height: 1;
  letter-spacing: -0.03em;
  color: var(--color-primary-lift);
  font-variant-numeric: tabular-nums;
}
.case-fig__unit {
  font-size: 0.42em;
  font-weight: 700;
  margin-left: 0.15em;
  letter-spacing: 0;
  /* L'unite herite du grand numeral en --color-primary-lift. Or a 68 px le
     numeral est en texte large (seuil 3:1, il mesure 4,90) tandis que l'unite
     tombe a 16 px : seuil 4,5, et elle mesurait 4,28. Le meme rouge est donc
     conforme sur l'un et pas sur l'autre — c'est la taille qui change de
     regime, pas la couleur. La variante soft rend l'unite lisible sans
     toucher au numeral. */
  color: var(--color-primary-soft);
}
.case-fig__label {
  margin: var(--space-2) 0 0;
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  line-height: 1.5;
  color: var(--color-muted);
}
.case-fig--lead .case-fig__num { font-size: clamp(46px, 6.4vw, 88px); }

/* L'anneau. Même grammaire que les trois du 1-10-60 : cadran d'une heure,
   l'arc rouge est la fraction réelle. On ne la réécrit pas, on la reprend. */
.case-ring { text-align: left; }
.case-ring__dial-wrap {
  position: relative;
  display: block;
  width: clamp(112px, 9vw, 150px);
  aspect-ratio: 1;
  margin-bottom: var(--space-2);
}
.case-ring__dial {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: conic-gradient(from 220deg,
    var(--color-primary) calc(var(--fill, 0) * 1%),
    rgba(248, 250, 252, 0.16) 0);
  -webkit-mask: radial-gradient(closest-side, transparent calc(100% - 11px), #000 calc(100% - 10px));
          mask: radial-gradient(closest-side, transparent calc(100% - 11px), #000 calc(100% - 10px));
}
/* La transition est sur le CONTENEUR : c'est lui qui porte --fill et donc lui
   qui change. Posee sur l'enfant, elle n'aurait rien a interpoler. */
/* 1600 ms : la duree unique de tout ce qui chiffre sur ce site, calee sur les
   compteurs de Trayectoria. Deux anneaux de meme facture ne doivent pas se
   dessiner a deux vitesses. */
.case-ring { transition: --fill 1600ms var(--ease-out); }
@media (prefers-reduced-motion: reduce) {
  .case-ring { transition: none; }
}
.case-ring__num {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 1px;
}
.case-ring__val {
  font-size: clamp(24px, 2.2vw, 34px);
  font-weight: 800;
  letter-spacing: -0.02em;
  color: var(--color-fg);
  font-variant-numeric: tabular-nums;
}
.case-ring__unit { font-size: 0.5em; font-weight: 700; color: var(--color-muted); }
.case-ring__label {
  margin: 0;
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  line-height: 1.5;
  color: var(--color-muted);
}

/* ── Antes / Después ──────────────────────────────────────────────────── */
.cases__story {
  display: grid;
  gap: clamp(16px, 1.8vw, 28px);
}
@media (min-width: 48rem) {
  .cases__story { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}


/* ══════════════════════════════════════════════════════════════════════════
   PRESENCIA : LES TROIS GROUPES SUR UN SEUL MODÈLE — 2026-08-14
   ══════════════════════════════════════════════════════════════════════════
   Demande de Gabriel, capture à l'appui : « Operación activa » et « Centro de
   monitoreo » doivent être EXACTEMENT du style de « En desarrollo », chacune
   avec sa couleur.

   Ce traitement n'existait que sur la carte « En desarrollo » et il était
   écrit en dur en cyan, à six endroits (rgba(6,182,212,…)). Le généraliser
   n'était donc pas une affaire de copier-coller : il fallait d'abord le
   PARAMÉTRER. Une seule variable, --grp, porte la couleur du groupe ; toutes
   les règles ci-dessous en dérivent. Trois déclarations suffisent ensuite pour
   les trois groupes, au lieu de trois copies du même bloc.

   Les couleurs sont celles de la légende du globe, pas des choix nouveaux :
   rouge pour l'actif, cyan pour le développement, violet pour le hub. */

/* Le conteneur : encadré pointillé, comme le modèle. */
.presence__group {
  --grp: var(--color-primary);
  background: rgba(23, 23, 23, 0.35);
  border: 1px dashed color-mix(in srgb, var(--grp) 30%, transparent);
  border-radius: var(--radius-lg);
  padding: var(--space-4) var(--space-4) var(--space-5);
}
/* LES TROIS COULEURS SONT DECLAREES APRES LA BASE, et c'est obligatoire.
   .presence__group--activa et .presence__group ont la MEME specificite (une
   classe chacun) : a specificite egale, c'est la derniere declaration qui
   gagne. Je les avais ecrites avant la base, et la base --grp: primary les
   ecrasait toutes les trois — les trois groupes sortaient rouges. Mesure :
   les trois bordures rendues a rgb(220,38,38) au lieu de rouge, cyan, violet.
   C'est le piege n°2 du repo, et il vient de resservir. */
.presence__group--activa     { --grp: var(--color-primary); }
.presence__group--desarrollo { --grp: var(--color-csirt); }
.presence__group--hub        { --grp: var(--color-zerotrust); }

.presence__group .presence__sub-prompt { color: color-mix(in srgb, var(--grp) 88%, white); }
.presence__group .presence__sub-count  { color: color-mix(in srgb, var(--grp) 70%, white); }

/* Les puces. Toutes identiques, la couleur vient du groupe qui les contient. */
.country--chip {
  background: rgba(23, 23, 23, 0.35);
  border-style: dashed;
  border-color: color-mix(in srgb, var(--grp) 25%, transparent);
}
.country--chip:hover {
  border-color: color-mix(in srgb, var(--grp) 55%, transparent);
  background: color-mix(in srgb, var(--grp) 4%, transparent);
}
.country--chip .country__flag {
  background: var(--grp);
  box-shadow: 0 0 5px color-mix(in srgb, var(--grp) 30%, transparent),
              inset 0 0 2px rgba(255, 255, 255, 0.25);
}
.country--chip .country__since {
  --plq: var(--grp);
  color: color-mix(in srgb, var(--grp) 55%, white);
  background: color-mix(in srgb, var(--grp) 6%, transparent);
  border-color: color-mix(in srgb, var(--grp) 20%, transparent);
}

/* La légende revient au centre DU GLOBE. Elle avait été poussée à gauche avec
   lui quand la colonne est passée en align-items: flex-start ; or le globe est
   un disque calé à gauche de sa colonne, pas la colonne entière. On recentre
   donc la légende sur la LARGEUR DU GLOBE, pas sur celle de la colonne. */
.presence__globe-wrap .presence__legend {
  width: 100%;
  max-width: 820px;      /* le plafond du globe : ils partagent leur axe */
  justify-content: center;
}


/* La piste du menu est centree — 2026-08-14, en meme temps que le retrait de la
   pastille « Hablar con un experto », demande de Gabriel.
   La regle generale de .subnav centre deja la piste au-dessus de 62rem
   (l.9315). En dessous elle DEFILE, et une piste qui defile ne se centre pas :
   justify-content: center sur un contenu plus large que sa boite pousse le
   debut hors champ a gauche, et la premiere entree devient inatteignable. On
   ne centre donc que la ou ca tient. */
.subnav--home .subnav__track { justify-content: center; }
@media (max-width: 61.99rem) {
  .subnav--home .subnav__track { justify-content: flex-start; }
}


/* ══════════════════════════════════════════════════════════════════════════
   #CASOS-EXITO : LE TEXTE À GAUCHE, LES CHIFFRES EN GRAND À DROITE
   ══════════════════════════════════════════════════════════════════════════
   2026-08-14, demande de Gabriel, et c'est la disposition de la référence :
   la phrase forte tient une colonne, les diagrammes l'autre.

   AU PASSAGE, LE DÉFAUT D'ALIGNEMENT QU'IL A VU. Mesuré à 1440 : les trois
   grands numéraux faisaient 93 px de haut, l'anneau 154. Leurs libellés
   partaient donc à 76 px pour les uns et 138 pour l'autre — quatre chiffres
   sur une ligne, deux lignes de libellés. La cause n'est pas un réglage
   oublié, c'est que le cercle et le texte n'ont aucune raison d'avoir la même
   hauteur. On leur en donne une : une ZONE DE VALEUR commune, du diamètre de
   l'anneau, dans laquelle les numéraux se calent en bas. Les libellés
   repartent alors tous du même endroit. */

@media (min-width: 62rem) {
  .cases__pane {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: clamp(32px, 4vw, 72px);
    align-items: start;
  }
}
.cases__figures {
  /* La zone de valeur, partagée par les numéraux et l'anneau. */
  /* LE PLAFOND DESCEND DE 148 A 128 PX. A 1920 la zone atteignait son maximum
     pendant que la colonne de texte, elle, ne grandit pas : le bloc des reperes
     depassait alors le bas de la carte de gauche de 23 px sur le volet mexicain.
     20 px de moins par zone, sur deux lignes, rendent les 40 px qui manquaient.
     128 reste tres au-dessus du corps des chiffres a cette largeur (76 px), donc
     rien n'est comprime. */
  --zone: clamp(104px, 8.4vw, 128px);
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  /* START ET NON END. Colles en bas de leur cellule, deux blocs d'une meme
     ligne dont les libelles n'ont pas le meme nombre de lignes ne commencaient
     pas a la meme hauteur : 16 px d'ecart mesures a 1440 entre « −30-40% »,
     dont le libelle court sur deux lignes, et « Data Manager », qui tient sur
     une. Le volet Ecuador le cachait, ses quatre libelles faisant une ligne
     chacun.
     Aligner par le haut ne coute pas l'alignement des valeurs : la zone porte
     deja min-height: var(--zone) et y colle son contenu en bas, donc les bases
     restent sur une meme ligne. Les deux alignements tiennent ensemble, ce que
     « end » interdisait des que les libelles differaient. */
  align-items: start;
  margin-bottom: 0;
}
.case-fig__num {
  min-height: var(--zone);
  display: flex;
  align-items: flex-end;
}
.case-ring__dial-wrap {
  width: var(--zone);
  margin-bottom: 0;
}
/* Les libellés repartent tous de la même ligne, quelle que soit la forme
   au-dessus d'eux. */
.case-fig__label,
.case-ring__label { margin-top: var(--space-2); }

/* Les chiffres grandissent : ils tiennent une colonne à eux, ils ont la place. */
@media (min-width: 62rem) {
  .case-fig__num { font-size: clamp(46px, 4.2vw, 76px); }
  .case-fig--lead .case-fig__num { font-size: clamp(56px, 5.4vw, 96px); }
  .cases__pane-title { max-width: none; }
}

/* ── Antes / Después, mis en avant ────────────────────────────────────────
   C'était deux lignes de 14 px derrière une étiquette de 10. Le contraste
   AVANT / APRÈS est l'argument même d'un cas client : il devient deux blocs
   lisibles, chacun marqué par un filet de couleur — neutre pour l'avant,
   vert pour l'après, les deux couleurs qui existaient déjà sur les étiquettes.
   On ne choisit pas de nouvelles couleurs, on donne du volume aux siennes. */
.cases__story {
  grid-template-columns: minmax(0, 1fr);
  gap: clamp(12px, 1.2vw, 18px);
  margin-top: clamp(26px, 2.8vw, 40px);
}
.cases__story .case-flow {
  display: block;
  padding: clamp(14px, 1.4vw, 20px) clamp(16px, 1.6vw, 22px);
  border-radius: var(--radius-md);
  border-left: 3px solid var(--color-border-strong);
  background: rgba(248, 250, 252, 0.03);
}
.cases__story .case-flow:has(.case-flow__tag--after) {
  border-left-color: #22C55E;
  background: rgba(34, 197, 94, 0.06);
}
.cases__story .case-flow__tag {
  display: inline-block;
  margin-bottom: var(--space-2);
  font-size: 11px;
  letter-spacing: 0.16em;
}
.cases__story .case-flow p {
  font-size: clamp(14px, 1.1vw, 16px);
  line-height: 1.6;
  color: rgba(248, 250, 252, 0.88);
}


/* Les quatre chiffres en 2 x 2 dans leur colonne — 2026-08-14.
   auto-fit donnait 3 + 1 a 1440 : trois chiffres sur une ligne et le quatrieme
   seul dessous. Quatre elements se divisent par deux, pas par trois. */
@media (min-width: 62rem) {
  .cases__figures { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* La derniere section avant le pied de page respire davantage au-dessus de son
   titre — 2026-08-14, demande de Gabriel. Le badge « > connect · ASHA CSIRT
   7×24 » qui vient d'en partir occupait cet espace : sans lui le titre montait
   se coller au bord haut de l'affiche. */
/* La marge haute du CTA final, sur LES TROIS pages qui en portent un. Elle
   avait ete posee pour la home seule, ou le retrait du badge laissait le titre
   monter contre le bord de l'affiche ; metodologia vient de perdre le sien pour
   la meme raison, et nosotros n'en a jamais eu mais souffre du meme manque
   d'air. Le selecteur passe donc de .final-cta--poster a .final-cta. */
.final-cta .final-cta__inner { padding-top: clamp(28px, 4vw, 72px); }


/* ══════════════════════════════════════════════════════════════════════════
   HEADER ET PIED DE PAGE SUR FOND BLANC — 2026-08-14
   ══════════════════════════════════════════════════════════════════════════
   Demande de Gabriel. Les deux barres passent du noir au sol clair, la
   navigation se centre, et le bouton « Contáctenos » quitte le header.

   VÉRIFIÉ AVANT D'ÉCRIRE, parce que c'est exactement là que ce genre de
   bascule casse : le logo `logo-asha.png` mesure 76/255 de luminance moyenne
   sur ses pixels opaques. Il est SOMBRE, il tient donc sur du blanc — au
   contraire des logos partenaires, mesurés entre 138 et 195, qui avaient
   demandé une inversion de filtre pour la bande d'alianzas. On ne suppose pas,
   on mesure, et la réponse n'est pas la même d'une image à l'autre.

   Deux exceptions gardées en sombre, et c'est délibéré : le sous-menu déroulant
   et le bloc « bootlog » du pied de page sont des surfaces de second plan qui
   se lisent comme des panneaux posés dessus. */

.site-header {
  background: color-mix(in srgb, var(--sol-clair) 92%, transparent);
  border-bottom: 1px solid rgba(16, 16, 16, 0.10);
}
/* La lueur rouge du logo était faite pour un fond noir ; sur du blanc elle
   devient un halo sale autour du lettrage. */
.site-header__logo,
.site-footer__logo { filter: none; }

/* La navigation est centrée sur la PAGE, pas entre ses deux voisins : une
   grille 1fr / auto / 1fr la tient au milieu quelle que soit la largeur du
   logo à gauche et des boutons à droite. space-between la décalait. */
@media (min-width: 62rem) {
  .site-header__inner {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    align-items: center;
  }
  .site-header__cta { justify-self: end; }
}

.site-header .main-nav__link { color: var(--color-fg-light); }
.site-header .main-nav__link:hover {
  color: var(--color-primary-deep);
  background: color-mix(in srgb, var(--color-primary) 7%, transparent);
}
.site-header .main-nav__link.is-active {
  color: var(--color-primary-deep);
  background: color-mix(in srgb, var(--color-primary) 10%, transparent);
}
.site-header .lang-switch__btn { color: var(--color-muted-light); }
.site-header .lang-switch__btn.is-active {
  color: var(--color-fg-light);
  background: color-mix(in srgb, var(--color-primary) 14%, transparent);
}
.site-header .lang-switch__sep { color: rgba(16, 16, 16, 0.28); }
.site-header .btn-secondary {
  color: var(--color-fg-light);
  border-color: rgba(16, 16, 16, 0.22);
  background: transparent;
}
.site-header .btn-secondary:hover {
  color: var(--color-primary-deep);
  border-color: var(--color-primary);
  background: color-mix(in srgb, var(--color-primary) 6%, transparent);
}
.site-header .mobile-menu-toggle { color: var(--color-fg-light); }

/* ── Le pied de page ──────────────────────────────────────────────────── */
.site-footer {
  background: var(--sol-clair);
  border-top: 1px solid rgba(16, 16, 16, 0.10);
  color: var(--color-fg-light);
}
.site-footer__col h3          { color: var(--color-fg-light); }
.site-footer__brand-text,
.site-footer__coverage,
.site-footer__contact,
.site-footer__contact a       { color: var(--color-muted-light); }
.site-footer__contact a:hover { color: var(--color-fg-light); }
.site-footer__list a          { color: var(--color-fg-light); }
.site-footer__bottom          { border-top-color: rgba(16, 16, 16, 0.10); }
.site-footer__bottom,
.site-footer__bottom a        { color: var(--color-muted-light); }
/* Les deux sceaux ISO mesurent 215 et 216 de luminance : ils portent un fond
   blanc cuit. Sur le sol clair ils se fondraient sans le liseré qui les
   detoure. FIRST, lui, mesure 59 et n'en a pas besoin — on le donne quand meme
   aux trois, pour que la rangee reste une rangee. */
.site-footer__badges img {
  background: #FFFFFF;
  border: 1px solid rgba(16, 16, 16, 0.12);
}


/* Le rouge des liens sur les deux barres claires. --color-primary y plafonne a
   3,87:1 (header) et 4,62 (pied de page) pour un seuil de 4,5 a 14 px : le
   premier echoue, le second passe sans marge. La variante deep rend 5,51 et
   6,58. Mesure faite sur les PIXELS RENDUS, pas sur les valeurs declarees —
   la pastille de l'entree active melange 10 % de rouge au fond, ce qu'aucun
   calcul sur les tokens seuls n'aurait vu. */
.site-footer__contact-cta { color: var(--color-primary-deep) !important; }
.site-footer__list a:hover,
.site-footer__bottom a:hover,
.site-footer__contact a:hover { color: var(--color-primary-deep); }
.site-footer__col h3 { color: var(--color-fg-light); }


/* ══════════════════════════════════════════════════════════════════════════
   METODOLOGIA : LES SOLS DE LA HOME — 2026-08-14
   ══════════════════════════════════════════════════════════════════════════
   .method peint son fond avec --band-bg, pas avec background-color : la règle
   générale des sols (l.9852) ne l'atteint donc pas, elle serait écrasée par
   `background: var(--band-bg)`. C'est la variable qu'il faut viser, pas la
   propriété. Trois lignes suffisent, et le reste de la bande — encre, filets,
   halo — suit tout seul puisqu'il dérive lui aussi de ces variables. */
.method[data-sol="0"] { --band-bg: var(--sol-0); }
.method[data-sol="1"] { --band-bg: var(--sol-1); }
.method[data-sol="2"] { --band-bg: var(--sol-2); }

/* La barre collante des six méthodologies était en #101010 écrit en dur, une
   valeur d'avant l'échelle noire. Elle se cale sur sol-1, comme le menu de la
   home, et ses masques de bord avec — écrits eux aussi en dur au même endroit,
   ils laissaient un rectangle plus clair aux extrémités dès que le fond
   changeait. */
.subnav { background: color-mix(in srgb, var(--sol-1) 94%, transparent); }
.subnav__inner::before {
  background: linear-gradient(90deg, var(--sol-1) 0%, color-mix(in srgb, var(--sol-1) 0%, transparent) 100%);
}
.subnav__inner::after {
  background: linear-gradient(270deg, var(--sol-1) 0%, color-mix(in srgb, var(--sol-1) 0%, transparent) 100%);
}

/* ══════════════════════════════════════════════════════════════════════════
   LE HEADER REVIENT AU SOMBRE — 2026-08-14, demande de Gabriel
   ══════════════════════════════════════════════════════════════════════════
   Le pied de page RESTE clair : il n'a demandé que le header.
   Ce qui reste de la passe blanche, parce que ce sont deux autres demandes :
   la hauteur portée à 88 px et la navigation centrée par la grille. */
.site-header {
  background: rgba(16, 16, 16, 0.85);
  border-bottom: 1px solid var(--color-border);
}
.site-header .main-nav__link { color: var(--color-fg); }
.site-header .main-nav__link:hover {
  color: var(--color-primary-lift);
  background: rgba(220, 38, 38, 0.08);
}
.site-header .main-nav__link.is-active {
  color: var(--color-primary-lift);
  background: rgba(220, 38, 38, 0.08);
}
.site-header .lang-switch__btn { color: var(--color-muted); }
.site-header .lang-switch__btn.is-active {
  color: var(--color-fg);
  background: rgba(220, 38, 38, 0.18);
}
.site-header .lang-switch__sep { color: rgba(248, 250, 252, 0.32); }
.site-header .btn-secondary {
  color: var(--color-fg);
  border-color: rgba(255, 255, 255, 0.18);
  background: rgba(255, 255, 255, 0.03);
}
.site-header .btn-secondary:hover {
  color: var(--color-fg);
  border-color: var(--color-primary);
  background: rgba(220, 38, 38, 0.12);
}
.site-header .mobile-menu-toggle { color: var(--color-fg); }
/* La lueur rouge du logo revient AVEC le fond sombre : elle était faite pour
   lui. Le logo du pied de page, lui, reste sans filtre — il est sur du clair. */
.site-header__logo { filter: drop-shadow(0 0 8px rgba(220, 38, 38, 0.25)); }


/* .theme-steel peint un degrade #171717 -> #1A1A1A en !important, une valeur
   d'avant l'echelle noire : elle se glisse ENTRE sol-1 et sol-2 et annule la
   frontiere (1,081 mesure). C'est la faute nommee ailleurs dans ce fichier —
   l'echelle monte, elle ne s'intercale pas.
   Neutralise pour LA SEULE section d'acreditaciones : theme-steel sert encore
   cinq fois sur nosotros.html, ou l'alternance est differente et ou personne
   n'a demande d'alignement. */
#acreditaciones.theme-steel { background: var(--sol-0) !important; }


/* La ligne de rôle de ZeroTrust prend la variante claire du violet : c'est le
   seul des six personas qui échouait une fois sa bande passée sur fond sombre.
   Mesuré sur les six : ASHA 5,58 · ZeroTrust 4,07 · NGSOC 17,03 · CSIRT 6,63 ·
   CTEM 7,49 · GRC 7,07. On corrige le cas, pas la règle. */
.method[data-persona="zerotrust"] .method__role { color: var(--color-zerotrust-soft); }


/* ══════════════════════════════════════════════════════════════════════════
   LE PLATEAU « SERVICIOS TÉCNICOS » PREND LA COULEUR DE SA MÉTHODOLOGIE
   ══════════════════════════════════════════════════════════════════════════
   2026-08-14, demande de Gabriel, captures a l'appui : le grand plateau blanc
   doit adopter le style du volet de #soluciones sur la home, dans la couleur du
   persona.

   CE N'ETAIT PAS UN RESTE DES BANDES CLAIRES. .method--dark declarait
   explicitement --plate-bg: var(--color-bg-light), avec une mesure a l'appui :
   « sur un aplat un cran plus sombre, les six encres tombaient a 4,31-4,35:1,
   sous le seuil AA ». Ce plateau clair etait donc un choix, pas un oubli, et le
   remplacer oblige a REPRENDRE cette mesure — c'est fait plus bas.

   LA BASCULE TIENT EN CINQ VARIABLES, parce que tout le bloc en derive : le
   chiffre, le libelle, les puces, le filet, le detail depliant. On ne touche a
   aucune regle de mise en page.

   --plate-ink DOIT CHANGER DE FAMILLE, et c'est le piege. Il valait
   --persona-ink, l'encre calibree pour un aplat CLAIR. Sur un aplat sombre il
   faut --persona-lift. Garder l'ancienne aurait donne du sombre sur du sombre
   sans qu'aucune regle ne paraisse fausse. */
.method--dark {
  --plate-bg:
    linear-gradient(180deg,
      color-mix(in srgb, var(--persona) 14%, transparent),
      color-mix(in srgb, var(--persona) 5%, transparent)),
    var(--color-surface);
  --plate-fg: var(--color-fg);
  --plate-muted: var(--color-muted);
  --plate-rule: color-mix(in srgb, var(--persona) 34%, transparent);
  --plate-ink: var(--persona-lift);
}
/* L'ombre portee etait faite pour une carte claire posee sur du sombre. Une
   carte sombre sur du sombre ne se detache pas par une ombre, elle se detache
   par sa bordure teintee — celle-ci la porte deja. */
.method__proof { box-shadow: none; }


/* « Ver el detalle » : 11,5 px, donc seuil 4,5. Sur le plateau devenu sombre,
   deux encres persona sur six passent en dessous — mesure des six : ASHA 3,76 ·
   ZeroTrust 3,58 · NGSOC 11,49 · CSIRT 5,83 · CTEM 5,05 · GRC 6,21.
   Ce sont les deux memes qui avaient deja besoin d'une variante claire ailleurs
   sur cette page : le rouge de marque et le violet. On leur donne la leur, on
   ne touche pas aux quatre autres. Le grand chiffre du plateau, lui, est a
   44 px : son seuil est de 3 et il passe avec la couleur pleine. */
.method[data-persona="asha"] .method__disclose-toggle span { color: var(--color-primary-soft); }
.method[data-persona="zerotrust"] .method__disclose-toggle span { color: var(--color-zerotrust-soft); }


/* ══════════════════════════════════════════════════════════════════════════
   LE VOLET MASQUÉ OCCUPAIT ENCORE SA PLACE — 2026-08-14
   ══════════════════════════════════════════════════════════════════════════
   Défaut signalé par Gabriel : « el caso de Ecuador esta muy bien presentado,
   el de Mexico no ». Mesuré, la cause n'était pas dans le cas Mexico mais dans
   les deux : le volet CACHÉ gardait 412 px de hauteur, à y=538 pour l'un et
   y=950 pour l'autre. D'où un trou de 430 px au-dessus du contenu de Mexico.

   L'attribut hidden n'est qu'un `display: none` de la feuille de l'agent
   utilisateur : la moindre règle d'auteur qui pose un display le bat. Ma règle
   `@media (min-width: 62rem) { .cases__pane { display: grid } }` le battait
   donc à toutes les largeurs de bureau, et le JS avait beau poser hidden, rien
   ne disparaissait — il ne restait que le fondu, sur deux volets superposés
   dans le flux.
   La même règle est posée sur le panneau de #soluciones, qui a exactement le
   même montage et où le piège n'attendait qu'un display pour se déclencher. */
.cases__pane[hidden],
.solpanel__pane[hidden] { display: none !important; }

/* Le chiffre du cas Mexico est une FOURCHETTE, « −30-40 », et non un nombre :
   à 77,76 px dans une colonne de 298 il se coupait en « −30- » puis « 40 »,
   avec le signe % rejeté à droite. Mesure, pas impression.
   Deux corrections : il ne se coupe plus, et le corps de la variante « lead »
   descend pour que la fourchette tienne sur sa ligne. Le grand corps était
   calibré sur un nombre de deux ou trois caractères, pas sur six. */
.case-fig__num { white-space: nowrap; }
.case-fig--lead .case-fig__num { font-size: clamp(38px, 3.6vw, 62px); }
@media (min-width: 62rem) {
  .case-fig--lead .case-fig__num { font-size: clamp(42px, 4vw, 68px); }
}


/* Un seul chiffre en face d'un texte pleine hauteur : la colonne de droite
   restait vide sur 250 px. Ce n'est pas un defaut de reglage, c'est la donnee —
   Ecuador a quatre metriques, Mexico une. On ne fabrique pas de chiffres pour
   remplir : on donne a celui qui existe la place qu'il merite, centre dans sa
   colonne et en pleine hauteur, pour qu'il se lise comme LE resultat du cas et
   non comme un item esseule en haut a droite. */
.cases__figures:has(> :only-child) {
  align-content: center;
  min-height: 100%;
}
@media (min-width: 62rem) {
  .cases__figures:has(> :only-child) .case-fig__num { font-size: clamp(52px, 5vw, 84px); }
  .cases__figures:has(> :only-child) .case-fig__label {
    font-size: 12px;
    max-width: 26ch;
  }
}


/* ══════════════════════════════════════════════════════════════════════════
   AUCUN TITRE AU-DELÀ DE DEUX LIGNES — 2026-08-14
   ══════════════════════════════════════════════════════════════════════════
   Demande de Gabriel : « el primer titulo deberia de ir en solo dos lineas
   jamas en tres, lo mismo en todos los titulos de todas las secciones ».

   CE QUI GOUVERNE LE NOMBRE DE LIGNES, C'EST LA MESURE, PAS LE CORPS. Un
   solveur a cherché par dichotomie la taille à laquelle chaque titre tiendrait
   en deux lignes : il descendait jusqu'à 10 px sans jamais y arriver. La raison
   est que les max-width sont écrits en `ch`, une unité qui SUIT le corps.
   Réduire la police rétrécit la mesure d'autant et le nombre de lignes ne bouge
   pas. C'est la mesure qu'il faut ouvrir, pas le corps qu'il faut baisser.

   Chaque valeur est le nombre de caractères du plus long titre de sa classe,
   divisé par deux, plus une marge de césure :
     .hero__title              35 car -> 20ch
     .section-title            55 car -> 30ch
     .final-cta__title         96 car -> 52ch   (nosotros, le plus long)
     .page-hero__title        125 car -> 66ch   (bolsa-de-trabajo)

   POUR LES DEUX PLUS LONGS la mesure seule ne suffit pas : 66ch à 60 px font
   plus de 2 000 px, au-delà de toute page. Leur corps descend donc aussi, et
   c'est un arbitrage assumé — un titre de 125 caractères ne tient pas en deux
   lignes à la taille d'un titre de 35. */

.hero__title { max-width: 20ch; }
.section-title { max-width: 30ch; }
.section-head { max-width: min(100%, 1000px); }
.final-cta__title,
.final-cta--poster .final-cta__title { max-width: 52ch; }
.page-hero__title { max-width: 66ch; }

.page-hero__title { font-size: clamp(26px, 3.1vw, 44px); }
.final-cta__title { font-size: clamp(26px, 2.9vw, 42px); }


/* Suite : la mesure du TITRE ne sert a rien si son CONTENEUR est plus etroit.
   Mesure : .hero__title annoncait max-width 1148px et se rendait a 680, les
   .section-title a 724-805 pour un max de 1189. C'est le conteneur qui coupe,
   et il fallait le voir avant d'accuser le titre.
   On ouvre donc les conteneurs, et on remonte la specificite la ou une regle a
   deux classes gagnait (.page-hero--league .page-hero__title, l.2678). */
.page-hero__inner { max-width: min(100%, 1240px); }
.page-hero--league .page-hero__title,
.page-hero .page-hero__title { font-size: clamp(26px, 3.1vw, 44px); max-width: 66ch; }
.section-head, .section-head--left { max-width: min(100%, 1060px); }
.hero .hero__title { max-width: 22ch; }
.hero__copy { max-width: min(100%, 1100px); }
.final-cta__inner .final-cta__title,
.final-cta--poster .final-cta__title { max-width: 52ch; font-size: clamp(26px, 2.9vw, 42px); }


/* Derniere passe : ce sont les CONTENEURS qui coupaient, chacun le sien.
   Chaine des largeurs relevee element par element :
     .hero__title      680px  <- .hero__col-left  max-width: 680px
     #industrias h2    724px  <- premiere colonne de la grille .industries__head
     .final-cta__title 614px  <- .final-cta__inner max-width: 760px
   On les ouvre juste assez pour deux lignes, pas plus : un titre qui traverse
   toute la page ne se lit pas mieux qu'un titre sur trois lignes. */
.hero__col-left { max-width: min(100%, 860px); }
.industries__head > div:first-child { max-width: min(100%, 900px); }
.final-cta__inner { max-width: min(100%, 1000px); }

/* text-wrap: balance repartit les lignes au lieu de laisser un mot orphelin.
   Il ne change pas le NOMBRE de lignes quand la mesure est trop etroite, mais
   il evite le cas frequent ou une troisieme ligne ne porte qu'un mot. */
.hero__title, .page-hero__title, .section-title, .final-cta__title {
  text-wrap: balance;
}


/* Le dernier cran, et c'est un ARBITRAGE, pas un reglage. Quatre titres
   resistaient encore : ce sont les quatre phrases les plus longues du site
   (49 a 125 caracteres) dans des conteneurs deja ouverts au maximum
   raisonnable. A mesure egale, deux lignes s'obtiennent alors en baissant le
   corps, et rien d'autre.
   Calcul pour le pire cas : « Vasta experiencia en sectores regulados y
   criticos », 49 caracteres dans 724 px de colonne. Deux lignes demandent
   25 caracteres par ligne, soit un corps d'au plus 55 px ; il etait a 56.
   On descend le plafond des titres de section a 48, celui des heros de page a
   40. Le texte reste grand — c'est le titre d'une section, pas un paragraphe —
   mais il tient la promesse des deux lignes. */
.section-title { font-size: clamp(26px, 3.3vw, 48px); }
.page-hero--league .page-hero__title,
.page-hero .page-hero__title { font-size: clamp(24px, 2.8vw, 40px); }
.final-cta__inner .final-cta__title,
.final-cta--poster .final-cta__title { font-size: clamp(24px, 2.6vw, 38px); }


/* Le dernier titre de bureau qui resistait : celui du CTA de nosotros, 96
   caracteres. Deux lignes demandent 48 caracteres par ligne ; dans les 854 px
   que lui laisse son bloc, cela plafonne le corps a 32 px. */
.final-cta__inner .final-cta__title,
.final-cta--poster .final-cta__title { font-size: clamp(23px, 2.2vw, 32px); }

/* ── SOUS 600 PX, LA REGLE NE PEUT PAS TENIR, ET C'EST DE L'ARITHMETIQUE ──
   A 320 px de large, un conteneur fait 280 px. Deux lignes y portent une
   cinquantaine de caracteres a 26 px. Or les titres du site font de 44 a 125
   caracteres : « Garantice la proteccion continua de su empresa con nuestra
   estrategia unificada » en compte 125, il lui faudrait cinq lignes a 26 px,
   ou un corps de 10 px pour en tenir deux. Aucun reglage ne rend cela lisible.
   On ne triche donc pas avec un font-size minuscule sur mobile : les titres y
   prennent le nombre de lignes que leur texte exige. La promesse des deux
   lignes est tenue de 900 a 1280 px, ou elle se verifie a 0 titre. */



/* Le fondu du volet, sur le meme motif que celui des casos. */
.solpanel--vivant .solpanel__pane {
  opacity: 0;
  transform: translateY(8px);
  transition: opacity 340ms var(--ease-out), transform 340ms var(--ease-out);
}
.solpanel--vivant .solpanel__pane.is-active { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
  .solpanel--vivant .solpanel__pane { transition: none; transform: none; }
}


/* ══════════════════════════════════════════════════════════════════════════
   LES DEUX THÈMES MAISON RENDENT LEUR SOL À L'ÉCHELLE — 2026-08-14
   ══════════════════════════════════════════════════════════════════════════
   .theme-deep-slate et .theme-steel peignaient un dégradé en dur, en
   !important : #0B0B0B->#101010 pour l'un, #171717->#1A1A1A pour l'autre. Ces
   valeurs s'intercalent entre sol-0, sol-1 et sol-2 au lieu de s'y poser, et
   c'est ce qui rendait quatre frontières sur huit invisibles sur nosotros.

   ON NE SUPPRIME PAS LES THÈMES, on leur retire le SOL. Ce qu'ils apportent
   d'autre — la lueur radiale au sommet, la grille en ::before, le traitement
   des cartes — reste : c'est de la texture, elle se pose sur n'importe quel
   barreau. Seul le dégradé de fond part, et data-sol reprend la main.

   Le !important d'origine oblige à répondre par un !important : c'est la seule
   fois de ce fichier où j'en écris un sans qu'il soit déjà là, et c'est pour
   défaire celui d'en face, pas pour en gagner un. */
main > section.theme-deep-slate,
main > section.theme-steel {
  background-image: radial-gradient(ellipse 100% 60% at 50% 0%,
    color-mix(in srgb, var(--color-primary) 5%, transparent), transparent 55%) !important;
  background-color: transparent !important;
}
main > section.theme-steel {
  background-image: radial-gradient(ellipse 100% 50% at 50% 0%,
    rgba(148, 163, 184, 0.06), transparent 55%) !important;
}
/* data-sol peut alors peindre : il pose une background-color, que les règles
   ci-dessus laissent passer en la mettant a transparent sur le raccourci. */
main > section.theme-deep-slate[data-sol="0"],
main > section.theme-steel[data-sol="0"] { background-color: var(--sol-0) !important; }
main > section.theme-deep-slate[data-sol="1"],
main > section.theme-steel[data-sol="1"] { background-color: var(--sol-1) !important; }
main > section.theme-deep-slate[data-sol="2"],
main > section.theme-steel[data-sol="2"] { background-color: var(--sol-2) !important; }
/* Le quatrieme cas de la serie, manquant jusqu'au 2026-08-15. Les sols 0, 1 et
   2 etaient couverts, pas « clair » : en passant trayectoria au clair sa
   section n'a recu AUCUN fond et est restee transparente. L'encre foncee des
   legendes se retrouvait alors sur le sol sombre du dessous, a 2,77:1.
   Le degrade decoratif de theme-steel reste pose par-dessus. */
main > section.theme-steel[data-sol="clair"],
/* deep-slate a exactement le meme trou que steel : les sols 0, 1 et 2 sont
   couverts, pas « clair ». Sans cette ligne, certificaciones se serait
   retrouvee transparente comme trayectoria l'a ete avant elle. */
main > section.theme-deep-slate[data-sol="clair"] { background-color: var(--sol-clair) !important; }


/* ══════════════════════════════════════════════════════════════════════════
   LES CARTES DE NOSOTROS SE DÉTACHENT DE LEUR SOL — 2026-08-14
   ══════════════════════════════════════════════════════════════════════════
   Mesuré après la pose des sols : sur sol-2, deux familles de cartes tombaient
   sous le seuil de bande.
       .about-card    #2B2B2B sur #212121 = 1,137:1   (seuil 1,14)
       .leader-card   #272828 sur #212121 = 1,085:1
   Ce n'est pas un réglage manquant, c'est le corollaire du passage à sol-2 :
   --color-surface était calibré pour se détacher de sol-0 et de sol-1, pas du
   barreau juste au-dessous de lui. Le système a déjà la réponse —
   --color-surface-elev, un cran plus haut — et c'est exactement à ça qu'elle
   sert : la carte monte quand son sol monte. L'échelle monte, elle ne
   s'intercale pas.
   Mesure de la parade : #383838 sur #212121 = 1,353:1. */
main > section[data-sol="2"] .about-card,
main > section[data-sol="2"] .leader-card {
  background: var(--color-surface-elev);
}


/* ══════════════════════════════════════════════════════════════════════════
   LA GRILLE DES HEROS DE PAGE SE VOIT ENFIN — 2026-08-14
   ══════════════════════════════════════════════════════════════════════════
   Gabriel : « ils ont pas de grille ». Elle existait pourtant en balisage
   (.page-hero__bg-grid) et en CSS. Mesure de son amplitude reelle sur les
   pixels rendus, sur une ligne au tiers haut :
       home              227 niveaux (la grille se lit)
       metodologia       0,6 niveau
       nosotros          2,3 niveaux
       bolsa-de-trabajo  2,3 niveaux
   La cause : 0,04 d'alpha multiplie par une opacite de 0,4, soit 0,016
   effectif, contre 0,07 x 0,55 = 0,0385 sur la home. Deux fois et demie plus
   faible, donc sous le seuil de perception sur un fond noir.
   On aligne sur la home. Le masque radial reste : c'est lui qui empeche la
   grille de courir jusqu'aux bords. */
.page-hero__bg-grid {
  background-image:
    linear-gradient(rgba(255, 255, 255, 0.07) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255, 255, 255, 0.07) 1px, transparent 1px);
  opacity: 0.55;
  /* LE MASQUE AUSSI, et c'est le vrai sujet. Il etait une ELLIPSE CENTREE :
     la grille etait donc absente sur les bords, c'est-a-dire A GAUCHE, la ou
     vit le texte et ou l'oeil se pose. On avait beau la renforcer, elle restait
     invisible la ou on la cherche. La home masque en degrade HORIZONTAL, opaque
     du cote du texte : on reprend le sien. */
  -webkit-mask-image: linear-gradient(to right, black 0%, black 45%, transparent 82%);
          mask-image: linear-gradient(to right, black 0%, black 45%, transparent 82%);
}


/* La bande blanche remonte un peu — 2026-08-14, demande de Gabriel : « un tout
   petit peu, mais vraiment juste un tout petit peu ».

   PAS PAR LE REMBOURRAGE. Premier essai en baissant padding-bottom : sans
   effet, pour deux raisons mesurees. La premiere est que .hero l.8226 en pose
   deja un en !important. La seconde, plus interessante : le hero a un
   min-height, donc reduire son rembourrage ne le raccourcit pas — le contenu
   se repositionne a l'interieur et la bande ne bouge pas d'un pixel.
   C'est le min-height qu'il faut toucher, et il est ecrit en 100vh moins un
   decalage d'en-tete de 93 px. On porte ce decalage a 117, soit 24 px de moins
   pour le hero et autant de gagne pour la bande. */
.hero {
  min-height: max(560px, calc(100vh - 117px)) !important;
  min-height: max(560px, calc(100svh - 117px)) !important;
}




/* ══════════════════════════════════════════════════════════════════════════
   TOUTES LES CARTES REAGISSENT AU SURVOL — 2026-08-14
   ══════════════════════════════════════════════════════════════════════════
   Demande de Gabriel : prendre pour reference les cartes de « Marcos ·
   Certificaciones · Partner levels ». Leur geste, releve tel quel a la l.2177 :
       transform: translateY(-3px)
       border-color: la teinte de la carte, a 55 %
       box-shadow: 0 12px 32px rgba(0,0,0,0.35)
       transition: all, duree normale, ease-out

   INVENTAIRE AVANT D'AGIR. Un balayage des classes reellement presentes dans
   les six pages, croise avec les regles :hover du CSS, a montre que la plupart
   des cartes en avaient deja un — .about-card, .alliance-card, .cert-card,
   .country, .feature-card, .framework, .highlight, .industry-card, .metric,
   .partner-level, .practice. CINQ familles n'en avaient aucun, et ce sont
   elles que la regle ci-dessous rattrape. Les dizaines d'autres classes sans
   survol sont des ENFANTS de cartes (__title, __label, __icon) : leur donner un
   etat propre ferait deux animations concurrentes sur le meme geste. */
.leader-card,
.cap,
.support-item,
.method__proof,
.layer {
  transition: transform var(--duration-normal) var(--ease-out),
              border-color var(--duration-normal) var(--ease-out),
              box-shadow var(--duration-normal) var(--ease-out);
}
.leader-card:hover,
.cap:hover,
.support-item:hover,
.method__proof:hover,
.layer:hover {
  transform: translateY(-3px);
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.35);
}
/* Chacune prend la teinte qu'elle porte deja : le persona pour les bandes de
   metodologia, le rouge de marque ailleurs. On n'introduit pas de couleur. */
.leader-card:hover,
.cap:hover,
.support-item:hover {
  border-color: color-mix(in srgb, var(--color-primary) 55%, transparent);
}
.method__proof:hover {
  border-color: color-mix(in srgb, var(--persona, var(--color-primary)) 62%, transparent);
}
.layer:hover {
  border-color: color-mix(in srgb, var(--color-primary) 45%, transparent);
}
/* .layer ET .cap NE MONTENT PAS, et c'est voulu apres mesure : les reveals GSAP
   leur posent un transform EN STYLE INLINE, qui bat toute regle de feuille.
   Leur disputer la propriete ferait clignoter la carte a chaque survol pendant
   que l'animation d'apparition tourne encore. Elles gardent donc la bordure et
   l'ombre, qui suffisent a repondre au curseur. C'est le meme couplage que la
   fiche de la skill signale : les reveals animent le transform, on ne le leur
   reprend pas.

   Le mouvement s'efface pour qui l'a demande. */
@media (prefers-reduced-motion: reduce) {
  .leader-card, .cap, .support-item, .method__proof, .layer { transition: none; }
  .leader-card:hover, .cap:hover, .support-item:hover,
  .method__proof:hover, .layer:hover { transform: none; }
}


/* ══════════════════════════════════════════════════════════════════════════
   #SOLUCIONES : UNE IMAGE PAR OPTION, EN FOND DE SECTION, PLEINEMENT VISIBLE
   ══════════════════════════════════════════════════════════════════════════
   2026-08-14. Gabriel : l'image en fond de toute la section, a pleine opacite,
   et une image DIFFERENTE par option.

   DEUX CALQUES QUI SE RELAIENT, et c'est ce qui permet le fondu. Une seule
   couche ne peut pas fondre d'une image vers une autre : le navigateur
   interpole des couleurs et des longueurs, pas des fichiers. On empile donc
   les six images en six pseudo-plans — impossible avec deux pseudo-elements —
   ou, plus simplement, on pose LES SIX en background-image du meme element et
   on ne fait varier que leur OPACITE respective. C'est cette seconde voie :
   six couches, une seule visible a la fois, chacune avec sa transition.

   PLEINE OPACITE, DONC UN VOILE QUI TRAVAILLE. Une photo a 100 % sous du texte
   blanc n'est pas lisible : la lisibilite est reportee sur le voile, qui est
   un degrade et non un aplat, pour que l'image reste franche la ou il n'y a
   rien d'ecrit. Contrastes verifies apres coup sur les six volets. */
#soluciones { position: relative; isolation: isolate; }
#soluciones .solpanel__fond {
  position: absolute;
  inset: 0;
  z-index: -2;
  overflow: hidden;
}
#soluciones .solpanel__fond span {
  position: absolute;
  inset: 0;
  background-size: cover;
  background-position: center;
  opacity: 0;
  transition: opacity 520ms var(--ease-out);
}
/* 1 -> 0,45 le 2026-08-14 : a pleine opacite l'image concurrencait le texte
   et il fallait un voile tres dense pour la rattraper, ce qui revenait a la
   masquer par l'autre bout. A 0,45 elle se voit franchement et le voile peut
   s'allager d'autant. */
#soluciones .solpanel__fond span.is-on { opacity: 0.45; }
/* LES SIX FONDS PASSENT AU JEU v2 le 2026-08-17 : photographies produites pour
   cette section, une par methode, dans une serie coherente (16:9, navy dominant,
   un seul accent rouge par image, personnages de dos et aucun visage
   identifiable, aucun caractere a l'ecran).
   DEUX POINTS QUE CA REGLE. La question de licence qui restait ouverte sur les
   fonds precedents n'a plus d'objet : ces images sont produites pour le site.
   Et la regle du projet sur les images sans texte est tenue, verifiee au zoom
   100 % sur les deux vues les plus exposees, le mur du SOC et l'ecran du conseil.
   LE CHEMIN CHANGE (v2/) ET C'EST OBLIGATOIRE : /assets/* est servi en immutable
   pour un an, un fichier de meme nom n'aurait jamais ete rafraichi.
   #razones sur nosotros continue de pointer l'ancien jeu — sa demande portait
   sur #soluciones. */
#soluciones .solpanel__fond span[data-bg="ctem"]      { background-image: url('../assets/images/bg/soluciones/v2/ctem.webp'); }
#soluciones .solpanel__fond span[data-bg="ngsoc"]     { background-image: url('../assets/images/bg/soluciones/v2/ngsoc.webp'); }
#soluciones .solpanel__fond span[data-bg="csirt"]     { background-image: url('../assets/images/bg/soluciones/v2/csirt.webp'); }
#soluciones .solpanel__fond span[data-bg="zerotrust"] { background-image: url('../assets/images/bg/soluciones/v2/zerotrust.webp'); }
#soluciones .solpanel__fond span[data-bg="grc"]       { background-image: url('../assets/images/bg/soluciones/v2/grc.webp'); }
#soluciones .solpanel__fond span[data-bg="bridge"]    { background-image: url('../assets/images/bg/soluciones/v2/bridge.webp'); }

/* Le voile porte toute la lisibilite, puisque l'image est a pleine opacite.
   Il est plus dense a gauche, sous la liste et le titre, et s'ouvre a droite
   ou le volet a son propre fond. */
#soluciones::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background:
    linear-gradient(90deg,
      color-mix(in srgb, var(--sol-2) 82%, transparent) 0%,
      color-mix(in srgb, var(--sol-2) 68%, transparent) 46%,
      color-mix(in srgb, var(--sol-2) 34%, transparent) 100%),
    linear-gradient(180deg,
      color-mix(in srgb, var(--sol-2) 34%, transparent),
      color-mix(in srgb, var(--sol-2) 10%, transparent) 40%,
      color-mix(in srgb, var(--sol-2) 46%, transparent));
}
@media (prefers-reduced-motion: reduce) {
  #soluciones .solpanel__fond span { transition: none; }
}


/* ══════════════════════════════════════════════════════════════════════════
   « POR QUÉ PREFERIRNOS » SUR LE MOTIF DE LA RÉFÉRENCE — 2026-08-14
   ══════════════════════════════════════════════════════════════════════════
   Gabriel a fourni une capture de l'ancien site : grande illustration au trait
   rouge en haut de carte, titre centré, texte centré, carte généreuse.

   PORTÉE : la seule section « 04 · Por qué preferirnos ». La classe
   .about-card sert AUSSI aux trois cartes de « 07 · Nuestro modelo » — mon
   premier essai les emportait toutes les neuf. D'où le modificateur sur le
   conteneur, qui borne exactement ce que Gabriel a nommé.

   CE QUI EST REPRIS : la structure. L'icône passe d'une pastille de 24 px à une
   illustration de ~96 px, tout se centre, la carte respire.

   CE QUI NE L'EST PAS, ET POURQUOI : le fond blanc. La référence vient du site
   à fond clair ; la page est passée à l'échelle noire ce matin, et six cartes
   blanches y feraient six trous. C'est la structure qui fait la ressemblance,
   pas la couleur du papier. Le blanc littéral, s'il est voulu, est une
   déclaration de plus.

   Les illustrations de la référence sont des dessins sur mesure que nous
   n'avons pas. Nos six icônes de sprite SONT du trait : agrandies et passées au
   rouge, elles tiennent le même rôle. */
.about-cards--illustre .about-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: var(--space-4);
  padding: clamp(28px, 3vw, 44px) clamp(22px, 2.4vw, 32px);
}
.about-cards--illustre .about-card__icon-wrap {
  width: clamp(72px, 7vw, 96px);
  height: clamp(72px, 7vw, 96px);
  display: grid;
  place-items: center;
  padding: 0;
  background: none;
  border: 0;
  box-shadow: none;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}
.about-cards--illustre .about-card__icon-wrap svg {
  width: 100%;
  height: 100%;
  color: var(--color-primary-lift);
  stroke-width: 1.2;
}
.about-cards--illustre .about-card__title {
  font-size: clamp(18px, 1.5vw, 22px);
  font-weight: 700;
}
.about-cards--illustre .about-card__desc {
  max-width: 34ch;
  margin-inline: auto;
  line-height: 1.65;
}


/* Le centrage des cartes illustrees, avec la specificite qu'il faut : une
   regle a deux classes posait align-items: flex-start et gagnait sur la mienne.
   Mesure du decalage avant correction : l'icone tombait a 134 px du centre de
   sa carte, le titre a 105. */
.about-cards.about-cards--illustre .about-card {
  align-items: center;
  justify-items: center;
}
.about-cards.about-cards--illustre .about-card__icon-wrap { margin-inline: auto; }


/* align-items ne cede pas : une regle adverse le tient a flex-start et je ne
   la battrai pas sans surenchere de specificite. On passe donc par l'enfant —
   align-self: stretch fonctionne quel que soit l'align-items du parent, et
   text-align: center fait le reste. Mesure avant : le titre tombait a 105 px
   du centre de sa carte. */
.about-cards--illustre .about-card > * { align-self: stretch; }
.about-cards--illustre .about-card__icon-wrap { align-self: center; }


/* ══════════════════════════════════════════════════════════════════════════
   LE CORRIDOR DE PARTICULES SUR LES SIX BANDES — 2026-08-14
   ══════════════════════════════════════════════════════════════════════════
   Le test sur GRC est valide, on l'etend. Ce qu'on a appris en chemin et qui
   vaut pour les six :

   1. EN FOND DE BANDE, pas de figure ni de pseudo-element. Un ::after a insets
      negatifs se resolvait en une lamelle de 264 x 14 px ; un fond sur la
      figure perdait l'essentiel de l'image, la figure etant un portrait de
      456 x 509 et l'image une scene 16:9.
   2. LE NOIR DISPARAIT PAR MELANGE. background-blend-mode: screen rend les
      pixels noirs neutres : seules les particules eclairent, et le fond reste
      exactement --band-bg partout ailleurs. Ni masque ni opacite.
   3. LA TEINTE EST TOURNEE A LA SOURCE. Un filter CSS s'appliquerait a tout le
      contenu de la section. Six fichiers de 67 a 75 Ko, 431 Ko au total, contre
      5,2 Mo pour le PNG d'origine — soit moins que le seul visuel anime de la
      bande NGSOC.
   4. L'ORIENTATION SUIT LE PERSONNAGE. Trois bandes ont leur visuel a gauche
      (asha, ctem, ngsoc) et trois a droite (csirt, zerotrust, grc). Le foyer du
      corridor doit tomber DERRIERE le personnage : les trois premieres images
      sont donc miroitees a la source, et leur voile est pose de l'autre cote.
   5. NGSOC EST EN ARGENT. Une rotation de teinte ne fait pas du gris : ce
      persona recoit en plus une desaturation a la source.
   6. LE VOILE PORTE LA LISIBILITE. Sans lui la luminance du fond variait d'un
      facteur 11,5 sous le lede. Il eteint le champ du cote du texte et le
      laisse entier du cote du personnage. */

.method--dark[data-persona] {
  background-size: cover;
  background-repeat: no-repeat;
  background-blend-mode: normal, screen;
  background-color: var(--band-bg);
}
.method--dark.method--media-end[data-persona] {
  background-position: center, 88% 46%;
  background-image:
    linear-gradient(90deg,
      var(--band-bg) 0%,
      var(--band-bg) 46%,
      color-mix(in srgb, var(--band-bg) 52%, transparent) 60%,
      transparent 76%),
    var(--corridor);
}
.method--dark.method--media-start[data-persona] {
  background-position: center, 12% 46%;
  background-image:
    linear-gradient(270deg,
      var(--band-bg) 0%,
      var(--band-bg) 46%,
      color-mix(in srgb, var(--band-bg) 52%, transparent) 60%,
      transparent 76%),
    var(--corridor);
}
/* ── LE CORRIDOR SUIT LE COTE DU PERSONNAGE       2026-08-22 ─────────────
   ══════════════════════════════════════════════════════════════════════════
   Gabriel, deux fois : « l'embleme a disparu dans ZeroTrust et CTEM ». Ma
   premiere correction reglait le mauvais parametre, et le defaut est reste.

   CE QU'IL FALLAIT COMPRENDRE. Chaque image de corridor porte une sphere
   lumineuse d'un cote et un couloir de particules qui s'en echappe. Sur les
   bandes d'origine, cette sphere se trouve DERRIERE LE PERSONNAGE : elle
   l'aureole, et le couloir file vers le texte. Ce n'est donc pas la position
   du cadrage qu'il faut rendre a l'image, c'est l'IMAGE qu'il faut mettre du
   cote du personnage.

   Mesure des six fichiers, en cherchant leur zone la plus lumineuse : asha,
   ctem et ngsoc ont leur sphere a 12 % ; csirt, grc et zerotrust a 82 %. Ces
   images ont ete fabriquees pour le cote que leur bande occupait alors.
   L'echange de ctem et zerotrust, fait pour aligner l'ordre sur la home, a
   donc mis chaque sphere du cote OPPOSE a son personnage.

   Cadrer autrement ne pouvait pas suffire : la sphere est peinte dans le
   fichier, aucun background-position ne la deplace vers l'autre bord. Les deux
   images sont donc RETOURNEES horizontalement, ce qui remet la sphere derriere
   son personnage et le couloir vers le texte, sans toucher aux couleurs. Le
   miroir est fait a la generation et non en CSS : un fond ne se retourne pas
   sans passer par un pseudo-element, qui aurait ajoute une couche a une bande
   qui en porte deja deux. */
.method--dark[data-persona="asha"]      { --corridor: url('../assets/images/bg/corridor/asha.webp'); }
/* ctem et zerotrust pointent leur corridor RETOURNE depuis le 2026-08-22 :
   l'echange des deux bandes a mis leur sphere du cote oppose au personnage.
   La declaration est modifiee ICI et non ajoutee plus haut : a specificite
   egale c'est la derniere qui gagne, et deux lignes posees au-dessus de
   celles-ci n'auraient rien fait — essaye, mesure, corrige. */
.method--dark[data-persona="ctem"]      { --corridor: url('../assets/images/bg/corridor/ctem-mirror.webp'); }
.method--dark[data-persona="ngsoc"]     { --corridor: url('../assets/images/bg/corridor/ngsoc.webp'); }
.method--dark[data-persona="csirt"]     { --corridor: url('../assets/images/bg/corridor/csirt.webp'); }
.method--dark[data-persona="zerotrust"] { --corridor: url('../assets/images/bg/corridor/zerotrust-mirror.webp'); }
.method--dark[data-persona="grc"]       { --corridor: url('../assets/images/bg/corridor/grc.webp'); }

@media (max-width: 61.99rem) {
  .method--dark.method--media-end[data-persona],
  .method--dark.method--media-start[data-persona] {
    background-position: center, center 62%;
    background-image:
      linear-gradient(180deg, var(--band-bg) 0%, var(--band-bg) 38%, transparent 66%),
      var(--corridor);
  }
}


/* ══════════════════════════════════════════════════════════════════════════
   LES TROIS CTA FINAUX A LA MEME DIMENSION — 2026-08-14
   ══════════════════════════════════════════════════════════════════════════
   Gabriel : celui de nosotros est le bon, les trois doivent lui ressembler, la
   carte centrale comme la section autour.

   MESURE AVANT, element par element :
       nosotros     section 700  carte 304   titre 67 · actions 56 · sceaux 17
       index        section 700  carte 330   + un lede d'une ligne (28)
       metodologia  section 788  carte 420   + un lede de TROIS lignes (84)
   Les deux premieres tenaient deja a 700 grace a un min-height ; seule
   metodologia le depassait, et son lede en portait les 116 px (84 + 32 de
   marge) a lui seul. Il est retire — Gabriel a explicitement autorise a couper
   du texte pour tenir la dimension.

   LE min-height DE LA CARTE fige ce qui reste : les titres n'ont pas la meme
   longueur d'une page a l'autre, et sans lui la carte respirerait differemment
   sur chacune. 304 px, la valeur de nosotros. */
.final-cta--poster .final-cta__inner {
  /* 304 est la valeur de nosotros a 1440. Mesure sur cinq largeurs : a 1920 les
     titres de metodologia et nosotros passent a deux lignes quand celui de la
     home tient sur une, et la carte y demande 310 ; sous 48rem, ou tous les
     titres s'allongent, il en faut 372. On prend donc le maximum de chaque
     regime plutot qu'une valeur unique qui laisserait un ecart quelque part. */
  min-height: 310px;
  display: flex;
  flex-direction: column;
  justify-content: center;
}

/* Sous 48rem les titres montent a trois ou quatre lignes et l'ecart entre les
   trois cartes atteignait 29 px (340 a 369). Le plancher y suit. */
@media (max-width: 48rem) {
  .final-cta--poster .final-cta__inner { min-height: 372px; }
}


/* ══════════════════════════════════════════════════════════════════════════
   LES SIX CARTES S'ALIGNENT SUR LE RESTE DE LA PAGE — 2026-08-14
   ══════════════════════════════════════════════════════════════════════════
   Defaut signale par Gabriel. Mesure des bords, element par element, dans un
   conteneur utile de 58 a 1382 :
       titre                58 .. 1067    aligne
       lede                 58 .. 1118    aligne
       grille des six       146 .. 1359   88 px a gauche, 23 a droite
   Elles n'etaient donc pas mal alignees ENTRE ELLES — le controle sur onze
   largeurs le confirmait — mais decalees par rapport a TOUT LE RESTE, et de
   facon asymetrique par-dessus le marche.

   La cause est la grille de .layer : une premiere colonne de 68 px porte le
   numero sur son rail, plus 20 de gouttiere, ce qui pousse le corps de 88. Sur
   les rangees de texte c'est le dessin voulu ; sur la rangee qui porte les six
   cartes, ca desaligne un bloc large de toute la page.
   Cette rangee-la passe donc en colonne unique : son numero rejoint le libelle,
   et la grille repart du bord du conteneur. Les six autres rangees gardent leur
   rail intact. */
.layer--fronts {
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-3);
}
.layer--fronts .layer__idx {
  justify-self: start;
  margin-bottom: var(--space-2);
}
.layer--fronts .layer__body { padding-inline: 0; }
/* Les 23 px qui restaient a droite ne venaient pas du corps mais de .layer
   lui-meme, qui porte un padding-right pour eloigner son texte du bord. Sur la
   rangee des cartes il n'y a pas de texte a eloigner, seulement une grille qui
   doit tomber sur le bord du conteneur comme le titre. */
.layer--fronts { padding-right: 0; }


/* ══════════════════════════════════════════════════════════════════════════
   L'ENCRE DU SOL CLAIR — 2026-08-14
   ══════════════════════════════════════════════════════════════════════════
   Gabriel passe « Nuestro modelo » et « Foco en industrias » en fond blanc. Le
   site n'avait jusqu'ici AUCUNE section claire portant du texte : la bande de
   clients et celle d'alianzas ne montrent que des logos. Toutes les encres
   etaient donc calibrees pour du sombre, et la bascule a produit 26 echecs de
   contraste mesures — jusqu'a 1,00:1, c'est-a-dire du blanc sur du blanc.

   On ne corrige pas cas par cas : on declare l'encre du sol clair une fois, au
   niveau de la section, et tout ce qui en herite suit. Les composants qui
   portent leur propre couleur (cartes persona, aplats rouges) ne sont pas
   touches — ils sont deja opaques et fournissent leur propre fond. */
main > section[data-sol="clair"] {
  color: var(--color-fg-light);
  --band-fg: var(--color-fg-light);
  --band-muted: var(--color-muted-light);
  --color-fg: var(--color-fg-light);
  --color-muted: var(--color-muted-light);
  --color-border: rgba(16, 16, 16, 0.12);
  --color-border-strong: rgba(16, 16, 16, 0.22);
}
main > section[data-sol="clair"] .section-title,
main > section[data-sol="clair"] .section-title .split-word,
main > section[data-sol="clair"] .layer__name,
main > section[data-sol="clair"] h3 { color: var(--color-fg-light); }
main > section[data-sol="clair"] .section-lede,
main > section[data-sol="clair"] .layer__note,
main > section[data-sol="clair"] p { color: var(--color-muted-light); }
/* L'accent des titres : le rouge de marque ne vaut que 3,87:1 sur du clair,
   la variante deep en rend 6,58. C'est le meme token que le header et le pied
   de page ont recu quand ils sont passes au blanc. */
main > section[data-sol="clair"] .section-title .accent,
main > section[data-sol="clair"] .section-title .accent .split-word {
  color: var(--color-primary-deep);
}
/* L'eyebrow sur sol clair : voir la regle plus bas, qui est celle qui gagne.
   Celle-ci est neutralisee — elle imposait l'aplat rouge plein. */
main > section[data-sol="clair"] .industries__coverage-stat {
  color: var(--color-primary-deep);
}
/* Les filets du diagramme et de la grille suivent le sol. */
main > section[data-sol="clair"] .layers::before,
main > section[data-sol="clair"] .layer,
main > section[data-sol="clair"] .layer__body {
  border-color: rgba(16, 16, 16, 0.14);
}


/* L'ENCRE CLAIRE NE DOIT PAS ENTRER DANS LES COMPOSANTS QUI ONT LEUR PROPRE
   FOND — 2026-08-14. En declarant --color-fg au niveau de la section, je l'ai
   fait descendre PARTOUT, y compris dans les six cartes de heros, qui sont des
   surfaces sombres opaques : leur encre y est passee au noir, d'ou 1,65:1 sur
   les titres et 1,86 sur les puces. Ces composants reprennent donc l'encre du
   sombre a leur niveau. C'est le meme principe que le plateau de metodologia :
   l'encre suit LE FOND QUI EST DESSOUS, pas celui de la section. */
main > section[data-sol="clair"] .practice,
main > section[data-sol="clair"] .layer--command .layer__body,
main > section[data-sol="clair"] .industry-card {
  --color-fg: #F8FAFC;
  --color-muted: rgba(203, 213, 225, 0.92);
  color: #F8FAFC;
}
main > section[data-sol="clair"] .practice__title,
main > section[data-sol="clair"] .industry-card__title { color: #F8FAFC; }
main > section[data-sol="clair"] .practice__desc { color: rgba(203, 213, 225, 0.92); }
main > section[data-sol="clair"] .practice__chip {
  color: rgba(248, 250, 252, 0.94);
  border-color: rgba(248, 250, 252, 0.22);
  background: rgba(248, 250, 252, 0.06);
}

/* L'EYEBROW SUR SOL CLAIR REPREND LA FORME DES AUTRES — 2026-08-15.
   Il etait le seul du site en aplat rouge plein, a angles vifs et sans
   padding : sur la home, la pastille de « Nuestro modelo » ne ressemblait a
   aucune des sept autres. Il redevient la meme pilule — meme rayon, meme
   padding, meme filet rouge — et seule l'encre change, parce qu'elle le doit :
   le blanc des sept autres serait illisible sur un fond clair.
   Mesure : #475569 sur le voile rouge a 7 % pose sur #F8FAFC rend 6,50:1,
   pour un seuil de 4,5 a 12 px gras. */
main > section[data-sol="clair"] > .container .eyebrow,
main > section[data-sol="clair"] .eyebrow {
  color: var(--color-muted-light) !important;
  background: rgba(220, 38, 38, 0.07) !important;
  border: 1px solid rgba(220, 38, 38, 0.42) !important;
  border-radius: 9999px !important;
  padding: 5px 12px 4px !important;
}
/* Le chiffre de couverture des industries porte le rouge : sur clair il prend
   la variante profonde. */
main > section[data-sol="clair"] .industries__coverage-stat {
  color: var(--color-primary-deep) !important;
}


/* Les deux derniers echecs du sol clair, et leur cause commune : un fond
   TRANSLUCIDE qui etait sombre tant que la section l'etait.

   1. Les six cartes de heros ont un fond rgba(23,23,23,0.85). A 85 % sur du
      noir il donne du noir ; sur du blanc il donne un gris moyen, et les rangs
      persona y tombaient a 2,92-4,17:1. Sur ce sol elles deviennent opaques.
   2. Le « 95 % » porte une plaque de la recette, elle aussi translucide et
      calibree pour du sombre. Sur clair il prend l'aplat rouge plein, ou son
      encre claire rend 4,62:1 — le meme geste que l'eyebrow. */
/* Trois classes plutot que deux : la declaration adverse est un raccourci
   background posé plus loin dans le fichier, et a specificite egale c'est elle
   qui gagnait. On monte d'un cran plutot que d'ecrire un !important. */
main > section[data-sol="clair"] .practices__grid--six .practice {
  background-color: var(--color-surface);
  background-image: none;
}
main > section[data-sol="clair"] .industries__coverage-stat {
  color: #F8FAFC !important;
  background: var(--color-primary) !important;
  border-color: var(--color-primary) !important;
}


/* ══════════════════════════════════════════════════════════════════════════
   « NUESTRO MODELO » APRES LE RETRAIT DU DIAGRAMME — 2026-08-14
   ══════════════════════════════════════════════════════════════════════════
   Les six rangees et le rail sont partis du HTML ; il reste le libelle et la
   grille, qui remontent directement dans le conteneur.

   ESPACEMENT EGAL SUR TOUS LES COTES, demande de Gabriel. La grille avait une
   gouttiere unique posee par --space-5, mais les cartes heritaient d'un
   padding-inline de la rangee qui les portait : l'ecart entre deux cartes
   n'etait donc pas le meme que l'ecart au bord. Sans la rangee, un seul gap
   suffit et il vaut pour les quatre cotes. */
.practices__label {
  margin: 0 0 clamp(20px, 2.2vw, 32px);
  font: 700 11px/1.4 var(--font-mono);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--color-muted);
}
main > section[data-sol="clair"] .practices__label { color: var(--color-muted-light); }
.practices__grid--six {
  gap: clamp(16px, 1.6vw, 24px);
  padding: 0;
  margin: 0;
}

/* LA CARTE REDEVIENT SOMBRE FRANCHE SUR LE SOL CLAIR. En passant a
   --color-surface (#2B2B2B) pour cesser d'etre translucide, elle avait
   ECLAIRCI le fond des rangs persona : mesure, ZeroTrust y tombait a 2,92:1
   pour un seuil de 4,5, ASHA a 4,17, CTEM a 4,12. Sur --sol-1 (#141414) ils
   retrouvent exactement les valeurs qu'ils avaient sur le sol sombre, ou les
   six passaient. Une carte sombre sur un sol clair est l'inversion normale de
   la regle : ce qui compte est l'ECART, pas le sens. */
main > section[data-sol="clair"] .practices__grid--six .practice {
  /* !important obligatoire : .practice porte deja un
     `background: rgba(23,23,23,0.85) !important`, et un !important bat
     n'importe quelle specificite. On ne gagne pas ce genre de duel en montant
     d'un cran, on y repond en nature. */
  background-color: var(--sol-1) !important;
  background-image: none !important;
}

/* ── LA COULEUR DU PERSONA HABILLE LA CARTE — 2026-08-15 ─────────────────
   Meme recette que la carte du panneau de #soluciones que Gabriel a donnee en
   reference : un degrade vertical de 12 % a 4 % du ton persona. La nuance qui
   compte est qu'il se pose ICI sur --sol-1 (#141414) et non sur --color-surface
   (#2B2B2B) : la regle juste au-dessus avait fait descendre la carte a ce
   niveau parce que le fond plus clair faisait tomber les rangs persona
   jusqu'a 2,92:1. En gardant cette base sombre sous le degrade, la carte prend
   la couleur sans remonter en luminance — verifie apres coup sur les six.

   La specificite est portee d'un cran (l'attribut [data-persona] en plus) pour
   passer devant le « background-image: none » de la regle precedente, qui
   reste juste pour les cartes sans persona. */
main > section[data-sol="clair"] .practices__grid--six .practice[data-persona] {
  background-image: linear-gradient(
      180deg,
      color-mix(in srgb, var(--p, var(--color-primary)) 12%, transparent),
      color-mix(in srgb, var(--p, var(--color-primary)) 4%, transparent)) !important;
}
main > section[data-sol="clair"] .practices__grid--six .practice[data-persona]:hover {
  background-image: linear-gradient(
      180deg,
      color-mix(in srgb, var(--p, var(--color-primary)) 20%, transparent),
      color-mix(in srgb, var(--p, var(--color-primary)) 7%, transparent)) !important;
}


/* La ligne de role d'ASHA prend la variante claire du rouge, sans condition de
   sol. Elle passait a 5,58:1 tant que sa bande etait en sol-0 ; la suppression
   de la section « Marcos » a decale l'alternance et l'a posee sur sol-2, ou le
   meme rouge ne vaut plus que 4,28 pour un seuil de 4,5.
   C'est la troisieme fois qu'une encre depend du VOISINAGE de sa section. On
   la descope : --color-primary-soft passe sur les deux sols, la regle n'a donc
   plus de raison d'etre conditionnelle. */
.method[data-persona="asha"] .method__role { color: var(--color-primary-soft); }


/* ══════════════════════════════════════════════════════════════════════════
   NOSOTROS : LE RAIL DE SECTION — 2026-08-15
   ══════════════════════════════════════════════════════════════════════════
   Refonte sur la reference Proofpoint : un menu secondaire cale a GAUCHE qui
   descend avec la page et marque la section courante, tout le contenu passant
   a droite.

   POURQUOI IL PEUT ETRE FIXE, ET CLAIR, SANS SE RELIRE A CHAQUE BANDE.
   Les huit sections de nosotros sont toutes en sol 0 ou sol 2 (#000000 et
   #212121) : il n'y a pas une seule bande claire sur cette page. Un rail en
   encre claire tient donc du haut en bas sans changer de couleur en route.
   Si une bande claire arrivait un jour ici, ce rail deviendrait illisible sur
   sa traversee : ce n'est pas une precaution theorique, c'est la condition qui
   rend le procede valable.

   IL N'EST PAS DANS LE FLUX, ET C'EST VOULU. Les sections sont des bandes
   pleine largeur avec leurs sols alternes ; les enfermer dans une grille a
   deux colonnes aurait casse ce rythme. Le rail flotte donc au-dessus, et
   c'est le CONTENU qui se retire pour lui — un padding a gauche sur les huit
   conteneurs, nommes un par un.

   LE SEUIL EST 75rem. En dessous il n'y a plus de marge libre a gauche : le
   rail disparait plutot que de recouvrir le texte. La page reste entierement
   navigable, elle perd seulement son reperage. */


/* LE RAIL VERTICAL A ETE RETIRE le 2026-08-15 : nosotros a repris le header
   secondaire des autres pages. Tout son CSS part avec lui — la boite fixee, la
   liste, les pastilles, et surtout le padding-left qui retirait le contenu de
   chaque section pour lui faire place. Sans ce retrait, les huit conteneurs
   seraient restes decales de 300 px vers la droite sans rien a cet endroit.
   La classe .container--lecture reste : c'est la colonne de lecture d'esencia,
   qui n'a jamais eu de rapport avec le rail.

   Ce qui SURVIT du chantier : la grammaire de section juste en dessous (filet
   d'ouverture, grilles calees, alignement a gauche). Elle valait pour elle-meme
   et pas seulement pour accompagner le rail. */
/* LA COLONNE DE LECTURE PART DU BORD GAUCHE, elle n'est plus centree.
   Elle gardait une max-width de 920 px avec les marges automatiques du
   .container : sa boite tombait donc au milieu de la page et son texte
   commencait 420 px a droite du titre de la section voisine, mesure a 1920.
   La formule reproduit l'origine EXACTE d'un conteneur pleine largeur — la
   marge automatique qu'il prend quand la fenetre depasse --container-max —
   de sorte que le premier caractere tombe sur la meme verticale que partout
   ailleurs, a toutes les largeurs. */
.container--lecture {
  max-width: calc(920px + max(0px, (100% - var(--container-max)) / 2));
  margin-inline: max(0px, calc((100% - var(--container-max)) / 2)) auto;
}

/* ══════════════════════════════════════════════════════════════════════════
   NOSOTROS : LA GRAMMAIRE DE SECTION — 2026-08-15
   ══════════════════════════════════════════════════════════════════════════
   Ecrite pour accompagner le rail vertical, elle lui a survecu et c'est tant
   mieux : chaque section s'ouvre par un filet, porte un titre, un lede borne a
   une longueur de lecture, puis son contenu sur une colonne unique calee a
   gauche. Rien la-dedans ne dependait du rail.

   Le numero est ecrit dans data-sec et sorti en ::before. Il n'est pas dans le
   HTML en tant que texte : c'est un repere de mise en page, pas du contenu —
   un lecteur d'ecran qui l'annoncerait ferait dire "zero un" avant chaque
   titre, huit fois, sans rien apporter. */
/* ── L'EN-TETE DE NOSOTROS SUIT CELUI DE LA HOME      2026-08-22 ──────────
   ══════════════════════════════════════════════════════════════════════════
   Gabriel : « les marges des grandes sections de nosotros ont leurs propres
   regles, comme la ligne qui est fondue, chose qu'on ne voit pas sur la home ;
   aligne cette page sur les regles de la home ».

   MESURE DES DEUX PAGES. Sur la home, le titre d'une section commence 96 px
   apres son bord. Sur nosotros, 129 : les 94 px de la section PLUS 35 px de
   padding propre a l'en-tete. Et six en-tetes sur huit portaient un filet en
   degrade que la home n'a nulle part — « la ligne fondue ». La page etait
   d'ailleurs incoherente avec elle-meme : « Trayectoria » n'avait ni le filet
   ni le padding, donc son titre commençait 35 px plus haut que ses voisins.

   Le padding propre disparait, le filet aussi, la marge basse rejoint les
   48 px de la home. Ces regles avaient ete ecrites pour accompagner un rail
   vertical qui n'existe plus : elles lui ont survecu sans qu'on remarque
   qu'elles faisaient de cette page une exception. */
.page-nosotros .section-head--rail {
  position: relative;
  padding-top: 0;
  margin-bottom: 48px;
}
/* Le filet d'ouverture. Il traverse toute la colonne de contenu et se degrade
   vers la droite : le poids est a gauche, la ou le rail se tient. */
/* Le filet d'ouverture est retire le 2026-08-22 : la home n'en a aucun, et
   c'est lui que Gabriel appelle « la ligne fondue ». Il ouvrait six sections
   sur huit, ce qui creait une inegalite jusque dans la page elle-meme. */
.page-nosotros .section-head--rail::after { content: none; }
/* PAS DE TROISIEME NUMERO. J'avais pose le numero de section en ::before dans
   la marge du titre. Il faisait doublon deux fois : le rail l'affiche deja a
   gauche, et l'eyebrow le porte deja en tete ("02 · NUESTRA ESENCIA"). Trois
   fois le meme chiffre sur la meme ligne d'oeil, ce n'est pas un reperage,
   c'est du bruit. Le filet d'ouverture suffit a marquer le debut de section. */

/* LE LEDE SE BORNE. La colonne utile fait environ 1450 px a 1920 : une phrase
   qui la traverse entierement demande un balayage de l'oeil que la reference
   n'impose jamais. 68ch est la borne haute de confort en lecture continue.
   Attention, ch suit la taille de police : reduire la police ne reduit PAS le
   nombre de lignes, la mesure est proportionnelle. */
.page-nosotros #quienes .section-lede,
.page-nosotros #esencia .section-lede,
.page-nosotros #trayectoria .section-lede,
.page-nosotros #razones .section-lede,
.page-nosotros #certificaciones .section-lede,
.page-nosotros #alianzas .section-lede,
.page-nosotros #modelo .section-lede,
.page-nosotros #liderazgo .section-lede { max-width: 68ch; }

@media (min-width: 75rem) {
  /* LES GRILLES SE RESSERRENT. Le rail a pris pres de 300 px a la colonne
     utile ; les grilles reglees pour la pleine largeur s'y retrouvent trop
     etroites, et celle des metriques tombait meme sur deux colonnes avec un
     trou beant a droite. On les fixe au nombre de colonnes que leur nombre
     d'items appelle, au lieu de les laisser se replier au hasard. */

  /* trayectoria : trois metriques, trois colonnes. Elle en montrait deux, et
     la troisieme se retrouvait seule sur une deuxieme rangee. */
  .page-nosotros #trayectoria .metrics { grid-template-columns: repeat(3, minmax(0, 1fr)); }

  /* razones : six raisons, trois colonnes de deux rangees. align-items:stretch
     parce que les six textes n'ont pas la meme longueur : sans lui les cartes
     d'une meme rangee finissaient a 323 et 349 px, et le decalage se voyait. */
  .page-nosotros #razones .about-cards {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    align-items: stretch;
  }
  .page-nosotros #razones .about-card { height: 100%; }

  /* modelo : trois piliers, trois colonnes. */
  .page-nosotros #modelo .about-cards { grid-template-columns: repeat(3, minmax(0, 1fr)); }

  /* liderazgo : deux responsables, deux colonnes et pas davantage — a trois
     ou quatre pistes deux cartes se perdent au bord gauche.
     margin-inline: 0 est indispensable : la regle de base porte margin:0 auto
     avec une max-width, ce qui centrait la paire dans la colonne utile. Elle
     demarrait 313 px a droite du titre a 1920 — le seul bloc de la page a ne
     pas tenir le bord gauche, et ca se voyait immediatement. */
  .page-nosotros #liderazgo .leadership {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    margin-inline: 0;
    max-width: min(100%, 860px);
  }

  /* certificaciones : cinq badges qui doivent rester sur une seule ligne. */
  .page-nosotros #certificaciones .cert-strip { grid-template-columns: repeat(5, minmax(0, 1fr)); }

  /* alianzas : cinq niveaux de partenariat, meme regle. */
  .page-nosotros #alianzas .partner-levels { grid-template-columns: repeat(5, minmax(0, 1fr)); }
}

/* LE RYTHME VERTICAL. La reference tient par des respirations egales : chaque
   section pese la meme chose, et c'est cette regularite qui fait qu'on lit le
   rail comme une progression plutot que comme un sommaire pose a cote. */
@media (min-width: 75rem) {
  .page-nosotros #quienes, .page-nosotros #esencia, .page-nosotros #trayectoria, .page-nosotros #razones,
  .page-nosotros #certificaciones, .page-nosotros #alianzas, .page-nosotros #modelo, .page-nosotros #liderazgo {
    /* ALIGNE SUR LA HOME — 2026-08-22. Ce clamp donnait 93,6 px a 1440 quand la
       home en tient 96 : deux pixels d'ecart invisibles seuls, mais ils
       s'ajoutaient au reste pour faire de nosotros une page a part. La valeur
       est desormais celle de .section, la meme partout. */
    padding-block: var(--space-24);
  }
}


/* ══════════════════════════════════════════════════════════════════════════
   NOSOTROS : PLUS RIEN N'EST CENTRE — 2026-08-15
   ══════════════════════════════════════════════════════════════════════════
   La grammaire de la reference tient sur un bord gauche unique : le rail, les
   filets, les eyebrows, les titres et les ledes s'y alignent tous. Six ilots
   resistaient encore en centre, herites de la mise en page precedente ou le
   contenu occupait toute la largeur — et c'est justement ce qui se remarquait,
   parce qu'un bloc centre au milieu d'une page calee a gauche se lit comme une
   erreur de gabarit plutot que comme une intention.

   CE QUI RESTE CENTRE, ET POURQUOI. Les logos dans les pistes defilantes
   d'alianzas, et l'initiale dans la pastille ronde de liderazgo : dans les
   deux cas le centrage est celui d'un objet dans sa propre boite, pas celui
   d'un bloc dans la page. Les aligner a gauche les decalerait de leur cadre. */

/* razones : les six cartes */
.page-nosotros #razones .about-card {
  text-align: left;
  align-items: flex-start;
  justify-content: flex-start;
}
/* align-self seulement : c'est la POSITION de la pastille dans la carte.
   J'y avais aussi mis justify-content, qui gouverne l'icone DANS la
   pastille de 48 px — la decaler la sortait de son propre cadre. */
.page-nosotros #razones .about-card__icon-wrap {
  align-self: flex-start;
  /* Et margin-inline a zero. align-self etait bien passe a flex-start, la
     pastille restait pourtant au centre : le variant --illustre lui met une
     marge automatique de chaque cote, qui centre l'element quel que soit
     l'alignement demande. La marge bat l'alignement, il fallait la lever. */
  margin-inline: 0;
}
.page-nosotros #razones .about-card__title,
.page-nosotros #razones .about-card__desc { text-align: left; }

/* modelo : les trois piliers */
.page-nosotros #modelo .about-card {
  text-align: left;
  align-items: flex-start;
}
/* align-self seulement : c'est la POSITION de la pastille dans la carte.
   J'y avais aussi mis justify-content, qui gouverne l'icone DANS la
   pastille de 48 px — la decaler la sortait de son propre cadre. */
.page-nosotros #modelo .about-card__icon-wrap { align-self: flex-start; }
.page-nosotros #modelo .about-card__title,
.page-nosotros #modelo .about-card__desc { text-align: left; }

/* certificaciones : le bloc des marcos de referencia, le plus visible des six */
.page-nosotros #certificaciones .about-frameworks { text-align: left; }
.page-nosotros #certificaciones .frameworks__label { text-align: left; }
.page-nosotros #certificaciones .frameworks__logos {
  justify-content: flex-start;
  text-align: left;
}
.page-nosotros #certificaciones .frameworks__grid { justify-content: flex-start; }

/* alianzas : les cinq niveaux de partenariat */
.page-nosotros #alianzas .partner-level {
  align-items: flex-start;
  text-align: left;
}
.page-nosotros #alianzas .partner-level__note { text-align: left; }


/* ══════════════════════════════════════════════════════════════════════════
   INDEX : TROIS CORRECTIONS DEMANDEES LE 2026-08-15
   ══════════════════════════════════════════════════════════════════════════ */

/* ── 1. LES DEUX PISTES D'ALIANZAS TRAVERSENT LA PAGE ─────────────────────
   Elles s'arretaient au bord du conteneur — 1386 px sur 1920 — alors que la
   bande claire des clients, elle, va d'un bord a l'autre. Ce n'etait pas
   l'animation qui s'arretait, c'etait la boite qui finissait la.

   La sortie de gouttiere se fait en margin negative de 50% - 50vw, la formule
   classique. Son defaut connu est que 100vw inclut la barre de defilement, ce
   qui ajoute une quinzaine de pixels de debordement horizontal a toute la
   page. overflow-x: clip sur la section l'absorbe — clip et non hidden, qui
   creerait un conteneur de defilement et casserait le position:sticky des
   elements au-dessus. */
#alianzas { overflow-x: clip; }
/* :not(.page-nosotros) : la meme section vit sur nosotros, ou un rail de
   navigation occupe la gouttiere gauche. Une piste pleine largeur lui
   passerait dessous — les logos traversaient le menu. Sur cette page la piste
   reste donc dans la colonne de contenu, ou elle a toute la place voulue. */
body:not(.page-nosotros) #alianzas .alliances__tier .marquee {
  width: 100vw;
  margin-inline: calc(50% - 50vw);
}
/* Les libelles de niveau, eux, restent sur la marge : ce sont des titres, pas
   la piste. Sans cette ligne ils suivraient la piste hors gouttiere. */
#alianzas .alliances__tier-label { width: auto; margin-inline: 0; }

/* ── 2. L'EYEBROW DE #sistema REPREND LA FORME DES SEPT AUTRES ────────────
   Il etait le seul en aplat rouge plein, a angles vifs et sans padding, quand
   les sept autres sont des pilules a fond sombre et filet rouge. La section
   est sur sol clair : garder l'encre blanche des autres l'aurait rendue
   illisible, l'encre passe donc au gris fonce. C'est la seule difference, et
   elle est imposee par le fond. */
/* (la regle generique sol=clair s'en charge desormais pour toutes les
   sections claires du site, pas seulement #sistema) */

/* ── 3. « EL RETO ES INTEGRARLO TODO » PASSE EN BANDE CLAIRE ──────────────
   C'est la bascule du diagnostic vers la reponse : le fond change avec elle.
   La phrase sort de la bande sombre en pleine largeur, comme les pistes
   ci-dessus, pour se lire comme une respiration et non comme un paragraphe
   de plus. Toute l'encre est redescendue avec le fond. */
.problema__turn {
  width: 100vw;
  margin-inline: calc(50% - 50vw);
  margin-top: clamp(48px, 5vw, 88px);
  margin-bottom: calc(-1 * clamp(56px, 6vw, 104px));
  padding: clamp(44px, 4.6vw, 76px) 0;
  /* Retour au clair le 2026-08-15, apres un passage par le rouge. Elle reste
     la seule surface claire de cette moitie de page, ce qui suffit a en faire
     une respiration entre le diagnostic et la reponse. */
  background: var(--color-fg);
}
#problema { overflow-x: clip; }
/* Le contenu de la bande se recale sur la grille du site : la bande est
   pleine largeur, son texte ne l'est pas. Et il part du bord gauche, comme
   les vingt-deux autres titres du site — la bande etait pleine largeur mais
   son texte restait centre, ce qui la faisait lire comme une citation posee
   au milieu plutot que comme la bascule de l'argument. */
.problema__turn > * {
  max-width: var(--container-max);
  margin-inline: auto;
  padding-inline: var(--container-px);
  /* CENTRE, et c'est la seule exception a l'alignement a gauche de la page.
     La bande ne porte plus qu'une phrase, sans surtitre ni suite : centree
     elle se lit comme un panneau, calee a gauche elle redevenait un
     paragraphe parmi les autres. */
  text-align: center;
}
/* La bande etant redevenue claire, l'accent ne peut plus etre blanc : il
   disparaitrait. Il reprend le rouge de marque, qui rend 4,61:1 sur ce fond
   pour un seuil de 3 a ces 64 px. La premiere moitie de la phrase garde le
   noir, a 18,19:1. Le centrage et l'absence de surtitre sont conserves. */
.problema__turn-text {
  color: var(--color-fg-light);
  text-align: center;
}
.problema__turn-text .accent,
.problema__turn-text .accent .split-word { color: var(--color-primary); }


/* ── LES SIX CARTES HEROS PRENNENT LA COULEUR, COMME LE PANNEAU SOLUCIONES ──
   Le panneau de #soluciones tient sa carte principale par trois gestes : un
   filet a 34 % de la couleur du persona, un voile du meme ton sur le corps, et
   la ligne de methode ecrite dans cette couleur. Les six cartes avaient deja
   la variable --p, mais ne s'en servaient qu'au survol : au repos elles etaient
   six cartes identiques. Elles reprennent donc le meme langage.

   ADAPTE A LA SITUATION, ET c'est le point : la carte du panneau est posee sur
   un sol sombre, celles-ci sur un sol clair avec un corps sombre a l'interieur.
   Le voile reste donc faible — 8 % — et se pose sur le corps, pas sur la
   section. Au-dela, les tons clairs (le violet de ZeroTrust, le vert de GRC)
   remontaient assez le fond pour attaquer la lisibilite du texte blanc. */
/* !important des deux cotes : .practice porte « background » et
   « border-color » en !important quelques milliers de lignes plus haut. A
   specificite egale ou superieure, seule une declaration de meme poids passe —
   on repond en nature, c'est la regle deja etablie pour ce selecteur. */
.practices__grid--six .practice[data-persona] {
  border-color: color-mix(in srgb, var(--p, var(--color-primary)) 34%, transparent) !important;
  /* EXACTEMENT LA RECETTE DU PANNEAU DE #soluciones : un degrade vertical de
     12 % a 4 % du ton persona, pose sur le fond de surface. J'avais d'abord
     mis un voile de 8 % qui s'eteignait a mi-hauteur — trop discret, la carte
     restait grise. Ici la couleur habille toute la carte, comme sur la
     reference. */
  background-image: linear-gradient(
      180deg,
      color-mix(in srgb, var(--p, var(--color-primary)) 12%, transparent),
      color-mix(in srgb, var(--p, var(--color-primary)) 4%, transparent)) !important;
}
/* LE FILET RESTE ANIME. Je l'avais fige a 100 % au repos en me disant qu'il
   identifiait le persona — sauf que c'est desormais le FOND colore qui fait
   ce travail, et que figer le filet supprimait l'animation de survol des six
   cartes, qui existait depuis le debut. Il repart donc de zero et se deploie
   au survol, comme avant. */
.practices__grid--six .practice[data-persona]:hover {
  border-color: var(--p, var(--color-primary)) !important;
  background-image: linear-gradient(
      180deg,
      color-mix(in srgb, var(--p, var(--color-primary)) 20%, transparent),
      color-mix(in srgb, var(--p, var(--color-primary)) 7%, transparent)) !important;
}
/* La pastille de rang porte deja la couleur ; on la confirme, et le chiffre
   d'ordre la reprend au lieu du gris. */
.practices__grid--six .practice[data-persona] .practice__rank { color: var(--p, var(--color-primary)); }
.practices__grid--six .practice[data-persona] .practice__num {
  color: color-mix(in srgb, var(--p, var(--color-primary)) 78%, transparent);
}


/* ── L'IMAGE DE FOND DES page-hero — 2026-08-15, corrigee ────────────────
   Premiere version, fausse et cassante : j'avais redeclare .page-hero__bg-img
   (qui existait deja plus haut, le motif etait prevu) et surtout pose
   position: relative sur les trois calques pour les faire passer devant.

   C'ETAIT L'ERREUR. Ces trois calques sont en position: absolute; inset: 0.
   Les repasser en relative les remet dans le flux : ils perdent leur inset,
   se retrouvent hauts de zero, et la grille comme les halos disparaissent —
   sur les trois pages a page-hero, pas seulement celle que je modifiais.

   Un z-index suffisait : sur des elements deja absolus il ordonne la pile
   sans toucher a la geometrie. C'est tout ce que la regle fait desormais. */
.page-hero__bg-img { z-index: 0; opacity: 0.5; }
.page-hero__bg-grad,
.page-hero__bg-grid,
.page-hero__bg-drift { z-index: 1; }


/* ── LA HERO DE METODOLOGIA REMPLIT L'ECRAN JUSQU'AU SOUS-MENU — 2026-08-15 ──
   Elle mesurait 756 px sur un ecran de 1080 : le sous-menu apparaissait bien,
   mais 175 px de vide trainaient sous lui. On la cale sur ce qui reste de
   l'ecran une fois l'en-tete et la bande du sous-menu retires, de sorte que
   cette bande grise ferme exactement le premier ecran.

   100svh et non 100vh : sur mobile, vh se mesure sur la fenetre BARRE
   D'ADRESSE RETRACTEE, ce qui pousse le sous-menu sous le pli tant que la
   barre est visible — soit au chargement, exactement quand ca compte. */
:root { --subnav-h: 60px; }
@media (max-width: 700px) { :root { --subnav-h: 54px; } }

.page-hero--liga {
  min-height: calc(100svh - var(--header-h) - var(--subnav-h));
  display: flex;
  align-items: center;
}

/* L'image des six heros est un groupe : on la cadre par le haut pour garder
   les visages, et on la laisse un peu plus presente que la vague de nosotros —
   elle porte ici le sujet de la page, elle n'est pas qu'un decor. */
/* (.page-hero__bg-img--liga retire : la hero de metodologia ne porte plus
   une image plate mais la rangee .liga-row, six fichiers composes) */


/* Le rang d'ASHA : sa couleur persona EST le rouge de marque, qui ne rend que
   3,81:1 sur le corps sombre de la carte, sous le seuil de 4,5 pour ces 12 px.
   Les cinq autres personas sont des tons clairs et passent. Seule la capitane
   prend donc la variante relevee — la couleur reste la sienne, elle est
   seulement remontee jusqu'au seuil. */
.practices__grid--six .practice[data-persona="asha"] .practice__rank {
  color: var(--color-primary-soft);
}


/* ══════════════════════════════════════════════════════════════════════════
   METODOLOGIA : LA RANGEE DES SIX DANS LE HERO — 2026-08-15
   ══════════════════════════════════════════════════════════════════════════
   Six personnages detoures, poses au fond du hero, chacun sur son halo de
   couleur. Elle est DANS .page-hero__bg et vient apres les trois calques,
   donc au-dessus de la grille : celle-ci reste visible entre les silhouettes,
   ce qui etait tout l'interet de la garder.

   Les figures sont alignees par le BAS et non centrees : les six fichiers ont
   des proportions differentes une fois recadres sur leur sujet (de 473 a
   1030 px de large pour une meme hauteur), et un centrage vertical les aurait
   fait flotter a des hauteurs differentes. Au sol, ils forment un groupe. */
.liga-row {
  position: absolute;
  /* inset: 0 et non « auto 0 0 0 ». Avec auto en haut, la boite prend la
     hauteur de son contenu — 1520 px, la hauteur native des fichiers — et le
     « height: 78% » des figures se calculait sur cette hauteur-la au lieu de
     celle du hero. La rangee debordait de 588 px vers le haut. */
  inset: 0;
  z-index: 2;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  /* Chevauchement plus franc : a 720 px de haut les six figures totalisent
     plus de 2000 px, et GRC sortait du cadre par la droite. Elles se serrent,
     ce qui les fait aussi lire comme un groupe plutot que comme une frise. */
  gap: clamp(-96px, -4.4vw, -40px);
  pointer-events: none;
  /* Le degrade du bas : les personnages entrent dans la bande sans ligne de
     coupe. Sans lui, six paires de pieds tranchees net au bord du hero. */
  -webkit-mask-image: linear-gradient(180deg, #000 0%, #000 82%, transparent 100%);
          mask-image: linear-gradient(180deg, #000 0%, #000 82%, transparent 100%);
}
.liga-row__fig {
  position: relative;
  display: block;
  flex: 0 0 auto;
  /* La hauteur suit celle du hero, bornee : au-dela de 78 % de la bande les
     tetes passaient derriere le titre. */
  /* Trois bornes, et la troisieme est la seule qui compte sous 1600 px.
     La largeur totale de la rangee vaut environ 2,8 fois sa hauteur une fois
     les chevauchements deduits : sans borne en vw, a 1440 px les figures
     restaient hautes et CTEM comme GRC sortaient du cadre de 25 px. */
  height: min(70%, 660px, 34vw);
}
.liga-row__fig img {
  display: block;
  height: 100%;
  width: auto;
  /* Les personnages sont un decor de fond : ils restent en retrait pour que
     le titre garde son avance. La capitane, elle, remonte un peu. */
  /* 0,72 : entre les deux demandes de Gabriel. Monte a 0,88 dans la journee
     parce qu'on ne reconnaissait pas les personnages, redescendu ensuite vers
     la transparence du CTA final — « pero tampoco tanto ». */
  opacity: 0.72;
  filter: saturate(0.95);
}
/* LE HALO DE COULEUR, un par persona — remis le 2026-08-15 apres un
   aller-retour. Le probleme n'etait pas ces halos-la mais leur superposition
   avec ceux du fond : ce sont les blobs du calque .page-hero__bg-drift qui
   partent, plus bas. Chaque personnage garde donc SA lueur, et elle ne se
   melange plus a quatre autres qui ne lui correspondaient pas.
   En ::before, donc DERRIERE l'image, jamais par-dessus. */
.liga-row__fig::before {
  content: '';
  position: absolute;
  left: 50%;
  bottom: 4%;
  width: 118%;
  aspect-ratio: 1;
  transform: translateX(-50%);
  border-radius: 50%;
  background: radial-gradient(circle,
              color-mix(in srgb, var(--p, var(--color-primary)) 42%, transparent) 0%,
              color-mix(in srgb, var(--p, var(--color-primary)) 14%, transparent) 42%,
              transparent 70%);
  filter: blur(26px);
  opacity: 0.55;
  z-index: -1;
}
.liga-row__fig--capitana::before { opacity: 0.7; }
.liga-row__fig[data-persona="ctem"]      { --p: var(--color-ctem); }
.liga-row__fig[data-persona="ngsoc"]     { --p: var(--color-ngsoc); }
.liga-row__fig[data-persona="csirt"]     { --p: var(--color-csirt); }
.liga-row__fig[data-persona="zerotrust"] { --p: var(--color-zerotrust); }
.liga-row__fig[data-persona="grc"]       { --p: var(--color-grc); }
.liga-row__fig[data-persona="asha"]      { --p: var(--color-primary); }

/* NGSOC prend la meme taille que la capitane, a la demande de Gabriel — il
   est le seul autre a la porter, et sa silhouette est plus etroite que les
   autres, ce qui le faisait paraitre en retrait a hauteur egale. */
.liga-row__fig[data-persona="ngsoc"] {
  height: min(80%, 740px, 38vw);
}

/* La capitane : au centre, plus grande, plus presente et devant les autres.
   C'est la seule hierarchie de la rangee, et elle correspond a ce que le
   reste du site dit d'elle — le principe organisateur, pas un frente parmi
   six. */
.liga-row__fig--capitana {
  height: min(80%, 740px, 38vw);
  z-index: 1;
}
.liga-row__fig--capitana img { opacity: 0.86; filter: none; }


/* Sous 1100 px la rangee de six devient une haie de silhouettes de 60 px de
   large : on garde la capitane seule, calee a droite, et le titre reprend
   toute la place. */
@media (max-width: 1100px) {
  .liga-row { justify-content: flex-end; padding-right: 2vw; }
  .liga-row__fig:not(.liga-row__fig--capitana) { display: none; }
  .liga-row__fig--capitana { height: min(74%, 560px); }
  .liga-row__fig--capitana img { opacity: 0.5; }
}
@media (max-width: 700px) {
  .liga-row { display: none; }
}


/* Le portrait des six cartes gagne 70 px : a 280 px les heros etaient cadres
   sous les epaules et on perdait ce qui les distingue. 350 px les montre en
   entier sans que la carte cesse de tenir a trois par rangee. */
.practices__grid--six .practice__hero { height: 350px; }
@media (max-width: 900px) {
  .practices__grid--six .practice__hero { height: 300px; }
}


/* ── LES page-hero PRENNENT LA HAUTEUR DU HERO DE LA HOME — 2026-08-15 ────
   Mesure avant : 963 px sur la home contre 756 sur nosotros et bolsa a
   1920x1080, 783 contre 663 a 1440x900. L'ecart se voyait d'une page a
   l'autre, les pages interieures paraissant tassees.

   La home tient sa hauteur d'un min-height en svh moins l'en-tete ; on
   reprend la meme regle plutot qu'un nombre de pixels, sinon l'alignement se
   deferait a la premiere fenetre d'une autre taille. svh et non vh : sur
   mobile, vh se mesure barre d'adresse retractee et le bas du hero passerait
   sous le pli au chargement.

   metodologia garde sa propre regle : elle, elle doit s'arreter juste au-dessus
   du sous-menu, ce qui fait une hauteur differente et voulue. */
.page-hero:not(.page-hero--liga) {
  min-height: calc(100svh - var(--header-h) - clamp(48px, 5vh, 88px));
  display: flex;
  align-items: center;
}


/* ── LA BANDE D'ALIANZAS REDEVIENT COMPACTE — 2026-08-15 ─────────────────
   Une regle .alliances--band posait deja un padding de 40 a 64 px, mais elle
   ne s'appliquait pas : .section porte le meme poids (une classe) et gagne en
   etant declaree plus loin. Le padding reel valait donc 124 px en haut comme
   en bas, soit 248 px de vide pour une bande dont le contenu ne fait que
   414 px — c'est ce que Gabriel voyait sous le bouton.
   Deux classes sur le meme element suffisent a passer devant, sans !important. */
.alliances.alliances--band {
  padding-top: clamp(44px, 3.4vw, 64px);
  padding-bottom: clamp(44px, 3.4vw, 64px);
}


/* ── TRAYECTORIA : LES TROIS METRIQUES SE CENTRENT — 2026-08-15 ──────────
   Le titre de chaque metrique est retire ; il ne reste que le nombre et sa
   legende, et ces deux-la se centrent l'un sous l'autre. A noter, puisque
   c'est un vrai changement de sens : sans « Años de experiencia » sous le
   12+, c'est desormais la legende seule qui doit dire de quoi on parle. */
.page-nosotros #trayectoria .metric {
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(10px, 1vw, 16px);
}
.page-nosotros #trayectoria .metric__num,
.page-nosotros #trayectoria .metric__caption {
  text-align: center;
  margin-inline: auto;
}
.page-nosotros #trayectoria .metric__caption { max-width: 34ch; }


/* ══════════════════════════════════════════════════════════════════════════
   FOCO EN INDUSTRIAS CLAVES : LA SECTION PASSE AU BLEU — 2026-08-15
   ══════════════════════════════════════════════════════════════════════════
   Le bleu est celui qui anime deja les vignettes au survol : --color-csirt.
   La section l'adopte pour ses trois reperes — la pastille de surtitre,
   l'accent du titre et le chiffre de couverture — au lieu de garder le rouge
   de marque a cote d'un survol bleu, qui se contredisaient. */

/* La pastille : fond et filet bleus, texte BLANC. Le chevron qui la precedait
   saute — c'etait un ornement herite du motif « prompt » des autres sections,
   et Gabriel le veut hors de celle-ci. */
.industries .eyebrow::before,
.industries__head .eyebrow::before { content: none !important; }
.industries .eyebrow,
main > section[data-sol="1"] .industries__head .eyebrow,
main > section[data-sol="2"] .industries__head .eyebrow {
  background: color-mix(in srgb, var(--color-csirt) 14%, transparent) !important;
  border: 1px solid color-mix(in srgb, var(--color-csirt) 46%, transparent) !important;
  border-radius: 9999px !important;
  padding: 5px 12px 4px !important;
  color: var(--color-fg) !important;
  gap: 0 !important;
  /* MEME HAUTEUR QUE LES AUTRES PASTILLES — 2026-08-22, releve par Gabriel.
     Mesure des huit eyebrows de la home : sept a 30 px, celui-ci a 23. Deux
     causes, toutes deux heritees de la regle d'origine plus haut (ligne ~5107).
     D'abord le raccourci « font: 600 11px/1 » : la forme courte impose un
     line-height de 1, quand les autres pastilles tiennent leur hauteur d'un 1,6
     — sept pixels perdus, exactement l'ecart mesure. Ensuite inline-flex, qui
     n'a plus de raison d'etre depuis que le chevron ::before a ete retire, et
     qui calculait la hauteur autrement que l'inline-block des voisines.
     On repose donc les deux valeurs, sans toucher au reste de la pastille. */
  display: inline-block !important;
  line-height: 1.6 !important;
}

/* « regulados y críticos » : l'accent du titre prend le meme bleu. La variante
   soft et non le ton plein — sur le sol sombre elle rend nettement plus, et
   c'est un titre, donc du grand texte qu'on ne veut pas voir vibrer. */
.industries .section-title .accent,
.industries .section-title .accent .split-word {
  color: var(--color-csirt-soft) !important;
}

/* Le 95 % : meme bleu que les deux precedents. */
.industries__coverage-stat,
main > section[data-sol="1"] .industries__coverage-stat,
main > section[data-sol="clair"] .industries__coverage-stat {
  color: var(--color-csirt-soft) !important;
  background: color-mix(in srgb, var(--color-csirt) 12%, transparent);
  border: 1px solid color-mix(in srgb, var(--color-csirt) 40%, transparent);
  border-radius: 9999px;
  padding: 3px 12px 2px;
}


/* ── NGSOC UN PEU PLUS GRAND SUR SA BANDE — 2026-08-15 ───────────────────
   460 px au lieu de 380. Il est le seul des six a etre agrandi, a la demande
   de Gabriel, et c'est coherent avec la rangee du hero ou il prend deja la
   taille de la capitane : sa silhouette est plus etroite que celle des autres,
   il paraissait en retrait a largeur egale.
   Les deux paliers mobiles ne sont pas touches — sous 920 px le personnage
   passe au-dessus du texte et doit rester un signe d'identite. */
@media (min-width: 920px) {
  #ngsoc .method__media img { max-width: 460px; }
}


/* ── LES BLOBS DE COULEUR DU FOND PARTENT DE LA HERO DE METODOLOGIA ──────
   .page-hero__bg-drift pose quatre taches radiales — rouge, cyan, vert,
   violet — qui derivent lentement. Elles ont un sens sur une hero sans
   personnages : elles font sentir « six frentes » sans les montrer. Ici les
   six sont la, chacun avec son propre halo : les quatre taches ajoutaient une
   seconde couche de couleur qui ne correspondait a personne.
   Scope a .page-hero--liga : nosotros et bolsa-de-trabajo les gardent, elles
   n'ont pas de personnages pour prendre le relais. */
.page-hero--liga .page-hero__bg-drift { display: none; }

/* Les personnages redescendent encore : 0,58 au lieu de 0,72, la capitane
   0,72 au lieu de 0,86. Troisieme reglage de la journee — le halo de chacun
   etant revenu, la silhouette a moins besoin de porter seule. */
.liga-row__fig img { opacity: 0.58; }
.liga-row__fig--capitana img { opacity: 0.72; }


/* ── INDUSTRIAS : LE ROUGE DES CARTES PASSE AU BLEU — 2026-08-15 ─────────
   Suite du basculement de la section. Il restait deux rouges sur les cartes
   elles-memes : le cadre qui s'allume au survol, et l'equerre posee dans le
   coin bas-gauche de chaque image. Ils juraient d'autant plus que le survol
   de la vignette, lui, etait deja bleu. */
.industries .industry-card:hover {
  border-color: color-mix(in srgb, var(--color-csirt) 62%, transparent) !important;
  box-shadow: 0 16px 40px rgba(0,0,0,0.40),
              0 0 32px color-mix(in srgb, var(--color-csirt) 26%, transparent) !important;
}
.industries .industry-card::after {
  border-bottom-color: var(--color-csirt) !important;
  border-left-color: var(--color-csirt) !important;
}

/* ── LA GRILLE DE LA HERO DE METODOLOGIA REDEVIENT UNIFORME ──────────────
   Elle portait un masque en degre vers la droite (opaque jusqu'a 45 %, nul a
   82 %) : la grille s'effacait sous la moitie droite du hero. Sur les autres
   pages ce fondu degage la zone du texte ; ici le texte est a gauche et les
   personnages occupent toute la largeur, le fondu ne protegeait plus rien et
   coupait la grille en deux. */
.page-hero--liga .page-hero__bg-grid {
  -webkit-mask-image: none;
          mask-image: none;
}


/* ── PRESENCIA : LES TROIS CARTES A LA MEME HAUTEUR — 2026-08-15 ─────────
   Perú est passe de « En desarrollo » a « Operación activa ». La carte perdant
   une entree, elle rapetissait — 141 px contre 191 pour sa voisine — et le
   trio se desalignait par le bas. Les hauteurs sont donc egalisees : chaque
   carte prend celle de la plus haute, quel que soit son nombre de pays.
   Le contenu reste cale en haut, sinon les listes flotteraient au milieu. */
/* PAS align-items: stretch — c'etait ma premiere correction et elle ne pouvait
   rien faire. .presence__cards est en flex-direction: column : les trois
   cartes sont EMPILEES, et sur cet axe stretch gouverne la largeur, pas la
   hauteur. Une min-height commune est ce qui les tient.
   12rem, c'est la hauteur de la plus grande (six pays) arrondie au cran
   au-dessus : « En desarrollo » ne rapetisse donc pas d'avoir cede Perú. */
.presence__cards > .presence__group,
.presence__cards > .presence__fallback,
.presence__cards > .presence__float--expanding {
  min-height: 12rem;
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
}


/* ── FOOTER : LA COUVERTURE DETAILLEE ET LE BOUTON EN PILULE — 2026-08-15 ──
   La couverture ne listait que cinq pays a plat. Elle reprend maintenant les
   trois groupes de la section « Presencia » — operation active, en
   developpement, centres de monitoreo — pour que les deux endroits du site
   qui parlent d'implantation disent la meme chose. */
.site-footer__coverage strong {
  display: block;
  margin-bottom: 2px;
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--color-primary-deep);
}
.site-footer__coverage-sub {
  display: inline-block;
  margin-top: 6px;
  opacity: 0.82;
}

/* Le bouton reprend la forme des surtitres de section : meme pilule, meme
   filet rouge, meme rayon. Au survol il se remplit — c'est l'animation
   demandee, et elle porte sur les trois proprietes qui bougent, jamais sur
   « all », qui animerait aussi la mise en page. */
.site-footer__contact-cta {
  display: inline-flex !important;
  align-items: center;
  gap: 6px;
  margin-top: var(--space-4);
  padding: 6px 14px 5px;
  border-radius: 9999px;
  border: 1px solid color-mix(in srgb, var(--color-primary) 46%, transparent);
  background: color-mix(in srgb, var(--color-primary) 8%, transparent);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  text-decoration: none;
  transition: background var(--duration-normal) var(--ease-out),
              border-color var(--duration-normal) var(--ease-out),
              color var(--duration-normal) var(--ease-out);
}
.site-footer__contact-cta:hover,
.site-footer__contact-cta:focus-visible {
  background: var(--color-primary);
  border-color: var(--color-primary);
  color: var(--color-fg) !important;
}
@media (prefers-reduced-motion: reduce) {
  .site-footer__contact-cta { transition: none; }
}


/* ── LES TROIS CADRANS S'ALIGNENT SUR LE MENU SECONDAIRE — 2026-08-15 ────
   Ils etaient centres avec un ecart fixe entre eux ; leurs bords exterieurs
   ne tombaient donc nulle part en particulier. Ils se repartissent desormais
   sur la largeur du conteneur, ce qui pose le bord gauche du premier et le
   bord droit du troisieme exactement sur la marge du site — la meme que celle
   ou commence et finit le menu secondaire.
   space-between remplace l'ecart fixe : c'est la largeur disponible qui
   commande, plus une valeur devinee. */
@media (min-width: 62rem) {
  /* NI max-width NI padding-inline ici : .how-stats vit deja dans un
     .container qui porte les deux. Les ajouter posait un second padding
     par-dessus le premier et decalait les cadrans de 64 px vers l'interieur
     — exactement la valeur de --container-px, ce qui a rendu la cause
     evidente a la mesure. space-between suffit. */
  .scene-hacked--anillos .how-stats {
    justify-content: space-between;
    column-gap: 0;
  }
}


/* ── LA BANNIERE ANIMEE DE LA HOME — 2026-08-15 ──────────────────────────
   Meme cadrage que l'image qu'elle recouvre : object-fit cover, meme inset,
   meme z-index. Elle ne remplace pas l'image dans le DOM, elle se pose
   dessus — c'est ce qui rend le repli gratuit. */
.hero__bg-video {
  position: absolute;
  inset: 0;
  z-index: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  pointer-events: none;
}
/* Moins de mouvement : la video disparait et l'image reprend sa place. Elle
   n'est pas seulement mise en pause — une video figee sur sa premiere image
   n'est pas la meme chose que le visuel compose qui sert de poster. */
@media (prefers-reduced-motion: reduce) {
  .hero__bg-video { display: none; }
}


/* ── TRAYECTORIA SUR SOL CLAIR : L'ENCRE SUIT LE FOND — 2026-08-15 ───────
   La bande est passee au clair a la demande de Gabriel. Les legendes des trois
   metriques gardaient l'encre pale du sol sombre et tombaient a 2,77:1 pour un
   seuil de 4,5 a 14 px. Elles prennent la variante foncee, mesuree a 7,5:1.
   Le chiffre lui-meme et son « + » sont deja geres par les regles generiques
   du sol clair ; seules les legendes manquaient. */
.page-nosotros #trayectoria .metric__caption { color: var(--color-muted-light); }
/* Le chiffre vit dans un <span data-counter> a l'interieur de .metric__num :
   colorer le conteneur ne suffisait pas, l'enfant gardait l'encre claire du
   sol sombre et rendait 1,05:1 sur le fond clair. Le « + » qui suit prend la
   tension rouge, comme sur les autres sols. */
.page-nosotros #trayectoria .metric__num,
.page-nosotros #trayectoria .metric__num span:not(.unit) {
  color: var(--color-fg-light);
  /* -webkit-text-fill-color EST INDISPENSABLE ICI. .metrics--editorial le pose
     a blanc, et cette propriete l'emporte sur color pour le rendu du glyphe :
     ma regle de couleur s'appliquait bien, les chiffres restaient blancs sur
     le fond clair. C'est aussi ce qui trompait mon controle de contraste, qui
     ne lisait que color et annoncait zero echec sur des chiffres invisibles. */
  -webkit-text-fill-color: var(--color-fg-light);
}
.page-nosotros #trayectoria .metric__num .unit {
  color: var(--color-primary-deep);
  -webkit-text-fill-color: var(--color-primary-deep);
}
/* Le halo rouge du chiffre etait fait pour un fond sombre ; sur du clair il
   salit le contour au lieu de le faire vibrer. */
.page-nosotros #trayectoria .metric__num span { text-shadow: none; }


/* ── CERTIFICACIONES SUR SOL CLAIR : LES LOGOS REDEVIENNENT NOIRS ────────
   Les quatre logos de referentiels — NIST, ITIL, MITRE ATT&CK, MISP — sont
   servis en noir sur transparent et blanchis par un filtre
   « brightness(0) invert(1) » fait pour le fond sombre. La section etant
   passee au clair, ce filtre les rendait invisibles : blanc sur blanc.
   On garde brightness(0), qui normalise n'importe quelle couleur source en
   noir, et on lache l'inversion. */
main > section[data-sol="clair"] .frameworks__logos .framework-logo img,
main > section[data-sol="clair"] .framework-logo img {
  filter: brightness(0) !important;
  opacity: 0.78;
}
main > section[data-sol="clair"] .framework-logo:hover img { opacity: 1; }


/* ══════════════════════════════════════════════════════════════════════════
   NUESTRA ESENCIA : DEUX COLONNES — 2026-08-17
   ══════════════════════════════════════════════════════════════════════════
   La section empilait quatre blocs dans une colonne de 872 px et laissait
   900 px de vide a droite sur un ecran de 1920. Elle prend la meme grammaire
   que « Quiénes somos » juste au-dessus : un objet a gauche, le texte a
   droite. Ici l'objet est le mot « aša » lui-meme avec son etymologie — il
   est le sujet de la section, pas une illustration.

   Le titre reste PLEINE LARGEUR au-dessus des deux colonnes : c'est lui qui
   ouvre la section, et le couper en deux le ferait lire comme une legende. */
@media (min-width: 62rem) {
  /* PLUS DE grid-row EXPLICITE ICI. Il forcait .essence-mark et .essence-body
     sur la premiere rangee ; quand un troisieme bloc (.essence-lead) est
     arrive, le placement automatique l'a envoye ailleurs et les colonnes se
     sont inversees a l'ecran. Laisser la grille placer les enfants dans
     l'ordre du DOM est ce qui garde lecture visuelle et ordre de tabulation
     alignes. */
  .page-nosotros #esencia .essence-duo {
    display: grid;
    /* Cette declaration est BATTUE : .essence-duo est declare quatre fois dans
       ce fichier et c'est la derniere qui s'applique. Le vrai reglage des
       colonnes se fait plus bas, cherchez « LES DEUX COLONNES S'EQUILIBRENT ». */
    grid-template-columns: minmax(240px, 0.8fr) minmax(0, 1.2fr);
    gap: clamp(40px, 5vw, 96px);
    align-items: start;
  }
  /* Le mot est cale en haut de sa colonne et son filet le souligne sur toute
     la largeur de celle-ci. */
  .page-nosotros #esencia .essence-mark { margin: 0; }
  /* Le texte garde une longueur de ligne lisible meme quand la colonne
     s'elargit : au-dela de 68ch l'oeil perd la ligne suivante. */
  .page-nosotros #esencia .essence-body > p,
  .page-nosotros #esencia .essence-body > .essence-pull { max-width: 68ch; }
}


/* ── CERTIFICACIONES : TROIS CARTES, PLUS GRANDES — 2026-08-17 ───────────
   MISP et MITRE sont sortis de la bande : leurs logos viennent d'entrer dans
   la ligne des referentiels juste en dessous, ils y faisaient doublon. Restent
   les trois vraies certifications — FIRST, ISO 9001, ISO/IEC 27001 — et elles
   prennent la place laissee libre plutot que de rester calibrees pour cinq.
   Le badge passe de 32 a 56 px : c'est un sceau, on doit pouvoir le lire. */
@media (min-width: 62rem) {
  .page-nosotros #certificaciones .cert-strip {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: clamp(20px, 2vw, 32px);
  }
}
.page-nosotros #certificaciones .cert-card {
  padding: clamp(20px, 2vw, 30px) clamp(22px, 2.2vw, 34px);
  gap: clamp(16px, 1.6vw, 24px);
  align-items: center;
}
.page-nosotros #certificaciones .cert-card__badge {
  width: clamp(48px, 4.4vw, 72px);
  height: auto;
  max-height: none;
}
.page-nosotros #certificaciones .cert-card strong {
  font-size: clamp(17px, 1.5vw, 23px);
  line-height: 1.2;
}
.page-nosotros #certificaciones .cert-card span {
  font-size: clamp(12px, 1vw, 14px);
}


/* Les numeros du panneau des raisons : sans data-persona, --p retombe sur le
   rouge de marque, qui ne rend que 4,13:1 en onglet et 2,93:1 en volet sur le
   sol sombre — sous le seuil de 4,5 a 10 et 11 px. La variante relevee les
   remet au-dessus sans quitter la tension rouge, et l'opacite heritee est
   levee : c'est elle qui faisait tomber le volet plus bas que l'onglet. */
.solpanel--razones .solpanel__tab-method,
.solpanel--razones .solpanel__pane-method {
  color: var(--color-primary-soft);
  opacity: 1;
}
.solpanel--razones .solpanel__tab[aria-selected="true"] .solpanel__tab-method {
  color: var(--color-primary-soft);
}


/* ── ESENCIA : LA DEVISE, EN GRAND SOUS LE MOT — 2026-08-17 ──────────────
   Elle remplace le lema espagnol qui vivait au milieu du texte. Mise ici, sous
   « aša », elle se lit comme la traduction du mot — ce qu'elle est — au lieu
   d'interrompre le paragraphe qui l'annonce.
   Le corps suit celui du mot de deux crans en dessous : assez grand pour etre
   une affirmation, assez petit pour que « aša » reste le sujet. */

main > section[data-sol="clair"] 

@media (min-width: 62rem) {
  /* Les colonnes s'inversent : le texte prend la plus large, a gauche ; le mot
     et sa devise la plus etroite, a droite. C'est l'ordre du DOM qui commande,
     aucune propriete order n'est necessaire — l'ordre de lecture au clavier et
     celui a l'ecran restent donc les memes. */
  /* Le mot et la devise a GAUCHE, le texte a droite — l'ordre du DOM a ete
     inverse avec, de sorte que la lecture au clavier suive la lecture a
     l'ecran. La colonne de gauche est la plus etroite : elle porte trois
     lignes, celle de droite deux paragraphes. */
  .page-nosotros #esencia .essence-duo {
    grid-template-columns: minmax(280px, 0.78fr) minmax(0, 1.22fr);
  }
}


/* ══════════════════════════════════════════════════════════════════════════
   NOSOTROS : LE CTA FINAL PASSE AU BLEU — 2026-08-17
   ══════════════════════════════════════════════════════════════════════════
   Le meme bleu que « Foco en industrias claves » : --color-csirt. La classe
   --azul est portee par cette section seule, donc les CTA de la home, de
   metodologia et des autres pages gardent le rouge — c'est un accent de page,
   pas un changement de design system.

   L'accent du titre prend la variante SOFT et non le ton plein : sur le fond
   sombre du poster, la variante claire rend nettement plus que le ton plein, et
   il s'agit d'un grand titre qu'on ne veut pas voir vibrer.

   ── L'ENCRE DU BOUTON S'INVERSE AVEC LE PASSAGE A #3773c2 — 2026-09-04 ────
   La regle ecrite ici disait « le bouton garde une encre SOMBRE : le bleu plein
   est clair, du blanc dessus tomberait sous le seuil ». C'etait vrai du cyan
   #06B6D4, qui est une couleur claire (encre sombre 7,84:1, blanc 2,32 ✗).
   Ce n'est PLUS vrai du bleu, qui est une couleur moyenne. Remesure :
       aplat #3773c2 · encre #101010  3,98:1  ECHEC
       aplat #3773c2 · blanc #FFFFFF  4,78:1  OK
   Le libelle passe donc au blanc, et c'est le seul etat conforme.

   AU SURVOL, L'INVERSE : le fond devient la variante claire #60A5FA, sur
   laquelle le blanc tombe a 2,54 ✗ et l'encre sombre rend 7,48 ✓. Le libelle
   change donc de couleur entre repos et survol. Ce n'est pas une coquetterie :
   c'est ce que les deux aplats imposent, l'un fonce et l'autre clair.
   Comme le rouge de marque a 4,62, le blanc au repos est conforme SANS MARGE :
   ne pas descendre ce libelle sous 16 px. */
.final-cta--azul .final-cta__title .accent,
.final-cta--azul .final-cta__title .final-cta__accent,
.final-cta--azul .final-cta__title .accent .split-word {
  color: var(--color-csirt-soft) !important;
  -webkit-text-fill-color: var(--color-csirt-soft) !important;
}
.final-cta--azul .btn-primary {
  background: var(--color-csirt) !important;
  border-color: var(--color-csirt) !important;
  color: #FFFFFF !important;
}
/* ── LE SURVOL DU CTA : LE FOND NE BOUGE PLUS      2026-09-06 ──────────────
   Gabriel : « retire l'effet d'eclaircissement des boutons, l'animation que
   je veux est le changement de couleur des lettres de blanc a noir,
   apparition d'un halo autour, et une petite animation ou le bouton bouge un
   peu vers le haut ».

   Ce bouton garde donc son aplat #3773C2 aux deux etats. Ce qui joue au
   survol : l'encre bascule vers #101010, le halo bleu apparait (24 px a
   45 %), et le bouton monte de 1 px — cette elevation lui vient d'ailleurs
   dans la feuille, elle n'est pas redeclaree ici pour ne pas l'ecraser.

   LE PRIX, MESURE : sans l'eclaircissement, l'encre sombre rend 3,98:1 sur ce
   bleu, pour un seuil de 4,5. C'etait 7,48:1 tant que le fond s'eclaircissait.
   Repasser le seuil a fond fixe demanderait d'eclaircir l'aplat AU REPOS
   d'environ 18 %, donc de changer le bleu de la marque. Arbitrage de Gabriel,
   signale et assume.

   LA REGLE VAUT SUR LES SEPT PAGES, et c'est voulu : le CTA est un composant
   unique repete, un geste different selon la page serait un defaut a lui
   seul. NE PAS le « realigner » sur le hero, arbitrage deja tranche le
   2026-09-06 apres un aller-retour. */
.final-cta--azul .btn-primary:hover,
.final-cta--azul .btn-primary:focus-visible {
  background: var(--color-csirt) !important;
  border-color: var(--color-csirt) !important;
  color: var(--color-fg-light) !important;
  -webkit-text-fill-color: var(--color-fg-light) !important;
}
/* Les quatre equerres de coin et la pastille de la ligne de meta suivent. */
.final-cta--azul .final-cta__corner {
  border-color: color-mix(in srgb, var(--color-csirt) 62%, transparent) !important;
}
.final-cta--azul .final-cta__meta-dot {
  background: var(--color-csirt) !important;
  box-shadow: 0 0 8px var(--color-csirt) !important;
}


/* Les deux equerres de la carte, en ::before et ::after de .final-cta__inner.
   Elles ne portent pas de classe a elles, il faut donc les viser par leur
   pseudo-element — c'est ce qui les avait laissees rouges quand tout le reste
   du CTA est passe au bleu. Et la pastille pulsee de l'eyebrow avec elles. */
.final-cta--azul .final-cta__inner::before,
.final-cta--azul .final-cta__inner::after {
  border-color: var(--color-csirt) !important;
}
.final-cta--azul .final-cta__eyebrow .pulse {
  background: var(--color-csirt) !important;
}


/* ══════════════════════════════════════════════════════════════════════════
   POR QUE PREFERIRNOS : COULEURS ET FONDS, COMME #soluciones — 2026-08-17
   ══════════════════════════════════════════════════════════════════════════
   Les regles de fond de #soluciones sont scopees a cette section : elles ne
   pouvaient pas servir ici. On les reprend pour #razones plutot que de
   descoper les originales — un selecteur qui s'appliquerait partout finirait
   par teinter une section qui ne l'a pas demande.

   La section doit etre un repere de position, sinon les calques en absolu
   remonteraient jusqu'a un ancetre plus haut et couvriraient la page. */
.page-nosotros #razones { position: relative; overflow: hidden; }
#razones .solpanel__fond {
  position: absolute;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  pointer-events: none;
}
#razones .solpanel__fond span {
  position: absolute;
  inset: 0;
  background-size: cover;
  background-position: center;
  opacity: 0;
  transition: opacity var(--duration-slow, 420ms) var(--ease-out);
}
/* 0,20 et non 0,45 comme sur #soluciones : la, le panneau est pose sur un sol
   sombre uni ; ici la section porte deja des cartes et un texte long, et
   au-dela de 0,2 la mesure de contraste des libelles commencait a tomber. */
#razones .solpanel__fond span.is-on { opacity: 0.20; }
/* Les six photos de cette section, produites pour elle le 2026-08-17.
   Elles ne sont plus celles de #soluciones : chaque raison a desormais son
   image, et le persona de chaque onglet a ete realigne sur la dominante de
   son image pour que le filet, le libelle actif et le fond s'accordent.
   Le calque reste a opacity 0.20 : c'est lui qui porte la lisibilite du
   texte par-dessus, et il vaut aussi pour ces photos plus lumineuses. */
#razones .solpanel__fond span[data-bg="zerotrust"] { background-image: url('../assets/images/bg/razones/zerotrust.webp'); }
#razones .solpanel__fond span[data-bg="ngsoc"] { background-image: url('../assets/images/bg/razones/ngsoc.webp'); }
#razones .solpanel__fond span[data-bg="grc"] { background-image: url('../assets/images/bg/razones/grc.webp'); }
#razones .solpanel__fond span[data-bg="csirt"] { background-image: url('../assets/images/bg/razones/csirt.webp'); }
#razones .solpanel__fond span[data-bg="ctem"] { background-image: url('../assets/images/bg/razones/ctem-nuit.webp'); }
#razones .solpanel__fond span[data-bg="bridge"] { background-image: url('../assets/images/bg/razones/bridge.webp'); }
@media (prefers-reduced-motion: reduce) {
  #razones .solpanel__fond span { transition: none; }
}
/* Le contenu passe devant les calques. */
.page-nosotros #razones > .container { position: relative; z-index: 1; }

/* Les six couleurs. bridge n'a pas de token a lui : c'est le tronc commun
   ASHA, il prend le rouge de marque. */
#razones .solpanel__tab[data-persona="ctem"],      #razones .solpanel__pane[data-persona="ctem"]      { --p: var(--color-ctem); }
#razones .solpanel__tab[data-persona="ngsoc"],     #razones .solpanel__pane[data-persona="ngsoc"]     { --p: var(--color-ngsoc); }
#razones .solpanel__tab[data-persona="csirt"],     #razones .solpanel__pane[data-persona="csirt"]     { --p: var(--color-csirt); }
#razones .solpanel__tab[data-persona="zerotrust"], #razones .solpanel__pane[data-persona="zerotrust"] { --p: var(--color-zerotrust); }
#razones .solpanel__tab[data-persona="grc"],       #razones .solpanel__pane[data-persona="grc"]       { --p: var(--color-grc); }
#razones .solpanel__tab[data-persona="bridge"],    #razones .solpanel__pane[data-persona="bridge"]    { --p: var(--color-primary); }

/* Le numero suit desormais la couleur de sa raison, et non plus le rouge
   unique — la regle posee ce matin devient donc conditionnelle : elle ne vaut
   plus que pour bridge, dont le ton EST le rouge et qui a besoin de la
   variante relevee pour tenir le seuil. */
#razones .solpanel__tab-method,
#razones .solpanel__pane-method { color: var(--p); opacity: 1; }
#razones .solpanel__tab[data-persona="bridge"] .solpanel__tab-method,
#razones .solpanel__pane[data-persona="bridge"] .solpanel__pane-method { color: var(--color-primary-soft); }


/* ── ESENCIA : LE RAPPORT ENTRE LE MOT ET LA DEVISE S'INVERSE — 2026-08-17 ──
   « aša » etait le plus gros element de la colonne, la devise deux crans en
   dessous. C'est la devise qui porte le propos — le mot n'est que son origine
   — et elle passe donc devant. Le mot reste lisible et reconnaissable, il
   cesse simplement d'ecraser la phrase qu'il annonce. */
.essence-mark__word { font-size: clamp(56px, 5.4vw, 96px) !important; }



/* nosotros porte un sous-menu comme metodologia : sa hero prend la MEME
   formule, celle qui reserve la place de ce sous-menu. Avec la formule
   generique la barre tombait 10 px plus bas que sur metodologia — assez pour
   se voir en passant d'une page a l'autre.
   CETTE REGLE DOIT RESTER APRES « .page-hero:not(.page-hero--liga) » : les
   deux valent une specificite de (0,2,0) — :not compte son argument — et a
   egalite c'est la derniere ecrite qui gagne. Placee avant, elle etait sans
   effet, ce que la mesure a montre tout de suite. */
.page-nosotros .page-hero {
  min-height: calc(100svh - var(--header-h) - var(--subnav-h));
}


/* La pastille de date d'un pays sans date connue : Peru est entre en operation
   active sans que sa date d'ouverture soit etablie, et une pilule vide se lit
   comme une donnee manquante plutot que comme une donnee absente. On la
   masque — l'inventer aurait ete pire. */
#presencia .country__since:empty { display: none; }


/* ══════════════════════════════════════════════════════════════════════════
   QUATRE CORRECTIONS DU 2026-08-17
   ══════════════════════════════════════════════════════════════════════════ */

/* ── 1. LES SURTITRES DU SOL-0 PRENNENT LA PILULE DES AUTRES ─────────────
   La serie couvrait sol-2 et sol-clair, jamais sol-0 : sur nosotros, les
   surtitres de « Nuestra esencia », « Por qué preferirnos » et « Alianzas »
   restaient des rectangles a angles vifs sans padding, a cote de pilules.
   Meme recette que le sol-2, l'encre claire y rendant tout aussi bien. */
main > section[data-sol="0"] > .container .eyebrow,
main > section[data-sol="0"] .section-head .eyebrow {
  display: inline-block;
  background: rgba(23, 23, 23, 0.55);
  border: 1px solid rgba(220, 38, 38, 0.42);
  border-radius: 9999px;
  padding: 5px 12px 4px;
  color: rgba(248, 250, 252, 0.96);
}

/* ── 2. CASOS DE EXITO PASSE AU VERT ─────────────────────────────────────
   --color-grc rend 7,07:1 sur le sol-2, mesure : il passe partout ou le rouge
   passait, y compris sur les petits corps. La bordure de l'onglet actif et les
   grands chiffres suivent, sinon la section garderait deux tensions. */
#casos-exito .section-title .accent,
#casos-exito .section-title .accent .split-word {
  color: var(--color-grc) !important;
  -webkit-text-fill-color: var(--color-grc) !important;
}
#casos-exito .cases__tab[aria-selected="true"],
#casos-exito .cases__tab.is-active {
  border-color: var(--color-grc) !important;
  color: var(--color-fg) !important;
}
#casos-exito .case-fig__num,
#casos-exito .case-fig__unit {
  color: var(--color-grc) !important;
  -webkit-text-fill-color: var(--color-grc) !important;
}
#casos-exito .ring-stat__dial,
#casos-exito .case-fig__ring { --p: var(--color-grc); }

/* ── 3. POR QUE PREFERIRNOS : LE TITRE ET SON SURTITRE EN BLEU ───────────
   Le meme bleu que « Foco en industrias claves » et que le CTA final. Les six
   couleurs de persona restent sur les onglets et les fonds : elles distinguent
   les raisons entre elles, le bleu identifie la section. */
#razones .section-title .accent,
#razones .section-title .accent .split-word {
  color: var(--color-csirt-soft) !important;
  -webkit-text-fill-color: var(--color-csirt-soft) !important;
}
#razones .eyebrow {
  background: color-mix(in srgb, var(--color-csirt) 14%, transparent) !important;
  border-color: color-mix(in srgb, var(--color-csirt) 46%, transparent) !important;
  color: var(--color-csirt-soft) !important;
}

/* ── 4. ESENCIA : LA DEVISE A GAUCHE, LE MOT A DROITE ET PLUS PETIT ──────
   Trois blocs et non deux : la devise ouvre a gauche en grand, le texte la
   suit dessous, et le mot avec son etymologie se retire a droite en petit —
   c'est une note d'origine, pas le sujet. */
@media (min-width: 62rem) {
  .page-nosotros #esencia .essence-duo {
    grid-template-columns: minmax(0, 1.32fr) minmax(220px, 0.68fr);
  }
}
.essence-mark__word { font-size: clamp(34px, 3vw, 52px) !important; }
.essence-mark__lang { font-size: clamp(10px, 0.78vw, 12px) !important; }



/* ── LA DEVISE : UNE SEULE REGLE, ET ASSEZ SPECIFIQUE POUR PASSER ────────
   Trois declarations de .essence-motto s'etaient empilees au fil des reglages,
   et aucune ne s'appliquait : « .essence-body p » vaut (0,1,1) et les battait
   toutes a (0,1,0). La devise s'affichait a 18 px au lieu de 60.
   Le selecteur porte donc la classe ET l'element, ce qui suffit a passer
   devant sans recourir a !important. */
.essence-body p.essence-motto,
.essence-lead p.essence-motto {
  margin: 0 0 clamp(20px, 2vw, 32px);
  font-size: clamp(32px, 3.6vw, 60px);
  font-weight: 700;
  line-height: 1.1;
  letter-spacing: -0.015em;
  /* La couleur ne se decide PAS ici : la devise porte un <span class="accent">
     et ses deux moities ont deux encres. Voir la declaration en fin de fichier,
     qui est celle qui gagne — ce selecteur est declare quatre fois dans ce
     fichier, et a specificite egale c'est la derniere qui s'applique. */
  /* Le plafond de 24ch la bornait a 554 px a 1440, quand il lui en faut 640
     pour tenir sa ligne : c'est lui qui la cassait en deux, avant meme la
     colonne. C'est desormais la colonne qui fait la contrainte, et elle a ete
     dimensionnee pour. */
  max-width: none;
}
main > section[data-sol="clair"] .essence-body p.essence-motto,
main > section[data-sol="clair"] .essence-lead p.essence-motto { color: var(--color-primary-deep); }


/* ── ESENCIA : LA DEVISE SEULE A GAUCHE — 2026-08-17 ─────────────────────
   La colonne de gauche ne porte plus qu'une phrase : elle peut donc etre
   etroite, et la devise y respire sur trois ou quatre lignes plutot que de
   traverser la page. La colonne de droite reprend le mot, son etymologie et
   l'explication, qui se lisent ensemble.
   La devise se cale en haut, sur la meme ligne que le mot d'en face. */
@media (min-width: 62rem) {
  /* LA DEVISE TIENT SUR DEUX LIGNES, LA COLONNE REVIENT AU TEXTE — 2026-08-22.
     Elle avait ete elargie le meme jour pour loger « How things should be
     done. » sur une seule ligne ; Gabriel a tranche pour deux lignes, avec la
     coupure apres « How things ». Sur deux lignes la devise ne reclame plus que
     la moitie de la largeur, et les 1,06fr qu'on lui avait donnes seraient pris
     au texte pour rien.
     Le partage revient donc a 0,8 contre 1,2, sa valeur d'origine : le texte
     retrouve ses 764 px a 1440, soit une longueur de lecture confortable.
     C'est ICI qu'il faut regler : .essence-duo est declare quatre fois dans ce
     fichier, et a specificite egale c'est la derniere qui gagne. */
  .page-nosotros #esencia .essence-duo {
    grid-template-columns: minmax(240px, 0.8fr) minmax(0, 1.2fr);
    align-items: start;
  }
}
.essence-lead p.essence-motto {
  margin: 0;
  font-size: clamp(32px, 3.4vw, 58px);
  font-weight: 700;
  line-height: 1.08;
  letter-spacing: -0.015em;
  color: var(--color-primary-soft);
  /* Le plafond de 16ch bornait la devise a 370 px quand il lui en faut 640
     pour tenir sa ligne : c'est lui qui la cassait en deux, avant meme la
     colonne. C'est desormais la colonne qui fait la contrainte, et elle a ete
     dimensionnee pour. */
  max-width: none;
}
main > section[data-sol="clair"] .essence-lead p.essence-motto { color: var(--color-primary-deep); }
/* Le mot ouvre la colonne de droite : marge basse pour le detacher du premier
   paragraphe, aucune marge haute pour qu'il s'aligne sur la devise. */
.essence-body .essence-mark { margin: 0 0 clamp(20px, 2vw, 30px); }


/* ── CASOS DE EXITO : LES DERNIERS ROUGES PASSENT AU VERT — 2026-08-17 ────
   Le surtitre, la bordure de l'onglet actif et l'anneau du chiffre etaient
   restes rouges : le premier n'etait pas dans ma liste, le deuxieme se marque
   par .is-active et non par aria-selected — le script pose les deux, mais la
   regle ne visait que l'attribut — et le troisieme prend sa couleur d'une
   variable --fill que je n'avais pas redefinie. */
#casos-exito .eyebrow {
  background: color-mix(in srgb, var(--color-grc) 14%, transparent) !important;
  border-color: color-mix(in srgb, var(--color-grc) 46%, transparent) !important;
  color: var(--color-grc) !important;
}
#casos-exito .cases__tab.is-active,
#casos-exito .cases__tab[aria-selected="true"] {
  border-color: var(--color-grc) !important;
  background: color-mix(in srgb, var(--color-grc) 10%, transparent) !important;
}
#casos-exito .ring-stat,
#casos-exito .case-ring,
#casos-exito [class*="ring"] { --p: var(--color-grc); --ring: var(--color-grc); }
#casos-exito .ring-stat__dial,
#casos-exito .case-fig__dial {
  background: conic-gradient(var(--color-grc) calc(var(--fill, 0) * 1%), rgba(248,250,252,0.10) 0) !important;
}

/* ── CERTIFICACIONES : LES SCEAUX SEULS, EN GRAND, ET LE TITRE CENTRE ─────
   Les trois cartes portaient chacune un sceau et deux lignes de libelle qui
   redisaient ce que le sceau montre deja. Il ne reste que l'image, nettement
   plus grande — c'est ce qu'on regarde. Le titre de la section se centre, et
   pour elle seule : c'est la seule page ou une exception a l'alignement a
   gauche se justifie, trois objets identiques centres sous un titre centre. */
.page-nosotros #certificaciones .section-head { text-align: center; }
.page-nosotros #certificaciones .section-head .section-title,
.page-nosotros #certificaciones .section-head .section-lede { margin-inline: auto; text-align: center; }
.page-nosotros #certificaciones .section-head .eyebrow { margin-inline: auto; }

.page-nosotros #certificaciones .cert-card {
  justify-content: center;
  padding: clamp(26px, 2.6vw, 40px);
}
.page-nosotros #certificaciones .cert-card__badge {
  width: clamp(92px, 9vw, 150px);
  height: auto;
  max-height: none;
}
/* Les marcos de referencia prennent toute la largeur de la section, avec les
   logos repartis dessus plutot que serres a gauche. */
.page-nosotros #certificaciones .about-frameworks { width: 100%; }
.page-nosotros #certificaciones .frameworks__label { text-align: center; }
.page-nosotros #certificaciones .frameworks__logos {
  display: flex;
  flex-wrap: wrap;
  /* center et non space-between : reparti sur toute la largeur, NIST se
     collait au bord gauche et MISP au bord droit, les quatre logos se lisant
     alors comme quatre elements separes plutot que comme une ligne. Centres
     avec une gouttiere large, ils forment un groupe sous le titre — lui aussi
     centre dans cette section. */
  justify-content: center;
  align-items: center;
  /* PLUS D'AIR, DEMANDE DEUX FOIS — 2026-08-22. La premiere passe avait
     augmente le gap de la regle generique (ligne ~8250) : sans effet, parce
     que CETTE declaration, plus specifique et plus bas dans le fichier, la
     bat. Mesure a l'appui, l'ecart etait reste a 64,8 px a 1440.
     La valeur est calee sur la place reellement disponible : a 1440 les quatre
     logos n'occupent que 504 px des 1 325 px du conteneur, il en restait 626
     inutilises. A 8vw, l'ecart vaut 115 px et la rangee tient toujours sur une
     seule ligne jusqu'a 768 px. */
  /* Troisieme passe, demandee a nouveau : 11vw, soit 158 px a 1440. Les quatre
     logos et leurs trois ecarts occupent alors 978 px des 1 325 px disponibles,
     la rangee tient toujours sur une ligne jusqu'a 768 px, et il reste de quoi
     respirer de chaque cote. */
  gap: clamp(48px, 11vw, 200px);
  width: 100%;
}
.page-nosotros #certificaciones .frameworks__grid {
  justify-content: center;
  width: 100%;
}


/* ── SOLUCIONES : LE TITRE ET SON SURTITRE EN BLEU — 2026-08-17 ──────────
   Meme bleu que « Foco en industrias claves », « Por qué preferirnos » et les
   CTA finaux. Les six couleurs de persona restent sur les onglets, les volets
   et les fonds : elles distinguent les solutions entre elles, le bleu
   identifie la section. */
/* ── TROIS EXCEPTIONS AU ROUGE DES TITRES      2026-08-22 ────────────────
   Gabriel affine la consigne de la veille : CINQ sections gardent la couleur de
   leur persona, et elles seules. Sur la home, « Soluciones » et « Foco en
   industrias clave » en BLEU, « Casos de exito » en VERT. Sur nosotros,
   « Por que preferirnos » en BLEU et « Certificaciones » en VERT — celle-ci
   dans la variante encre, la seule qui tienne sur son sol clair.

   La regle generale ne change pas et reste ecrite plus haut : un seul rouge de
   titre, #B01E1E sur fond clair et #DC2626 sur fond sombre. Ces trois sections
   sont des exceptions NOMMEES, pas un retour a l'etat d'avant — la ou l'on
   comptait six couleurs de titre sans regle, on en compte maintenant deux plus
   trois exceptions assumees.

   Contrastes mesures sur leurs sols respectifs : le bleu clair rend 11,11:1 sur
   le sol 2 et 12,71:1 sur le sol 1, le vert 7,07:1. Tous trois tres au-dessus
   du seuil de 3:1 applicable a ces titres (48 px, poids 700). */
#soluciones .section-title .accent,
#soluciones .section-title .accent .split-word {
  color: var(--color-csirt-soft) !important;
  -webkit-text-fill-color: var(--color-csirt-soft) !important;
}
#soluciones > .container > .section-head .eyebrow,
#soluciones .section-head .eyebrow {
  background: color-mix(in srgb, var(--color-csirt) 14%, transparent) !important;
  border-color: color-mix(in srgb, var(--color-csirt) 46%, transparent) !important;
  color: var(--color-csirt-soft) !important;
}


/* ══════════════════════════════════════════════════════════════════════════
   CINQ CORRECTIONS DU 2026-08-17 (suite)
   ══════════════════════════════════════════════════════════════════════════ */

/* ── 1. LE TITRE DE CERTIFICACIONES AU CENTRE DE LA PAGE ─────────────────
   text-align: center centrait le texte DANS .section-head, un bloc de 1060 px
   lui-meme cale a gauche : son centre tombait a 674 px quand celui de la page
   est a 960. Il faut donc centrer LE BLOC, pas seulement son contenu. */
.page-nosotros #certificaciones .section-head {
  margin-inline: auto;
  max-width: min(100%, 1060px);
}

/* ── 2. LES QUATRE LOGOS DE REFERENTIELS, PLUS GRANDS ────────────────────
   Ils faisaient 21 a 26 px de haut, soit la taille d'une ligne de texte.
   La hauteur est desormais imposee et la largeur suit : les quatre logos
   n'ont pas le meme rapport, seule une hauteur commune les met a la meme
   echelle optique. */
.page-nosotros #certificaciones .frameworks__logos img {
  height: clamp(30px, 3vw, 52px) !important;
  width: auto !important;
  max-height: none !important;
  max-width: none !important;
}

/* ── 3. CERTIFICACIONES EN VERT ──────────────────────────────────────────
   Le meme vert que « Casos de éxito » : la section parle de certifications
   obtenues, un fait acquis, et le vert le dit mieux que la tension rouge.
   Sur le sol clair, la variante ink : --color-grc n'y rend que 2,1:1, ce que
   la mesure a confirme, alors que #17843F passe. */
.page-nosotros #certificaciones .section-title .accent,
.page-nosotros #certificaciones .section-title .accent .split-word {
  color: var(--color-grc-ink) !important;
  -webkit-text-fill-color: var(--color-grc-ink) !important;
}
.page-nosotros #certificaciones .section-head .eyebrow {
  background: color-mix(in srgb, var(--color-grc) 12%, transparent) !important;
  border-color: color-mix(in srgb, var(--color-grc) 46%, transparent) !important;
  /* Un cran plus sombre que --color-grc-ink : celui-ci rend 4,13:1 sur la
     pilule claire, juste sous le seuil de 4,5 exige par ces 12 px. Le melange
     a 78 % avec du noir monte a 6,58:1. Le TITRE, lui, garde le ton ink :
     a 47 px son seuil est 3, et il le passe largement. */
  color: color-mix(in srgb, var(--color-grc-ink) 78%, black) !important;
}

/* ── 4. LE CERCLE DE CASOS DE EXITO EN VERT ──────────────────────────────
   Il s'appelle .case-ring__dial et non .ring-stat__dial : mes regles
   precedentes visaient les deux autres anneaux du site et laissaient
   celui-la en rouge. L'angle de depart et le reste du degrade sont repris
   tels quels, seule la couleur change. */
#casos-exito .case-ring__dial {
  background-image: conic-gradient(from 220deg,
    var(--color-grc) calc(var(--fill, 0) * 1%),
    rgba(248, 250, 252, 0.16) 0deg) !important;
}

/* ── 5. LE BADGE « ANTES » EN GRIS ───────────────────────────────────────
   « Antes » decrit l'etat de depart : le colorer lui donnait le meme poids
   qu'« Después », qui est le resultat. En gris il devient ce qu'il est, un
   repere de comparaison. */
#casos-exito .case-flow__tag--before {
  background: rgba(248, 250, 252, 0.07) !important;
  border-color: rgba(248, 250, 252, 0.22) !important;
  color: var(--color-muted-lift) !important;
}


/* La devise se centre verticalement sur la colonne de texte. align-self et
   non align-items sur la grille : celui-ci aurait aussi recentre la colonne
   de droite, dont le premier mot doit rester au niveau du titre. */
@media (min-width: 62rem) {
  .page-nosotros #esencia .essence-lead { align-self: center; }
}


/* ══════════════════════════════════════════════════════════════════════════
   HERO DE METODOLOGIA : LES BOUTONS REVEILLENT LEUR PERSONNAGE — 2026-08-17
   ══════════════════════════════════════════════════════════════════════════
   1. LE LIBELLE PREND SA COULEUR. Au survol, les six libelles passaient tous
      au rouge : la regle de survol utilisait --color-primary alors que chaque
      noeud porte deja son --persona-color. Il suffisait de s'en servir.

   2. LE PERSONNAGE S'ALLUME. Survoler « ASHA » remet la capitane a pleine
      opacite et rallume son halo, et ainsi des six.

   POURQUOI :has(). Le bouton et le personnage sont deux branches separees du
   hero — aucun selecteur de descendance ou de fratrie ne relie l'un a l'autre.
   :has() sur leur ancetre commun le fait sans une ligne de JavaScript, et sur
   un navigateur qui ne le connait pas la regle est simplement ignoree : on
   perd l'effet, jamais la page. */
.liga-constellation__node:hover .liga-constellation__label,
.liga-constellation__node:focus-visible .liga-constellation__label {
  color: var(--persona-color, var(--color-primary));
}
/* ASHA seule prend la variante relevee : sa couleur de persona EST le rouge de
   marque, qui rend 4,35:1 sur le noir a ces 12 px — sous le seuil de 4,5.
   Les cinq autres tons sont clairs et passent de 7,49 a 17,03:1, mesures.
   C'est la quatrieme fois aujourd'hui que ce meme couple #DC2626 sur fond
   sombre a petite taille demande la variante soft. */
.liga-constellation__node[data-persona="asha"]:hover .liga-constellation__label,
.liga-constellation__node[data-persona="asha"]:focus-visible .liga-constellation__label {
  color: var(--color-primary-soft);
}
.liga-constellation__node:hover .liga-constellation__dot {
  background: var(--persona-color, var(--color-primary));
  box-shadow: 0 0 10px var(--persona-color, var(--color-primary));
}

/* La transition doit etre declaree sur l'etat de repos, sinon le retour se
   fait d'un coup : c'est l'element qui porte la transition, pas le survol. */
.liga-row__fig img,
.liga-row__fig::before {
  transition: opacity var(--duration-normal) var(--ease-out),
              filter var(--duration-normal) var(--ease-out),
              transform var(--duration-normal) var(--ease-out);
}

.page-hero--liga:has(.liga-constellation__node[data-persona="asha"]:hover) .liga-row__fig[data-persona="asha"] img,
.page-hero--liga:has(.liga-constellation__node[data-persona="asha"]:focus-visible) .liga-row__fig[data-persona="asha"] img {
  opacity: 1;
  filter: none;
}
.page-hero--liga:has(.liga-constellation__node[data-persona="asha"]:hover) .liga-row__fig[data-persona="asha"]::before,
.page-hero--liga:has(.liga-constellation__node[data-persona="asha"]:focus-visible) .liga-row__fig[data-persona="asha"]::before {
  opacity: 1;
  transform: translateX(-50%) scale(1.12);
}
.page-hero--liga:has(.liga-constellation__node[data-persona="zerotrust"]:hover) .liga-row__fig[data-persona="zerotrust"] img,
.page-hero--liga:has(.liga-constellation__node[data-persona="zerotrust"]:focus-visible) .liga-row__fig[data-persona="zerotrust"] img {
  opacity: 1;
  filter: none;
}
.page-hero--liga:has(.liga-constellation__node[data-persona="zerotrust"]:hover) .liga-row__fig[data-persona="zerotrust"]::before,
.page-hero--liga:has(.liga-constellation__node[data-persona="zerotrust"]:focus-visible) .liga-row__fig[data-persona="zerotrust"]::before {
  opacity: 1;
  transform: translateX(-50%) scale(1.12);
}
.page-hero--liga:has(.liga-constellation__node[data-persona="ngsoc"]:hover) .liga-row__fig[data-persona="ngsoc"] img,
.page-hero--liga:has(.liga-constellation__node[data-persona="ngsoc"]:focus-visible) .liga-row__fig[data-persona="ngsoc"] img {
  opacity: 1;
  filter: none;
}
.page-hero--liga:has(.liga-constellation__node[data-persona="ngsoc"]:hover) .liga-row__fig[data-persona="ngsoc"]::before,
.page-hero--liga:has(.liga-constellation__node[data-persona="ngsoc"]:focus-visible) .liga-row__fig[data-persona="ngsoc"]::before {
  opacity: 1;
  transform: translateX(-50%) scale(1.12);
}
.page-hero--liga:has(.liga-constellation__node[data-persona="csirt"]:hover) .liga-row__fig[data-persona="csirt"] img,
.page-hero--liga:has(.liga-constellation__node[data-persona="csirt"]:focus-visible) .liga-row__fig[data-persona="csirt"] img {
  opacity: 1;
  filter: none;
}
.page-hero--liga:has(.liga-constellation__node[data-persona="csirt"]:hover) .liga-row__fig[data-persona="csirt"]::before,
.page-hero--liga:has(.liga-constellation__node[data-persona="csirt"]:focus-visible) .liga-row__fig[data-persona="csirt"]::before {
  opacity: 1;
  transform: translateX(-50%) scale(1.12);
}
.page-hero--liga:has(.liga-constellation__node[data-persona="ctem"]:hover) .liga-row__fig[data-persona="ctem"] img,
.page-hero--liga:has(.liga-constellation__node[data-persona="ctem"]:focus-visible) .liga-row__fig[data-persona="ctem"] img {
  opacity: 1;
  filter: none;
}
.page-hero--liga:has(.liga-constellation__node[data-persona="ctem"]:hover) .liga-row__fig[data-persona="ctem"]::before,
.page-hero--liga:has(.liga-constellation__node[data-persona="ctem"]:focus-visible) .liga-row__fig[data-persona="ctem"]::before {
  opacity: 1;
  transform: translateX(-50%) scale(1.12);
}
.page-hero--liga:has(.liga-constellation__node[data-persona="grc"]:hover) .liga-row__fig[data-persona="grc"] img,
.page-hero--liga:has(.liga-constellation__node[data-persona="grc"]:focus-visible) .liga-row__fig[data-persona="grc"] img {
  opacity: 1;
  filter: none;
}
.page-hero--liga:has(.liga-constellation__node[data-persona="grc"]:hover) .liga-row__fig[data-persona="grc"]::before,
.page-hero--liga:has(.liga-constellation__node[data-persona="grc"]:focus-visible) .liga-row__fig[data-persona="grc"]::before {
  opacity: 1;
  transform: translateX(-50%) scale(1.12);
}


/* Le cadre de survol des trois sceaux passe au vert, comme le reste de la
   section. Deux regles le posaient en rouge — .cert-card:hover et
   .section--dark .cert-card:hover — et la seconde s'applique encore bien que
   la section soit passee au clair : elle porte toujours la classe
   section--light ET section--dark n'a jamais ete retiree du HTML. On vise donc
   par l'id, qui passe devant les deux. */
.page-nosotros #certificaciones .cert-card:hover,
.page-nosotros #certificaciones .cert-card:focus-within {
  border-color: var(--color-grc) !important;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.10),
              0 0 0 1px color-mix(in srgb, var(--color-grc) 40%, transparent) !important;
}


/* La devise porte desormais un <span class="accent"> : sa premiere moitie
   reste en encre claire, la seconde prend la tension rouge. La regle de
   couleur devait donc quitter le paragraphe entier pour ne viser que ce qui
   n'est pas accentue — sinon le rouge s'appliquait aux deux moities. */
.essence-lead p.essence-motto { color: var(--color-fg); }
/* L'ACCENT DE LA DEVISE : BLEU LE 22/08, ROUGE LE 08/09, ET C'EST LE MEME
   DEMANDEUR. Gabriel avait dit « change le rouge de how things should be done
   par le bleu qu'on utilise » ; il dit aujourd'hui « le "should be done." sur
   la version ordi doit etre en rouge ». Le telephone l'a deja depuis ce matin,
   le bureau le rejoint : c'est le SEUL des quatre points du soir qui ne
   concerne pas le telephone, et Gabriel l'a precise de lui-meme.

   C'est bien l'ACCENT qu'on change et non le paragraphe : la premiere moitie
   garde son encre claire, c'est l'architecture posee ici et elle est juste.

   --color-primary-lift ET NON --color-primary : c'est le token prevu pour du
   rouge en TEXTE sur sol sombre. Mesure a ce corps (49 px, 700) sur le noir de
   la section : 5,05:1 pour le lift contre un seuil de 3 pour du texte large.
   Le rouge plein descendrait a 3,6:1 — il passerait aussi, mais on prend celui
   qui est fait pour, et c'est celui que le telephone utilise deja depuis ce
   matin. Les deux affichages disent donc exactement la meme couleur.

   La regle est ecrite ICI et nulle part ailleurs : ce selecteur est declare
   quatre fois dans ce fichier, et a specificite egale c'est la derniere qui
   s'applique. Une couleur posee plus haut n'aurait rien fait — essaye le
   22/08, mesure blanche, corrige. */
.essence-lead p.essence-motto .accent { color: var(--color-primary-lift); }
main > section[data-sol="clair"] .essence-lead p.essence-motto { color: var(--color-fg-light); }
/* Sur sol clair le rouge lift tomberait sous le seuil : c'est le rouge profond
   qui y va, le token prevu pour du texte rouge sur fond clair. Regle dormante
   aujourd'hui, la section etant sombre — elle existe pour que la bascule de sol
   ne fasse pas disparaitre la devise. */
main > section[data-sol="clair"] .essence-lead p.essence-motto .accent { color: var(--color-primary-deep); }


/* ══════════════════════════════════════════════════════════════════════════
   CASOS DE EXITO : LE VOLET EN TROIS TEMPS — 2026-08-17
   ══════════════════════════════════════════════════════════════════════════
   Antecedentes, Solución, Resultado. Le motif Antes/Después a deux colonnes ne
   pouvait pas porter trois temps : les trois blocs s'empilent, chacun ouvert
   par son etiquette et suivi de ses points.

   La coloration dit le sens de la lecture : le premier bloc en gris — c'est
   l'etat de depart, pas un resultat — les deux suivants en vert, comme le
   reste de la section. Le meme arbitrage que le badge « Antes ». */
.cases__story--steps {
  display: grid;
  gap: clamp(18px, 1.8vw, 28px);
}
.case-step {
  padding: clamp(16px, 1.6vw, 24px) clamp(18px, 1.8vw, 26px);
  border: 1px solid rgba(248, 250, 252, 0.10);
  border-left-width: 3px;
  border-radius: var(--radius-md);
  background: rgba(248, 250, 252, 0.02);
}
.case-step__tag {
  margin: 0 0 clamp(10px, 1vw, 14px);
  font: 700 11px/1 var(--font-mono);
  letter-spacing: 0.16em;
  text-transform: uppercase;
}
.case-step__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 7px;
}
.case-step__list li {
  position: relative;
  padding-left: 16px;
  font-size: var(--text-sm);
  line-height: 1.55;
  color: var(--color-muted-lift);
}
/* La puce est un tiret cadratin, pas un disque : ce sont des constats, pas une
   liste de courses. */
.case-step__list li::before {
  content: '—';
  position: absolute;
  left: 0;
  opacity: 0.55;
}
/* L'etat de depart en gris, les deux temps suivants en vert. */
.case-step--antecedentes { border-left-color: rgba(248, 250, 252, 0.28); }
.case-step--antecedentes .case-step__tag { color: var(--color-muted-lift); }
.case-step--solucion,
.case-step--resultado { border-left-color: var(--color-grc); }
.case-step--solucion .case-step__tag,
.case-step--resultado .case-step__tag { color: var(--color-grc); }
/* Le resultat est ce qu'on retient : son fond est un peu plus present. */
.case-step--resultado { background: color-mix(in srgb, var(--color-grc) 6%, transparent); }


/* ── HERO : LE SOUS-TITRE ET LA LIGNE DE SCEAUX SE RECALENT — 2026-08-17 ──
   .hero__subtitle portait une max-width de 640 px avec des marges
   automatiques : il se centrait dans la colonne et son premier caractere
   tombait a 362 px quand tout le reste du hero commence a 144. La ligne de
   sceaux se decalait de la meme facon a 1440.
   La borne de longueur reste — une ligne de 640 px se lit bien — seule la
   marge automatique part, ce qui la cale a gauche comme ses voisines. */
.hero__subtitle {
  margin-inline: 0 auto;
  text-align: left;
}
/* PAS DE REGLE SUR .hero__trust-line : je l'avais crue desalignee parce que
   son bord gauche tombe a 467 px. Elle vit en fait dans un flex
   .hero__trust--inline, a DROITE des deux points d'appui — c'est le layout
   voulu, pas un defaut. Seul le sous-titre au-dessus etait reellement centre
   par une marge automatique. */


/* Le lede joint du hero : encre claire pleine, une seule voix. Les deux
   paragraphes precedents n'avaient ni le meme corps ni la meme encre, ce qui
   faisait lire une rupture la ou il n'y a qu'une phrase.
   Le corps se cale entre les deux anciens : assez present pour suivre le
   titre, assez sobre pour porter trois lignes. */
.hero__support--lede {
  color: var(--color-fg);
  font-size: clamp(16px, 1.25vw, 20px);
  line-height: 1.62;
  max-width: 62ch;
}


/* ══════════════════════════════════════════════════════════════════════════
   TROIS TRAITEMENTS DE CADRE — 2026-08-17
   ══════════════════════════════════════════════════════════════════════════
   La reference de Gabriel : un cadre a filet rouge fin, fond sombre voile de
   rouge depuis le haut, coins arrondis, un repere a gauche et le texte en
   blanc. Ce qui la caracterise n'est pas la couleur mais le RAPPORT — un filet
   franc, un fond a peine teinte, et un repere qui ne rivalise pas avec le
   texte. C'est ce rapport qui est repris ici. */

/* ── 1. LES SEPT PROBLEMATIQUES DEVIENNENT DES CADRES ────────────────────
   Elles n'avaient qu'un filet a gauche. Le numero, deja present, fait office
   du repere de la reference : il n'y a rien a ajouter au HTML. */
#problema .symptom {
  padding: clamp(16px, 1.5vw, 22px) clamp(18px, 1.7vw, 24px);
  border: 1px solid rgba(220, 38, 38, 0.30);
  border-left-width: 1px;
  border-radius: var(--radius-md);
  background: linear-gradient(180deg,
              rgba(220, 38, 38, 0.10) 0%,
              rgba(220, 38, 38, 0.02) 62%,
              transparent 100%),
              rgba(16, 16, 16, 0.60);
  transition: border-color var(--duration-normal) var(--ease-out),
              background var(--duration-normal) var(--ease-out),
              translate var(--duration-normal) var(--ease-out);
}
#problema .symptom:hover {
  border-color: rgba(220, 38, 38, 0.62);
  /* meme raison que les colonnes : le reveal pose translate ET transform inline */
  translate: 0 -2px !important;
}
#problema .symptom__text { color: var(--color-fg); font-weight: 600; }

/* ── 2. LES SIX CARTES DE « NUESTRO MODELO » PRENNENT LE MEME FILET ──────
   Le filet passe de 34 a 46 % du ton persona : sur la reference il est franc,
   et a 34 % il se devinait plutot qu'il ne se voyait. Les couleurs de persona
   sont conservees — c'est ce qui distingue les six, et Gabriel les a validees.
   Seul le RAPPORT filet/fond suit la reference. */
.practices__grid--six .practice[data-persona] {
  border-color: color-mix(in srgb, var(--p, var(--color-primary)) 46%, transparent) !important;
  border-radius: var(--radius-lg);
}

/* ── 3. LES DEUX COLONNES DE LA COMPARAISON S'ANIMENT AU SURVOL ──────────
   Elles etaient les seuls grands blocs de la page a ne rien faire sous la
   souris. Chacune s'anime dans SA couleur : le modele habituel en gris — il ne
   doit pas devenir desirable — et le systeme ASHA en rouge.
   La transition est declaree sur l'etat de repos, sinon le retour se ferait
   d'un coup ; et elle nomme ses proprietes plutot que « all », qui animerait
   aussi la mise en page. */
.versus__col {
  transition: border-color var(--duration-normal) var(--ease-out),
              background var(--duration-normal) var(--ease-out),
              box-shadow var(--duration-normal) var(--ease-out),
              translate var(--duration-normal) var(--ease-out);
}
/* translate AVEC !important, et c'est la seule facon. Le reveal GSAP ecrit en
   INLINE « translate: none; rotate: none; scale: none; transform: none » : il
   neutralise donc les deux proprietes a la fois, et un style inline ne se bat
   pas a la specificite. Premiere tentative avec transform : none au survol,
   mesure. Seconde avec translate sans !important : none encore, pour la meme
   raison. Un !important est ici le comportement correct, pas un contournement.
   C'est le meme piege que les hovers de cartes, deja paye sur ce repo. */
.versus__col--them:hover {
  border-color: rgba(248, 250, 252, 0.30);
  background: rgba(248, 250, 252, 0.04);
  translate: 0 -3px !important;
  box-shadow: 0 14px 34px rgba(0, 0, 0, 0.34);
}
.versus__col--us:hover {
  border-color: var(--color-primary);
  background: color-mix(in srgb, var(--color-primary) 9%, transparent);
  translate: 0 -3px !important;
  box-shadow: 0 14px 34px rgba(0, 0, 0, 0.34),
              0 0 0 1px color-mix(in srgb, var(--color-primary) 34%, transparent);
}
@media (prefers-reduced-motion: reduce) {
  #problema .symptom, .versus__col { transition: none; }
  #problema .symptom:hover, .versus__col:hover { translate: none !important; }
}


/* ── HERO : DE L'AIR ENTRE LE LEDE ET LES BOUTONS — 2026-08-17 ───────────
   Mesure : le lede finissait a 718 px et les boutons commencaient a 718. Zero
   pixel entre les deux. Le lede n'avait pas de marge basse et la colonne est
   un flex sans gap — rien ne les separait donc.
   La marge est posee sur le lede plutot qu'un gap sur la colonne : les autres
   ecarts de la colonne (24, 40, 48 px) sont deja regles un par un, un gap
   global les aurait tous ecrases. */
.hero__support--lede { margin-bottom: clamp(28px, 2.6vw, 40px); }

/* ── « INTEGRARLO TODO. » EN BLEU ────────────────────────────────────────
   --color-csirt-ink, LE TOKEN DU DS pour le bleu sur fond clair. J'avais
   d'abord bricole un color-mix a 72 % avec du noir — ca tenait le contraste
   mais ce n'etait pas le bleu du systeme, et ca se voyait. Le ton plein
   --color-csirt ne convient pas ici : il ne rend que 2,32:1 sur la bande
   claire, sous le seuil de 3 exige meme par ces 64 px. L'ink en rend 4,55:1.
   Meme logique que --color-primary-deep et --color-grc-ink ailleurs : chaque
   teinte du DS a sa valeur pour les fonds clairs, il suffit de la prendre. */
.problema__turn-text .accent,
.problema__turn-text .accent .split-word {
  /* --color-csirt, le ton plein : c'est LE bleu que le reste du site montre,
     celui du bouton du CTA. Gabriel l'a demande deux fois, c'est donc lui.
     A DIRE FRANCHEMENT : sur cette bande claire il rend 2,32:1, sous le seuil
     de 3 exige par ces 64 px. Aucun bleu reconnaissable du DS ne passe ici —
     le soft est a 1,39:1, l'ink a 4,55 mais ne ressemble plus au bleu du site.
     Le choix est assume, pas ignore. */
  color: var(--color-csirt) !important;
  -webkit-text-fill-color: var(--color-csirt) !important;
}


/* ── LES REPERES EN MOTS SONT PLUS PETITS QUE LES CHIFFRES — 2026-08-17 ───
   « Data Manager » et « Proactiva » heritaient du corps des grands nombres,
   calibre pour deux ou trois glyphes : sur un mot de douze lettres ca devient
   une banniere. Ils descendent a un tiers, ce qui les garde marquants sans
   qu'ils ecrasent le chiffre a cote — c'est lui la mesure. */
.case-fig__num--mot {
  /* Le plancher redescend a 22 px : a 390 px de large la carte ne fait que
     165 px et « Data Manager » a 26 px en demandait 180. */
  font-size: clamp(22px, 2.6vw, 42px) !important;
  /* MEME INTERLIGNE QUE LES CHIFFRES, qui sont a 1. A 1,12 il restait 5 px de
     demi-interligne sous la derniere ligne du mot, donc 5 px de plus entre lui
     et son libelle que pour un chiffre voisin. Sur un mot qui tient sur une
     ligne — c'est le cas des deux, a toutes les largeurs — un interligne de 1
     ne change rien d'autre que ce decalage. */
  line-height: 1;
  letter-spacing: -0.01em;
  /* PAS DE display ICI. Il y en avait un — block — et il ecrasait le flex de
     .case-fig__num, donc le align-items: flex-end qui colle la valeur au bas de
     sa zone. Resultat mesure : 92 px de vide entre le mot et son libelle, quand
     les chiffres d'a cote en ont zero. La valeur heritee est la bonne. */
  flex-wrap: wrap;   /* un mot de douze lettres peut demander deux lignes */
  max-width: 12ch;
}

/* ── « NUESTRO MODELO » : LES TROIS CASES AU MOTIF DE LA REFERENCE ────────
   Meme rapport que les problematiques de la home : filet franc, fond voile
   depuis le haut, coins arrondis, et l'icone en repere a gauche du texte sans
   lui disputer la place. La section est sur sol-2, le voile reste donc discret. */
.page-nosotros #modelo .about-card {
  padding: clamp(20px, 1.9vw, 28px) clamp(20px, 1.9vw, 28px);
  border: 1px solid rgba(220, 38, 38, 0.30) !important;
  border-radius: var(--radius-md);
  background: linear-gradient(180deg,
              rgba(220, 38, 38, 0.10) 0%,
              rgba(220, 38, 38, 0.02) 62%,
              transparent 100%),
              rgba(16, 16, 16, 0.55) !important;
  transition: border-color var(--duration-normal) var(--ease-out),
              background var(--duration-normal) var(--ease-out),
              translate var(--duration-normal) var(--ease-out);
}
.page-nosotros #modelo .about-card:hover {
  border-color: rgba(220, 38, 38, 0.62) !important;
  /* translate et !important : le reveal pose transform ET translate en inline */
  translate: 0 -2px !important;
}
/* L'icone devient le repere de la reference : petite, rouge, sans pastille. */
.page-nosotros #modelo .about-card__icon-wrap {
  width: 34px !important;
  height: 34px !important;
  background: none !important;
  border: 0 !important;
  box-shadow: none !important;
  margin-bottom: clamp(10px, 1vw, 14px);
}
.page-nosotros #modelo .about-card__icon-wrap svg { width: 22px; height: 22px; }
.page-nosotros #modelo .about-card__title { font-size: var(--text-lg); }
@media (prefers-reduced-motion: reduce) {
  .page-nosotros #modelo .about-card { transition: none; }
  .page-nosotros #modelo .about-card:hover { translate: none !important; }
}



/* ── LES QUATRE TUILES DE « COMO OPERAMOS » S'ANIMENT ────────────────────
   Meme geste que les problematiques et les cases de « Nuestro modelo » : le
   filet s'affirme, le fond se teinte, la tuile se souleve de 2 px.
   translate en !important pour la meme raison que partout ailleurs : le reveal
   GSAP pose translate ET transform en inline sur ces elements. */
.opcard {
  transition: border-color var(--duration-normal) var(--ease-out),
              background var(--duration-normal) var(--ease-out),
              box-shadow var(--duration-normal) var(--ease-out),
              translate var(--duration-normal) var(--ease-out);
}
.opcard:hover {
  border-color: rgba(220, 38, 38, 0.62) !important;
  background: color-mix(in srgb, var(--color-primary) 8%, transparent) !important;
  translate: 0 -2px !important;
  box-shadow: 0 12px 30px rgba(0, 0, 0, 0.30);
}
@media (prefers-reduced-motion: reduce) {
  .opcard { transition: none; }
  .opcard:hover { translate: none !important; }
}



/* ── LES TROIS REPERES DU CAS MEXICAIN SE REMETTENT EN COLONNE ────────────
   La grille les repartissait sur deux colonnes en flux libre : le chiffre
   tombait a gauche au milieu, « Data Manager » en haut a droite loin de son
   libelle, « Proactiva » plus bas encore. Trois blocs de nature differente —
   un nombre et deux mots — ne peuvent pas s'aligner dans une grille reglee
   pour des nombres seuls.
   Ils passent donc en UNE colonne : chaque repere au-dessus de son libelle,
   les trois espaces egaux, lus de haut en bas comme la phrase Antes/Después
   d'a cote. La zone de valeur commune (--zone) est neutralisee ici : elle
   reserve la hauteur d'un grand nombre, ce qui creusait un vide sous les mots. */
/* LE MEME MOTIF QUE LE VOLET EQUATORIEN, qui est la reference : une grille a
   deux colonnes, la valeur en grand puis son libelle en petites capitales
   mono juste dessous, et RIEN d'autre — ni filet, ni retrait, ni cadre.
   Deux essais avant celui-la : la grille d'origine, reglee pour des nombres
   seuls, eparpillait les trois reperes en flux libre ; ma colonne unique a
   filet vert les alignait mais inventait un motif que la page n'a nulle part
   ailleurs. Le troisieme repere occupe seul la deuxieme rangee, comme l'anneau
   du volet equatorien occupe seul la sienne. */
#caso-2-pane .cases__figures {
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(26px, 2.8vw, 44px) clamp(20px, 2.4vw, 40px);
  /* align-content: start est RETIRE le 2026-08-18 : plus specifique que la
     regle commune, il empechait ce volet de repartir sa hauteur et laissait
     « Proactiva » finir 114 px au-dessus du bas de la colonne de texte. Le
     volet Ecuador, lui, n'avait pas cette surcharge et s'alignait deja. */
}
#caso-2-pane .case-fig {
  display: grid;
  gap: 6px;
  padding-left: 0;
  border-left: 0;
}
/* LA SURCHARGE D'ALIGNEMENT EST RETIREE le 2026-08-17 : min-height: 0 et
   display: block annulaient la zone de valeur partagee qui aligne le volet
   Ecuador, d'ou les 17 px de decalage mesures entre le chiffre et les mots.
   Le volet mexicain repasse sous le mecanisme commun. Ne restent ici que deux
   reglages qui ne touchent pas a l'alignement : la largeur des mots, qui n'ont
   pas a etre brides a 12 caracteres dans une colonne large, et celle des
   libelles, plus longs que ceux d'Ecuador. */
#caso-2-pane .case-fig__num--mot { max-width: none; }
#caso-2-pane .case-fig__label { max-width: 34ch; }


/* ── NUESTRO MODELO : L'ICONE PASSE A GAUCHE DU TEXTE — 2026-08-17 ────────
   Sur la reference elle n'est pas au-dessus mais A COTE, alignee sur la
   premiere ligne du titre, et nettement plus lumineuse que ce que j'avais pose.

   La carte devient une grille a deux colonnes : l'icone occupe la premiere sur
   les deux rangees, le titre et le texte la seconde. C'est ce qui garde le
   texte aligne sur lui-meme quand le titre passe sur deux lignes — un simple
   flex aurait recentre l'icone entre les deux. */
.page-nosotros #modelo .about-card {
  display: grid !important;
  grid-template-columns: auto minmax(0, 1fr);
  grid-template-rows: auto auto;
  column-gap: clamp(14px, 1.3vw, 20px);
  row-gap: 6px;
  align-items: start !important;
}
.page-nosotros #modelo .about-card__icon-wrap {
  grid-column: 1;
  grid-row: 1 / span 2;
  margin: 0 !important;
  align-self: start !important;
  width: 26px !important;
  height: 26px !important;
  /* le meme decalage optique que la reference : l'icone tombe sur la hauteur
     de x du titre, pas sur son sommet */
  margin-top: 3px !important;
}
/* Plus lumineuse : le ton plein du rouge de marque au lieu de l'encre sombre
   heritee, et l'opacite levee. Sur le fond de la carte il rend 4,35:1 — au-dela
   du seuil de 3 qui s'applique a un pictogramme, qui n'est pas du texte. */
.page-nosotros #modelo .about-card__icon-wrap svg {
  width: 26px;
  height: 26px;
  color: var(--color-primary-soft) !important;
  opacity: 1 !important;
}
.page-nosotros #modelo .about-card__title { grid-column: 2; grid-row: 1; margin: 0; }
.page-nosotros #modelo .about-card__desc  { grid-column: 2; grid-row: 2; }


/* Les libelles du volet mexicain suivent ceux du volet equatorien : petites
   capitales en mono, interlettrage ouvert. Ils s'en ecartaient parce que je
   leur avais donne une largeur de lecture de 34ch, calibree pour une phrase. */
#caso-2-pane .case-fig__label {
  margin: 0;
  max-width: 26ch;
  font-family: var(--font-mono);
  font-size: clamp(10px, 0.8vw, 12px);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  line-height: 1.4;
}


/* ══════════════════════════════════════════════════════════════════════════
   TROIS AJUSTEMENTS DU 2026-08-17 (fin de journee)
   ══════════════════════════════════════════════════════════════════════════ */

/* ── 1. LES SURTITRES DE NOSOTROS RETROUVENT LE FOND DE CEUX DE LA HOME ───
   Mesure : toutes leurs proprietes sont identiques a celles de la home, au
   pixel. Ce qui differe est ce qu'il y a DERRIERE — sur la home la pilule est
   semi-transparente et laisse passer le halo rouge de sa section, ce qui lui
   donne un fond brun sombre ; sur nosotros la section sol-0 est un noir pur et
   la pilule parait plus dure.
   On ne peut pas ajouter un halo de section sans changer la section : le voile
   rouge est donc pose DANS le fond de la pilule, ce qui reproduit exactement le
   resultat visuel. */
main > section[data-sol="0"] > .container .eyebrow,
main > section[data-sol="0"] .section-head .eyebrow {
  background:
    linear-gradient(rgba(220, 38, 38, 0.10), rgba(220, 38, 38, 0.10)),
    rgba(23, 23, 23, 0.55);
}

/* ── 2. LE LEDE DE « NUESTRO MODELO » S'EQUILIBRE SUR DEUX LIGNES ─────────
   Mesure : 124 caracteres sur la premiere ligne, 10 sur la seconde — le mot
   « capacidad. » restait seul. La ligne courait sur 1060 px sans borne.
   68ch coupe apres « operación 7×24, » et laisse « coordinadas como una sola
   capacidad. » a la seconde. La borne est en ch et non en pixels : elle suit
   la taille de police, donc la coupure reste equilibree a toutes les largeurs. */
#sistema .section-lede { max-width: 68ch; }



/* ── ESENCIA : LE MOT SE CENTRE SUR LA LARGEUR DU TEXTE ──────────────────
   « aša » et son etymologie etaient cales a gauche de leur colonne, le mot
   court laissant un vide a sa droite. Ils se centrent sur l'axe horizontal du
   bloc de texte qui les suit, donc sur la meme verticale que son milieu. */
/* LA BORNE PASSE SUR LE CONTENEUR COMMUN, et c'est le seul endroit ou elle
   donne le meme axe aux deux. Posee sur le bloc du mot, « 68ch » se calculait
   avec SA police — 52 px contre 18 pour le texte — d'ou une largeur trois fois
   trop petite : le milieu tombait 50 px a gauche au lieu de 21 a droite.
   Portee par .essence-body, la borne vaut une seule fois pour tout le monde et
   les deux centres coincident par construction. */
.page-nosotros #esencia .essence-body { max-width: 68ch; }
.page-nosotros #esencia .essence-body > p { max-width: none; }
.essence-body .essence-mark {
  align-items: center;
  text-align: center;
  max-width: none;
}

/* ── NUESTRO MODELO : L'ICONE SE CENTRE SUR LA HAUTEUR DU TEXTE ───────────
   Elle etait alignee sur la premiere ligne du titre — ce que la reference
   fait — mais sur ces cartes le bloc titre + texte est plus haut, et l'icone
   restait accrochee en haut. align-self: center la place au milieu des deux
   rangees qu'elle traverse, donc au milieu du texte.
   Le decalage optique de 3 px n'a plus lieu d'etre : il servait a la faire
   tomber sur la hauteur de x du titre. */
.page-nosotros #modelo .about-card__icon-wrap {
  align-self: center !important;
  margin-top: 0 !important;
}


/* ═══════════════════════════════════════════════════════════════════════════
   « COMO OPERAMOS » : LE RAIL DE CARTES              2026-08-17
   Reference Palo Alto, mesuree sur la capture a 1920 px de large :
     carte     609 px  →  31,7 vw
     gouttiere  37 px  →   1,93 vw
     la troisieme carte coupee nette au bord droit du viewport
     la commande (« View all → ») en haut a droite, au-dessus des cartes
   Les valeurs ci-dessous sont ces mesures ramenees en vw et bornees, pas des
   proportions estimees a l'oeil.
   ═════════════════════════════════════════════════════════════════════════ */

/* L'en-tete et la commande partagent une ligne, comme dans la reference :
   l'argument a gauche dans sa colonne de lecture, la commande alignee sur son
   bord droit. La composition en deux colonnes de la fiche 08 laisse la place
   au rail, qui a besoin de toute la largeur pour deborder. */
.oprail__top {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: clamp(24px, 3vw, 48px);
  margin-bottom: clamp(28px, 3vw, 44px);
}
.oprail__top > .operacion__head {
  flex: 1 1 420px;
  max-width: 640px;
  margin-bottom: 0;
  text-align: left;
}

/* ── LA COMMANDE ──────────────────────────────────────────────────────────
   Compteur, barre, deux fleches. Elle dit la position dans le RAIL, la seule
   progression qui soit vraie ici : la frise au-dessus compte six etapes pour
   quatre cartes, les deux ne peuvent pas partager un curseur. */
.oprail__ctrl {
  display: flex;
  align-items: center;
  gap: clamp(12px, 1.4vw, 20px);
  flex: 0 0 auto;
  padding-bottom: 4px;
}
.oprail__ctrl[hidden] { display: none; }

.oprail__count {
  margin: 0;
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: 0.12em;
  color: var(--color-muted);
  white-space: nowrap;
}
/* Le chiffre courant est en encre PLEINE, pas dans le rouge de marque :
   mesure, #DC2626 sur le sol 2 rend 3,33:1 la ou 12 px exigent 4,5. Il se
   distingue deja du total, qui reste en encre sourde. Le rouge sert la
   barre de progression, ou aucun seuil de texte ne s'applique. */
.oprail__cur { color: var(--color-fg); }
.oprail__slash { margin: 0 0.35em; opacity: 0.5; }

.oprail__bar {
  position: relative;
  width: clamp(56px, 8vw, 120px);
  height: 2px;
  background: var(--color-border-strong);
  overflow: hidden;
}
/* La barre se remplit par transform et non par width : une largeur animee
   redeclenche la mise en page a chaque image du defilement. */
.oprail__fill {
  --oprail-avance: 0;
  position: absolute;
  inset: 0;
  background: var(--color-primary);
  transform-origin: left center;
  transform: scaleX(var(--oprail-avance));
  transition: transform 120ms linear;
}

.oprail__arrows { display: flex; gap: 8px; }
.oprail__arrow {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  /* 44 px : le plancher de cible tactile du projet. */
  width: 44px;
  height: 44px;
  padding: 0;
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-full);
  background: rgba(255, 255, 255, 0.03);
  color: var(--color-fg);
  cursor: pointer;
  transition: border-color var(--duration-normal) var(--ease-out),
              background var(--duration-normal) var(--ease-out),
              opacity var(--duration-normal) var(--ease-out);
}
.oprail__arrow .icon { width: 18px; height: 18px; }
/* La fleche de gauche est la meme forme retournee : un second symbole dans le
   sprite pour un dessin miroir serait deux fois la meme matiere. */
.oprail__arrow--prev .icon { transform: scaleX(-1); }
.oprail__arrow:hover:not(:disabled) {
  border-color: var(--color-primary);
  background: rgba(220, 38, 38, 0.12);
}
.oprail__arrow:disabled { opacity: 0.32; cursor: default; }

/* ── LE RAIL ──────────────────────────────────────────────────────────────
   Il vit hors du .container pour sortir par le bord droit. Sa marge de gauche
   RECALCULE celle du container au lieu de la copier : width 100% borne a
   --container-max avec --container-px de chaque cote, donc le bord du contenu
   tombe a max(px, (100% - max) / 2 + px).
   AUCUN vw DANS CE CALCUL, ET C'EST LA RAISON D'ETRE DE LA FORMULE. Sur ce
   poste 100vw inclut la barre de defilement : le meme calcul en vw depassait
   de 8 px a droite et ajoutait une barre horizontale a la page entiere. Le
   pourcentage, lui, se mesure sur le parent, qui est deja hors barre. */
.oprail {
  --oprail-marge: max(var(--container-px),
                      calc((100% - var(--container-max)) / 2 + var(--container-px)));
}

.oprail__track {
  display: flex;
  gap: clamp(16px, 1.93vw, 37px);          /* la gouttiere mesuree */
  margin: 0;
  padding: 4px var(--oprail-marge);
  list-style: none;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;
  /* Le snapport commence a la marge, sinon la carte visee viendrait se coller
     au bord gauche de la fenetre au lieu de s'aligner sur le contenu. */
  scroll-padding-left: var(--oprail-marge);
  scrollbar-width: none;
}
.oprail__track::-webkit-scrollbar { display: none; }
.oprail__track:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 4px;
}

/* ── LA CARTE ─────────────────────────────────────────────────────────────
   Angles vifs et largeur fixe, comme la reference. Le plateau noir est celui
   des cartes de piliers et de heros : la reference a un brun orange qui n'est
   pas notre palette, et une carte sur quatre teintee de rouge, ecartee parce
   que le DS ne tient qu'une tension rouge et que les quatre moyens sont de
   meme rang.
   Le grand numero prend la place de l'image de la reference : nous n'avons pas
   d'images pour ces quatre moyens et il n'y en aura pas d'inventees. */
.opcard {
  flex: 0 0 clamp(272px, 31.7vw, 500px);   /* la largeur mesuree */
  display: flex;
  flex-direction: column;
  gap: clamp(28px, 3vw, 56px);
  min-height: clamp(300px, 24vw, 400px);
  padding: clamp(22px, 2vw, 34px);
  background: var(--color-plate);
  border: 1px solid var(--color-border-strong);
  border-radius: 0;                        /* angles vifs, comme la reference */
  scroll-snap-align: start;
}
.opcard__idx {
  font-family: var(--font-mono);
  font-size: clamp(40px, 4.2vw, 68px);
  font-weight: 500;
  line-height: 0.9;
  letter-spacing: -0.02em;
  color: var(--color-primary);
}
/* Le corps est pousse en bas : le vide se place ENTRE le numero et le texte,
   comme la reference place son blanc entre le titre et l'image. Un vide en fin
   de carte se lirait comme un manque. */
.opcard__body { margin-top: auto; }
.opcard__title {
  margin: 0 0 10px;
  font-size: clamp(17px, 1.15vw, 21px);
  font-weight: 600;
  line-height: 1.25;
  color: var(--color-fg);
}
.opcard__text {
  margin: 0;
  font-size: var(--text-sm);
  line-height: 1.6;
  color: var(--color-muted);
}

/* La frise reprend toute la largeur du container : elle n'est plus dans une
   colonne de gauche puisque la composition en deux colonnes a disparu. */
#operacion .flow { margin-bottom: clamp(28px, 3vw, 44px); }

@media (max-width: 720px) {
  .oprail__top { align-items: flex-start; }
  .oprail__ctrl { width: 100%; justify-content: flex-start; }
}

/* Le bouton des metodologias : le placement seulement. Son apparence vient
   entierement de .btn .btn-secondary .btn-pill, comme celui d'alianzas. */
/* Meme placement que .alliances__band-cta, a la valeur pres. */
.diferenciador__cta-wrap {
  display: flex;
  justify-content: center;
  margin-top: clamp(24px, 2.6vw, 40px);
}


/* ── LE FOOTER : COUVERTURE, SCEAUX, LINKEDIN        2026-08-17 ───────────── */

/* Les trois listes de pays prennent leur propre ligne sous leur libelle. Les
   <br> qui les separaient sont tombes avec la restructuration : c'est le bloc
   qui porte l'espacement, pas un saut de ligne dans le texte. */
.site-footer__coverage strong { margin-top: 12px; }
.site-footer__coverage strong:first-child { margin-top: 0; }
.site-footer__coverage span {
  display: block;
  opacity: 0.9;
}
/* La classe des deux anciennes lignes secondaires n'a plus de porteur : les
   trois blocs sont desormais de meme rang, ce qui etait le sens de la demande. */

.site-footer__badges { gap: 12px; }

/* Le glyphe LinkedIn etait dans un cercle de 36 px avec un dessin de 16 : a
   cette taille il ne se lisait pas comme un logo. Le cercle passe au plancher
   de cible tactile de 44 px et le glyphe a 20. */
.site-footer .social-icons { gap: 10px; margin-top: var(--space-5); }
/* IL N'ETAIT PAS PETIT, IL ETAIT INVISIBLE, et c'est la mesure du footer qui
   le dit : le fond y est clair, alors que .social-icon declare
   color: var(--color-fg), c'est-a-dire le #F8FAFC du systeme. Un glyphe blanc
   sur un fond blanc. Sa bordure, prise dans --color-border-strong, est un blanc
   translucide : invisible aussi. Le meme piege que le bouton des metodologias,
   au meme endroit du raisonnement — une variable d'encre lue hors de son sol.
   Le footer n'est pas une <section data-sol>, donc aucune regle de sol ne venait
   la corriger : l'encre est donc posee ici, explicitement.
   #101010 sur le fond clair rend 18,9:1, la bordure sombre a 12 % se voit sans
   peser. */
.site-footer .social-icon {
  width: 44px;
  height: 44px;
  color: var(--color-fg-light);
  border-color: rgba(16, 16, 16, 0.18);
}
.site-footer .social-icon:hover {
  color: var(--color-primary);
  border-color: var(--color-primary);
}
.site-footer .social-icon .icon { width: 20px; height: 20px; }

/* Le bleu et le violet des libelles « En desarrollo » et « Centro de monitoreo »
   sont retires le 2026-08-18. Les trois retombent sur la regle commune, deja en
   --color-primary-deep : on retire au lieu de reposer du rouge, pour ne pas
   maintenir la meme couleur a deux endroits. */


/* ── ALIANZAS : LA RANGEE FIXE                       2026-08-17 ───────────── */

/* Les deux pistes qui defilaient deviennent deux rangees centrees. La base des
   cartes est bornee en pourcentage ET en pixels : le pourcentage tient les cinq
   logos sur une seule ligne aux grandes largeurs, le plancher de 120 px les fait
   passer a deux par ligne sur telephone au lieu d'une seule, ce qui evite une
   colonne de cinq lignes. */
.alliances__row {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: clamp(14px, 1.4vw, 24px);
}
.alliances__row .alliance-card {
  flex: 0 1 clamp(120px, 18%, 232px);
}
/* Le survol garde son elevation : c'est le seul mouvement de la section
   maintenant que le defilement est parti, et il repond a une intention. */


/* ── LE HEROS S'ALLUME AUSSI QUAND ON LE SURVOLE LUI-MEME    2026-08-17 ────
   Reciproque de l'effet pose sur les boutons de la constellation, avec les
   MEMES valeurs d'arrivee : opacite pleine, filtre neutre, halo a 1,12.

   DEUX REGLES POUR SIX PERSONAS, ET C'EST LA DIFFERENCE DE NATURE ENTRE LES
   DEUX SENS. Allumer une figure depuis son bouton demande de nommer le persona
   des deux cotes du :has(), donc six blocs et vingt-quatre selecteurs. Ici la
   cible EST l'element survole : le persona n'a pas a etre nomme, la variable
   --p de la figure fait deja le reste.

   La transition est deja declaree sur l'etat de repos quelques lignes plus
   haut, donc le retour se fait en fondu et pas d'un coup.

   LE CURSEUR EST DEVENU UNE MAIN le 2026-08-18 : ces figures menent desormais
   a leur section. Le commentaire disait ici l'inverse — « un curseur de main
   promettrait un clic qui n'existe pas » — et c'etait juste tant que le clic
   n'existait pas. Maintenant qu'il existe, l'absence de curseur le cacherait. */
.liga-row__fig:hover img {
  opacity: 1;
  filter: none;
}
.liga-row__fig:hover::before {
  opacity: 1;
  transform: translateX(-50%) scale(1.12);
}

/* ── ET IL FAUT ENCORE QUE LE POINTEUR ARRIVE JUSQU'AUX HEROS ──────────────
   La regle de survol ci-dessus ne servait a rien telle quelle, et le test l'a
   dit avant l'oeil : « .container.page-hero__inner intercepts pointer events ».
   Le bloc de texte de la hero est un calque pose PAR-DESSUS les figures et il
   couvre toute la section, y compris ses zones vides. La souris ne touchait
   donc jamais un heros, quelle que soit la regle de :hover.

   Le passage est ouvert de la seule facon qui ne coute rien : le CONTENEUR
   cesse de capter le pointeur, ses enfants directs le captent a nouveau. Les
   zones vides laissent passer vers les figures, et le titre, le lede, les six
   boutons et les deux CTA restent cliquables et selectionnables comme avant.
   Un pointer-events: none pose sans le rendre aux enfants aurait rendu la hero
   entierement inerte.

   Les figures vivent dans .page-hero__bg, un decor en aria-hidden : elles
   reprennent le pointeur une par une, pas tout le fond, pour que les trois
   calques de halo et de grille restent transparents au pointeur. */
.page-hero--liga .page-hero__inner { pointer-events: none; }
/* SEULS LES ELEMENTS INTERACTIFS REPRENNENT LE POINTEUR. Une premiere version le
   rendait a tous les enfants directs : le titre et le lede, qui occupent toute
   la largeur de leur colonne meme la ou ils n'ont pas de glyphe, formaient un mur
   devant les heros. Mesure, quatre a cinq figures sur six n'avaient plus aucun
   point atteignable.
   Le surtitre, le titre et le lede sont du texte pur, sans lien ni champ : ils
   n'ont pas besoin du pointeur. Ils cessent en revanche d'etre selectionnables a
   la souris, et c'est le prix assume de heros cliquables sur toute leur surface. */
.page-hero--liga .liga-constellation,
.page-hero--liga .page-hero__actions { pointer-events: auto; }
.page-hero--liga .liga-row__fig { pointer-events: auto; }


/* ── ALIANZAS SUR NOSOTROS : EN-TETE CENTRE ET QUATRE PHARES   2026-08-17 ── */

/* L'en-tete de cette seule section passe au centre. Le filet d'ouverture, lui,
   reste pleine largeur : il marque le debut de section, il ne suit pas le texte. */
/* C'EST LE HEADER QU'IL FAUT CENTRER, PAS SON CONTENU, et la mesure le dit
   sans ambiguite : le header porte max-width: min(100%, 1060px) avec des marges
   a zero, donc il se cale a gauche d'un conteneur de 1760 px. Le titre etait
   deja centre A L'INTERIEUR de ce header (20 px de marge de chaque cote), mais
   le header entier tombait 286 px a gauche de l'axe de la page. Centrer le
   texte une deuxieme fois n'aurait rien change ; c'est la boite qui devait se
   deplacer. */
.page-nosotros #alianzas .section-head--rail {
  text-align: center;
  margin-inline: auto;
}
.page-nosotros #alianzas .section-head--rail .section-title,
.page-nosotros #alianzas .section-head--rail .section-lede {
  margin-inline: auto;
}
.page-nosotros #alianzas .alliances__tier-label { text-align: center; }

.fantastic4 { margin-bottom: clamp(36px, 3.6vw, 60px); }

/* Quatre plaques egales. auto-fit avec un plancher de 150 px : quatre de front
   au-dela de 760 px environ, deux par deux en dessous, jamais une colonne de
   quatre logos ecrases. */
.fantastic4__row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: clamp(14px, 1.6vw, 26px);
  margin: 0;
  padding: 0;
  list-style: none;
}
.fantastic4__item {
  display: flex;
  align-items: center;
  justify-content: center;
  /* Un rapport fixe donne quatre plaques identiques quel que soit le format du
     logo : Netskope est empile (rapport 2,45), CrowdStrike est en ligne (5,48).
     Sans rapport impose, la rangee aurait quatre hauteurs differentes. */
  aspect-ratio: 16 / 9;
  padding: clamp(14px, 1.4vw, 22px);
  background: #F8FAFC;
  border: 1px solid rgba(16, 16, 16, 0.10);
  border-radius: var(--radius-md);
  transition: border-color var(--duration-normal) var(--ease-out),
              box-shadow var(--duration-normal) var(--ease-out),
              translate var(--duration-normal) var(--ease-out);
}
/* Le survol reprend le geste des autres cartes de la page : filet qui s'affirme
   et 2 px d'elevation. translate en !important parce que le reveal GSAP pose
   translate ET transform en inline sur ces elements. */
.fantastic4__item:hover {
  border-color: rgba(220, 38, 38, 0.50);
  box-shadow: 0 12px 30px rgba(0, 0, 0, 0.28);
  translate: 0 -2px !important;
}
/* contain, et les deux bornes : le logo ne depasse ni en hauteur ni en largeur,
   et garde de l'air autour. 84 % de large et 62 % de haut donnent aux quatre un
   poids optique comparable malgre des rapports allant de 2,45 a 5,48. */
.fantastic4__logo {
  max-width: 84%;
  max-height: 62%;
  width: auto;
  height: auto;
  object-fit: contain;
  /* Aucun filtre : ce sont les couleurs officielles des marques. */
  filter: none;
}
@media (prefers-reduced-motion: reduce) {
  .fantastic4__item { transition: none; }
  .fantastic4__item:hover { translate: none !important; }
}


/* ── LE LOGO NETSKOPE RETROUVE SON POIDS OPTIQUE      2026-08-17 ───────────
   Les cinq fichiers font 120 px de haut, mais leurs rapports vont de 2,33
   (Netskope) a 5,21 (CrowdStrike). La regle commune borne la hauteur a 44 px
   et la largeur a 82 % : a 44 px, Netskope occupe 103 x 44, soit 4 500 px²,
   quand CrowdStrike bute sur la largeur a 200 x 38, soit 7 600. Un rapport de
   1 a 1,7, et c'est ce que l'oeil voyait.
   58 px de haut lui rendent 135 x 58, soit 7 800 px² : comparable aux autres.
   La correction ne vise que lui — relever la borne commune aurait fait grossir
   quatre logos qui sont deja a la bonne taille. */
.partner-level[data-brand="netskope"] .partner-level__logo {
  /* LA TAILLE EST EN POURCENTAGE, PAS EN PIXELS, et c'est ce qui la rend stable.
     Une premiere version bornait sa hauteur a 58 px : les quatre autres logos
     etant bornes par une LARGEUR de 82 % de la plaque, les deux ne suivaient pas
     la meme reference et l'ecart de surface variait avec la fenetre — 16 % a
     1920, 63 % a 1100, ou Netskope devenait le plus gros des cinq.
     Exprimee en pourcentage de la meme plaque, sa taille suit exactement la
     leur. Le calcul du 58 % : a 82 % de large, les autres ont un rapport moyen
     de 4,7, donc une surface de 0,143 P² ; Netskope a un rapport de 2,33, donc
     0,429 x² P². L'egalite donne x = 0,577.
     max-height: none est indispensable : la borne commune de 44 px
     l'ecraserait avant que le pourcentage ne joue. */
  width: 58%;
  max-width: 58%;
  /* DEUX BORNES, PARCE QU'IL Y A DEUX REGIMES. Sur plaque etroite c'est la
     largeur qui limite les cinq logos, et le 58 % suffit. Sur plaque large les
     quatre autres butent sur la borne commune de 44 px de haut : leur surface
     se fige a environ 9 100 px², et Netskope sans borne montait a 23 000, soit
     57 % d'ecart mesure a 900 px. 62 px lui donnent 145 x 62, soit 9 000 px² :
     l'equivalence tient dans les deux regimes. */
  max-height: 62px;
}


/* ── LES QUATRE CARTES DE « COMO OPERAMOS » PRENNENT LEUR PHOTO   2026-08-17 ──
   L'image est DANS la carte et non derriere la section, donc elle passe sous le
   texte : les 20 % d'opacite qui suffisent a #soluciones et #razones, ou l'image
   vit loin du texte, seraient ici illisibles.
   Deux couches, chacune son role :
     ::before  la photo a 30 %, assez pour se lire comme une photo ;
     ::after   un degrade noir monte depuis le BAS, la ou le corps de la carte
               est pousse par son margin-top: auto — dense sous le texte,
               presque transparent en haut ou il n'y a que le grand numero.
   Un voile uniforme aurait eteint l'image partout pour ne servir qu'en bas. */
.opcard {
  position: relative;
  overflow: hidden;
  isolation: isolate;
}
.opcard::before,
.opcard::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
}
.opcard::before {
  background-size: cover;
  background-position: center;
  opacity: 0.42;
  transition: opacity var(--duration-normal) var(--ease-out);
}
.opcard::after {
  /* Le bas garde sa densite — c'est lui qui porte le texte — et le haut
     s'ouvre : 0,22 -> 0,08 au sommet, 0,55 -> 0,38 aux deux tiers. */
  background: linear-gradient(to top,
              rgba(0, 0, 0, 0.92) 0%,
              rgba(0, 0, 0, 0.82) 34%,
              rgba(0, 0, 0, 0.38) 62%,
              rgba(0, 0, 0, 0.08) 100%);
}
/* Le contenu passe devant les deux couches. */
.opcard__idx,
.opcard__body {
  position: relative;
  z-index: 1;
}
/* Au survol la photo s'affirme un peu : c'est le meme geste que le filet qui
   se colore, pas un effet de plus. */
.opcard:hover::before { opacity: 0.55; }

.opcard[data-bg="oficina"]::before    { background-image: url('../assets/images/bg/operamos/oficina.webp'); }
.opcard[data-bg="ingenieria"]::before { background-image: url('../assets/images/bg/operamos/ingenieria.webp'); }
.opcard[data-bg="tecnologia"]::before { background-image: url('../assets/images/bg/operamos/tecnologia.webp'); }
.opcard[data-bg="api"]::before        { background-image: url('../assets/images/bg/operamos/api.webp'); }

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

/* LE CENTRAGE EST ANNULE, et la mesure dit pourquoi. Centrer le bloc entier
   dans sa colonne faisait commencer « Proactiva » a 63 px du bord de son bloc
   quand « −30-40% », juste au-dessus, commence a 0 : le mot flottait, d'autant
   plus qu'il est seul sur sa ligne.
   Ce qui tient cette grille, c'est le bord gauche commun — les trois blocs
   mexicains et les quatre d'Ecuador partagent la meme verticale. Le mot et son
   libelle partent donc du meme bord, comme un chiffre et le sien. */
#caso-2-pane .case-fig--mot { text-align: start; }

/* Les cartes n'ont plus de numero depuis le 2026-08-17 : la photographie en
   fond a pris le role d'element graphique qu'il tenait, et deux reperes
   visuels dans la meme carte se disputaient l'attention.
   Le corps reste pousse en bas — c'est lui qui doit rester sur la partie dense
   du voile — et le haut de la carte s'ouvre desormais sur l'image. */
.opcard__idx { display: none; }

/* ── LES REPERES DE CAS SE CALENT EN HAUT           2026-08-18 ─────────────
   Trois etats successifs, et c'est la mesure qui a tranche :
     1. sans rien, le bloc finissait 114 px au-dessus du bas de la carte de
        gauche — il prenait la hauteur de son seul contenu ;
     2. avec align-content: space-between, les bases s'alignaient a 1440 mais a
        1920 le dernier repere DEPASSAIT la limite de 23 px : space-between
        repartit l'espace disponible et laisse deborder quand le contenu est plus
        haut que lui. La reserve en pied ajoutee pour « remonter » le bloc
        aggravait ce debordement ;
     3. cale en haut, le bloc remonte au maximum et ne franchit jamais la ligne
        du bas de la carte de gauche — sa hauteur naturelle est inferieure a
        celle de la colonne de texte de 1024 a 1920, verifie.
   L'alignement des hauts et des bases par ligne ne depend pas de align-content
   mais de align-items: start et de la zone de valeur a hauteur fixe : il tient. */
.cases__pane .cases__figures {
  align-self: start;
  align-content: start;
}

/* ── #problema : LE LEDE SE RAPPROCHE DU TITRE        2026-08-18 ───────────
   A SIGNALER : les 14 px mesures ici sont l'ecart STANDARD du site — versus et
   sistema affichent la meme valeur au pixel. Ce resserrement est donc une
   divergence assumee sur cette seule section, a la demande de Gabriel, et non
   la correction d'une anomalie. Si le meme rapprochement est voulu partout,
   c'est la marge commune qu'il faudra changer, pas cette regle. */
#problema .section-head .section-title { margin-bottom: 16px; }
#problema .section-head .section-lede { margin-top: 0; margin-bottom: 2px; }
#problema .section-head .section-lede + .section-lede { margin-top: 2px; }

/* « Proactiva » remonte : l'alignement exact sur le bas de la colonne de texte,
   pose plus tot, le descendait trop bas a l'oeil. La repartition reste
   space-between — ce qui aligne haut et bas — mais la colonne garde une reserve
   en pied, donc la derniere ligne remonte d'autant sans decrocher le haut. */
/* La reserve en pied est retiree : elle poussait le bloc vers le bas alors que
   la consigne est qu'il ne depasse pas la carte de gauche. */

/* ── LES TROIS ICONES DE « NUESTRO MODELO » DEVIENNENT DES SCENES  2026-08-18 ──
   Elles etaient trois pictogrammes abstraits a 24 px dans une plaquette de 48 :
   un curseur de reglage, une medaille, une liste cochee. La reference fournie
   dessine des scenes — une main qui porte un groupe, une rosette a rubans, une
   tete avec un cerveau — a trait fin et en grand.
   Le dessin gagne en detail (trait 1,4 au lieu de 1,6, plusieurs traces par
   icone) et la plaquette passe de 48 a 56 px pour un glyphe de 30 : la
   reference monte a ~90, mais la rangee de trois cartes ne le supporterait pas
   sans se reorganiser. */
/* LA TAILLE DOIT PASSER PAR !important, ET C'EST LA TROISIEME COUCHE SUR CES
   ICONES. La derniere en place impose 26 px en !important, avec l'icone placee
   a GAUCHE du texte — la disposition demandee sur une reference precedente. Une
   regle sans !important, meme ecrite plus bas, restait sans effet : mesure,
   la plaquette faisait 26 px et mon glyphe de 30 debordait.

   36 ET NON 90. La reference affiche ses scenes a environ 90 px, mais elle les
   pose AU-DESSUS d'un texte centre. Ici l'icone occupe la premiere colonne d'une
   grille a deux colonnes : la porter a 90 px repousserait le titre et le
   paragraphe sur un tiers de la carte. 36 px est le point ou le detail de ces
   traces se lit sans reorganiser la carte. Si les grandes icones de la
   reference sont voulues telles quelles, c'est la disposition qu'il faut
   reprendre, pas seulement la taille. */
.page-nosotros #modelo .about-card__icon-wrap {
  width: 36px !important;
  height: 36px !important;
}
.page-nosotros #modelo .about-card__icon-wrap svg {
  width: 36px !important;
  height: 36px !important;
  stroke-width: 1.4;
}

/* ── LES QUATRE CARTES DE « AREAS DE CARRERA » PRENNENT LA PLAQUE ROUGE ─────
   Elles etaient sur un aplat gris opaque rgb(43,43,43) avec un filet blanc a
   8 % : rien ne les rattachait au reste du site. Elles reprennent la plaque de
   .versus__col--us, celle de la reference — memes declarations, pas des valeurs
   approchantes.
   Le fond reste semi-transparent, donc la plaque prend le sol de SA section
   (sol-1, plus sombre que le sol-2 de la reference). C'est voulu : un aplat
   opaque se serait detache de sa bande. */
#areas .about-card {
  --plq: var(--color-primary);
  border: 1px solid color-mix(in srgb, var(--plq) 42%, transparent);
  background:
    linear-gradient(180deg,
      color-mix(in srgb, var(--plq) 14%, transparent),
      color-mix(in srgb, var(--plq) 6%, transparent)),
    rgba(23, 23, 23, 0.55);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.06),
    0 0 0 1px color-mix(in srgb, var(--plq) 8%, transparent),
    0 12px 32px -16px color-mix(in srgb, var(--plq) 35%, transparent);
  transition: border-color var(--duration-normal) var(--ease-out),
              box-shadow var(--duration-normal) var(--ease-out),
              translate var(--duration-normal) var(--ease-out);
}
/* Le survol reprend le geste des autres cartes du site : le filet s'affirme et
   la carte se souleve de 2 px. translate en !important, comme partout, parce
   que le reveal GSAP pose translate ET transform en inline. */
#areas .about-card:hover {
  border-color: color-mix(in srgb, var(--plq) 62%, transparent);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.10),
    0 0 0 1px color-mix(in srgb, var(--plq) 14%, transparent),
    0 16px 38px -14px color-mix(in srgb, var(--plq) 45%, transparent);
  translate: 0 -2px !important;
}
@media (prefers-reduced-motion: reduce) {
  #areas .about-card { transition: none; }
  #areas .about-card:hover { translate: none !important; }
}

/* ── #csirt-form : LA CARTE D'INFORMATION SUIT LE FORMULAIRE   2026-08-18 ───
   Mesure : la carte fait 545 px de haut, le formulaire 1 690. La grille etant
   en align-items: start, elle restait en haut avec ~1 100 px de vide dessous.
   Collante, l'adresse et le telephone restent sous les yeux pendant qu'on
   remplit les quatorze champs — ce qui est leur seule raison d'etre a cet
   endroit.
   AU-DELA DE 960 PX SEULEMENT : en dessous la grille passe en une colonne, et
   une carte collante y recouvrirait le formulaire. */
@media (min-width: 960px) {
  .contact-grid > .contact-info {
    position: sticky;
    top: calc(var(--header-h) + var(--subnav-h, 0px) + 16px);
  }
}

/* « Paises cubiertos » portait .eyebrow, la classe des surtitres de SECTION :
   il y avait donc deux surtitres de section dans la meme section, dont un dans
   une carte. Meme apparence, classe qui lui appartient. */
.contact-info__countries .contact-info__countries-label {
  display: inline-block;
  margin-bottom: var(--space-2);
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--color-primary-soft);
}

/* Les figures de la hero sont cliquables : le curseur doit le dire. */
.page-hero--liga .liga-row__fig[data-persona] { cursor: pointer; }

/* ── #csirt-form : L'EN-TETE PASSE A DROITE            2026-08-18 ──────────
   Le header est borne a min(100%, 1060px) dans un conteneur de 1760 : cale a
   gauche par defaut, il laissait 700 px de vide a sa droite. margin-inline-start
   auto le pousse contre le bord droit du contenu, et text-align: right y range
   le surtitre comme le titre — sans quoi la pilule serait restee seule a gauche
   d'un bloc aligne a droite.
   C'est la meme lecon que l'en-tete d'alianzas : ce qui deplace un bloc borne,
   c'est sa marge, pas l'alignement de son texte. Ici il faut les deux, parce que
   le bloc ET son contenu doivent bouger. */
/* CHAQUE SECTION EST VISEE PAR SON ID. La regle precedente visait
   .contact-section, une classe que PORTENT LES DEUX sections : #bolsa-form a
   donc pris l'alignement a droite sans que personne ne l'ait demande. Meme
   faute qu'une cle i18n partagee — une portee trop large qui atteint un second
   endroit par accident. */
#csirt-form .section-head {
  margin-inline-start: 0;
  margin-inline-end: auto;
  text-align: left;
}
#csirt-form .section-head .eyebrow { margin-inline: 0; }
#bolsa-form .section-head {
  margin-inline: auto;
  text-align: center;
}
#bolsa-form .section-head .eyebrow { margin-inline: auto; }
#bolsa-form .section-head .section-title,
#bolsa-form .section-head .section-lede { margin-inline: auto; }

/* ── #csirt-form : LA SECTION PASSE AU BLEU DU CSIRT     2026-08-18 ─────────
   Les variables sont redefinies dans la portee de la section : tout ce qui
   demande var(--color-primary) ici — pilule du surtitre, accent du titre,
   numeros d'etape, intitules de groupe, bouton d'envoi, liens — suit sans qu'on
   le repeigne un par un. C'est aussi ce qui garantit qu'aucun element n'est
   oublie, et que ceux qu'on ajoutera demain seront bleus eux aussi.
   Le bleu retenu est celui du CSIRT, l'equipe dont cette section parle. */
/* #csirt-form ET NON .contact-section : cette classe est portee aussi par
   #bolsa-form, qui s'est retrouve repeint en cyan sans que personne ne l'ait
   demande. Troisieme fuite par cette meme classe, apres l'alignement. */
#csirt-form {
  --color-primary: var(--color-csirt);
  --color-primary-deep: var(--color-csirt-ink);
  --color-primary-soft: var(--color-csirt-soft);
  --color-primary-lift: var(--color-csirt-soft);
  --plq: var(--color-csirt);
}
/* Le liseré de la carte revient au bleu : il l'avait ce matin, je l'avais passe
   au rouge pour l'accorder a la section, et c'est la section qui bascule. */
#csirt-form .contact-info { border-top-color: var(--color-csirt); }

/* Les valeurs ECRITES EN DUR ne suivent pas une variable : celles-la doivent
   etre reprises nommement. Le rouge #DC2626 vaut rgb(220,38,38) — on cherche
   donc ses ecritures rgba() dans cette section. */
#csirt-form .csirt-form__step-num,
#csirt-form .csirt-form__group-title,
#csirt-form .form-group__num {
  color: var(--color-csirt) !important;
}

/* Le bouton plein de cette section porte desormais un aplat CYAN, bien plus
   lumineux que le rouge : son encre claire rendait 2,32:1 pour un seuil de 4,5.
   Un aplat clair demande une encre sombre — #101010 sur #06B6D4 donne 7,8:1.
   -webkit-text-fill-color avec, parce qu'il bat color pour le rendu du glyphe. */
#csirt-form .btn-primary,
#csirt-form .btn-primary span,
#csirt-form .csirt-form__submit,
#csirt-form button[type="submit"] {
  color: #101010 !important;
  -webkit-text-fill-color: #101010 !important;
}
#csirt-form .btn-primary .icon,
#csirt-form .csirt-form__submit .icon,
#csirt-form button[type="submit"] .icon { color: #101010 !important; }

/* ── #brief : LE CONTENU REVIENT A LA MARGE DU SITE      2026-08-18 ─────────
   Mesure : son contenu commencait a 564 px quand toutes les autres sections
   commencent a 144 — 420 px de decalage vers le milieu, parce que son conteneur
   est borne bien plus etroit que le container standard et se centre.
   On lui rend la largeur commune et l'alignement a gauche. Le lede garde une
   borne de lecture : c'est la largeur du texte qui doit etre limitee, pas la
   colonne qui le porte. */
/* Le conteneur n'a plus besoin d'etre force : il portait un
   style="max-width: 920px" EN INLINE, qui battait toute regle de la feuille.
   Le style est parti du HTML, .container reprend donc ses valeurs communes et il
   n'y a rien a redeclarer ici. */
#brief .section-head,
#brief .section-head > * {
  margin-inline-start: 0;
  margin-inline-end: 0;
  text-align: left;
}
#brief .section-lede { max-width: 68ch; }

/* Les deux boutons RFC 2350 se rangent a gauche, sous le lede, comme tout le
   contenu de cette section desormais. */
#brief .rfc-row {
  justify-content: flex-start;
  margin-inline: 0;
}


/* ── #bolsa-form : L'EN-TETE A GAUCHE, LA PHOTO A DROITE   2026-08-18 ───────
   Le centrage pose plus tot est annule : Gabriel le veut a gauche, comme le
   reste du site. La photo prend la colonne de droite.
   La colonne de texte passe en premier dans la grille ET dans le HTML : c'est ce
   qui donne le meme ordre a l'oeil et a la lecture d'ecran, sans avoir a jouer
   sur order. */
.bolsa-top {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: clamp(24px, 2.6vw, 40px) clamp(32px, 4.2vw, 80px);
  /* STRETCH ET NON CENTER : la photo doit monter sur toute la hauteur de la
     colonne de gauche — en-tete plus formulaire — et non se centrer sur elle. */
  align-items: stretch;
  /* LA GRILLE EST BORNEE, PAS LA PHOTO. Borner la photo aurait laisse 336 px de
     vide a sa droite a 1920 ; borner la grille reduit la colonne de droite sans
     creer de trou, puisque le bloc se termine ou la photo se termine. Effet de
     bord bienvenu : la largeur de la photo devient stable — 424 px a 1920, 388 a
     1360 — la ou elle variait du double. */
  /* 1400 et non 1300 : apres les 820 px du formulaire et les 80 de gouttiere,
     il reste 500 px pour la photo, soit 750 de haut en 2:3 — la hauteur du
     formulaire a 8 px pres. */
  max-width: 1400px;
  margin-bottom: clamp(32px, 3.6vw, 60px);
}
/* Les trois enfants sont places nommement : c'est ce qui permet a la photo de
   partager la ligne du formulaire et rien d'autre. */
.bolsa-top > .section-head { grid-column: 1; grid-row: 1; }
.bolsa-top > form { grid-column: 1; grid-row: 2; min-width: 0; }
.bolsa-top > .bolsa-photo { grid-column: 2; grid-row: 2; }
@media (min-width: 1360px) {
  /* 820 px est la largeur que le formulaire avait avant que son style inline
     ne soit retire, et Gabriel la juge bonne. C'est un MAXIMUM, pas une
     largeur fixe : sous 1024 px la colonne se comprime au lieu d'ecraser la
     photo, qui garde un plancher de 260 px. */
  .bolsa-top { grid-template-columns: minmax(0, 820px) minmax(260px, 1fr); }
}
#bolsa-form .bolsa-top .section-head {
  margin-inline: 0;
  text-align: left;
  max-width: 62ch;
}
#bolsa-form .bolsa-top .section-head .eyebrow,
#bolsa-form .bolsa-top .section-head .section-title,
#bolsa-form .bolsa-top .section-head .section-lede { margin-inline: 0; }

/* Le cadre est en 4:5 et l'image le remplit : le master est en 16:9, un contain
   y aurait laisse deux bandes vides. */
.bolsa-photo {
  margin: 0;
  overflow: hidden;
  border-radius: var(--radius-lg);
  border: 1px solid var(--color-border-strong);
}
/* LE RAPPORT 4:5 VAUT A TOUTES LES LARGEURS DESORMAIS. Etiree sur la hauteur du
   formulaire, la photo faisait 742 px pour 424 de large — un rapport de 0,57 la
   ou l'image est cadree en 0,8 : cover coupait donc du haut et du bas, et c'est
   ce qui la faisait paraitre trop haute.
   A son rapport, elle tombe a 530 px pour 424 de large et retrouve les
   proportions dans lesquelles elle a ete recadree. */
/* 2:3, le rapport du 35 mm : celui dans lequel un portrait se cadre par
   defaut, et il laisse moins de vide sous la photo que le 4:5 — 106 px
   contre 212 face a un formulaire de 742. */
.bolsa-photo { aspect-ratio: 2 / 3; }
@media (min-width: 1360px) {
  /* CENTREE sur le formulaire : son milieu tombe sur celui du formulaire, ce que
     align-self: start ne faisait pas — il la calait sur le bord haut. */
  .bolsa-photo { align-self: center; }
}
.bolsa-photo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 32%;   /* le visage est dans le tiers haut */
  display: block;
}
/* Sous 900 px la photo passe sous le texte : en portrait plein cadre elle
   prendrait tout l'ecran, on la borne et on la centre. */
/* Sous 1360 px la photo passe sous le texte : en portrait plein cadre elle
   prendrait tout l'ecran, on la borne et on la centre. */
@media (max-width: 1359px) {
  .bolsa-photo { max-width: 300px; margin-inline: auto; }
}

/* ── #bolsa-form PASSE AU BLEU AUSSI                   2026-08-18 ──────────
   Meme dispositif que #csirt-form : les variables sont redefinies dans la portee
   de la section, donc surtitre, accent du titre, numeros d'etape, intitules de
   groupe, bouton d'envoi et liens suivent sans etre repeints un par un.
   ECRIT POUR CET ID ET NON POUR LA CLASSE PARTAGEE : .contact-section, que
   portent les deux sections, a deja fait fuiter trois regles aujourd'hui. Deux
   blocs qui se ressemblent valent mieux qu'un selecteur qui atteint une section
   non demandee. */
#bolsa-form {
  --color-primary: var(--color-csirt);
  --color-primary-deep: var(--color-csirt-ink);
  --color-primary-soft: var(--color-csirt-soft);
  --color-primary-lift: var(--color-csirt-soft);
  --plq: var(--color-csirt);
}
#bolsa-form .csirt-form__step-num,
#bolsa-form .csirt-form__group-title,
#bolsa-form .form-section__num,
#bolsa-form .form-group__num {
  color: var(--color-csirt) !important;
}
/* Le bouton plein prend un aplat cyan, bien plus lumineux que le rouge : son
   encre claire rendrait 2,32:1 pour un seuil de 4,5. Meme correction que sur
   contacto — encre sombre, 7,8:1. */
#bolsa-form .btn-primary,
#bolsa-form .btn-primary span,
#bolsa-form .csirt-form__submit,
#bolsa-form button[type="submit"] {
  color: #101010 !important;
  -webkit-text-fill-color: #101010 !important;
}
#bolsa-form .btn-primary .icon,
#bolsa-form .csirt-form__submit .icon,
#bolsa-form button[type="submit"] .icon { color: #101010 !important; }

/* Sous 1360 px la grille n'a qu'une colonne : les placements nommes ci-dessus
   y laisseraient la photo accrochee a la ligne du formulaire, donc a cote de
   rien. On les libere et l'ordre du HTML reprend la main. */
@media (max-width: 1359px) {
  .bolsa-top > .section-head,
  .bolsa-top > form,
  .bolsa-top > .bolsa-photo { grid-column: auto; grid-row: auto; }
}

/* ── LA PHOTO DE BOLSA PREND L'ANIMATION DES CARTES D'INDUSTRIES  2026-08-18 ──
   Meme geste que .industry-card : l'image se rapproche de 4 % au survol et une
   equerre marque son coin bas gauche.
   L'equerre demande var(--color-primary), que cette section redefinit en cyan :
   elle est donc bleue sans qu'on l'ecrive, et suivrait un autre changement de
   couleur de section sans retouche. */
.bolsa-photo { position: relative; }
.bolsa-photo img {
  transition: transform var(--duration-slow) var(--ease-out);
}
.bolsa-photo:hover img { transform: scale(1.04); }
.bolsa-photo::after {
  content: '';
  position: absolute;
  bottom: 12px;
  left: 12px;
  width: 36px;
  height: 36px;
  border-bottom: 2px solid var(--color-primary);
  border-left: 2px solid var(--color-primary);
  z-index: 2;
  opacity: 0.6;
  transition: opacity var(--duration-normal) var(--ease-out);
  pointer-events: none;
}
.bolsa-photo:hover::after { opacity: 1; }
/* LES DEUX GESTES QUI MANQUAIENT. .industry-card:hover ne fait pas que reveler son
   equerre et rapprocher son image : son filet s'affirme et une ombre se creuse
   sous elle. Sans eux, l'equerre apparaissait sur un cadre immobile.
   Les valeurs sont celles de la carte, avec la couleur de la section — donc le
   cyan ici, et non le rouge ecrit en dur dans la regle d'origine. */
.bolsa-photo {
  transition: border-color var(--duration-normal) var(--ease-out),
              box-shadow var(--duration-normal) var(--ease-out);
}
.bolsa-photo:hover {
  border-color: color-mix(in srgb, var(--color-primary) 55%, transparent);
  box-shadow: 0 16px 40px rgba(0, 0, 0, 0.40),
              0 0 32px color-mix(in srgb, var(--color-primary) 18%, transparent);
}
@media (prefers-reduced-motion: reduce) {
  .bolsa-photo { transition: none; }
}
@media (prefers-reduced-motion: reduce) {
  .bolsa-photo img { transition: none; }
  .bolsa-photo:hover img { transform: none; }
}

/* ── CASOS DE EXITO : LE CTA DEVIENT UN BOUTON PLEIN VERT   2026-08-18 ──────
   Il n'etait qu'un texte suivi d'une fleche. Il prend la forme de
   « Hablar con un experto » — pilule a aplat plein — avec le vert de la section.
   L'ENCRE EST SOMBRE, ET C'EST MESURE : le vert #22C55E est bien plus lumineux
   que le rouge, l'encre claire du systeme y rendrait environ 1,9:1 pour un seuil
   de 4,5 a 16 px. #101010 donne environ 9:1. Meme piege que sur les aplats cyan
   de contacto et de bolsa, pris d'emblee cette fois. */
#casos-exito .section-cta {
  padding: 14px 28px;
  border-radius: var(--radius-full);
  background: var(--color-grc);
  border: 1px solid var(--color-grc);
  color: #101010 !important;
  -webkit-text-fill-color: #101010 !important;
  font-size: var(--text-base);
  font-weight: 600;
  letter-spacing: -0.01em;
  white-space: nowrap;
  transition: background var(--duration-normal) var(--ease-out),
              box-shadow var(--duration-normal) var(--ease-out);
}
#casos-exito .section-cta .icon { color: #101010 !important; }
#casos-exito .section-cta:hover {
  background: color-mix(in srgb, var(--color-grc) 84%, #000);
  box-shadow: 0 0 24px color-mix(in srgb, var(--color-grc) 42%, transparent);
}
/* Le soulignement anime que portait le lien n'a plus de sens sur un aplat. */
#casos-exito .section-cta::after { display: none; }

/* ── LES REPERES DE CAS FORMENT ENFIN UNE GRILLE      2026-08-22 ──────────
   ══════════════════════════════════════════════════════════════════════════
   Gabriel : « la partie a droite ou il y a les numeros flotte partout, rien
   n'est aligne ». C'etait exact, et voici ce que la mesure a montre.

   Ces reperes etaient colles au BORD DROIT de leur cellule (justify-items:
   end). Leurs bords droits s'alignaient donc parfaitement — verifie, 1381 px
   pour les deux items de la colonne 2. Mais leur largeur suit leur CONTENU :
   142 px pour « 122 », 166 px pour « 365 días ». Alignes par la droite, des
   blocs de largeurs differentes n'ont plus aucune verticale commune a gauche,
   la ou l'oeil cherche justement le debut de chaque chiffre. D'ou l'impression
   de flottement : ce n'etait pas un defaut d'alignement, c'etait un alignement
   sur le mauvais bord.

   Les reperes remplissent maintenant leur cellule et leur contenu part de la
   gauche. Consequence : deux colonnes franches, quatre chiffres qui demarrent
   sur deux verticales, et des libelles qui se lisent depuis leur bord gauche
   comme partout ailleurs sur ce site.

   Les DEUX volets sont concernes, pas seulement celui d'Equateur : ils
   partagent la grille, et n'en aligner qu'un ferait sauter le bloc au
   changement d'onglet. */
.cases__pane .cases__figures {
  justify-items: stretch;
  /* Deux colonnes explicites, et non un auto-fit : avec quatre reperes, le
     auto-fit passait a quatre colonnes des que la place le permettait, ce qui
     ecrasait les libelles sur deux ou trois lignes chacun. */
  grid-template-columns: repeat(2, minmax(0, 1fr));
  align-items: start;
}
.cases__pane .cases__figures .case-fig,
.cases__pane .cases__figures .case-ring { text-align: left; }
.cases__pane .cases__figures .case-fig__num { justify-content: flex-start; }
.cases__pane .cases__figures .case-fig__label,
.cases__pane .cases__figures .case-ring__label { margin-inline-start: 0; }
/* Le cadran garde sa taille propre mais part du meme bord que les chiffres :
   sans cette ligne il restait centre dans sa cellule et cassait la verticale
   de la premiere colonne. */
.cases__pane .cases__figures .case-ring__dial-wrap { margin-inline: 0; }



/* ==========================================================================
   ADAPTATION TELEPHONE (iPhone / Android) — 2026-08-18
   --------------------------------------------------------------------------
   Tout ce bloc est enferme dans des media queries de petite largeur. Aucune
   regle ne s'applique au-dessus de 919 px (a l'exception du rail d'onglets,
   qui suit la media query du composant lui-meme, 61.99rem, parce que le
   defaut corrige n'existe que lorsque le rail est deja passe a l'horizontale).
   Le poste de travail ne voit donc rien changer.

   Place en fin de fichier a dessein : plusieurs selecteurs de cette feuille
   sont declares jusqu'a quatre fois, et a specificite egale c'est la derniere
   declaration qui gagne.
   ========================================================================== */

@media (max-width: 919px) {

  /* --- 1. Le selecteur de langue dans le menu -----------------------------
     .lang-switch est masque sous 900 px pour le header ; il doit vivre ici. */
  .mobile-menu__lang {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
    margin: 0 0 var(--space-4);
    padding: 12px 4px 0;
    border-top: 1px solid var(--color-border);
  }
  .mobile-menu__lang-label {
    font: 700 11px/1 var(--font-mono);
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--color-muted);
  }
  .mobile-menu .lang-switch { display: inline-flex; margin-right: 0; }
  /* 44 px de cible tactile sur chaque langue, contre 28 px auparavant. */
  .mobile-menu .lang-switch__btn {
    min-width: 44px;
    min-height: 44px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 12px;
  }

  /* --- 2. Saisie : plus jamais de zoom automatique ------------------------
     Safari iOS agrandit la page des qu'un champ est sous 16 px, et ne revient
     pas en arriere quand on en sort. Quatre zones de texte, le champ de
     fichier et le champ de l'assistant etaient a 13,5 et 14 px. La graisse et
     la fonte ne changent pas, seulement la taille, et seulement au telephone. */
  .form-textarea,
  .form-textarea--mono,
  .form-file,
  .form-input,
  .form-select,
  .aia-card__input {
    font-size: 16px;
  }
  /* La case de consentement faisait 13 px : sous le doigt, c'est une cible
     qu'on rate. Le libelle entier reste cliquable, comme avant. */
  .form-checkbox input[type="checkbox"] {
    width: 20px;
    height: 20px;
    flex: 0 0 20px;
  }
  .form-checkbox {
    gap: 12px;
    align-items: flex-start;
  }

  /* --- 3. Cibles tactiles ------------------------------------------------- */
  /* Le bouton qui reduit l'assistant faisait 27 px. On elargit la zone sans
     grossir le dessin : c'est la surface qui compte, pas l'icone. */
  .aia-card__min {
    min-width: 44px;
    min-height: 44px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
  }
  /* Les liens de colonnes du pied de page etaient hauts de 18 px, colles les
     uns aux autres : on rate systematiquement le voisin. */
  .site-footer__col a,
  .site-footer nav a {
    display: inline-block;
    padding-block: 9px;
  }

  /* --- 4. Textes d'interface sous le plancher de lisibilite ---------------
     10 a 11 px se lisent a l'ecran d'un poste de travail, pas a bout de bras.
     On remonte a 12 px les etiquettes qui portent une information, en laissant
     leur graisse et leur interlettrage : le dessin ne change pas, la taille
     seulement. */
  .practice__chip,
  .method__chip,
  .solpanel__tab-method,
  .solpanel__pane-method,
  .liga-constellation__label,
  .metric__label,
  .practices__label,
  .frameworks__label,
  .how-stats__label,
  .partner-level__tag,
  .final-cta__meta-item,
  .form-section__num,
  .form-label,
  .method__proof-label,
  .contact-info__countries-label {
    font-size: 12px;
  }
  .method__role { font-size: 12px; }
  .ring-stat__unit { font-size: 11px; }
  /* La mention legale de l'assistant et son lien : 10,5 px, et le lien n'avait
     que 13 px de haut. */
  .aia-card__fine { font-size: 12px; }
  .aia-card__privacy { display: inline-block; padding-block: 6px; }
}

/* --- 5. Le rail d'onglets des solutions ---------------------------------
   Sous 62rem la liste passe a l'horizontale (regle existante, section 2f).
   Deux defauts mesures a 390 px : chaque onglet heritait de width:100%, donc
   occupait 350 px et UN SEUL etait visible ; et rien n'indiquait que le rail
   se balaie, si bien que cinq des six solutions n'existaient pas pour le
   visiteur. On rend donc l'onglet a la largeur de son texte, et on fond le
   bord droit pour dire qu'il y a une suite. */
@media (max-width: 61.99rem) {
  .solpanel__tab { width: auto; max-width: 68vw; }
  .solpanel__list {
    scroll-snap-type: x mandatory;
    scroll-padding-left: 4px;
    /* Le fondu des deux bords est le signe qu'il y a autre chose a cote. Il
       est purement decoratif et ne mange aucune zone cliquable. */
    -webkit-mask-image: linear-gradient(to right, transparent 0, #000 18px, #000 calc(100% - 26px), transparent 100%);
            mask-image: linear-gradient(to right, transparent 0, #000 18px, #000 calc(100% - 26px), transparent 100%);
  }
  .solpanel__tab { scroll-snap-align: start; }
  /* Meme signal pour la sous-navigation de page, dont les entrees suivantes
     etaient coupees net au bord. */
  .subnav__track {
    -webkit-mask-image: linear-gradient(to right, transparent 0, #000 14px, #000 calc(100% - 22px), transparent 100%);
            mask-image: linear-gradient(to right, transparent 0, #000 14px, #000 calc(100% - 22px), transparent 100%);
  }
}

/* --- 6. Le seul debordement horizontal du site -------------------------
   nosotros a 320 px : le document mesurait 324 px de large. Cause trouvee a
   la mesure, ce n'est pas une marge mal reglee. La bande des certifications
   est une grille de deux colonnes en 1fr ; or 1fr vaut minmax(AUTO, 1fr), et
   ce minimum automatique interdit a la colonne de descendre sous la largeur
   de son contenu. Les colonnes restaient donc a 146 px chacune, soit
   146 + 12 + 146 = 304 px dans un conteneur qui n'en offre que 280.
   minmax(0, 1fr) retire ce plancher et rend la colonne compressible.
   Cadre a 639 px : au-dessus, la bande passe a trois puis cinq colonnes et
   ces regles-la n'ont pas le defaut. */
@media (max-width: 639px) {
  .cert-strip { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .cert-card { min-width: 0; }
  .cert-card strong, .cert-card span { min-width: 0; overflow-wrap: anywhere; }
}

/* --- 7. Etiquettes que la premiere passe n'avait pas atteintes ----------
   Elles portaient toutes un selecteur plus specifique ailleurs dans cette
   feuille (.metrics--editorial .metric__label, .partner-level--elite
   .partner-level__tag, .contact-info__countries .contact-info__countries-label,
   .about-frameworks .frameworks__label). La classe est donc redoublee ici :
   meme element, specificite egale a celle qui gagnait, et la derniere
   declaration l'emporte. Aucune ne s'applique au-dessus de 919 px. */
@media (max-width: 919px) {
  .metric__label.metric__label,
  .frameworks__label.frameworks__label,
  .partner-level__tag.partner-level__tag,
  .contact-info__countries-label.contact-info__countries-label,
  .case-fig__label.case-fig__label,
  .case-ring__label.case-ring__label,
  .case-flow__tag.case-flow__tag,
  .cases__tab.cases__tab,
  .presence__sub-label.presence__sub-label,
  .highlight__label.highlight__label,
  .country__since.country__since,
  .essence-mark__lang.essence-mark__lang {
    font-size: 12px;
  }
  /* Mon propre ajout du menu suit la meme regle que ce qu'il cotoie. */
  .mobile-menu__lang-label { font-size: 12px; }

  /* Deux cas decouverts a l'audit, apres la premiere passe.
     Le tag Elite/Platinum/Gold : sa taille de 11 px est posee plus haut avec
     !important (ligne ~4954), qu'aucune specificite ne peut battre. Meme
     importance ici, plus tard dans la feuille et sous media query : c'est le
     seul !important de tout ce bloc, et il ne fait que repondre a l'autre.
     Le libelle "Ver el detalle" du depliant des methodologies etait a 11,5 px
     (sa cible tactile, elle, fait deja 44 px de haut). */
  .partner-level__tag { font-size: 12px !important; }
  .method__disclose-toggle span { font-size: 12px; }
}

/* --- 8. Le personnage qu'on met en mouvement ---------------------------
   Sur telephone le heros est servi en pose fixe et son animation ne se
   telecharge qu'au toucher (persona-motion.js). Deux etats a montrer, sinon
   le geste n'a pas de reponse : un pouce pendant le telechargement des
   quelques megaoctets, et rien de particulier une fois l'animation en place.
   Aucune de ces regles n'existe au-dessus de 919 px. */
@media (max-width: 919px) {
  .method__media { cursor: pointer; }
  .method__media.is-loading-motion img { opacity: 0.55; transition: opacity 200ms ease; }
  .method__media.is-loading-motion::after {
    content: '';
    position: absolute;
    left: 50%; top: 50%;
    width: 26px; height: 26px;
    margin: -13px 0 0 -13px;
    border-radius: 50%;
    border: 2px solid rgba(248, 250, 252, 0.25);
    border-top-color: var(--color-primary);
    animation: persona-spin 720ms linear infinite;
    z-index: 3;
  }
  @keyframes persona-spin { to { transform: rotate(360deg); } }
  @media (prefers-reduced-motion: reduce) {
    .method__media.is-loading-motion::after { animation: none; }
  }
}

/* --- 9. Le menu compact sur ecran court ---------------------------------
   A 320 x 568 (petits iPhone), les quatre liens ne tenaient pas entre le
   bandeau du haut et le bloc langue + boutons : le quatrieme n'apparaissait
   qu'a moitie. La zone est scrollable, donc rien n'etait perdu, mais un menu
   de quatre entrees ne devrait pas demander un geste de plus. Sous 640 px de
   HAUTEUR, les liens et les marges se resserrent : les liens restent a plus
   de 50 px de cible tactile. Les ecrans normaux ne changent pas. */
@media (max-width: 919px) and (max-height: 640px) {
  .mobile-menu__link { padding: 9px 4px; font-size: var(--text-xl); }
  .mobile-menu__inner { padding-top: var(--space-4); padding-bottom: var(--space-2); }
  .mobile-menu__lang { margin-bottom: var(--space-2); padding-top: 8px; }
  .mobile-menu__cta { padding-top: var(--space-3); }
  .mobile-menu__cta .btn { padding-top: 12px; padding-bottom: 12px; }
}

/* ══════════════════════════════════════════════════════════════════════════
   DIRECTEUR DE SCENES — enveloppes de mots des titres        2026-08-21
   ══════════════════════════════════════════════════════════════════════════
   Le mot glisse depuis la droite A L'INTERIEUR de son enveloppe, qui coupe ce
   qui depasse. C'est ce qui permet une entree laterale sans jamais produire de
   barre de defilement horizontale : rien ne sort de la mise en page.

   AUCUNE REGLE ICI NE CACHE QUOI QUE CE SOIT. Les etats de depart sont poses
   par scene-director.js, en JavaScript. Sans lui, les titres sont lisibles
   exactement comme avant — c'est la regle du depot : un script absent ne doit
   jamais rendre un contenu invisible.

   Le padding et la marge negative valent la place des jambages. Sans eux, le
   « overflow: hidden » de l'enveloppe coupe le bas des g, j, p, q et des
   accents bas : mesure faite sur « investigación », dont le g etait rase. */
.sc-w {
  display: inline-block;
  overflow: hidden;
  vertical-align: top;
  /* La paire padding/marge s'annule dans le flux : la ligne garde sa hauteur,
     l'enveloppe gagne de la place sous la ligne de base. */
  padding-bottom: 0.16em;
  margin-bottom: -0.16em;
}
.sc-w__in {
  display: inline-block;
  /* will-change seulement pendant la scene : le poser en permanence sur tous
     les mots de la page reviendrait a demander une couche de composition par
     mot, pour rien. La classe est retiree a la fin de la timeline. */
}
.sc-playing .sc-w__in { will-change: transform, opacity; }

@media (prefers-reduced-motion: reduce) {
  /* Le directeur ne tourne pas du tout sous cette preference, donc aucun mot
     n'est jamais decoupe. La regle est la par securite, pour le cas ou un
     decoupage subsisterait d'un changement de preference en cours de session. */
  .sc-w { overflow: visible; padding-bottom: 0; margin-bottom: 0; }
  .sc-w__in { transform: none !important; opacity: 1 !important; }
}


/* ── QUIENES SOMOS : L'INTERTITRE DE LA POLITIQUE      2026-08-22 ─────────
   Le second paragraphe de la section EST la politique de qualite et de securite
   de l'information ; Gabriel a demande qu'elle soit nommee. Un h3 et non un
   paragraphe en gras : la structure du document doit dire ce que la mise en
   forme montre, et un lecteur d'ecran doit pouvoir naviguer jusque-la.
   Le corps reste petit et l'interlettrage large : c'est une etiquette de
   section, pas un titre concurrent du h2 juste au-dessus. */
/* LA TYPO S'ACCORDE A CELLE DU TEXTE — 2026-09-04, releve par Gabriel :
   « ce texte est dans une typo pas comme les autres, accorde-la a la typo du
   texte et laisse sa couleur rouge ».
   Il avait raison, et l'ecart etait triple : la famille MONOSPACE quand les
   deux paragraphes qui l'encadrent sont en Plus Jakarta Sans, un corps de 11 a
   13 px quand ils sont a 18, et une CAPITALISATION forcee avec 0,14em
   d'interlettrage. Un intertitre plus petit que son propre texte se lisait
   comme une etiquette technique, pas comme le titre de la politique qualite.
   Il prend donc la famille et le corps du texte (.how__text p, --text-lg).
   CE QUI RESTE POUR LE DISTINGUER, et c'est suffisant : la graisse 700 et le
   rouge. La graisse n'est pas touchee parce que la demande porte sur la typo et
   que sans elle un h3 de meme famille, meme corps et meme casse que son
   paragraphe ne se distinguerait plus que par la couleur — ce qui exclut du
   sens quiconque ne la percoit pas.
   CONTRASTE : la section #quienes porte data-sol="clair", donc c'est la seconde
   regle qui s'applique, --color-primary-deep #B01E1E, mesure a 6,58:1 sur
   #F8FAFC. Le rouge de base y rendrait 4,62, conforme aussi. Sur fond SOMBRE en
   revanche aucun des deux ne passerait (4,35 / 3,81 / 3,33 selon le sol) : si
   cette section basculait un jour en sombre, il faudrait --color-primary-soft
   #F87171, qui rend 7,59 / 6,66 / 5,82. */
.who__policy-title {
  margin: clamp(22px, 2.4vw, 34px) 0 clamp(8px, 0.9vw, 12px);
  font-family: inherit;
  font-size: var(--text-lg);
  font-weight: 700;
  letter-spacing: normal;
  text-transform: none;
  line-height: var(--leading-snug);
  color: var(--color-primary);
}
main > section[data-sol="clair"] .who__policy-title { color: var(--color-primary-deep); }

/* ── LA PHRASE DES CERTIFICATIONS EST CENTREE      2026-08-22 ────────────
   Elle ferme le bloc des quatre alliances majeures, sous une rangee de quatre
   logos centres : alignee a gauche, elle partait du bord d'une rangee qui,
   elle, est centree — et se lisait comme un debut de paragraphe orphelin.
   Centree, elle se pose sous les logos et fait la transition vers les
   alliances specialisees.
   Sa longueur de ligne est bornee : centrer un texte long sans le borner
   donne des lignes de largeurs tres inegales, ce qui est pire que l'aligner a
   gauche. */
.fantastic4 .alliances__note {
  margin-inline: auto;
  max-width: 62ch;
  text-align: center;
}

/* ── LES SIX FIGURES DU HERO N'ONT PLUS LA MEME TAILLE   2026-08-22 ───────
   ══════════════════════════════════════════════════════════════════════════
   Gabriel : « les super-heros sont tous de meme taille, varie-les pour que ce
   soit naturel, en gardant NGSOC comme le plus grand ».

   Jusqu'ici cinq figures partageaient exactement min(70%, 660px, 34vw) et seule
   la capitane montait a 80 % : six personnages debout, alignes par les pieds,
   dont cinq ont la tete rigoureusement a la meme hauteur. L'oeil lit un
   gabarit, pas un groupe.

   L'echelle descend depuis le centre vers les bords, ce qui est la façon dont
   un groupe se place naturellement pour une photo : NGSOC domine, la capitane
   le suit de pres, et les silhouettes s'abaissent en s'eloignant. Les ecarts
   sont assez larges pour se voir (4 points de pourcentage entre voisins) et
   assez petits pour qu'aucune figure ne paraisse rapetissee.

   LES TROIS BORNES SONT CONSERVEES sur chaque figure, et ce n'est pas
   decoratif : la note d'origine explique que la largeur totale de la rangee
   vaut environ 2,8 fois sa hauteur une fois les chevauchements deduits, et
   qu'a 1440 px sans la borne en vw, CTEM et GRC sortaient du cadre. Les trois
   valeurs de chaque ligne gardent donc le meme rapport entre elles. */
.page-hero--liga .liga-row__fig[data-persona="ngsoc"]     { height: min(80%, 748px, 38.0vw); }
.page-hero--liga .liga-row__fig[data-persona="asha"],
.page-hero--liga .liga-row__fig--capitana                 { height: min(76%, 716px, 36.5vw); }
.page-hero--liga .liga-row__fig[data-persona="csirt"]     { height: min(72%, 678px, 34.5vw); }
.page-hero--liga .liga-row__fig[data-persona="zerotrust"] { height: min(69%, 650px, 33.0vw); }
.page-hero--liga .liga-row__fig[data-persona="ctem"]      { height: min(66%, 622px, 31.5vw); }
.page-hero--liga .liga-row__fig[data-persona="grc"]       { height: min(64%, 604px, 30.5vw); }

/* ── LA BARRE DES CAS : ONGLETS ET BOUTON SUR UNE LIGNE   2026-08-22 ──────
   Le bouton « Cuentenos su proyecto » vivait dans l'en-tete de section, face au
   titre, dans un espacement automatique : il commençait a 1 117 px quand les
   deux onglets commencent a 58, sans partager d'alignement avec quoi que ce
   soit. Il descend dans leur rangee.
   La barre enveloppe le tablist ET le bouton : le bouton reste hors du role
   tablist, qui ne doit contenir que des onglets. Sous 47,5 rem la barre passe
   en colonne, le bouton se rangeant sous les onglets plutot que de les
   comprimer. */
.cases__bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: clamp(16px, 2vw, 28px);
  margin-bottom: clamp(26px, 2.8vw, 44px);
}
/* La marge du bas vivait sur .cases__tabs : elle appartient desormais a la
   barre, sinon les deux se cumulaient. */
.cases__bar .cases__tabs { margin-bottom: 0; }
@media (max-width: 47.5rem) {
  .cases__bar { flex-direction: column; align-items: flex-start; }
}

/* ── LES DEUX BLOCS DE TEXTE SONT JUSTIFIES      2026-08-22 ───────────────
   ══════════════════════════════════════════════════════════════════════════
   Gabriel : « les blocs de texte d'esencia et de nosotros ne sont pas carres
   du cote droit ». Ils etaient en drapeau, chaque ligne s'arretant ou le mot
   suivant ne tenait plus. Justifies, leurs deux bords tombent sur une verticale
   nette.

   LA CESURE VIENT AVEC, ET CE N'EST PAS OPTIONNEL. Un texte justifie SANS
   coupure de mots ne peut etaler que les espaces : sur une colonne etroite et
   avec des mots longs — « ciberseguridad », « inmobiliario »,
   « transformacion » — cela creuse des trous et fait apparaitre ces rivieres
   blanches qui traversent le paragraphe. Le remede est la cesure, qui repartit
   la contrainte sur les mots au lieu de la concentrer sur les blancs.
   hyphens: auto s'appuie sur l'attribut lang du document, qui vaut « es » et
   passe a « en » quand i18n change la langue : la cesure suit donc la langue
   affichee sans qu'on ait rien a declarer de plus. Le prefixe -webkit- reste
   necessaire pour Safari.

   Seuls les PARAGRAPHES sont justifies. Les titres, la devise et les libelles
   gardent leur drapeau : justifier un texte de deux ou trois lignes produit
   exactement les trous qu'on cherche a eviter, la derniere ligne etant seule a
   ne pas etre etiree. */
.how__text > p,
.essence-body > p {
  text-align: justify;
  -webkit-hyphens: auto;
          hyphens: auto;
  /* Garde-fou : sans limite, un mot peut etre coupe apres deux lettres, ce qui
     se lit mal et laisse une syllabe orpheline en bout de ligne. */
  -webkit-hyphenate-limit-before: 3;
  -webkit-hyphenate-limit-after: 3;
          hyphenate-limit-chars: 6 3 3;
}
/* Sous 62 rem la colonne se retrecit fortement : en dessous d'une quarantaine
   de caracteres par ligne, la justification ne trouve plus assez de mots par
   ligne pour repartir les blancs, et le drapeau redevient le meilleur choix. */
@media (max-width: 47.5rem) {
  .how__text > p,
  .essence-body > p { text-align: left; }
}

/* ── LE SOUS-MENU DE LA HOME PORTE HUIT ENTREES      2026-08-22 ───────────
   « Industrias Clave » a ete ajoutee a la demande de Gabriel. Mesure avant/
   apres : a sept entrees la piste tenait exactement dans sa largeur a toutes
   les tailles ; a huit elle debordait de 4 px a 1440, 18 a 1280 et 35 a 1200,
   ce qui declenchait un defilement horizontal sur une barre qui, jusque-la,
   montrait toutes ses sections d'un coup. Perdre cette vue d'ensemble pour
   quatre pixels serait un mauvais echange.

   La gouttiere de chaque lien se resserre donc d'un cran, sur la home
   UNIQUEMENT : huit liens a deux gouttieres font seize marges, et deux pixels
   repris de chaque cote rendent trente-deux pixels — davantage que ce qui
   manque partout au-dessus de 1200 px. Le sous-menu de metodologias, qui n'a
   que six entrees et de la place de reste, garde le sien.
   Reglage arrete a la mesure, en deux passes : a 0,85vw il restait 3 px de
   trop a 1280 px, ce qui suffisait a rallumer le defilement. A 0,72vw la barre
   tient en entier de 1920 jusqu'a 1280 px. En dessous, le defilement reste le
   comportement prevu, avec ses masques de bord — une barre de huit entrees ne
   peut pas tenir sur une tablette sans ecraser ses libelles. */
.subnav--home .subnav__link { padding-inline: clamp(6px, 0.72vw, 14px); }

/* ── LES PUCES DE PAYS ONT TOUTES LA MEME HAUTEUR      2026-08-22 ─────────
   ══════════════════════════════════════════════════════════════════════════
   Gabriel : « je voudrais que Mexico, Chile, Ecuador, Panama, CDMX et Tenerife
   soient de la meme taille que Colombia ». Sa liste designait exactement les
   puces qui mesuraient 44 px quand les cinq autres en faisaient 67.

   LA CAUSE N'ETAIT PAS DANS LES PUCES. Mesure des enfants d'une puce haute et
   d'une puce basse : rigoureusement identiques — pastille 8x8, nom 90x22,
   badge 43x20. C'est donc la puce elle-meme qui etait ETIREE, pas son contenu.
   .country-list est une grille, et une grille etire ses enfants par defaut :
   des qu'une puce d'une rangee depasse — a certaines largeurs un nom long et
   son badge ne tiennent plus sur une ligne — sa voisine s'etire avec elle. Le
   resultat changeait d'une largeur a l'autre : a 1920 c'etaient Rep.
   Dominicana, Colombia, Peru, Estados Unidos et Espana ; a 1280, Ecuador et
   Rep. Dominicana. Un pays n'a pas a etre plus haut qu'un autre parce que son
   voisin de rangee porte un nom plus long.

   align-items: start rend a chaque puce sa hauteur naturelle. Elles tombent
   toutes a 44 px, contenu identique oblige, et celles dont le texte passe
   vraiment sur deux lignes grandissent seules sans entrainer leurs voisines. */
.country-list { align-items: start; }
/* LA TAILLE D'ORIGINE EST RENDUE — 2026-08-22. J'avais resserre la puce
   (gouttiere 12 -> 8 px, marge 14 -> 11) et releve le seuil de la grille de 180
   a 205 px pour faire tenir « Rep. Dominicana » et « Estados Unidos » sur une
   ligne. Vu en place, Gabriel prefere les proportions d'avant : le seuil plus
   haut elargissait nettement les puces sur grand ecran, 299 px a 1920 contre
   197 auparavant.
   CE QUI RESTE, ET C'EST L'ESSENTIEL : le align-items: start ci-dessus. C'etait
   lui le vrai correctif — il empeche une puce d'etre etiree parce que sa voisine
   de rangee porte un nom plus long. Sans lui, cinq puces sur onze prenaient une
   hauteur qu'elles n'avaient pas demandee, et le groupe changeait d'une largeur
   a l'autre.
   Consequence assumee du retour en arriere : les deux noms les plus longs
   repassent sur deux lignes a certaines largeurs. Ils sont alors seuls a le
   faire, sans entrainer personne. */

/* ── LE RECAPITULATIF DE PRISE DE RENDEZ-VOUS      2026-08-22 ─────────────
   L'assistant affiche ce qu'il a compris avant que le visiteur s'en aille : si
   un champ a ete mal saisi, il le voit et peut relancer une demande corrigee,
   au lieu d'attendre un rappel qui n'arrivera jamais. */
.aia-msg__recap {
  margin-top: 10px;
  padding: 10px 12px;
  border-radius: 10px;
  background: color-mix(in srgb, var(--color-primary) 8%, transparent);
  border: 1px solid color-mix(in srgb, var(--color-primary) 22%, transparent);
}
.aia-msg__recap-title {
  margin: 0 0 6px;
  font-family: var(--font-mono, ui-monospace, monospace);
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--color-primary);
}
.aia-msg__recap-line { margin: 0 0 3px; font-size: 13px; line-height: 1.45; }
.aia-msg__recap-line:last-child { margin-bottom: 0; }

/* ── LA DEVISE SE COUPE APRES « HOW THINGS »      2026-08-22 ──────────────
   Gabriel veut deux lignes, avec « should be done. » a la ligne. La coupure
   est donc DECLAREE et non laissee au hasard de la largeur : l'accent passe en
   bloc, ce qui la place toujours au meme endroit, quelle que soit la taille de
   l'ecran ou la longueur de la traduction. Laisser le texte revenir a la ligne
   tout seul aurait donne une coupure differente a chaque largeur — parfois
   apres « should », parfois apres « be ».
   La ligne de base reste celle de la devise : c'est une seule phrase en deux
   lignes, pas deux paragraphes. */
.essence-motto .accent {
  display: block;
}

/* ── Les onze puces de pays ont toutes la meme hauteur ──── 2026-08-24 ──
   Demande de Gabriel, et c'est l'inverse du reglage precedent : plutot que de
   faire rentrer « Rep. Dominicana » et « Estados Unidos » sur une ligne, on
   donne a TOUTES les puces la hauteur de ces deux-la. Les huit pays et les
   trois villes — CDMX, Tenerife et Panama, celles a pastille violette du
   centre de supervision — sont desormais du meme gabarit.

   D'OU VIENT LA VALEUR. Elle est mesuree, pas choisie : une puce a deux lignes
   fait 66,78 px, et ce nombre se decompose exactement. Deux lignes de nom a
   22,4 px (soit 1,6 em pour un corps de 14), plus 20 px de marge interne haut
   et bas, plus 2 px de filet. D'ou calc(3.2em + 22px), qui redonne 66,8 px.

   ELLE EST ECRITE EN EM ET NON EN PIXELS, volontairement. La part liee au
   texte suit le corps de la puce : si --text-sm bouge un jour, ou si un
   visiteur agrandit la police de son navigateur, la hauteur suit au lieu de
   couper le nom. Seules les marges internes et le filet, qui eux sont fixes,
   restent en pixels.

   MIN-HEIGHT ET NON HEIGHT : un nom qui passerait un jour sur trois lignes
   agrandit sa puce au lieu de deborder. Le grid interne porte deja
   align-items: center, donc le contenu des puces a une seule ligne se centre
   dans la hauteur rendue disponible, sans retomber en haut de la boite.

   Rien ici ne touche a la largeur : le seuil de grille reste a 180 px, les
   proportions horizontales sont bien celles que Gabriel a redemandees. */
.country { min-height: calc(3.2em + 22px); }


/* ══════════════════════════════════════════════════════════════════════════
   LE BLEU EDITORIAL CESSE D'EMPRUNTER LA COULEUR DU CSIRT — 2026-09-04
   ══════════════════════════════════════════════════════════════════════════
   Gabriel, ce jour : « il y avait une erreur concernant le bleu qu'on a
   utilise, voila le bon bleu : #3773c2 », et, sur le perimetre : le bleu
   editorial seulement, la persona CSIRT garde son cyan.

   POURQUOI CE BLOC EST UN SCOPE DE TOKENS ET NON SOIXANTE REMPLACEMENTS.
   --color-csirt est appele environ soixante fois dans ce fichier, et ces
   appels sont de DEUX natures melangees : la persona CSIRT (sa carte, sa
   figure de La Liga, sa constellation, son onglet de sous-nav, le liseré de
   son formulaire) et le bleu editorial de cinq sections. Remplacer au texte
   aurait demande de trancher soixante fois, avec une chance de se tromper a
   chaque ligne, et la faute aurait ete invisible : un cyan et un bleu se
   ressemblent sur une capture.
   Ici, on redefinit les trois tokens du cyan DANS le sous-arbre des sections
   editoriales. Aucune regle existante n'est touchee, l'heritage des custom
   properties fait le travail, et la persona CSIRT est intacte par
   construction. C'est aussi reversible en supprimant ce bloc.

   POURQUOI IL EST EN FIN DE FICHIER : piege 2 du repo. A specificite egale
   c'est la derniere declaration qui gagne. Aucune autre regle ne definit
   --color-csirt sur ces conteneurs, mais la place en fin de fichier evite
   d'avoir a le reverifier a chaque ajout futur.

   LES CINQ SECTIONS, ET UN FORMULAIRE :
     .industries         « Foco en industrias claves » (home)
     .final-cta--azul    le CTA final de la home, de metodologia ET de nosotros
                         — la remarque « portee par cette section seule » du
                         bloc de 2026-08-17 est PERIMEE, mesure ce jour :
                         index.html:1493, metodologia.html:828, nosotros.html:605
     #soluciones         titre et pastille (home)
     #razones            « Por que preferirnos » (nosotros)
     .essence-lead       la devise d'esencia (nosotros)
     .problema__turn-text « INTEGRARLO TODO. » (home)
     #bolsa-form         les numeros d'etape du formulaire d'emploi. Ce n'est
                         pas la persona CSIRT : c'est le meme emprunt
                         decoratif, il suit donc le bleu.
   HORS SCOPE, VOLONTAIREMENT : #csirt-form, qui est le formulaire de
   l'equipe CSIRT et dont le bleu EST sa couleur d'equipe ; et tout selecteur
   portant [data-persona="csirt"]. */
.industries,
.final-cta--azul,
#soluciones,
#razones,
#presencia,
.essence-lead,
.problema__turn-text,
#bolsa-form {
  --color-csirt:      var(--color-azul);
  --color-csirt-soft: var(--color-azul-soft);
  --color-csirt-ink:  var(--color-azul-ink);
}

/* ── LES TEXTES QUI ETAIENT AU TON PLEIN DOIVENT PASSER AU SOFT ───────────
   Le cyan #06B6D4 est une couleur claire : en TEXTE sur les sols sombres il
   rendait 8,65 / 7,59 / 6,63:1. Le bleu #3773c2 est une couleur moyenne et
   rend 4,39 / 3,85 / 3,37 : il ECHOUE sur les trois, noir pur compris.
   Les regles ci-dessous sont donc obligatoires, pas cosmetiques : sans elles
   le passage au bleu rendrait ces libelles non conformes.
   Mesure apres correctif : 8,26 / 7,25 / 6,33:1. */
#bolsa-form .csirt-form__step-num,
#bolsa-form .csirt-form__group-title,
#bolsa-form .form-section__num,
#bolsa-form .form-group__num {
  color: var(--color-azul-soft) !important;
}

/* ── UN DEFAUT ASSUME EN AOUT SE TROUVE REPARE PAR CE CHANGEMENT ──────────
   « INTEGRARLO TODO. » est pose sur la bande CLAIRE de la home. Le bloc du
   2026-08-17 le disait franchement : le cyan plein n'y rendait que 2,32:1,
   sous le seuil de 3 exige meme par ces 64 px, et aucune variante du cyan ne
   convenait (le soft a 1,39, l'ink a 4,55 mais ne ressemblait plus au bleu du
   site). Le choix etait assume faute de mieux.
   Le bleu de Gabriel resout la situation sans exception a poser : #3773c2
   rend 4,57:1 sur --sol-clair, donc il passe le seuil de 3 de ce titre ET
   celui de 4,5 du texte courant. Rien a ajouter ici, c'est note pour que
   personne ne rouvre le sujet en croyant le defaut encore la. */


/* ══════════════════════════════════════════════════════════════════════════
   UN BOUTON DE CONTACT PAR METODOLOGIA — 2026-09-04
   ══════════════════════════════════════════════════════════════════════════
   Demande de Gabriel : « un bouton de contactanos en dessous de chaque card de
   servicios, de la meme couleur que la section, chaque metodologie aura le
   sien, trouve un emplacement strategique ».

   L'EMPLACEMENT RETENU : dans .method__proof, APRES le <details> « Ver el
   detalle ». Trois raisons.
   D'abord, c'est le bas du seul bloc de la bande qui apporte une preuve (le
   nombre de services, les referentiels, puis le detail) : le bouton arrive
   quand le visiteur vient de lire ce que le frente sait faire.
   Ensuite, le detail est FERME par defaut : le bouton est donc visible sans
   qu'on ait rien a deplier, et il descend naturellement quand on ouvre.
   Enfin, il reste DANS la carte de preuve et non sous la bande entiere : sur
   les bandes ou le personnage est a droite, un bouton pose sous la bande se
   serait retrouve seul au milieu d'une gouttiere.

   LA COULEUR VIENT DE --persona ET DE --persona-on, qui existaient deja et que
   ce bouton n'a fait que consommer. C'est ce qui garantit le contraste, et il
   est mesure pour les six : aplat + encre du DS rend
       asha 4,62 · ctem 6,79 · ngsoc 15,44 · csirt 7,84 · zerotrust 4,81 · grc 8,35
   Le plus faible est ASHA a 4,62:1, seul aplat de la palette a porter du BLANC,
   conforme SANS MARGE : ne pas descendre ce libelle sous 16 px.

   LE SURVOL NE TOUCHE PAS LA COULEUR DE FOND, et c'est une mesure qui l'a
   decide. Assombrir l'aplat de 12 % — le reflexe habituel — donne
       asha 5,68 · ctem 5,33 · ngsoc 11,78 · csirt 6,12 · grc 6,49
   mais ZEROTRUST TOMBE A 3,87:1, sous le seuil. Le violet est le faux ami que
   la doctrine des deux regimes signale deja : il parait sombre et ne l'est pas
   assez. Et l'eclaircir a la place ne marche pas non plus, puisque ASHA porte
   du blanc et les cinq autres de l'encre sombre : la direction sure serait
   inverse selon la persona.
   Le survol passe donc par l'elevation et une lueur, exactement comme le fait
   deja .persona:hover ailleurs sur le site. Aucun ratio ne bouge. */
.method__cta {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  margin-top: var(--space-6);
  padding: 12px 22px;
  border-radius: var(--radius-full);
  border: 1px solid var(--persona, var(--color-primary));
  background: var(--persona, var(--color-primary));
  color: var(--persona-on, var(--color-fg));
  /* 16 px et non 14 : le ratio d'ASHA est a 4,62:1, conforme sans marge, et le
     seuil de 4,5 ne vaut que pour du texte de cette taille au moins. */
  font-size: var(--text-base);
  font-weight: 600;
  line-height: 1.2;
  text-decoration: none;
  transition: transform var(--duration-normal) var(--ease-out),
              box-shadow var(--duration-normal) var(--ease-out);
}
.method__cta .icon {
  width: 18px;
  height: 18px;
  transition: transform var(--duration-normal) var(--ease-out);
}
.method__cta:hover,
.method__cta:focus-visible {
  transform: translateY(-2px);
  box-shadow: 0 10px 24px rgba(0, 0, 0, 0.35),
              0 0 22px color-mix(in srgb, var(--persona, var(--color-primary)) 42%, transparent);
}
.method__cta:hover .icon,
.method__cta:focus-visible .icon { transform: translateX(3px); }
/* Le focus clavier garde un anneau visible EN PLUS de l'elevation : sur un
   aplat colore, une ombre portee ne suffit pas a dire ou est le focus. */
.method__cta:focus-visible {
  outline: 2px solid var(--color-fg);
  outline-offset: 3px;
}
/* Sur la bande CLAIRE (CTEM et GRC, data-sol="clair"), l'aplat persona reste
   l'aplat persona : les six ratios ci-dessus sont ceux de l'aplat contre son
   encre, ils ne dependent pas du sol. Rien a redefinir ici, c'est note pour
   qu'on ne cherche pas une regle manquante. */

/* ── LA ZONE DE REPONSE DU FORMULAIRE DE CONTACT ─────────────────────────
   Nouvelle classe, pour la nouvelle page contacto.html. Elle est vide au
   chargement et n'occupe alors aucune place : sans le :empty, une marge et une
   hauteur de ligne creusaient un trou sous les boutons.
   Les trois etats disent trois choses differentes et ne doivent pas se
   ressembler — surtout « warn », qui signale que l'envoi automatique n'est pas
   encore branche et que le visiteur doit ecrire a l'adresse. */
.form-estado {
  margin-top: var(--space-5);
  padding: 12px 16px;
  border-radius: var(--radius-md);
  border: 1px solid var(--color-border);
  background: var(--color-surface);
  color: var(--color-fg);
  font-size: var(--text-sm);
  line-height: var(--leading-body);
}
.form-estado:empty {
  display: none;
}
/* --color-muted sur --color-surface nu : 5,52:1. */
.form-estado.is-pending {
  color: var(--color-muted);
}
/* Vert du DS sur son propre fond a 12 %, soit rgb(42,61,49) : 5,06:1, au-dessus
   du seuil de 4,5 pour ces 14 px. */
.form-estado.is-ok {
  border-color: color-mix(in srgb, var(--color-success) 46%, transparent);
  background: color-mix(in srgb, var(--color-success) 12%, var(--color-surface));
  color: var(--color-success);
}
/* L'etat « pas encore branche ». Il n'est ni un succes ni une erreur : c'est
   l'orange de CTEM, seule couleur chaude du systeme qui ne soit pas le rouge
   de l'echec.
   MAIS PAS L'ORANGE PUR, et c'est une mesure qui l'a impose : --color-ctem
   #F97316 sur son propre fond a 12 % (rgb 68,52,40) ne rend que 4,26:1, sous le
   seuil. Trois issues testees — baisser le fond a 8 % rend 4,52, conforme sans
   marge ; l'orange-400 rend 5,27 ; l'orange-300 rend 7,08 mais derive de 6
   degres de teinte. Retenu : --color-ctem-soft, orange-400, 5,27:1 et 2,4
   degres d'ecart. C'est le meme geste que --color-primary-soft (red-400),
   --color-zerotrust-soft (purple-400) et --color-azul-soft (blue-400) : la
   famille de variantes claires du DS gagne son quatrieme membre. */
.form-estado.is-warn {
  border-color: color-mix(in srgb, var(--color-ctem) 46%, transparent);
  background: color-mix(in srgb, var(--color-ctem) 12%, var(--color-surface));
  color: var(--color-ctem-soft);
}
/* Le rouge d'ERREUR et non le rouge de MARQUE : --color-primary #DC2626 ne rend
   que 2,61:1 sur ce fond, tres loin du seuil. --color-danger-soft #FCA5A5 rend
   6,64:1 et se lit toujours comme un rouge. */
.form-estado.is-error {
  border-color: color-mix(in srgb, var(--color-destructive) 46%, transparent);
  background: color-mix(in srgb, var(--color-destructive) 12%, var(--color-surface));
  color: var(--color-danger-soft);
}


/* ── LA MENTION « QUELLE VERSION FAIT FOI » DE L'AVIS DE CONFIDENTIALITE ──
   Posee le 2026-09-04 avec la traduction de cette page en anglais et en
   francais. Sa valeur espagnole est une chaine VIDE : en espagnol le
   paragraphe reste donc sans contenu, et :empty le retire du flux. C'est ce
   qui permet d'avoir une mention dans deux langues sur trois sans dupliquer
   la page ni ajouter un test dans un script.
   Le liseré rouge et l'italique la distinguent du corps juridique : c'est un
   avertissement sur le document, pas une clause du document. */
.legal-aviso-traduccion {
  margin: 0 0 var(--space-8);
  padding: var(--space-4) var(--space-5);
  border-left: 3px solid var(--color-primary);
  background: color-mix(in srgb, var(--color-primary) 8%, var(--color-surface));
  border-radius: 0 var(--radius-md) var(--radius-md) 0;
  font-size: var(--text-sm);
  font-style: italic;
  line-height: var(--leading-body);
  /* --color-muted sur ce fond compose, rgb(57,43,43) : 5,29:1, au-dessus du
     seuil de 4,5 pour ces 14 px. Le rouge de marque n'y passerait pas
     (2,81:1) : c'est le liseré qui porte la couleur, pas le texte. */
  color: var(--color-muted);
}
.legal-aviso-traduccion:empty { display: none; }


/* ══════════════════════════════════════════════════════════════════════════
   L'EN-TETE S'EFFACE AU-DESSUS DU HERO DE LA HOME — 2026-09-05
   ══════════════════════════════════════════════════════════════════════════
   Demande de Gabriel : voir l'animation du bouclier DERRIERE l'en-tete tant
   qu'on est sur le hero, puis retrouver l'en-tete actuel des qu'on le quitte.

   ── CE QUI RENDAIT LA DEMANDE IMPOSSIBLE TELLE QUELLE ────────────────────
   `.site-header` est en `position: sticky`, donc il OCCUPE SA PLACE DANS LE
   FLUX. Mesure faite avant d'ecrire : le header va de y=0 a y=89, et le hero
   commence a y=89, exactement dessous. Il n'y a RIEN derriere le header.
   Le passer en `background: transparent` aurait donc laisse voir le fond noir
   du body : la demande aurait paru executee, et l'animation ne serait jamais
   apparue. C'est le genre de correctif qui se verifie a l'oeil et se croit
   fait.

   ── LE HERO REMONTE SOUS L'EN-TETE, AVEC DEUX COMPENSATIONS ──────────────
   1. `margin-top` negatif de la hauteur du header : le hero passe dessous.
   2. Le CONTENU redescend d'autant, par un padding sur `.hero__inner`. On ne
      touche PAS au padding de `.hero`, et c'est deliberé : il est declare deux
      fois, dont une en `!important` dans une requete media pour les ecrans peu
      hauts (l. ~8311, « padding-top: 44px !important »). Le modifier aurait
      demande de rejouer ce cas particulier ; le compenser ailleurs le laisse
      intact. `.hero__inner` n'a qu'une seule declaration, `width: 100%`.
   3. La HAUTEUR gagne la meme valeur. Sans cela le bas du hero remonterait de
      89 px et le liseré de la bande de logos apparaitrait trop tot — or ce
      calibrage est explicite : `calc(100vh - 117px)`, un chiffre pose le
      2026-08-12 pour laisser voir « un LISERE de la bande blanche, pas les
      logos ». La position du bas du hero est donc identique au pixel pres
      avant et apres ce changement.

   `--hauteur-entete` vaut `--header-h` PLUS un pixel : le header mesure 89 px
   et non 88, la bordure du bas s'ajoutant a la hauteur de `.site-header__inner`.
   Elle suit toute seule le passage a 76 px sous 768 px.

   ── LA TRANSPARENCE N'EST PAS TOTALE, ET C'EST UNE MESURE QUI L'A DECIDE ──
   Voir le bloc de mesure plus bas.                                          */

:root { --hauteur-entete: calc(var(--header-h) + 1px); }

.hero {
  margin-top: calc(-1 * var(--hauteur-entete));
  /* Le bas du hero ne bouge pas : on rend a la hauteur ce que la marge lui a
     pris. Les deux lignes reprennent la forme de la regle du 2026-08-12
     (vh en repli, svh pour ignorer la barre d'URL mobile) et son !important,
     sans quoi celle-la gagnerait. */
  min-height: max(calc(560px + var(--hauteur-entete)), calc(100vh - 117px + var(--hauteur-entete))) !important;
  min-height: max(calc(560px + var(--hauteur-entete)), calc(100svh - 117px + var(--hauteur-entete))) !important;
}
.hero__inner { padding-top: var(--hauteur-entete); }

/* L'etat transparent. La classe est posee par header-hero.js et par lui seul :
   sans JavaScript, l'en-tete reste opaque et lisible. La transparence est un
   enrichissement, jamais une condition de lisibilite. */
.site-header {
  transition: background-color var(--duration-slow) var(--ease-out),
              border-color var(--duration-slow) var(--ease-out),
              backdrop-filter var(--duration-slow) var(--ease-out);
}
/* Le tout premier etat est pose sans transition, sinon l'en-tete s'allume du
   noir vers le transparent a chaque chargement de la home. */
.site-header.sans-transition { transition: none !important; }

.site-header.is-sur-hero {
  /* ── TRANSPARENCE TOTALE, ET C'EST LA MESURE QUI L'AUTORISE ────────────
     Le reflexe aurait ete de poser un voile degrade « par securite ». Il
     n'etait pas necessaire, et le verifier a pris cinq minutes.
     Methode : en-tete masque, video calee sur six instants (0, 2, 4, 6, 8 et
     9,9 s), bande de 1440x89 capturee a chaque fois, puis contraste du texte
     blanc juge sur le 90e centile de luminance du fond — le pire cas realiste,
     les pixels les plus clairs. Les quatre zones sont mesurees separement
     parce que les elements de l'en-tete ne sont pas au meme endroit, et que
     c'est a DROITE que le bouclier se forme et s'illumine :

         zone                  t=0     t=2     t=4     t=6     t=8   t=9,9
         logo (gauche)       18,36   18,36   18,36   18,36   18,36   18,36
         navigation          18,40   18,41   18,42   18,46   18,49   18,51
         selecteur langue    18,20   18,20   18,19   18,19   18,18   18,18
         bouton ASHA CSIRT    6,78    6,78    6,78    6,78    6,78    6,78

     Pire cas toutes zones et tous instants : 6,78:1, pour un seuil de 4,5.
     La raison tient a la composition de l'animation : le bouclier occupe le
     milieu-droit du cadre, jamais les 89 premiers pixels, et le haut de la
     video reste sombre du debut a la fin. Les six captures different bien
     entre elles (ecart croissant de 15 000 a 90 000 sur la somme des
     differences), donc le calage a fonctionne : la constance des ratios est
     un fait, pas une mesure ratee.

     A REVERIFIER si l'animation du hero change : c'est SA composition qui
     autorise cette transparence, pas une propriete du header. Une video dont
     le haut serait clair demanderait un voile, et le script de mesure est
     conserve dans le journal du chantier. */
  background: transparent;
  border-bottom-color: transparent;
  /* Le flou de fond part : il est fait pour separer l'en-tete du contenu, et
     ici on veut exactement l'inverse, voir l'animation nette derriere. */
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}

/* Ecrans peu hauts : la regle media de la l. ~8311 ecrase le padding du hero
   en !important, mais elle ne touche pas .hero__inner, donc la compensation
   tient. Rien a ajouter ici, c'est note pour qu'on ne cherche pas une regle
   manquante. */

/* MOBILE. Sous 920 px la video ne se charge pas — le hero montre l'image de
   fond, ce que le script du hero decide depuis le 2026-08-18 pour ne pas
   telecharger 2,6 Mo sur un forfait. Le voile reste donc pose sur une image
   fixe, mesuree elle aussi. */


/* ── L'EMBLEME DU HAUT-DROIT NE DOIT PLUS ETRE COUPE — 2026-09-06 ────────
   Gabriel : « baisser un peu la video vers le bas pour qu'on puisse voir
   l'embleme en haut a droite, en ce moment cette partie est coupee ».

   CE QUE LA MESURE A DIT, ET LA CAUSE N'ETAIT PAS CELLE QU'ON CROYAIT.
   L'embleme occupe x de 1613 a 1828 et y de 26 a 196 dans la video source,
   soit a 2,4 % du haut et a 92 px du bord droit. La video est en 16:9 et le
   hero est PLUS HAUT que 16:9 sur la plupart des ecrans : `cover` cale donc
   sur la hauteur et rogne les COTES. C'est ce rognage lateral qui coupait
   l'embleme, pas un debordement vers le haut — mesure a 11 px de coupe sur un
   ecran 1512, 151 px sur un 1100.
   Descendre la video seule n'aurait donc rien regle : elle serait toujours
   coupee a droite.

   LE REGLAGE RETENU : `object-position: right`, et lui seul.
   Il envoie tout le rognage lateral a GAUCHE. Comme l'embleme est a 92 px du
   bord droit de la source, il ne peut plus etre coupe : verifie sur neuf
   largeurs de 1920 a 960, aucune coupe.
   Effet de bord voulu : le bouclier se cale a droite, ce qui renforce la
   composition du hero, titre a gauche et sujet a droite.

   ── LA DESCENTE DE 80 PX A ETE POSEE PUIS RETIREE LE MEME JOUR ───────────
   Elle repondait a la demande litterale « baisser un peu la video ». Elle a
   ete faite par `top: 80px; height: calc(100% - 80px)`, et le commentaire que
   j'avais ecrit affirmait que « la jonction ne se voit pas ». JE NE L'AVAIS
   PAS VERIFIE, et c'etait faux.
   Gabriel l'a vu tout de suite : « c'est bizarre, maintenant le header n'est
   plus transparent sur le hero ». Il l'etait pourtant — mesure,
   `background-color: rgba(0, 0, 0, 0)` et la classe bien posee. Mais la video
   commencait 80 px plus bas, donc DERRIERE l'en-tete transparent on ne voyait
   plus l'animation : on voyait le fond du hero, une bande sombre et unie qui
   se lit exactement comme un en-tete opaque.
   Mesure de la rupture, cote droit, luminance moyenne par bande :
       40-80 px (fond du hero)   0,03012
       80-89 px (jonction)       0,00577
       90-130 px (video)         0,02282
   Une ligne franche a 80 px, precisement ce qu'on cherchait a supprimer en
   rendant l'en-tete transparent.

   LA LECON, et elle vaut au-dela de ce bloc : rendre un en-tete transparent
   n'a de sens que si quelque chose de VIVANT passe dessous. Tout ce qui
   deplace le contenu du hero vers le bas annule le benefice, meme si l'en-tete
   reste techniquement transparent. Les deux reglages se contredisaient, et
   c'est le second qui saute.

   A REVERIFIER si l'animation change : la position de l'embleme dans CETTE
   video est ce qui rend `right` suffisant. */
.hero__bg-video {
  /* `top` ET NON `center`, 2026-09-06. Quand le hero est plus large que 16:9,
     `cover` cale sur la largeur et rogne la HAUTEUR ; en `center` ce rognage
     se partage, donc la partie SUPERIEURE de la video est coupee. Mesure du
     haut perdu : 14 px a 1920x1080, 1600x900 et 2560x1440, 9 px a 1760x1000,
     et l embleme tombait a 4 px du bord sur 1366x768.
     En `top`, tout le rognage passe en BAS : la partie superieure est toujours
     entiere, et le sujet gagne les 14 px qu il perdait. Le cout est de 28 px
     au maximum perdus en bas, sur le champ de particules qui se poursuit. */
  object-position: right top;
  /* ── SIX PIXELS VERS LE HAUT — 2026-09-06 ─────────────────────────────
     Gabriel : « l embleme doit etre vraiment a la meme hauteur que le bouton
     ASHA CSIRT, il faut juste monter la video de quelques petits pixels ».
     Mesure sur sa capture d ecran (1920x1032, Chrome) : le centre du texte du
     bouton est a y=164, le noyau lumineux de l embleme a y=170, soit six pixels.
     Porte a SEPT le 2026-09-06 a sa demande, apres controle a l ecran : la
     mesure donnait 1,5 px d ecart residuel a six, elle en donne 0,5 a sept.

     LA BOITE MONTE DE 6 PX ET GAGNE 6 PX DE HAUT, et les deux vont ensemble :
     un `top: -6px` seul decouvrirait 6 px de fond du hero en BAS du hero. En
     ajoutant la meme valeur a la hauteur, la boite couvre toujours exactement
     de 0 a la fin du hero, et c est le CONTENU qui monte.
     La valeur est une variable : elle s ajuste d un chiffre. */
  --hero-video-montee: 7px;
  top: calc(-1 * var(--hero-video-montee));
  height: calc(100% + var(--hero-video-montee));
}


/* ══════════════════════════════════════════════════════════════════════════
   LE BLEU GAGNE LES DEUX FORMULAIRES ET LE HALO DU CTA — 2026-09-06
   ══════════════════════════════════════════════════════════════════════════
   Trois demandes de Gabriel : le bleu de la page ASHA CSIRT actualise, le
   formulaire de la page contacto passe au bleu lui aussi, et le halo qui
   s'allume au survol du bouton bleu du CTA final cesse d'etre ROUGE.

   CE QUE CELA REVISE, ET IL FAUT LE DIRE. Le 2026-09-04, l'arbitrage etait
   « bleu editorial seulement, la persona CSIRT garde son cyan », et
   #csirt-form avait ete explicitement laisse HORS du scope avec ce
   commentaire : « le bleu retenu est celui du CSIRT, l'equipe dont cette
   section parle ». Gabriel revient dessus aujourd'hui pour le formulaire.
   CONSEQUENCE A CONNAITRE : la persona CSIRT garde son cyan la ou elle est un
   PERSONNAGE (sa carte de la home, sa figure de La Liga, sa constellation, son
   onglet de sous-nav dans metodologia). Les deux formulaires, eux, sont
   desormais bleus. Un visiteur qui passe de la bande CSIRT de metodologia au
   formulaire de la page CSIRT verra donc deux bleus differents. C'est
   coherent avec « le bleu est la couleur des surfaces editoriales et des
   formulaires, le cyan celle du personnage », mais ce n'est vrai que si on le
   sait : d'ou cette note. */

/* 1. LES DEUX FORMULAIRES. On vise les IDENTIFIANTS et non .contact-section,
      qui est portee aussi par #bolsa-form — le commentaire du 2026-08-22
      signale que cette classe a deja repeint le formulaire d'emploi en cyan
      trois fois sans que personne l'ait demande. */
#csirt-form,
#form {
  --color-csirt:      var(--color-azul);
  --color-csirt-soft: var(--color-azul-soft);
  --color-csirt-ink:  var(--color-azul-ink);
}

/* 2. LES LIBELLES PASSENT AU TON CLAIR, et ce n'est pas cosmetique.
      Le cyan etait une couleur claire, le bleu est une couleur moyenne :
        ton plein #3773c2 sur sol-1  3,85:1  ECHEC
        ton plein #3773c2 sur sol-2  3,37:1  ECHEC
        soft      #60A5FA sur sol-1  7,25:1  OK
        soft      #60A5FA sur sol-2  6,33:1  OK
      Sans ces trois lignes, le passage au bleu rendrait les numeros d'etape et
      les intitules de groupe non conformes sur les deux pages. */
#csirt-form .csirt-form__step-num,
#csirt-form .csirt-form__group-title,
#csirt-form .form-section__num,
#csirt-form .form-group__num,
#form .csirt-form__step-num,
#form .csirt-form__group-title,
#form .form-section__num,
#form .form-group__num {
  color: var(--color-azul-soft) !important;
}

/* 3. LE HALO DU CTA FINAL. `.btn-primary:hover` pose `box-shadow:
      var(--glow-primary)`, un halo ROUGE de la regle generique (l. ~133), et
      la regle du CTA bleu ne remplacait que le fond et la bordure : le bouton
      devenait bleu et s'allumait en rouge au survol.
      Le halo reprend la teinte du bouton, meme rayon et meme alpha que
      --glow-primary pour que le geste reste identique. */
.final-cta--azul .btn-primary:hover,
.final-cta--azul .btn-primary:focus-visible {
  box-shadow: 0 0 24px color-mix(in srgb, var(--color-azul) 45%, transparent) !important;
}
/* Le bouton d'envoi des deux formulaires suit la meme regle : il herite du
   bleu par --color-primary, mais son halo restait rouge. */
#csirt-form .btn-primary:hover,
#csirt-form .btn-primary:focus-visible,
#form .btn-primary:hover,
#form .btn-primary:focus-visible {
  box-shadow: 0 0 24px color-mix(in srgb, var(--color-azul) 45%, transparent) !important;
}


/* ── PLUS D'ESPACE VIDE A DROITE DU FORMULAIRE D'EMPLOI — 2026-09-06 ─────
   Gabriel : « montrer plus de l'image a droite du formulaire pour qu'il n'y
   ait pas d'espace vide a droite, soit elargir l'image ou le formulaire, soit
   un peu des deux ».

   MESURE DE L'ETAT ANTERIEUR, dans le conteneur de la section :
       1920 px : conteneur 1760, bloc 1400  ->  296 px de vide a droite
       1760 px : conteneur 1760, bloc 1400  ->  296 px
       1600 px : conteneur 1600, bloc 1400  ->  136 px
       1512 px et moins : 55 a 60 px, c'est-a-dire rien
   La cause est le `max-width: 1400px` pose sur .bolsa-top le 2026-08-18. Son
   commentaire dit qu'il evitait « un vide a sa droite a 1920 » : il l'a en
   realite deplace, du bord de la photo au bord du bloc.

   LA FORMULE RETENUE, « un peu des deux » :
     · le bloc prend toute la largeur du conteneur, le vide disparait ;
     · le formulaire passe de 820 a 960 px au maximum, +17 %. Il reste sous le
       millier de pixels, au-dela duquel une ligne de formulaire devient
       inconfortable a lire ;
     · la photo prend TOUT le reste, soit environ 640 px a 1760 contre 500
       avant, +28 %. C'est elle qui gagne le plus, comme demande.

   POURQUOI LE RAPPORT FIXE DISPARAIT ICI. Le 2:3 pose le 18/08 servait a
   accorder la hauteur de la photo a celle du formulaire pour UNE largeur de
   colonne donnee (500 px -> 750 de haut). Des que la colonne s'elargit, ce
   rapport la fait depasser le formulaire de 100 a 280 px selon l'ecran. En
   `align-self: stretch` sans rapport impose, elle prend exactement la hauteur
   du formulaire quelle que soit la largeur : les deux blocs s'alignent en haut
   ET en bas, ce que ni le 2:3 ni le 4:5 ne pouvaient garantir aux deux bouts.
   Le recadrage reste gouverne par `object-position: 50% 32%`, qui tient le
   visage dans le tiers haut.

   SOUS 1360 px, RIEN NE CHANGE : la photo passe deja sous le texte, bornee a
   300 px et centree. Ces largeurs n'avaient pas de vide a corriger. */
@media (min-width: 1360px) {
  .bolsa-top {
    max-width: none;
    grid-template-columns: minmax(0, 960px) minmax(320px, 1fr);
  }
  .bolsa-photo {
    aspect-ratio: auto;
    align-self: stretch;
  }
}

/* CORRECTIF DU MEME JOUR, trouve a la mesure juste apres. Sans rapport impose
   et en `stretch`, `.bolsa-photo` n'avait plus de hauteur propre : son <img>,
   en `height: 100%` dans un parent sans hauteur resolue, retombait sur sa
   hauteur INTRINSEQUE — 598 x 1650/1100 = 897 px. La photo poussait donc la
   ligne, et le formulaire passait de 750 a 896 px de haut pour la suivre.
   Mesure : 887 px a 1920, 896 a 1760, contre 742 partout ailleurs.
   L'image sort du calcul de hauteur en passant en absolu dans son cadre, qui
   est deja `position: relative`. La ligne reprend alors la hauteur du
   formulaire, et la photo s'y etire exactement. */
@media (min-width: 1360px) {
  .bolsa-photo { min-height: 0; }
  .bolsa-photo img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
  }
}


/* ── LE TITRE DU HERO DE contacto PASSE SUR L'EMBLEME — 2026-09-06 ───────
   Defaut trouve a la mesure juste apres avoir pose la nouvelle image, et c'est
   le meme piege que celui deja paye sur le hero de la home en aout : du rouge
   sur du rouge.
   Le titre accentue est en --color-primary-lift #EF4444, et sa seconde moitie
   (« le respondemos en menos de 24 horas. ») s'etend jusqu'a 85 % de la
   largeur, donc PAR-DESSUS l'embleme en mosaique. Mesure sur les pixels
   rendus, texte masque, 90e centile du fond :
       1280 px  2,23:1     1440 px  2,69:1     1920 px  3,43:1
   pour un seuil de 3,0 a ce corps. Deux largeurs sur trois echouaient.

   Le voile est un DEGRADE HORIZONTAL et non un aplat : il est dense la ou le
   texte se pose et s'efface a droite, pour que l'embleme garde son eclat au
   bord. Valeur retenue apres calcul sur les trois captures — 30 % de noir a
   85 % de la largeur, la ou le titre se termine, donne 3,21 / 3,66 / 4,30.
   Le lede blanc, lui, passait deja largement (15,0 a 19,6:1). */
.page-hero--contact .page-hero__bg-grad {
  background:
    linear-gradient(90deg,
      rgba(0, 0, 0, 0.60) 0%,
      rgba(0, 0, 0, 0.45) 55%,
      rgba(0, 0, 0, 0.30) 85%,
      rgba(0, 0, 0, 0.05) 100%);
}


/* ── LA DESCENTE DE LA VIDEO : DEUX ESSAIS, DEUX ECHECS, ET POURQUOI ────
   2026-09-06. Gabriel a demande deux fois de descendre la video du hero. Les
   deux tentatives ont ete retirees, et la raison est structurelle : elle merite
   d'etre ecrite pour que personne ne la retente sans le savoir.

   ESSAI 1 — `top: 80px; height: calc(100% - 80px)`.
   Derriere l'en-tete transparent, on voyait le FOND du hero au lieu de
   l'animation : une bande unie qui se lit comme un en-tete opaque. Retire.

   ESSAI 2 — le meme, plus un `box-shadow` noir pur au-dessus de la video pour
   supprimer la jonction. La jonction a bien disparu (ecart ramene de 1,44:1 a
   1,01:1, sous le seuil de 1,14), MAIS le resultat est pire : la bande derriere
   l'en-tete devient un aplat NOIR, c'est-a-dire exactement l'apparence d'un
   en-tete opaque. Corriger la jonction ne servait a rien, le probleme n'etait
   pas la frontiere mais le fait qu'il n'y ait plus d'animation derriere.

   CE QUI REND LES DEUX DEMANDES INCOMPATIBLES EN L'ETAT. L'embleme est a 2,4 %
   du haut de l'image source (y de 26 a 196 sur 1080). Il n'y a presque rien
   au-dessus de lui dans la video. Donc :
     · pour voir l'animation DERRIERE l'en-tete, la video doit commencer a y=0 ;
     · pour descendre son contenu, il faut montrer ce qui est au-dessus de
       l'embleme — et il n'y a rien.
   Aucun reglage CSS ne cree du contenu absent. Les seules vraies issues sont
   de reduire la hauteur du hero, ou de regenerer une animation dont le sujet
   n'est pas colle au bord haut.

   L'ETAT CONSERVE est donc : video pleine (top 0, hauteur 100 %), cadrage colle
   a droite pour que l'embleme ne soit jamais coupe. */



/* ══════════════════════════════════════════════════════════════════════════
   LES BOUTONS DES FORMULAIRES BLEUS NE VIRENT PLUS AU ROUGE — 2026-09-06
   ══════════════════════════════════════════════════════════════════════════
   Gabriel : « les boutons du formulaire ASHA CSIRT deviennent rouges au survol
   alors qu'ils devraient rester bleus ».

   LA CAUSE, et elle etait a deux tokens pres. Le passage au bleu redefinit
   dans la portee des formulaires --color-primary, --color-primary-deep,
   --color-primary-soft et --color-primary-lift. Il OUBLIAIT les deux que le
   survol utilise :
       .btn-primary:hover { background: var(--color-primary-hover);   <- #B91C1C
                            box-shadow: var(--glow-primary); }        <- rouge
   Au repos le bouton etait donc bleu, et il redevenait rouge des qu'on le
   survolait. Meme chose pour le bouton d'envoi de l'assistant et pour celui du
   selecteur de fichier, qui lisent le meme token.

   LE GESTE EST CELUI DU ROUGE, TRANSPOSE. Le rouge s'assombrit au survol,
   #DC2626 -> #B91C1C, et gagne un halo de sa propre teinte. Le bleu fait
   exactement pareil : #3773c2 -> #2E63A8, halo bleu.
   Contraste du libelle blanc verifie aux deux etats : 4,78:1 au repos, 6,06:1
   au survol. Pour comparaison le rouge donne 6,47 au survol : meme ordre. */
#csirt-form,
#form,
#bolsa-form {
  --color-primary-hover: var(--color-azul-ink);
  --glow-primary: 0 0 24px color-mix(in srgb, var(--color-azul) 45%, transparent);
}

/* SECOND DEFAUT, TROUVE PAR LA MEME MESURE : le bouton d'envoi de la page
   contacto etait ROUGE AU REPOS, et l'est depuis sa creation le 2026-09-04.
   #csirt-form et #bolsa-form redefinissent --color-primary chacun dans son
   bloc (l. ~16736 et ~16889), mais #form, la section de la nouvelle page,
   n'avait jamais recu l'equivalent : le passage au bleu du 06/09 n'avait
   redefini que les tokens --color-csirt, dont .btn-primary ne se sert pas.
   Mesure avant correctif : repos #DC2626 sur contacto, #3773C2 sur les deux
   autres. */
#form {
  --color-primary: var(--color-azul);
  --color-primary-deep: var(--color-azul-ink);
  --color-primary-soft: var(--color-azul-soft);
  --color-primary-lift: var(--color-azul-soft);
  --plq: var(--color-azul);
}


/* ── LE SELECTEUR DE FICHIER, EN TROIS LANGUES — 2026-09-06 ──────────────
   Le libelle du bouton d'un <input type="file"> est dessine par le NAVIGATEUR
   et suit SA langue. Aucune regle CSS ni aucun attribut ne le renomme :
   ::file-selector-button pouvait le repeindre, pas le traduire. D'ou un
   « Choose File » anglais au milieu d'un formulaire espagnol.
   L'input reste dans le DOM — il porte la valeur, `accept` et `required`, donc
   la validation du navigateur continue de fonctionner — et c'est un <label>
   lie par `for` qui joue le bouton. Le label ouvre le selecteur au clic ET a
   la touche Entree sans JavaScript : masquer l'input ne coute donc rien a
   l'accessibilite, a condition de ne PAS le mettre en `display: none`, qui le
   sortirait de l'ordre de tabulation. Il est rendu invisible tout en restant
   focalisable, et le focus se voit sur le label grace a :focus-within. */
.form-file-wrap {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  flex-wrap: wrap;
}
.form-file-input {
  /* Invisible mais toujours focalisable et toujours dans le formulaire. */
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}
.form-file-btn {
  display: inline-flex;
  align-items: center;
  padding: 10px 18px;
  border-radius: var(--radius-md);
  border: 1px solid var(--color-primary);
  background: var(--color-primary);
  /* Blanc pur et non --color-fg : sur l'aplat bleu des formulaires il rend
     4,78:1 contre 4,57, et le rouge des autres contextes le porte deja. */
  color: #FFFFFF;
  font-size: var(--text-sm);
  font-weight: 600;
  line-height: 1.2;
  cursor: pointer;
  transition: background var(--duration-normal) var(--ease-out),
              box-shadow var(--duration-normal) var(--ease-out);
}
.form-file-btn:hover {
  background: var(--color-primary-hover);
  box-shadow: var(--glow-primary);
}
/* L'anneau de focus se pose sur le LABEL, puisque l'input est invisible.
   Sans cette regle, un visiteur au clavier ne saurait pas ou il est. */
.form-file-wrap:focus-within .form-file-btn {
  outline: 2px solid var(--color-fg);
  outline-offset: 3px;
}
.form-file-name {
  font-size: var(--text-sm);
  color: var(--color-muted);
  /* Un nom de fichier long ne doit pas pousser la mise en page. */
  max-width: min(100%, 42ch);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* Quand un fichier est joint, le nom passe a l'encre pleine : c'est le seul
   retour visuel que le champ est rempli. --color-muted rend 8,19:1 sur sol-0,
   --color-fg 20,07 : les deux passent, l'ecart fait la difference. */
.form-file-name.is-rempli { color: var(--color-fg); }

/* Le bouton de contact de « Quienes somos », 2026-09-06. Il a besoin d'air
   au-dessus : il suit un paragraphe, pas une liste, et sans marge il se colle
   a la derniere ligne. */
.who__cta {
  margin-top: clamp(20px, 2.2vw, 30px);
  /* L'ENCRE EST FORCEE AU BLANC, et c'est une mesure qui l'impose.
     La section #quienes porte data-sol="clair", et une regle du sol clair pose
     une encre SOMBRE sur les boutons. Sur l'aplat rouge de marque cela donne
     3,94:1, sous le seuil. La doctrine des deux regimes du design system le
     dit depuis le 2026-08-12 : des six aplats persona, le rouge est le SEUL
     qui porte du blanc (4,83:1 en blanc pur, 4,62 avec --color-fg) et le seul
     qui refuse l'encre sombre. Mesure apres correctif : 4,83:1.
     Conforme sans marge, comme partout ou ce rouge porte du texte : ne pas
     descendre ce libelle sous 16 px. */
  color: #FFFFFF !important;
}
.who__cta .icon { color: #FFFFFF; }


/* ══════════════════════════════════════════════════════════════════════════
   QUATRE BOUTONS SECONDAIRES, UN SEUL GESTE — 2026-09-06
   ══════════════════════════════════════════════════════════════════════════
   Gabriel : « aligner l'animation du bouton Hablar con el CSIRT sur Conozca
   nuestras metodologias, ou quand la souris passe devant ca devient rouge ;
   faire de meme avec Contactenos du pied de page ; ces deux boutons doivent
   etre comme Conozca nuestras metodologias et Alianzas estrategicas ».

   ── CE QUE LA MESURE A TROUVE AVANT D'ALIGNER QUOI QUE CE SOIT ───────────
   Les trois premiers portent DEJA les memes classes (.btn .btn-secondary
   .btn-pill). L'ecart ne venait donc pas d'eux mais de leur SOL :
       Conozca et Alianzas   sol #F8FAFC (clair)   encre #101010
       Hablar con el CSIRT   sol #000000 (noir)    encre #F8FAFC
   Recopier la regle des references sur le troisieme aurait pose une encre
   SOMBRE sur un fond NOIR. Le geste se transpose, il ne se copie pas.

   ── ET UN DEFAUT DANS LA REFERENCE ELLE-MEME ─────────────────────────────
   Au survol, les deux boutons de reference passent a `var(--color-primary)`
   #DC2626 sur un fond de 6 % de ce meme rouge sur le sol clair. Mesure :
   4,20:1, sous le seuil de 4,5. Les copier tels quels aurait propage le
   defaut a deux boutons de plus.
   Les quatre prennent donc --color-primary-deep #B01E1E, qui EST le token du
   systeme pour le rouge sur fond clair (tokens.css, 2026-08-14 : « le rouge
   des FONDS CLAIRS »). Mesure : 5,99:1. Meme teinte, meme geste, conforme.

   ── ET SUR LE SOL NOIR ───────────────────────────────────────────────────
   Le rouge de marque y rend 4,24:1 sur son fond de survol, il echoue aussi.
   C'est --color-primary-lift #EF4444 qu'il faut la, mesure 5,38:1. Le systeme
   a une valeur par sol, il suffit de prendre la bonne. */

/* 1. LES TROIS BOUTONS SUR SOL CLAIR : les deux references et celui du pied
      de page, qui vient de recevoir les memes classes dans les sept pages. */
.alliances--band .btn-secondary:hover,
.diferenciador__cta-wrap .btn-secondary:hover,
.site-footer__contact-cta:hover,
.site-footer__contact-cta:focus-visible {
  color: var(--color-primary-deep);
  border-color: var(--color-primary-deep);
  background: color-mix(in srgb, var(--color-primary) 6%, transparent);
}
/* ── LE PIED DE PAGE : IL FAUT DEFAIRE SON ANCIEN STYLE AVANT DE POSER
      CELUI DES REFERENCES ────────────────────────────────────────────────
   `.site-footer__contact-cta` est declaree HUIT fois dans ce fichier, dont
   trois en `!important` sur la couleur (l. ~836, ~10877, ~12978) et une qui en
   faisait une petite pastille de 12 px a fond rouge (l. ~14745), avec un
   survol qui la remplissait de rouge plein (l. ~14763).
   Ce n'etait donc pas « un bouton sans animation » : c'en etait un autre, avec
   sa propre animation. Lui donner les classes .btn .btn-secondary .btn-pill ne
   suffisait pas, ces huit declarations gagnaient.
   On reprend ici, valeur par valeur, la geometrie relevee sur le bouton de
   reference : 16 px, graisse 600, 14/28 de rembourrage, 8 px de gouttiere,
   bordure de 1 px, rayon plein, hauteur finale 56 px. Les `!important` ne sont
   poses que sur ce qui doit vaincre un `!important` existant. */
.site-footer__contact-cta {
  display: inline-flex !important;
  align-items: center;
  gap: 8px;
  padding: 14px 28px !important;
  border-radius: 9999px;
  border: 1px solid color-mix(in srgb, var(--color-fg-light) 28%, transparent) !important;
  background: transparent !important;
  color: var(--color-fg-light) !important;
  font-size: var(--text-base) !important;
  font-weight: 600 !important;
  /* L'ancien lien vivait dans une <address> : sans marge il se colle au
     numero de telephone juste au-dessus. */
  margin-top: var(--space-4);
}
.site-footer__contact-cta:hover,
.site-footer__contact-cta:focus-visible {
  color: var(--color-primary-deep) !important;
  border-color: var(--color-primary-deep) !important;
  background: color-mix(in srgb, var(--color-primary) 6%, transparent) !important;
}
.site-footer__contact-cta .icon { width: 18px; height: 18px; }

/* 2. LE BOUTON SUR SOL NOIR : meme geste, valeur du sol sombre. */
.anillos__cta .btn-secondary:hover,
.anillos__cta .btn-secondary:focus-visible {
  color: var(--color-primary-lift);
  border-color: var(--color-primary-lift);
  background: color-mix(in srgb, var(--color-primary) 6%, transparent);
}

/* ══ LE GESTE DE SURVOL DES APLATS, SUR TOUT LE SITE      2026-09-06 ═══════
   Gabriel, apres avoir juge l'essai sur le bouton vert : « si c'est bien on
   arrive a le lire, maintenant repand ceci sur tout le site ».

   LE GESTE, DECOMPOSE SUR LE CTA AVANT D'ETRE COPIE (survol reel, pas lecture
   de regles) : le fond NE BOUGE PAS, l'encre passe du blanc a #101010, un halo
   de 24 px a ~45 % de la couleur du bouton apparait, et le bouton monte de
   1 px. Les `.method__cta` montaient de 2 px : ramenes a 1 px, sinon ce n'est
   plus « la meme animation ».

   NEUF FAMILLES D'APLAT RELEVEES A LA MACHINE SUR LES SEPT PAGES :
   `.btn-primary` en rouge et en bleu, les six `.method__cta` de metodologia,
   `.section-cta`, et `.skip-link`. Les fonds noirs, blancs et gris sont hors
   sujet, la demande porte sur les aplats de COULEUR.

   DEUX EXCEPTIONS, ET ELLES SONT MESUREES.
   - NGSOC (argent #E2E8F0) garde son encre sombre aux deux etats : le blanc y
     rend 1,15:1, le texte disparaitrait purement et simplement. Ce n'est pas
     un oubli, c'est la seule valeur possible.
   - `.skip-link` n'est pas touche : c'est le lien d'evitement, il n'apparait
     qu'au focus clavier et n'a pas d'etat de survol utile.

   LE PRIX DU FOND FIXE, MESURE ET ASSUME PAR GABRIEL apres avoir vu le rendu :
   l'encre blanche au repos descend sous 4,5:1 sur cinq aplats (rouge 4,62 est
   le seul conforme ; violet 3,96 ; orange 2,80 ; cyan 2,43 ; vert 2,28). En
   contrepartie l'etat de SURVOL, lui, remonte partout au-dessus du seuil grace
   a l'encre sombre. Le tableau complet est dans la reponse du 2026-09-06. */

/* ── 1. TOUS LES .btn-primary, LES SEPT PAGES ────────────────────────────
   `var(--color-primary)` et non une valeur en dur : dans les formulaires ce
   token est redefini en bleu, la regle y rend donc le bleu du repos, ce qui
   est exactement le comportement voulu. */
.btn-primary:hover,
.btn-primary:focus-visible {
  background: var(--color-primary) !important;
  border-color: var(--color-primary) !important;
  color: var(--color-fg-light) !important;
  -webkit-text-fill-color: var(--color-fg-light) !important;
}
.btn-primary:hover .icon,
.btn-primary:focus-visible .icon {
  color: var(--color-fg-light) !important;
}

/* ── 2. LE BOUTON DU HERO DE LA HOME : SEUL LE MOUVEMENT EST A FORCER ────
   `!important` obligatoire et c'est mesure : GSAP anime ce hero et laisse un
   transform INLINE sur le bouton (matrice identite au repos, la ou les autres
   boutons sont a `none` — c'est le signe qui trahit). Une declaration normale
   perd contre un style inline. Verifie en forcant :hover par CDP, souris hors
   de cause. Le reste du geste lui vient de la regle generique ci-dessus. */
.hero .hero__actions .btn-primary:hover,
.hero .hero__actions .btn-primary:focus-visible {
  transform: translateY(-1px) !important;
}

/* ── 3. LES SIX .method__cta DE METODOLOGIA ──────────────────────────────
   `color` est AJOUTE a leur transition : elle n'animait que transform et
   box-shadow, la bascule d'encre serait seche. */
.method__cta {
  color: #FFFFFF !important;
  -webkit-text-fill-color: #FFFFFF !important;
  transition: transform var(--duration-normal) var(--ease-out),
              box-shadow var(--duration-normal) var(--ease-out),
              color var(--duration-normal) var(--ease-out);
}
/* L'exception argent, expliquee en tete de bloc. */
.method[data-persona="ngsoc"] .method__cta {
  color: var(--color-fg-light) !important;
  -webkit-text-fill-color: var(--color-fg-light) !important;
}
.method__cta:hover,
.method__cta:focus-visible {
  color: var(--color-fg-light) !important;
  -webkit-text-fill-color: var(--color-fg-light) !important;
  transform: translateY(-1px);
}

/* ── 4. LE BOUTON VERT DE LA HOME ────────────────────────────────────────
   Le seul aplat dont l'encre de repos a du etre posee a la main : sa regle
   d'origine la figeait en #101010 avec `-webkit-text-fill-color`. */
#casos-exito .section-cta {
  color: #FFFFFF !important;
  -webkit-text-fill-color: #FFFFFF !important;
  transition: background var(--duration-normal) var(--ease-out),
              box-shadow var(--duration-normal) var(--ease-out),
              color var(--duration-normal) var(--ease-out),
              transform var(--duration-normal) var(--ease-out);
}
#casos-exito .section-cta .icon { color: #FFFFFF !important; }
#casos-exito .section-cta:hover,
#casos-exito .section-cta:focus-visible {
  background: var(--color-grc) !important;
  color: var(--color-fg-light) !important;
  -webkit-text-fill-color: var(--color-fg-light) !important;
  transform: translateY(-1px);
}
#casos-exito .section-cta:hover .icon,
#casos-exito .section-cta:focus-visible .icon {
  color: var(--color-fg-light) !important;
}

/* ── 5. LES HEROS DE PAGE MONTENT AUSSI ──────────────────────────────────
   Meme cause que sur la home : `page-hero-reveal.js` anime ces heros et laisse
   un transform inline sur le bouton, qui bat toute declaration normale. Sans
   `!important` ici, les boutons de metodologia, nosotros, contacto, asha-csirt
   et bolsa restaient immobiles alors que tous les autres montaient. */
.page-hero__actions .btn-primary:hover,
.page-hero__actions .btn-primary:focus-visible {
  transform: translateY(-1px) !important;
}

/* ── 6. LES DEUX BOUTONS D'ENVOI RESTES A L'ENCRE DU CYAN ────────────────
   DEFAUT PREEXISTANT, trouve a la mesure en repandant le geste. Les regles
   `#csirt-form .btn-primary` et `#bolsa-form .btn-primary` (lignes ~16782 et
   ~16927) posent une encre SOMBRE, et leur commentaire dit pourquoi : le
   bouton etait alors CYAN #06B6D4, ou l'encre claire rendait 2,32:1.
   Ces boutons sont passes au BLEU #3773C2 depuis, et le calcul s'inverse —
   l'encre sombre y rend 3,98:1 quand le blanc rend 4,78:1. La justification
   d'origine est devenue fausse en meme temps que la couleur a change.
   Ces deux boutons rejoignent donc « Enviar mensaje » de contacto, reste clair.
   La specificite d'ID est reprise telle quelle : une regle de classe ne peut
   pas les atteindre. */
#csirt-form .btn-primary,
#csirt-form .btn-primary span,
#csirt-form .csirt-form__submit,
#csirt-form button[type="submit"],
#bolsa-form .btn-primary,
#bolsa-form .btn-primary span,
#bolsa-form .csirt-form__submit,
#bolsa-form button[type="submit"] {
  color: #FFFFFF !important;
  -webkit-text-fill-color: #FFFFFF !important;
}
#csirt-form .btn-primary .icon,
#csirt-form .csirt-form__submit .icon,
#csirt-form button[type="submit"] .icon,
#bolsa-form .btn-primary .icon,
#bolsa-form .csirt-form__submit .icon,
#bolsa-form button[type="submit"] .icon { color: #FFFFFF !important; }

/* Et la bascule au survol, a la meme specificite, sinon les regles d'ID
   ci-dessus l'emporteraient aussi sur l'etat survole. */
#csirt-form .btn-primary:hover,
#csirt-form .btn-primary:hover span,
#csirt-form .btn-primary:focus-visible,
#csirt-form .csirt-form__submit:hover,
#csirt-form button[type="submit"]:hover,
#bolsa-form .btn-primary:hover,
#bolsa-form .btn-primary:hover span,
#bolsa-form .btn-primary:focus-visible,
#bolsa-form .csirt-form__submit:hover,
#bolsa-form button[type="submit"]:hover {
  color: var(--color-fg-light) !important;
  -webkit-text-fill-color: var(--color-fg-light) !important;
}
#csirt-form .btn-primary:hover .icon,
#csirt-form .csirt-form__submit:hover .icon,
#csirt-form button[type="submit"]:hover .icon,
#bolsa-form .btn-primary:hover .icon,
#bolsa-form .csirt-form__submit:hover .icon,
#bolsa-form button[type="submit"]:hover .icon { color: var(--color-fg-light) !important; }

/* ══ LE BANDEAU DE CONSENTEMENT      2026-09-06 ════════════════════════════
   Gabriel : « rajoute une case en bas de la page qui apparait quand on rentre
   sur le site, garde exactement ce qui est dit dans la reference mais
   actualise le style autour ».

   LE TEXTE EST CELUI DE LA REFERENCE, MOT POUR MOT. Ce qui change est autour :
   la v1 posait un rectangle gris fonce a coins arrondis pose sur la page ; ici
   c'est la matiere du site — verre sombre, filet de 1 px, grand rayon, ombre
   portee — et le bouton d'acceptation est un `.btn-primary` du systeme, donc
   il prend seul le geste de survol repandu aujourd'hui sur les sept pages.

   IL NE BLOQUE PAS LA PAGE, et c'est voulu : ce n'est pas une modale. Le site
   ne charge aucune mesure d'audience (verifie), le bandeau informe et
   enregistre un choix, il n'interdit rien derriere lui. D'ou un `region` et
   non un `dialog`, pas de voile, et aucun piege a focus.

   POSITION : ancre en bas, largeur bornee, et une marge basse qui le tient
   au-dessus du bouton « haut de page ». */
.consent {
  position: fixed;
  left: 50%;
  bottom: var(--space-5);
  z-index: 1200;              /* au-dessus du contenu, sous le menu mobile */
  width: min(1080px, calc(100vw - 2 * var(--space-5)));
  display: flex;
  align-items: center;
  gap: var(--space-6);
  flex-wrap: wrap;
  padding: var(--space-5) var(--space-6);
  border-radius: var(--radius-xl, 20px);
  background: var(--color-glass-bg, rgba(23, 23, 23, 0.82));
  border: 1px solid var(--color-glass-border, rgba(255, 255, 255, 0.12));
  backdrop-filter: blur(18px) saturate(140%);
  -webkit-backdrop-filter: blur(18px) saturate(140%);
  box-shadow: 0 24px 60px -20px rgba(0, 0, 0, 0.75);
  /* L'etat de depart de l'entree. `translate` porte les deux mouvements :
     le centrage horizontal ET la montee. Les melanger dans une seule
     propriete evite qu'une animation future n'ecrase le centrage. */
  transform: translate(-50%, calc(100% + var(--space-5)));
  opacity: 0;
  transition: transform 420ms var(--ease-out, cubic-bezier(0.4, 0, 0.2, 1)),
              opacity   420ms var(--ease-out, cubic-bezier(0.4, 0, 0.2, 1));
}
.consent.is-visible {
  transform: translate(-50%, 0);
  opacity: 1;
}
/* La preference systeme coupe le glissement, pas l'apparition. */
@media (prefers-reduced-motion: reduce) {
  .consent { transition: opacity 200ms linear; transform: translate(-50%, 0); }
}

.consent__texte { flex: 1 1 460px; min-width: 0; }

/* Le titre est rouge dans la reference : il le reste, mais dans le rouge
   ECLAIRCI du systeme. Mesure : le verre du bandeau se compose sur le noir du
   site a #0E0E0E, ou --color-primary (#DC2626) rend 4,00:1 pour un seuil de
   4,5 — 17 px en gras n'atteint pas les 18,66 px qui feraient tomber le seuil
   a 3. --color-primary-lift (#EF4444) existe exactement pour ce cas et rend
   5,13:1. C'est le meme rouge que le lien juste en dessous, l'ensemble y gagne
   en unite. */
.consent__titre {
  margin: 0 0 var(--space-2);
  font-size: var(--text-lg, 17px);
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--color-primary-lift, #EF4444);
}
.consent__corps {
  margin: 0;
  font-size: var(--text-sm, 14px);
  line-height: 1.55;
  color: var(--color-muted-lift, #A0AEC2);
}
/* Le lien vers l'avis de confidentialite garde le rouge de la reference, mais
   avec un soulignement : sur un corps gris, la couleur seule ne suffit pas a
   dire qu'il s'agit d'un lien pour qui ne distingue pas les teintes. */
.consent__lien {
  color: var(--color-primary-lift, #EF4444);
  text-decoration: underline;
  text-underline-offset: 2px;
}
.consent__lien:hover,
.consent__lien:focus-visible { color: var(--color-fg); }

.consent__actions {
  display: flex;
  align-items: center;
  gap: var(--space-5);
  flex: 0 0 auto;
  margin-left: auto;
}
/* Le refus est un bouton de texte, comme dans la reference. Il reste un
   VRAI bouton, pas un lien : il ne mene nulle part. */
.consent__refus {
  padding: 10px 4px;
  background: none;
  border: 0;
  font-family: inherit;
  font-size: var(--text-sm, 14px);
  font-weight: 600;
  color: var(--color-muted-lift, #A0AEC2);
  cursor: pointer;
  transition: color var(--duration-normal) var(--ease-out);
}
.consent__refus:hover,
.consent__refus:focus-visible { color: var(--color-fg); }
.consent__accepter { white-space: nowrap; }

/* Sous 720 px la ligne casse : le texte prend toute la largeur et les deux
   actions passent dessous, le bouton plein en pleine largeur pour rester une
   cible confortable au pouce. */
@media (max-width: 719px) {
  .consent {
    bottom: 0;
    width: 100vw;
    border-radius: var(--radius-xl, 20px) var(--radius-xl, 20px) 0 0;
    border-left: 0;
    border-right: 0;
    border-bottom: 0;
    gap: var(--space-4);
    padding: var(--space-5);
  }
  .consent__actions { margin-left: 0; width: 100%; justify-content: space-between; }
  .consent__accepter { flex: 1 1 auto; justify-content: center; }
}

/* ══ « VER EL DETALLE » ET LE BOUTON DE CONTACT PARTAGENT UNE LIGNE  2026-09-06 ══
   Gabriel : « les boutons Hablar con el equipo tu peux les mettre sur la meme
   ligne que les boutons Ver el detalle mais dans la partie droite de ces
   grandes cards ».

   LE BOUTON EST EN ABSOLU, PAS EN COLONNE DE GRILLE, et c'est le point qui
   compte. Le panneau deroulant vit DANS le <details> : une grille a deux
   colonnes l'aurait enferme dans celle de gauche et lui aurait pris les 229 px
   du bouton plus la gouttiere, soit un tiers de sa largeur a 1440. En absolu,
   le <details> garde ses 753 px et c'est le bouton qui se pose au-dessus.

   LE POINT DE RUPTURE EST MESURE, sur les six cartes et dans les trois langues.
   Place restante entre le resume et le bouton, pire cas (espagnol, dont le
   libelle du bouton est le plus long a 229 px) :
       1440 px -> 341    1100 px -> 157    700 px -> 202
       1280 px -> 251     960 px ->  85    600 px -> 102
       480 px -> -10  : ils se chevauchent.
   La bascule est donc posee a 560 px, ou il reste une soixantaine de pixels.
   En dessous, le bouton reprend sa place dans le flux, sous le resume.

   GARDE-FOU A CONNAITRE : le resume mesure 182 a 187 px dans les trois langues
   et ne s'etire pas. Une traduction bien plus longue pourrait passer sous le
   bouton — le cas ne se produit pas aujourd'hui, il faudra le remesurer si un
   libelle change. */
.method__ligne {
  position: relative;
}

@media (min-width: 560px) {
  .method__ligne .method__cta {
    position: absolute;
    top: 0;
    right: 0;
    margin-top: 0;
  }
}

/* ══ LE CONSTAT QUI OUVRE LA BANDE DES TROIS TEMPS      2026-09-06 ═════════
   Gabriel : « montrer que maintenant a cause de l'IA la menace peut etre
   instantanee, donc la reponse avec nos IA doit etre aussi instantanee ».

   DEUX LIGNES, DEUX POIDS, ET C'EST TOUT LE PROPOS. La premiere enonce ce qui
   a change dans le monde, en encre claire : c'est un constat, pas une promesse.
   La seconde est la reponse d'ASHA, en rouge : c'est la seule chose que la
   maison s'engage a tenir. L'oeil lit le probleme puis la reponse, dans cet
   ordre, avant d'arriver aux chiffres qui la prouvent.

   Le bloc se pose AVANT `.how-stats`, donc au-dessus du filet qui ouvre la
   rangee d'anneaux : il n'entre pas dans le flex de la rangee et n'a pas a
   ruser avec son `flex-basis: 100%`.

   La mesure des contrastes sur le noir de cette section est dans la reponse du
   2026-09-06. */
.anillos__bascule {
  max-width: 46ch;
  /* L'AIR SOUS LE CONSTAT SE POSE ICI, ET PAS SUR .how-stats. Le 2026-08-14,
     une regle avait mis a zero le margin-top, le padding-top et le filet de
     .how-stats, parce que plus rien ne la precedait : le filet flottait dans
     135 px de noir. Le constat vient de remettre quelque chose au-dessus, donc
     l'espace redevient necessaire — mais la raison de 2026-08-14 reste valable
     pour le FILET, qui ne revient pas : le constat et les trois temps sont un
     seul propos, un trait les couperait en deux.
     Mesure avant correction : 0 px entre le bas du constat et le label
     « OBJETIVO OPERATIVO DEL NGSOC », qui le touchait. */
  margin: 0 auto clamp(28px, 3vw, 44px);
  text-align: center;
}
.anillos__bascule-menace {
  margin: 0;
  font-size: clamp(20px, 2.4vw, 30px);
  font-weight: 700;
  line-height: 1.25;
  letter-spacing: -0.015em;
  color: var(--color-fg);
  text-wrap: balance;
}
.anillos__bascule-respuesta {
  margin: var(--space-2) 0 0;
  font-size: clamp(20px, 2.4vw, 30px);
  font-weight: 700;
  line-height: 1.25;
  letter-spacing: -0.015em;
  /* --color-primary-lift et non --color-primary : c'est le token prevu pour
     du texte rouge sur fond sombre. Mesure sur les pixels reellement peints
     derriere cette ligne (90e centile de luminance, fond a L=0,0000, du noir
     pur) : 5,58:1, quand la premiere ligne en #F8FAFC rend 20,07:1. Le seuil
     est de 3 ici, 30 px en gras, donc les deux passent avec de la marge — le
     lift est pris pour que la reponse se DETACHE du constat, pas seulement
     pour etre lisible. */
  color: var(--color-primary-lift, #EF4444);
  text-wrap: balance;
}

/* ══ LA HERO SUR TELEPHONE : LE TITRE DOMINE, LE RESTE S'EFFACE   2026-09-07 ══
   Gabriel, capture de la home de CrowdStrike a l'appui : « les boutons de la
   hero doivent etre plus petits, proportionnels au format, fais pareil pour la
   ligne ISO, retire "Desde 2014 · Operación en 7 países · CSIRT certificado" ».

   CE QUE LA REFERENCE FAIT, MESURE SUR SA CAPTURE (ramenee en px CSS pour un
   ecran de 360) : titre a environ 40 px, bouton de 100 x 25 px, soit 28 % de la
   largeur de l'ecran. Chez nous, avant : titre 40 px lui aussi, mais bouton de
   249 x 56 px, soit 69 % de la largeur. Le titre etait deja bon ; c'est tout le
   reste qui pesait trop lourd a cote.

   LE BOUTON NE DESCEND PAS SOUS 44 px DE HAUT, et c'est le seul endroit ou je
   m'ecarte de la reference. A 25 px, un bouton se rate au pouce : c'est le
   seuil d'Apple, et l'audit du jour a justement releve sept cibles trop petites
   sur le site. Le rembourrage vertical est donc calcule pour tomber a 44 px
   pile — le plancher, pas un choix esthetique. La reduction reelle est de 56 a
   44 px de haut et de 249 a environ 213 px de large.

   L'EYEBROW DISPARAIT SUR TELEPHONE, PAS AILLEURS. Ce qu'il porte — depuis
   2014, sept pays, CSIRT certifie — n'est ecrit nulle part ailleurs dans la
   hero. Sur grand ecran il reste. Sur telephone, la place manque et Gabriel a
   tranche : le titre doit dominer.

   Tout est borne a 760 px, le point de rupture telephone deja utilise quinze
   fois dans cette feuille, dont deux fois sur .hero__eyebrow juste au-dessus. */
@media (max-width: 760px) {

  /* 0. LA HERO SE RACCOURCIT POUR LAISSER VOIR LA SUITE ------------------
     Gabriel : « coupe un peu du bas de la hero, il faut qu'on voie quand on
     entre dans le site la bande blanche et le header secondaire ».

     MESURE AVANT : hero de 804 px sur un ecran de 844. La bande blanche des
     logos commencait a 804 (il en restait 40 px visibles sur 72) et la
     sous-navigation, a 876, etait entierement hors champ. Rien ne disait qu'il
     y avait quelque chose apres.

     LES 140 px RETIRES SONT LA SOMME DE CE QU'ON VEUT VOIR : 72 px de bande
     blanche + 54 px de sous-navigation + 14 px de marge pour que la
     sous-navigation ne soit pas coupee au ras. Ce n'est pas un chiffre choisi
     a l'oeil.

     `svh` ET NON `vh` : sur telephone, `100vh` vaut la hauteur SANS la barre
     d'adresse du navigateur, qui est pourtant visible a l'arrivee sur le site
     — exactement le moment que Gabriel decrit. `100svh` prend la hauteur avec
     la barre, donc le pire cas, et garantit que la bande blanche se voit des
     le premier ecran. `vh` reste en repli pour les navigateurs sans `svh`.

     LE PLANCHER EST A 520 px, ET IL EST MESURE. A 560, un iPhone SE (667 px)
     donnait une hero de 560 dont le contenu n'occupait que 509 : 51 px de vide
     en bas, et la sous-navigation coupee a 646 pour 667 d'ecran. A 520, elle
     entre entierement, et il reste 11 px sous le contenu. C'est juste, mais
     c'est du vide en trop qu'on retire, pas du texte. */
  .hero {
    /* 152 px ET NON 140 : la bande blanche est passee de 72 a 92 px quand
       Gabriel a demande de l'agrandir, et la soustraction n'avait pas suivi —
       la sous-navigation ressortait de 6 px sous la ligne de flottaison sur
       tous les appareils. 92 (bande) + 54 (sous-navigation) + 6 (marge) = 152. */
    /* 164 px : la bande blanche a grandi deux fois — 72, puis 92, puis 104 px
       quand les logos sont passes a 44. La soustraction suit a chaque fois,
       sinon la sous-navigation ressort sous la ligne de flottaison.
       104 (bande) + 54 (sous-navigation) + 6 (marge) = 164. */
    min-height: max(520px, calc(100vh - 164px)) !important;
    min-height: max(520px, calc(100svh - 164px)) !important;
    padding-top: 60px;
    /* 6 px et non 30 : sur les petits ecrans, ce n'est plus le min-height qui
       commande la hauteur mais le CONTENU, et ces 24 px sont du vide pur sous
       la ligne ISO. Les rendre, c'est faire remonter la bande blanche d'autant
       sans toucher a un seul mot.
       Descendu de 12 a 6 quand le titre est repasse de 27 a 30 px : les 6 px
       gagnes par le titre etaient exactement ceux qui faisaient sortir la
       sous-navigation de l'ecran sur un iPhone SE (667 px de haut). */
    padding-bottom: 6px;
  }
  /* Meme raison : la ligne ISO n'a plus besoin de son air d'origine, elle est
     desormais le dernier element avant le bas de la hero. */
  .hero .hero__trust--inline { margin-bottom: var(--space-3); }

  /* 1. L'EYEBROW S'EN VA, CINQUIEME ET DERNIERE DECISION -----------------
     Retiree, remise, retiree, remise, retiree. Gabriel, le 2026-09-08 :
     « tu peux retirer Desde 2014 · CSIRT certificado de la hero de la home
     page ».
     `display: none` ET NON UN RETRAIT DU HTML, et c'est la consigne qui le
     decide : « on travaille uniquement sur la version telephone jusqu'a ce que
     je te dise le contraire ». Le <span> reste donc dans index.html et la
     pastille reste visible sur ordinateur. Toucher au balisage l'aurait retiree
     partout, ce qui n'est pas ce qui est demande.
     LES VALEURS DE LA VERSION VISIBLE SONT GARDEES EN COMMENTAIRE, parce que
     cette ligne est revenue quatre fois : si elle revient une cinquieme, elle
     revient avec son calibrage et non avec celui du bureau.
         font-size: 10px; letter-spacing: 0.04em;
         padding: 6px 11px; line-height: 1.4;
         margin-bottom: var(--space-3);
     Le seul concurrent possible sur `display` a ete verifie : `html.js
     .hero__eyebrow` (ligne 4251) est plus specifique, mais il ne declare que
     `opacity` — le gate anti-FOUC. Rien ne se bat ici. */
  .hero .hero__eyebrow { display: none; }
}

/* SUR UN ECRAN COURT, L'EYEBROW REPART — ET C'EST UN ARBITRAGE MESURE.
   Sur un iPhone SE (667 px de haut), le contenu de la hero impose 593 px a lui
   seul : avec la bande blanche (92) et la sous-navigation (54), il faudrait
   739 px pour tout montrer. Il en manque 72, et l'eyebrow en vaut 66.
   Le critere est la HAUTEUR, pas la largeur : un telephone large mais court
   (paysage, vieux modeles) a le meme probleme qu'un petit. 700 px est la
   frontiere mesuree — au-dessus tout rentre avec l'eyebrow, en dessous non. */
@media (max-width: 760px) and (max-height: 700px) {
  .hero .hero__eyebrow { display: none; }
  /* La bande blanche reprend son rembourrage d'origine sur ces ecrans : elle
     passe de 92 a 72 px, et ces 20 px sont exactement ce qui manquait pour que
     la sous-navigation entre sur un iPhone SE (mesure : elle depassait de 18).
     L'agrandissement demande par Gabriel reste en place partout ailleurs. */
  .trustband { padding: 20px 0; }
  /* La taille des logos de cet ecran est posee en fin de feuille, apres la
     regle qui les agrandit — sinon celle-ci gagnerait. */

  /* 2. LES DEUX BOUTONS SE RESSERRENT ------------------------------------
     Ils gardent leur largeur naturelle : c'est le texte qui la fait, aucune
     largeur n'est imposee. Les reduire, c'est donc reduire la police et le
     rembourrage, rien d'autre. */
  .hero .hero__actions .btn {
    /* 13 px en haut et en bas + 18 px de hauteur de ligne = 44 px pile. */
    padding: 13px 20px;
    font-size: 14px;
    line-height: 1.3;
  }
  .hero .hero__actions .btn .icon {
    width: 16px;
    height: 16px;
  }
  .hero .hero__actions { gap: 10px; }

  /* 3. LA LIGNE DES CERTIFICATIONS S'EFFACE -------------------------------
     11 px : c'est petit, et c'est assume. Cette ligne n'est pas du texte de
     lecture mais une mention de conformite, la meme famille que les mentions
     legales d'un pied de page. Elle doit se lire si on la cherche, pas capter
     l'oeil avant le titre. */
  .hero .hero__trust--inline { margin-bottom: var(--space-5); }
  .hero .hero__trust-line {
    font-size: 11px;
    /* 0,02em et non 0,06 : en 11 px de chasse fixe, les 48 signes de la ligne
       occupent 348 px avec l'interlettrage d'origine, pour 350 px disponibles a
       390 px d'ecran — elle passait donc sur deux lignes, et « MIEMBRO FIRST »
       tombait seul en dessous. Resserree, elle tient sur une ligne des 360 px.
       C'est la lisibilite du bloc qui gagne, pas la place. */
    letter-spacing: 0.02em;
    line-height: 1.5;
  }
}

/* ══ TELEPHONE : LES SIX HEROS DEFILENT, LA HERO SE RESSERRE   2026-09-07 ══
   Gabriel : « dans la section Nuestro modelo, en version telephone, qu'on
   puisse defiler vers la droite pour voir tous les heros. Dans la hero, reduis
   la taille du grand titre, du texte, des deux boutons et de la ligne ISO ».

   ── 1. LES SIX CARTES PASSENT EN RANGEE DEFILANTE ──────────────────────────
   Mesure avant : la grille tombait a une colonne, six cartes de 620 px
   empilees, soit 3 913 px de haut. Il fallait faire defiler quatre ecrans
   entiers pour voir les six heros, et rien ne disait qu'il y en avait six.
   En rangee, on en voit une et le bord de la suivante : le geste est evident
   et la section tient sur un ecran.

   LA CARTE FAIT 82 % DE LA LARGEUR, ET CE N'EST PAS UN CHIFFRE ROND POUR RIEN.
   A 100 % on ne voit pas qu'il y a une suite. Les 18 % restants laissent
   apparaitre la tranche de la carte voisine, qui est le seul indice qu'on peut
   pousser vers la droite — aucune fleche, aucun point, juste la matiere.

   LE DEBORDEMENT DE MARGE EST VOULU : `margin-inline` negatif puis
   `padding-inline` egal, pour que la rangee parte du bord de l'ecran tout en
   gardant la premiere carte alignee sur le texte au-dessus. Sans cela, une
   bande vide reste a droite et le defilement a l'air casse.

   PAS DE `tabindex` sur le conteneur : les cartes SONT des liens, le clavier
   les atteint et le navigateur fait defiler tout seul jusqu'a celle qui prend
   le focus. En ajouter un creerait un arret de tabulation qui ne fait rien. */
@media (max-width: 760px) {
  .practices__grid--six {
    display: flex;
    grid-template-columns: none;
    overflow-x: auto;
    overscroll-behavior-x: contain;   /* le geste ne remonte pas a la page */
    scroll-snap-type: x mandatory;
    /* SANS CETTE LIGNE, LE `padding-inline` NE SERT A RIEN. `scroll-snap-align:
       start` cale la carte sur le bord de la « snapport », qui est par defaut la
       boite de rembourrage : le navigateur decale donc le defilement de 22 px
       des le chargement pour respecter l'ancrage, et la premiere carte se
       retrouve collee au bord de l'ecran alors que le titre au-dessus commence
       a 20 px. Mesure avant correction : carte a 0, titre a 20, scrollLeft a
       22. `scroll-padding-inline` deplace ce bord, et les deux se rejoignent. */
    scroll-padding-inline: var(--container-px);
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    gap: 12px;
    margin-inline: calc(-1 * var(--container-px));
    padding-inline: var(--container-px);
    /* de l'air en bas : sans lui, l'ombre des cartes est rognee par l'overflow */
    padding-bottom: 4px;
  }
  .practices__grid--six::-webkit-scrollbar { display: none; }

  .practices__grid--six > .practice--card {
    /* 88 % et non 82 : Gabriel, « augmente legerement la largeur des cartes des
       super-heros ». Les 12 % qui restent laissent toujours voir la tranche de
       la carte suivante, seul indice qu'on peut pousser vers la droite — c'est
       la seule contrainte a respecter en montant cette valeur. */
    flex: 0 0 88%;
    scroll-snap-align: start;
    /* `height: auto` ET C'EST TOUTE LA CORRECTION — 2026-09-08, Gabriel : « les
       cards des super-heros n'ont pas toutes les memes dimensions, certaines
       sont plus longues, tu peux aligner tout ».

       LA CAUSE N'ETAIT PAS ICI, elle etait a la ligne 3991 :
       `.practices__grid > .practice { height: 100% }`. Sur ordinateur la rangee
       est une GRILLE, ou 100 % vaut la hauteur de la piste : c'est ce qui tient
       les six cartes a hauteur egale. Sur telephone la rangee devient un FLEX a
       hauteur indefinie, et ce 100 % n'a plus rien contre quoi se resoudre : il
       retombe sur la hauteur du contenu. Le piege est la — une hauteur declaree,
       meme retombee sur `auto`, N'EST PAS `auto` au sens de la specification,
       donc `align-items: stretch` du conteneur est purement et simplement
       ignore. Le stretch etait bien la, actif, sans effet.

       MESURE AVANT : 600 / 600 / 639 / 639 / 655 / 600 px, 55 px d'ecart, et
       il suit le nombre de lignes de `.practice__desc` (deux, trois ou quatre
       selon le hero). APRES : 655 px pour les six. La rangee ne grandit pas,
       c'etait deja sa hauteur ; ce sont les quatre cartes courtes qui montent.

       Rien d'autre n'a eu besoin de bouger : `.practice__more { margin-top:
       auto }` existe depuis l'origine et colle le lien « ver mas » en bas de
       carte. L'air gagne tombe donc entre les puces et le lien, a l'endroit
       prevu pour lui, et non sous le texte. */
    height: auto;
  }
  /* La derniere carte doit pouvoir venir se caler a gauche comme les autres :
     sans cette marge, le defilement s'arrete avant et elle reste a droite. */
  .practices__grid--six > .practice--card:last-child { margin-right: var(--container-px); }

  /* LES PERSONNAGES DESCENDENT DE 14 px ─────────────────────────────────────
     Gabriel : « la pure image des heros dans leurs cards est trop en haut et
     parfois la tete est coupee, redescends-les ». Verifie sur les six : les
     tetes ne sont pas coupees, mais elles FROLENT le bord haut — NGSOC et GRC
     n'ont pas un pixel d'air au-dessus du crane, ce qui se lit comme une coupe.

     ON NE PEUT PAS LE REGLER AVEC `object-position`. L'image est en `cover` et
     calee a `0%`, c'est-a-dire deja tout en haut : il n'y a rien a remonter.
     Pour donner de l'air, il faut RETRECIR l'image dans son cadre et la
     decaler, ce que fait ce couple hauteur + marge. Les 14 px liberes laissent
     voir le fond de la carte, qui est un degrade sombre : l'effet est celui
     d'un personnage qui respire, pas d'une bande vide. */
  .practice__hero img {
    height: calc(100% - 14px);
    margin-top: 14px;
  }

  /* LES LOGOS DE LA BANDE BLANCHE GRANDISSENT — et il a fallu deux essais
     rates pour trouver ou ecrire cette regle.
     PREMIER PIEGE : c'est `height` qui les dimensionne, pas `max-height`. Ils
     portent `height: clamp(24px, 2.7vw, 38px)`, et sur telephone 2,7vw vaut
     10 px : le clamp rend donc sa borne BASSE, 24 px. Un `max-height` plus
     grand ne change rien puisque la hauteur reelle est deja dessous.
     SECOND PIEGE : ma regle etait ecrite TRENTE LIGNES AVANT celle d'origine.
     A specificite egale, la derniere declaree gagne — c'est le piege numero
     deux de cette feuille de 19 000 lignes, ou les selecteurs reviennent. Elle
     est donc ici, en fin de fichier.
     34 et 44 px : les logos occupent un peu plus de la moitie des 92 px de la
     bande, au-dela ils toucheraient les bords. */
  .trustband__item img { height: 34px; }
  .trustband__item--sq img { height: 44px; }

  /* ── 1bis. LES SEPT SYMPTOMES DEFILENT PAR PAIRES ────────────────────────
     Gabriel : « dans la section problematica tu peux faire defiler les 7
     cards, je voudrais 2, du coup on aurait 1 et 2, on defile, 3 et 4, et
     ainsi de suite ».

     DEUX PAR ECRAN, ET LE SNAP TOUS LES DEUX. Chaque carte fait la moitie de
     la largeur utile moins la gouttiere ; l'ancrage n'est pose que sur les
     cartes IMPAIRES (1re, 3e, 5e, 7e), sinon le defilement s'arreterait carte
     par carte et on lirait 2-3 puis 4-5, jamais les paires demandees.

     PAS DE DEBORD DE MARGE ICI, contrairement a la rangee des heros : les
     symptomes sont des lignes de texte courtes alignees sur le corps de la
     section, les faire partir du bord de l'ecran les detacherait du propos.
     C'est la reglette qui dit qu'on peut defiler. */
  .symptoms {
    /* DEUX CARTES L'UNE SOUS L'AUTRE, ET NON COTE A COTE — 2026-09-07 :
       « je prefere que les deux cases soient au-dessus et en dessous au lieu
       de droite et gauche ». Avec deux cartes cote a cote, chacune faisait
       170 px de large et le texte s'y enroulait sur six lignes.
       `grid-auto-flow: column` avec DEUX RANGEES fait exactement cela : les
       cartes se remplissent de haut en bas, puis passent a la colonne
       suivante. Chaque colonne fait toute la largeur, donc chaque carte
       retrouve les 350 px du texte courant. Sept cartes donnent quatre
       colonnes, la derniere n'en portant qu'une. */
    display: grid;
    /* `none` OBLIGATOIRE, et c'est mesure : la regle d'origine pose
       `grid-template-columns: 350px`. Combinee a l'auto-flow en colonne, elle
       laissait une premiere colonne EXPLICITE que la grille reduisait a 0 px,
       et les deux premieres cartes se retrouvaient a 38 px de large collees
       l'une sur l'autre. Sans elle, toutes les colonnes sont implicites et
       prennent les 100 % de `grid-auto-columns`. */
    grid-template-columns: none;
    grid-auto-flow: column;
    /* `1fr` ET NON `auto` : Gabriel, « les deux cards ne sont pas de meme
       taille, celle du haut est plus petite que celle du bas, fais la taille de
       celle du bas ». Avec `auto`, chaque rangee prend la hauteur de son propre
       contenu et les deux cartes d'une paire sont depareillees. Avec `1fr`,
       les deux rangees partagent la hauteur a egalite, donc celle du texte le
       plus long — exactement ce qui est demande. */
    grid-template-rows: repeat(2, 1fr);
    grid-auto-columns: 100%;
    align-content: start;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    gap: 10px;
    padding-bottom: 4px;
  }
  .symptoms::-webkit-scrollbar { display: none; }
  .symptoms > .symptom { min-width: 0; }
  /* L'ancrage sur une carte sur deux : c'est lui qui fait les paires. */
  .symptoms > .symptom:nth-child(odd) { scroll-snap-align: start; }

  /* ── 2. LA HERO SE RESSERRE ENCORE ───────────────────────────────────────
     Deuxieme passe, apres celle du meme jour. Tout descend d'environ un
     cinquieme, dans le meme rapport, pour que la hierarchie ne bouge pas :
     titre 40 -> 32, texte 17 -> 15, boutons 14 -> 13, ligne ISO 11 -> 10. */
  /* `!important` OBLIGATOIRE, et c'est mesure : une regle posee plus haut dans
     cette feuille fixe `clamp(40px, min(6.4vw, 11vh), 82px) !important` sur le
     titre. Son plancher de 40 px ne descend jamais, quelle que soit la largeur.
     Une declaration ordinaire, meme plus specifique, ne peut pas la battre. */
  /* TROISIEME PASSE SUR LA HERO. 40 -> 32 le matin, 32 -> 27 ce soir :
     « reduit encore le titre et le texte ». Le titre garde son `!important`,
     une regle posee plus haut lui fixe un plancher de 40 px qu'aucune
     declaration ordinaire ne peut franchir.
     La hierarchie est preservee : le titre reste a 1,9 fois le texte, le
     rapport qu'il avait a 40/21 comme a 32/15. */
  .hero .hero__title { font-size: 30px !important; line-height: 1.08 !important; }
  .hero .hero__support--lede { font-size: 14px; line-height: 1.5; }

  /* TROISIEME REDUCTION DES BOUTONS — 2026-09-08, « reduis un peu plus la
     taille des boutons ». 56 px de haut a l'origine, puis 39, et 32 ici. La
     largeur n'est jamais imposee : elle vient du texte, donc reduire un bouton
     ici c'est reduire son corps, son rembourrage et son interligne.

     LA `line-height` EST LA TROISIEME VARIABLE, ET C'EST ELLE QUI COMMANDAIT.
     Premiere version de cette passe : corps a 11 px et rembourrage a 8, sans
     toucher a l'interligne. Mesure : 35,6 px sur un ecran haut contre 32,3 px
     sur un ecran court — pour les MEMES declarations. La cause est que le bloc
     des ecrans courts, lui, posait `line-height: 1.3` depuis une passe
     precedente, quand les ecrans hauts retombaient sur le 1,6 de base. Onze
     pixels de corps a 1,6 font 17,6 px de ligne, a 1,3 ils en font 14,3 : trois
     pixels et demi d'ecart, soit la quasi-totalite de la reduction demandee.
     Sans cette ligne, la demande etait donc honoree sur les petits telephones
     et pratiquement perdue sur les grands, ce qui est exactement l'inverse de
     ce qu'on veut.
     8 + 8 de rembourrage + 14,3 de ligne + 2 de filet = 32,3 px, partout. */
  .hero .hero__actions .btn {
    padding: 8px 14px;
    font-size: 11px;
    line-height: 1.3;
  }
  /* LA ZONE DE TOUCHE RESTE A 44 px MEME SI LE BOUTON N'EN FAIT PLUS QUE 32.
     C'est la seule facon d'obeir a la demande sans ajouter deux cibles trop
     petites au site : un rectangle invisible deborde le bouton en haut et en
     bas. Le doigt vise 44, l'oeil voit 32.
     C'est aussi la limite du procede, et autant l'ecrire ici : le debord est
     passe de 4 a 6 px, et un rectangle de touche qui deborde de plus du quart
     de son bouton commence a attraper les gestes destines a ce qui l'entoure.
     Sous 30 px de bouton, il faudra reduire autre chose que les boutons. */
  .hero .hero__actions .btn { position: relative; }
  .hero .hero__actions .btn::after {
    content: '';
    position: absolute;
    /* −6 px : 32,3 + 6 + 6 = 44,3 px. Mesure faite, pas estimee. */
    inset: -6px 0;
    border-radius: inherit;
  }
  .hero .hero__actions .btn .icon { width: 14px; height: 14px; }

  .hero .hero__trust-line { font-size: 10px; letter-spacing: 0.02em; }

  /* ── 4. L'EMBLEME DU CHATBOT PREND MOINS DE PLACE ────────────────────────
     Gabriel : « reduis la taille de l'embleme qui est notre chatbot ASHA IA ».
     Mesure : 92 x 92 px sur un ecran de 390, soit pres d'un quart de la
     largeur. Il masquait le coin bas droit de chaque page — il s'est retrouve
     par-dessus le contenu sur toutes mes captures de controle de la journee.
     64 px est la taille d'un bouton flottant standard, et reste tres au-dessus
     des 44 px de la cible tactile : on ne perd rien a le toucher. */
  .aia-reopen {
    width: 64px;
    height: 64px;
    /* `touch-action: none` EST LA CONDITION DU DEPLACEMENT. Sans elle, le
       navigateur interprete le glissement comme un defilement de la page et
       n'envoie jamais les `pointermove` : le bouton reste colle et rien ne
       laisse deviner pourquoi. Elle ne desactive que les gestes SUR le bouton,
       le reste de la page defile normalement. */
    touch-action: none;
    user-select: none;
    -webkit-user-select: none;
  }
  /* ET VOICI CE QUI BLOQUAIT VRAIMENT LE GLISSEMENT, trouve a la trace :
     l'embleme est une <img>, et le navigateur lance SON PROPRE glisser-deposer
     d'image des qu'on tire dessus. Il emettait alors un `pointercancel` juste
     apres le premier `pointermove`, et le script rendait la main sans rien
     avoir deplace — sans erreur, sans trace, rien.
     `pointer-events: none` fait passer le doigt a travers l'image jusqu'au
     bouton : plus d'image sous le curseur, donc plus de drag natif. */
  .aia-reopen img,
  .aia-reopen svg,
  .aia-reopen canvas {
    pointer-events: none;
    -webkit-user-drag: none;
  }

  /* ── 6bis. LE PIED DE PAGE SE REPLIE, ET LE LOGO PASSE EN BAS ────────────
     Gabriel : « il faudrait que Empresa ait une petite fleche simple et si on
     appuie toutes les pages de Empresa s'ouvrent, de meme pour Metodologias et
     Cobertura LATAM. Il faudrait inverser aussi la position, mettre le logo en
     bas et les trois sections au-dessus ».

     MESURE AVANT : le pied de page faisait 1616 px de haut sur telephone, dont
     931 px pour les trois listes de liens deroulees. On finissait la page par
     un mur de liens, et le bloc de marque — logo, phrase, reseaux — arrivait
     en PREMIER, avant meme de savoir de quoi on parlait.

     `order: 99` PLUTOT QU'UN DEPLACEMENT DANS LE HTML : la colonne de marque
     reste la premiere dans le document, donc premiere aussi pour un lecteur
     d'ecran et sur grand ecran ou la grille ne change pas. Seul l'ordre
     d'affichage change, et seulement ici. */
  .site-footer__grid {
    display: flex;
    flex-direction: column;
    gap: 0;
  }
  .site-footer__col--brand {
    order: 99;
    margin-top: var(--space-6);
    padding-top: var(--space-6);
    border-top: 1px solid var(--color-border);
  }

  /* Chaque colonne devient une ligne d'accordeon : un filet au-dessus, le
     titre en bouton pleine largeur, le contenu dessous. */
  .site-footer__col:not(.site-footer__col--brand) {
    border-top: 1px solid var(--color-border);
  }
  /* Le <h3> est maintenant DANS le bouton : il ne porte plus la mise en page,
     il ne porte que son texte. */
  .site-footer__col:not(.site-footer__col--brand) h3 { margin: 0; }
  .site-footer__pli > h3 { flex: 1 1 auto; }

  .site-footer__pli {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    width: 100%;
    /* 16 px en haut et en bas + 14 px de hauteur de ligne = 46 px : toute la
       ligne du titre est une cible, pas seulement le mot. Mesure : a 14 px de
       rembourrage la cible tombait a 42, sous le seuil de 44. */
    padding: 16px 0;
    background: none;
    border: 0;
    font: inherit;
    color: inherit;
    text-align: left;
    cursor: pointer;
  }

  /* LA FLECHE EST DESSINEE EN CSS, PAS IMPORTEE. Deux traits qui se croisent :
     une bordure sur deux cotes d'un carre, tourne de 45 degres. Aucun fichier
     a charger, aucune icone a maintenir, et elle prend la couleur du texte
     qui l'entoure. Elle pivote d'un demi-tour a l'ouverture. */
  .site-footer__chevron {
    flex: 0 0 auto;
    width: 8px;
    height: 8px;
    border-right: 1.5px solid currentColor;
    border-bottom: 1.5px solid currentColor;
    transform: rotate(45deg) translate(-2px, -2px);
    transition: transform var(--duration-normal) var(--ease-out);
    opacity: 0.7;
  }
  .is-ouvert .site-footer__chevron {
    transform: rotate(-135deg) translate(-2px, -2px);
    opacity: 1;
  }

  .site-footer__pliable { display: none; }
  .is-ouvert .site-footer__pliable { display: block; padding-bottom: var(--space-5); }

  /* ── 6ter. LA LEGENDE DU GLOBE DEVIENT UNE COMMANDE ──────────────────────
     Les trois listes de pays s'empilaient sous le globe : 534 + 202 + 268 px,
     soit mille pixels de listes. La legende, juste au-dessus, ne servait qu'a
     decoder trois couleurs de points. Elle les pilote maintenant, une seule
     ouverte a la fois. Le detail de la mecanique est dans presence-legende.js. */
  .presence__legend.is-onglets {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    justify-content: flex-start;
  }
  .presence__legend.is-onglets .presence__legend-item { margin: 0; }

  .presence__legend-btn {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    /* 10 px en haut et en bas + la ligne : la pastille seule ferait 8 px de
       cible, on vise la ligne entiere. */
    padding: 10px 12px;
    border-radius: 9999px;
    border: 1px solid var(--color-border);
    background: transparent;
    font: inherit;
    color: inherit;
    cursor: pointer;
    transition: background var(--duration-normal) var(--ease-out),
                border-color var(--duration-normal) var(--ease-out);
  }
  /* L'onglet ouvert se remplit, comme la reglette des heros et les eyebrows :
     un seul geste visuel pour dire « c'est celui-ci » dans toute la page. */
  .presence__legend-item.is-actif .presence__legend-btn {
    background: rgba(255, 255, 255, 0.10);
    border-color: rgba(255, 255, 255, 0.34);
  }

  /* Les listes : masquees sauf celle de l'onglet ouvert. Le quatrieme bloc
     (CSIRT Sectorial) n'a pas d'onglet et reste donc visible — le masquer
     sans commande pour le rouvrir l'aurait rendu inatteignable. */
  /* `--activa` en espagnol du cote des listes, `--active` du cote de la
     legende : les deux vocabulaires coexistent dans cette feuille, les deux
     sont donc vises. */
  .presence__cards.is-onglets > .presence__group--activa,
  .presence__cards.is-onglets > .presence__group--active,
  .presence__cards.is-onglets > .presence__float--expanding,
  .presence__cards.is-onglets > .presence__group--hub { display: none; }
  .presence__cards.is-onglets > .is-actif { display: block; }

  /* ── 7. LA VIDEO DU HERO SE CADRE SUR LE BOUCLIER ────────────────────────
     Gabriel : « fais apparaitre la video de la hero sur la version telephone,
     centree sur le bouclier ».

     LE CADRAGE EST UN CALCUL, PAS UN REGLAGE A L'OEIL. La video est en
     1920x1080 ; le hero de telephone est en portrait. `cover` cale donc sur la
     HAUTEUR et ne laisse voir qu'une bande verticale de 598 px de large sur
     les 1920 — 31 % de l'image. Quelle bande ? Celle qu'on choisit ici.
     Le bouclier a ete releve a l'image : il occupe x de 1200 a 1620, soit
     62 a 84 % de la largeur, centre a 73,4 %. Pour l'amener au milieu de la
     fenetre, son bord gauche doit tomber a 1111 px, ce qui donne
     (1111 / (1920 − 598)) = 84 % d'object-position.
     Verifie pour les quatre formats courants : a 84 % le bouclier tient
     ENTIER dans la fenetre, il n'est coupe d'aucun cote.

     `center` EN VERTICAL et non le `top` du bureau : sur un hero portrait,
     c'est la largeur qui est rognee, pas la hauteur. Le reglage vertical du
     bureau (une montee de quelques pixels pour ne pas couper l'embleme du
     haut-droit) n'a plus d'objet ici, l'embleme n'est de toute facon pas dans
     la bande visible. */
  .hero__bg-video {
    /* 80 % ET NON 84 : Gabriel, « bouge la video un peu vers la droite ». Un
       object-position PLUS PETIT decale l'image vers la droite — c'est
       contre-intuitif, mais le pourcentage designe le point de l'IMAGE qu'on
       aligne, pas un deplacement. Verification faite avant de choisir : a 80 %
       la fenetre visible couvre x de 1058 a 1656 dans la video, et le bouclier
       (1200 a 1620) y tient toujours entier. En dessous de 79 % il serait
       coupe a droite. */
    /* 78 % : deuxieme decalage vers la droite. La fenetre visible couvre alors
       x de 1031 a 1629 dans la video, et le bouclier (1200 a 1620) y tient
       encore entier — de justesse, 9 px de marge a droite. C'est le plancher :
       en dessous de 78 % il serait rogne. */
    /* 76 % : troisieme decalage vers la droite. C'est le premier qui coute
       quelque chose — la fenetre visible s'arrete a 1600 dans la source quand
       le bouclier va jusqu'a 1620 : 20 px lui sont retires a droite, soit 5 %
       de sa largeur. En dessous ca s'aggrave vite (11 % a 74 %, 24 % a 70 %). */
    /* 74 % : quatrieme decalage, demande le 2026-09-08 (« il faut deplacer le
       bouclier encore un peu vers la droite »). LE PRIX EST ANNONCE, il est
       calculable et il double : la fenetre visible s'arrete a 1574 dans la
       source, donc 46 px du bord droit du bouclier sortent du cadre, 11 % de
       ses 420 px de largeur.

       ET IL N'Y A PAS DE VERSION GRATUITE DE CE GESTE, verifie avant de
       l'ecrire. Deplacer la BOITE vers la droite plutot que le cadrage ne
       change rien : le hero rogne au meme endroit, c'est le meme bord. Elargir
       la boite non plus — `cover` cale sur la hauteur, et une boite plus haute
       montre une bande de source plus ETROITE, pas plus large. Tout pas vers
       la droite se paie sur le bord droit du bouclier. Le pas suivant coute
       encore 27 px (17 % a 72 %). */
    object-position: 74% center;
    /* LA VIDEO REMONTE DE 36 px. Gabriel : « monte un peu la video vers le
       haut ». Attention au reflexe : `object-position` en Y n'y peut RIEN ici.
       Le hero de telephone est en portrait, la video en 16:9 : `cover` cale
       sur la HAUTEUR et rogne la largeur, donc la hauteur est deja entierement
       visible et le reglage vertical n'a aucun effet. Il faut deplacer la
       boite elle-meme, et lui rendre en hauteur ce qu'on lui prend en haut,
       sinon un vide apparait en bas. Meme mecanique que sur le bureau. */
    top: -36px;
    height: calc(100% + 36px);
  }

  /* ── 5. LE HEADER RESTE OPAQUE SUR TELEPHONE ─────────────────────────────
     Gabriel : « fais apparaitre le header dans la version telephone dans la
     hero, normalement elle est transparente, en version mobile je veux pas
     qu'elle soit transparente ».

     LA TRANSPARENCE AVAIT UNE RAISON QUI NE VAUT PLUS ICI. Elle a ete posee le
     2026-09-04 pour laisser voir l'animation du bouclier derriere l'en-tete.
     Or SOUS 920 px la video ne se charge meme pas : le hero montre une image
     fixe, decision du 2026-08-18 pour ne pas faire telecharger 2,6 Mo sur un
     forfait mobile. Il n'y a donc plus d'animation a laisser voir, et le
     header transparent ne fait que poser du texte blanc sur une image.

     ON REMET EXACTEMENT LES VALEURS DU HEADER ORDINAIRE (l. 168) plutot que
     d'ecrire `all: revert` : la regle `.is-sur-hero` est posee par
     header-hero.js au defilement, elle reviendrait a chaque bascule. Le
     `!important` la bat quel que soit le moment ou la classe est ajoutee. */
  /* ── 6. LES TITRES DU SITE RENTRENT DANS L ECHELLE ───────────────────────
     Gabriel : « les titres des sections doivent etre un peu plus petits que le
     titre de la hero, aligne tout pour que ce soit coherent sur la version
     mobile ».

     POURQUOI CES REGLES EXISTENT ALORS QUE L'ECHELLE EST DANS LES TOKENS :
     plusieurs titres portent un `clamp()` avec un PLANCHER EN DUR, pose au fil
     des chantiers, qui ne descend jamais quelle que soit la largeur. Le titre
     de section, par exemple, etait fige a `clamp(26px, 3.3vw, 48px)` : son
     plancher de 26 px ignorait --text-3xl et laissait 4 px d'ecart seulement
     avec le titre de la hero. Ces trois lignes les rendent a l'echelle.

     LA HIERARCHIE OBTENUE, DE HAUT EN BAS :
       30  titre de la hero          — le sommet
       24  titres de section         — le cran demande, six points en dessous
       20  titres de bande et de CTA
       17  titres de carte
       14  le corps

     `!important` SUR CERTAINS, ET C'EST VERIFIE : leurs regles d'origine sont
     plus specifiques que celles-ci (`.page-hero--league .page-hero__title`,
     par exemple) ou portent un clamp a plancher fixe. Une declaration
     ordinaire ne les atteint pas — mesure avant de retirer ces mots. */
  .section-title { font-size: var(--text-3xl) !important; }
  .page-hero__title { font-size: 30px !important; }
  .method__name { font-size: var(--text-3xl) !important; }
  .cases__pane-title { font-size: var(--text-3xl); }
  .final-cta__title { font-size: var(--text-2xl) !important; }
  .solpanel__pane-title { font-size: var(--text-2xl); }

  .site-header.is-sur-hero {
    background: rgba(16, 16, 16, 0.85) !important;
    border-bottom-color: var(--color-border) !important;
    backdrop-filter: saturate(160%) blur(12px) !important;
    -webkit-backdrop-filter: saturate(160%) blur(12px) !important;
  }
}

/* ══ LA REGLETTE DES SIX HEROS      2026-09-07 ═════════════════════════════
   Gabriel, capture de CrowdStrike a l'appui : « chaque case est de la couleur
   du heros et s'allume quand on est sur la case, ceci est pour savoir qu'il
   faut scroller et combien de cases il y a en tout ».

   CE QUI EST REPRIS DE LA REFERENCE : la forme. Des barres horizontales
   epaisses aux bouts arrondis, largement espacees, posees sur une ligne. Pas
   des pastilles rondes — la barre dit une PROGRESSION, le point dit une
   position, et ici on veut les deux.

   CE QUI EN DIFFERE, ET C'EST LA DEMANDE DE GABRIEL : chez CrowdStrike les
   barres inactives sont blanches et l'active est rouge, toutes du meme rouge.
   Ici chaque barre porte la couleur de SON heros. La reglette devient donc
   aussi une legende : on lit les six couleurs de La Liga avant meme d'avoir
   fait defiler.

   L'ETAT ETEINT EST A 34 % D'OPACITE, PAS PLUS BAS. En dessous, l'argent de
   NGSOC (#E2E8F0) et le vert de GRC se confondent sur le fond sombre et on ne
   compte plus six barres mais quatre. C'est le compte qui compte : c'est la
   raison d'etre de la reglette.

   ELLE N'EXISTE QUE SUR TELEPHONE. Au-dessus de 760 px les six cartes sont en
   grille, tout est visible d'un coup : six barres allumees en permanence
   seraient un ornement sans fonction. */
.practices__pager { display: none; }

@media (max-width: 760px) {
  .practices__pager {
    display: flex;
    align-items: center;
    gap: 8px;
    /* Elle se pose juste au-dessus de la rangee, alignee sur le texte. */
    margin: 0 0 var(--space-4);
    padding: 0;
  }

  /* ELLE PARLE LA LANGUE DES EYEBROWS DE SECTION — 2026-09-07, demande de
     Gabriel : « elle doit suivre le meme design que les petits titres dans les
     eyebrow des differentes sections, le meme style sans le texte ».
     Relevé sur les eyebrows de la page : fond de la couleur a 7-14 %, filet de
     1 px a 42-46 %, rayon complet, hauteur 29 px. La reglette reprend les trois
     premiers ; seule la hauteur descend, parce qu'une pilule vide de 29 px
     serait un bouton, pas un repere. */
  .practices__pager-item {
    flex: 1 1 0;
    min-width: 0;
    height: 12px;
    padding: 0;
    border-radius: 9999px;
    background: color-mix(in srgb, var(--persona, var(--color-fg)) 12%, transparent);
    border: 1px solid color-mix(in srgb, var(--persona, var(--color-fg)) 55%, transparent);
    cursor: pointer;
    position: relative;
    transition: background var(--duration-normal) var(--ease-out),
                border-color var(--duration-normal) var(--ease-out);
  }
  /* Le rectangle invisible qui donne les 44 px au doigt sans epaissir la barre. */
  .practices__pager-item::after {
    content: '';
    position: absolute;
    inset: -16px 0;   /* 12 + 2 x 16 = 44 px sous le doigt */
  }

  /* L'active se REMPLIT, elle ne grossit plus : la pilule pleine contre la
     pilule vide est le meme contraste qu'entre un eyebrow allume et le fond,
     et il se lit sans changer la geometrie de la ligne. */
  .practices__pager-item.is-actif {
    background: var(--persona, var(--color-fg));
    border-color: var(--persona, var(--color-fg));
  }

  .practices__pager-item:focus-visible {
    outline: 2px solid var(--color-fg);
    outline-offset: 6px;
  }

  /* Chaque barre prend la couleur de son heros. Les memes tokens que les
     cartes, les cercles de la Liga et les bandes de metodologia : une seule
     source pour les six couleurs. */
  /* LES TONS -ink, ET PAS LES COULEURS PLEINES : cette section est posee sur
     un SOL CLAIR (data-sol="clair"). Les couleurs pleines y sont trop pales —
     l'argent de NGSOC (#E2E8F0) rempli sur du blanc etait litteralement
     invisible, la pilule active ne se distinguait pas des cinq eteintes.
     Les tokens -ink existent pour ce cas exact : ce sont les memes teintes
     assombries jusqu'a tenir 4,5:1 sur #F8FAFC. La reglette parle donc la meme
     langue que les eyebrows des sections CLAIRES, qui prennent aussi l'encre
     -ink plutot que la couleur pleine. */
  .practices__pager-item[data-persona="asha"]      { --persona: var(--color-primary-ink); }
  .practices__pager-item[data-persona="ctem"]      { --persona: var(--color-ctem-ink); }
  .practices__pager-item[data-persona="ngsoc"]     { --persona: var(--color-ngsoc-ink); }
  .practices__pager-item[data-persona="csirt"]     { --persona: var(--color-csirt-ink); }
  .practices__pager-item[data-persona="zerotrust"] { --persona: var(--color-zerotrust-ink); }
  .practices__pager-item[data-persona="grc"]       { --persona: var(--color-grc-ink); }

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

/* ══ LES ECRANS COURTS GARDENT DES LOGOS PLUS PETITS      2026-09-08 ═══════
   Ce bloc doit venir APRES celui qui agrandit les logos, sinon il est ecrase :
   meme specificite, la derniere declaration gagne. C'est la troisieme fois de
   la journee que l'ordre de declaration decide du resultat dans cette feuille.
   Sur un ecran de moins de 700 px de haut, la bande blanche et ses logos
   reprennent une taille reduite : c'est ce qui permet a la sous-navigation
   d'entrer sous la hero, mesure faite sur un iPhone SE. */
@media (max-width: 760px) and (max-height: 700px) {
  .trustband__item img { height: 26px; }
  .trustband__item--sq img { height: 34px; }
}


/* ══════════════════════════════════════════════════════════════════════════
   TELEPHONE — QUATRE DEMANDES DU 2026-09-08
   ══════════════════════════════════════════════════════════════════════════
   1. Le bas du pied de page : LinkedIn a gauche, FR EN ES a droite, l'avis de
      confidentialite colle sous le copyright.
   2. « Por qué ASHA » : les deux colonnes en accordeon.
   3. « Cómo operamos » : la frise des six etapes revient a l'horizontale.
   4. La bande d'alianzas : ses logos a la taille de ceux de la bande blanche
      du haut, et la bande recalee sur cette nouvelle taille.

   TOUT EST BORNE A 760 px, consigne permanente de Gabriel depuis le 2026-09-07 :
   « on travaille uniquement sur la version telephone jusqu'a ce que je te dise
   le contraire ». Rien de ce bloc n'atteint l'ordinateur.

   PLACE EN FIN DE FEUILLE, ET C'EST LA CONDITION POUR QUE CA MARCHE : plusieurs
   de ces selecteurs existent deja plus haut a specificite egale, et dans cette
   feuille c'est la DERNIERE declaration qui gagne. La frise, en particulier,
   est passee a la verticale par un `@media (max-width: 900px)` de la ligne 9145.
   Declaree avant lui, la regle horizontale ci-dessous n'aurait rien fait.       */

@media (max-width: 760px) {

  /* ── 1. LE BAS DU PIED : TROIS RANGEES AU LIEU D'UNE ─────────────────────
     Gabriel : « au lieu de Aviso de privacidad, mets le bouton LinkedIn a
     gauche et a droite les trois boutons FR EN ES ; le bouton Aviso de
     privacidad va colle en dessous de ASHA Solution 2026 ».
     Les deux elements deplaces viennent d'ailleurs dans la page — le LinkedIn
     du bloc de marque, les langues de l'en-tete — c'est pied-bas-mobile.js qui
     les amene ici. Ce bloc ne fait que les habiller. */
  .site-footer__bottom.pied-bas--mobile {
    flex-direction: column;
    align-items: stretch;
    /* 4 px, et c'est le mot « colle » de la demande : le copyright et l'avis
       forment une seule signature, pas deux lignes distinctes. L'air se met
       au-dessus, sous la rangee des commandes. */
    gap: 4px;
    text-align: center;
  }
  .pied-bas__rangee {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    margin-bottom: 14px;
  }
  /* .social-icons portait un `margin-top` utile dans la colonne de marque,
     nuisible ici ou il est seul sur sa ligne. */
  .pied-bas__rangee .social-icons { margin-top: 0; }

  .pied-bas__langues { display: flex; align-items: center; gap: 2px; }
  .pied-bas__langue {
    appearance: none;
    -webkit-appearance: none;
    background: none;
    border: 0;
    /* 44 px de cote : ces trois boutons sont la cible tactile la plus dense de
       la page, trois mots de deux lettres cote a cote. En dessous du seuil, on
       change de langue par erreur. */
    min-width: 44px;
    min-height: 44px;
    padding: 0 6px;
    border-radius: var(--radius-full);
    font-family: var(--font-mono);
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.08em;
    color: var(--color-muted-light);
    cursor: pointer;
    transition: color var(--duration-normal) var(--ease-out),
                background-color var(--duration-normal) var(--ease-out);
  }
  /* La langue en cours se distingue par l'encre ET par une plaque : l'encre
     seule (muted-light vers fg-light) ne fait qu'un ecart de gris, invisible du
     coin de l'oeil sur trois libelles de deux lettres. */
  .pied-bas__langue.is-actif {
    color: var(--color-fg-light);
    background: rgba(16, 16, 16, 0.06);
  }
  .pied-bas__langue:hover { color: var(--color-fg-light); }

  /* ── 2. « POR QUÉ ASHA » PASSE EN ACCORDEON ──────────────────────────────
     Gabriel : « fais El modelo habitual et El sistema ASHA en mode accordeon,
     petite fleche, et la card s'agrandit ».
     Les deux colonnes empilees faisaient 566 px de comparaison a faire defiler,
     donc une comparaison qu'on ne peut plus faire : la premiere carte est hors
     de l'ecran quand on lit la seconde. Repliees, les deux etiquettes tiennent
     dans un meme ecran. Meme grammaire de chevron que le pied de page, a la
     ligne 19282 : un carre a deux bordures qu'on fait pivoter. */
  .versus__col {
    padding: 6px 16px;
    gap: 0;
  }
  .versus__pli {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    width: 100%;
    padding: 12px 0;
    background: none;
    border: 0;
    font: inherit;
    color: inherit;
    text-align: left;
    cursor: pointer;
  }
  /* L'etiquette garde sa pilule mais perd son `align-self`, qui la collait a
     gauche du conteneur flex de la colonne : dans le bouton, c'est
     `justify-content` qui place, et l'alignement d'origine annulait le rejet
     du chevron a droite. */
  .versus__pli .versus__tag { align-self: auto; }
  .versus__chevron {
    flex: 0 0 auto;
    width: 8px;
    height: 8px;
    border-right: 1.5px solid currentColor;
    border-bottom: 1.5px solid currentColor;
    transform: rotate(45deg) translate(-2px, -2px);
    transition: transform var(--duration-normal) var(--ease-out);
    opacity: 0.7;
  }
  .versus__col.is-ouvert .versus__chevron {
    transform: rotate(-135deg) translate(-2px, -2px);
    opacity: 1;
  }
  .versus__col .versus__list { display: none; }
  .versus__col.is-ouvert .versus__list {
    display: flex;
    padding-bottom: 16px;
  }

  /* ── 3. LA FRISE DES SIX ETAPES REVIENT A L'HORIZONTALE ──────────────────
     Gabriel : « dans la section como operamos il faut refaire la partie
     Evaluar Diseñar Integrar Desplegar Operar Optimizar, il faut essayer que ce
     soit sur une ligne horizontale ».

     LE PROBLEME A RESOUDRE EST ARITHMETIQUE. Six libelles sur 350 px de
     colonne, c'est 58 px par etape ; « Desplegar » et « Optimizar » font neuf
     signes. Tout mettre sur une seule rangee obligeait a descendre sous 9 px de
     corps, c'est-a-dire a rendre la frise illisible pour la rendre horizontale.

     LA SORTIE : les libelles ALTERNENT au-dessus et en dessous du trait. Chacun
     dispose alors de deux fois sa largeur de colonne, environ 117 px, et le
     corps remonte a 10 px. La frise, elle, est bien une seule ligne horizontale
     — c'est le trait et ses six noeuds, ce que la demande designe.

     CHAQUE ETAPE EST UNE GRILLE DE TROIS RANGEES : haut, noeud, bas. Le noeud
     est toujours en rangee 2, le libelle en 1 ou en 3 selon la parite. Les
     items de `.flow__steps` s'etirent a hauteur egale, donc les six noeuds
     tombent tous a 50 % de la hauteur et le trait les traverse exactement.
     C'est aussi pourquoi le libelle a du recevoir un <span class="flow__nom">
     dans index.html : un noeud de texte nu est un item de grille anonyme, et
     un item anonyme ne peut pas se voir assigner une rangee. */
  .flow__steps {
    grid-template-columns: repeat(6, minmax(0, 1fr));
    gap: 2px;
  }
  .flow__steps::before {
    top: 50%;
    bottom: auto;
    left: calc(100% / 12);
    right: calc(100% / 12);
    width: auto;
    height: 1px;
    background: linear-gradient(90deg,
      var(--color-primary),
      rgba(255, 255, 255, 0.16) 30%,
      rgba(255, 255, 255, 0.16) 70%,
      var(--color-primary));
  }
  .flow__step {
    display: grid;
    grid-template-rows: 1fr auto 1fr;
    justify-items: center;
    align-items: center;
    gap: 6px;
    text-align: center;
    font-size: 10px;
    line-height: 1.15;
    letter-spacing: 0;
  }
  .flow__step .flow__dot { grid-row: 2; grid-column: 1; }
  .flow__nom { grid-column: 1; }
  /* Impairs au-dessus du trait, pairs en dessous : c'est l'alternance qui rend
     les 117 px a chaque libelle. `align-self` colle chacun contre le trait,
     sinon les libelles du haut flotteraient au plafond de leur rangee. */
  .flow__step:nth-child(odd)  .flow__nom { grid-row: 1; align-self: end; }
  .flow__step:nth-child(even) .flow__nom { grid-row: 3; align-self: start; }

  /* ── 4. LES LOGOS D'ALIANZAS A LA TAILLE DE CEUX DE LA BANDE BLANCHE ─────
     Gabriel : « fais les logos de la bande blanche cuadrante gartner /
     soluciones nichos de meme taille que la premiere bande blanche avec les
     logos, adapte la taille generale de la bande blanche en fonction de cela ».

     LA REFERENCE EST MESURABLE : la bande du haut pose ses logos a 34 px, et
     44 px pour les carres (voir .trustband__item img en fin de feuille). Ce
     sont ces deux valeurs qui sont reprises ici, a l'identique.

     ON PASSE D'UNE LARGEUR IMPOSEE A UNE HAUTEUR IMPOSEE, et c'est le coeur de
     la correction. Les cartes d'alianzas font 240 x 88 px avec un logo borne
     par `max-height`. Comme ces logos sont larges — CrowdStrike fait 1068 x 205
     — c'est la LARGEUR de la carte qui les dimensionnait, jamais le plafond de
     hauteur : leur taille reelle variait d'un logo a l'autre selon son rapport,
     ce qui est exactement l'incoherence relevee avec la bande du haut. En
     posant `height: 34px` et en liberant la largeur, les deux bandes obeissent
     enfin a la meme regle : hauteur egale, largeur libre. */
  .alliances--band .marquee .alliance-card {
    width: auto;
    height: auto;
    min-height: 0;
    padding: 0;
  }
  .alliances--band .marquee .alliance-card[data-brand="darkivore"] { width: auto; }
  .alliances--band .alliance-card__logo {
    height: 34px;
    width: auto;
    max-height: none;
    max-width: none;
  }
  /* Darkivore est le seul logo en portrait (222 x 260) : c'est le cas que la
     bande du haut traite avec .trustband__item--sq, et a la meme valeur. */
  .alliances--band .alliance-card[data-brand="darkivore"] .alliance-card__logo {
    height: 44px;
  }
  /* Le meme intervalle que la piste de la bande du haut, sinon la respiration
     entre logos trahirait la difference que l'on vient d'effacer. */
  .alliances--band .marquee__track { gap: 30px; }

  /* LA BANDE SE RECALE, second volet de la demande. Chaque piste perd 54 px de
     hauteur de carte, deux pistes en font 108 ; garder 44 px de rembourrage
     aurait laisse la bande aussi haute qu'avant pour un contenu plus court.
     30 px, c'est le rembourrage de la bande du haut : les deux bandes claires
     de la page ont alors le meme rythme. */
  .alliances.alliances--band {
    padding-top: 30px;
    padding-bottom: 30px;
  }
  .alliances--band .alliances__tier { margin-bottom: 0; }
  .alliances--band .alliances__tier-label { margin-bottom: 12px; }
  .alliances--band .alliances__tier + .alliances__tier { margin-top: 18px; }
  .alliances__band-cta { margin-top: 22px; }
}


/* ══════════════════════════════════════════════════════════════════════════
   TELEPHONE — QUATRE DEMANDES DE PLUS, MEME JOURNEE
   ══════════════════════════════════════════════════════════════════════════
   A. Tous les boutons d'action a la taille de ceux de la hero.
   B. Le secondaire de la hero prend le style du lien du CTA final.
   C. La carte du CTA final, beaucoup trop grande pour ce qu'elle contient.
   D. Le vide sous les sceaux du pied de page.

   Toujours borne a 760 px, et toujours pour la meme raison : « on travaille
   uniquement sur la version telephone jusqu'a ce que je te dise le contraire ».  */

@media (max-width: 760px) {

  /* ── A. TOUS LES BOUTONS A LA TAILLE DE CEUX DE LA HERO ──────────────────
     Gabriel : « Hablar con un experto, Cuéntenos su proyecto, Alianzas
     estratégicas, Hablar con el CSIRT, Conozca nuestras metodologías, je
     voudrais que tous ces boutons aient la meme taille que les boutons de la
     hero de la home page ».

     L'ECART MESURE AVANT : les deux boutons de la hero font 32 px de haut,
     tous les autres 52 — corps de 14 px, rembourrage de 14, interligne de
     22,4. Soit vingt pixels d'ecart, et deux grammaires de bouton sur la meme
     page. Ils reprennent les trois valeurs de la hero, a l'identique.

     LE REMBOURRAGE HORIZONTAL N'EST PAS DANS CETTE REGLE, ET C'EST VOULU :
     `.btn-pill` le fixe a 28 px avec `!important` (ligne 4316). Les boutons de
     la hero le subissent deja, donc les autres s'alignent dessus sans que rien
     ne soit a ecrire. Poser un 14 px ici aurait demande un `!important` de plus
     pour un resultat different de la reference demandee. */
  .btn {
    position: relative;
    padding: 8px 14px;
    font-size: 11px;
    line-height: 1.3;
  }
  .btn .icon { width: 14px; height: 14px; }
  /* La zone de touche reste a 44 px, meme dispositif que dans la hero. */
  .btn::after {
    content: '';
    position: absolute;
    inset: -6px 0;
    border-radius: inherit;
  }

  /* TROIS FAMILLES RESTENT A LEUR TAILLE, ET IL FAUT DIRE POURQUOI.
     Gabriel a nomme cinq boutons, et les cinq sont des liens d'action dans le
     contenu. Ces trois-la n'en sont pas :
       — les boutons de FORMULAIRE (« Enviar mensaje », « Enviar postulación »,
         « Limpiar ») terminent une saisie ; un bouton d'envoi de 32 px au bas
         d'un formulaire de dix champs se cherche, alors qu'un lien de section
         se lit en passant ;
       — celui du BANDEAU DE CONSENTEMENT est la seule commande d'un bandeau
         qui recouvre le bas de l'ecran, et il doit se voir du premier coup ;
       — ceux du MENU DEROULANT font toute la largeur du tiroir : reduire leur
         corps sans reduire leur boite ne produirait qu'un texte perdu au
         milieu d'un aplat.
     Ils sont donc remis a leurs valeurs d'avant, explicitement — y compris
     l'interligne, que la regle ci-dessus aurait sinon change a lui seul. Si
     Gabriel les veut aussi, il y a trois lignes a retirer ici. */
  form .btn,
  .consent__accepter,
  .mobile-menu__cta .btn {
    padding-top: 14px;
    padding-bottom: 14px;
    font-size: 14px;
    line-height: 1.6;
  }
  .mobile-menu__cta .btn { padding-top: 16px; padding-bottom: 16px; }
  form .btn .icon,
  .consent__accepter .icon,
  .mobile-menu__cta .btn .icon { width: 16px; height: 16px; }
  form .btn::after,
  .consent__accepter::after,
  .mobile-menu__cta .btn::after { content: none; }

  /* « CUÉNTENOS SU PROYECTO » N'EST PAS UN BOUTON, et c'est pour ca qu'il
     n'apparait pas dans le releve ci-dessus : c'est un `.section-cta`, un lien
     flechee sans plaque. Gabriel le cite dans la meme liste, il prend donc le
     meme corps que les autres. Sa fleche descend de 20 a 14 px pour rester
     proportionnee au texte, et `min-height: 44px`, pose ailleurs dans cette
     feuille pour la cible tactile, continue de tenir la zone de touche. */
  .section-cta,
  /* `#casos-exito .section-cta` existe plus haut (ligne 18554) et porte un
     identifiant : une classe seule ne pouvait pas passer devant, et le lien
     « Cuentenos su proyecto » — celui que Gabriel cite — est justement dans
     cette section. Mesure avant correction : 14 px quand tous les autres
     etaient a 11. Le selecteur est donc double a l'identique. */
  #casos-exito .section-cta { font-size: 11px; gap: 7px; }
  .section-cta .icon,
  #casos-exito .section-cta .icon { width: 14px; height: 14px; }

  /* ── B. LE SECONDAIRE DE LA HERO DEVIENT UN LIEN ─────────────────────────
     Gabriel : « je voudrais que le bouton Conocer el sistema ASHA soit du meme
     style que le bouton Agendar una sesión du CTA ».

     CE QUE CA CHANGE DANS LA HIERARCHIE, parce que c'est le vrai effet : la
     hero passe de deux plaques a une plaque plus un lien. C'est exactement la
     grammaire du CTA final, ou un seul aplat rouge porte l'action et le second
     choix se donne en lien flechee. Les deux extremites de la page se mettent
     donc a parler pareil.

     LES `!important` SONT LA A CAUSE DE `.btn-pill`, PAS PAR PARESSE. Cette
     classe pose `border-radius` et les deux rembourrages lateraux en
     `!important` (ligne 4315). Sans les reprendre, le lien gardait 28 px de
     retrait a gauche — son texte ne serait plus aligne ni sur le bouton
     au-dessus ni sur le titre — et son filet bas se serait arrondi aux deux
     bouts. Ce sont les deux seules declarations concernees.

     Les valeurs viennent de `.final-cta__link` (ligne 4730), transposees au
     corps de la hero : meme encre a 85 %, meme filet bas a 15 %, meme
     glissement de 3 px au survol. Le rembourrage vertical passe a 9 px pour
     que la boite fasse les 32 px du bouton d'a cote. */
  .hero .hero__actions .btn-secondary {
    padding: 9px 4px !important;
    border: 0;
    border-bottom: 1px solid rgba(255, 255, 255, 0.15);
    border-radius: 0 !important;
    background: none;
    box-shadow: none;
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    color: rgba(241, 245, 249, 0.85);
    font-weight: 600;
    /* Le lien ne doit pas s'etirer a la largeur du conteneur, sinon son filet
       bas traverse tout l'ecran. C'est le bloc L qui s'en charge desormais, par
       `align-items: center` sur la rangee — et qui centre en meme temps le lien
       sous le bouton, ce que `align-self: flex-start` interdisait. */
    transition: color 200ms var(--ease-out),
                border-color 200ms var(--ease-out),
                transform 200ms var(--ease-out);
  }
  .hero .hero__actions .btn-secondary:hover,
  .hero .hero__actions .btn-secondary:focus-visible {
    color: var(--color-fg);
    background: none;
    border-bottom-color: rgba(255, 255, 255, 0.5);
    /* Le glissement lateral du CTA, et non la montee des plaques : un lien qui
       se souleve n'a pas de plaque a soulever. */
    transform: translateX(3px) !important;
    box-shadow: none;
  }

  /* ── C. LA CARTE DU CTA FINAL SE REGLE SUR SON CONTENU ───────────────────
     Gabriel : « la card dans le CTA est beaucoup trop grande pour ce qu'elle
     contient ».

     LA MESURE DONNE RAISON A L'OEIL, ET DEUX FOIS. Sur la home, a 390 px :
     section de 591 px pour 159 px de contenu, soit 432 px de vide. Sur
     metodologia : 591 px pour 207 px de contenu.

     ET LA CAUSE EST HISTORIQUE, pas accidentelle. Trois choses se cumulaient :
       — `padding: clamp(96px, 14vw, 184px)`, qui plafonne a 96 px sur
         telephone, donc 192 px a lui seul ;
       — `min-height: 70vh` sur la section, soit 591 px sur un ecran de 844 ;
       — `min-height: 372px` sur la carte, pose sous 48rem pour egaliser les
         trois CTA du site quand ils portaient encore un lede, un badge et une
         ligne de mentions.
     Ces trois textes ont ete retires les uns apres les autres a la demande de
     Gabriel — le lede le 14/08, le badge le 14/08, la ligne de mentions le
     07/09 — et les planchers sont restes derriere eux. Ils tenaient une carte
     qui n'a plus la moitie de son contenu.

     LES DEUX PLANCHERS TOMBENT DONC, et le rembourrage descend a 44 px. La
     carte se regle sur ce qu'elle contient : environ 250 px sur la home. Le
     plancher inter-pages n'a plus d'objet sur telephone, ou les trois CTA sont
     l'un sous l'autre dans le parcours et jamais cote a cote. */
  .final-cta--poster {
    padding-top: 44px;
    padding-bottom: 44px;
    min-height: 0;
  }
  .final-cta--poster .final-cta__inner { min-height: 0; }
  /* LES 40 px SOUS LES ACTIONS TOMBENT AUSSI. `.final-cta--poster
     .final-cta__actions` porte `margin-bottom: var(--space-10)`, pose quand une
     ligne de mentions suivait le bloc. Sur la home cette ligne n'existe plus
     depuis le 07/09 : la marge separait donc les actions du BORD de la carte,
     par-dessus le rembourrage de section. Mesure : 45 px au-dessus du titre
     contre 85 px sous les actions, pour une carte censee etre centree.
     Sur metodologia, ou la ligne de mentions subsiste, la marge garde son role
     et c'est elle qui explique le 33 px du bas — d'ou `:last-child`, qui ne
     retire la marge que quand les actions ferment la carte. */
  .final-cta--poster .final-cta__actions:last-child { margin-bottom: 0; }
  /* Ce rembourrage haut compensait le badge retire ; le rembourrage de section
     s'en charge maintenant, et le garder ajoutait 28 px au vide. */
  .final-cta .final-cta__inner { padding-top: 0; }
  /* Les equerres suivent la carte : 40 px a 24 px des bords sur une carte de
     250 px se rejoignaient presque au milieu des cotes. */
  .final-cta__corner { width: 28px; height: 28px; }
  .final-cta__corner--tl { top: 14px; left: 14px; }
  .final-cta__corner--tr { top: 14px; right: 14px; }
  .final-cta__corner--bl { bottom: 14px; left: 14px; }
  .final-cta__corner--br { bottom: 14px; right: 14px; }
  /* Le lien secondaire du CTA prend le corps commun, comme son jumeau de la
     hero. Son rembourrage vertical tenait la cible tactile a 44 px sans aide ;
     a 11 px de corps il en faut 15, la valeur est donc recalculee et non
     reprise : 15 + 15 + 14,3 = 44,3 px. */
  .final-cta__link { padding: 15px 4px; font-size: 11px; }
  .final-cta__link .icon { width: 13px; height: 13px; }

  /* ── D. LE VIDE SOUS LES SCEAUX DU PIED DE PAGE ──────────────────────────
     Gabriel : « il y a de l'espace vide entre Certificación ISO 9001:2015 […]
     FIRST, Improving Security Together et la ligne de en dessous ».

     CE VIDE A UNE CAUSE PRECISE, ET ELLE EST DE CE MATIN. `.site-footer__bottom`
     porte `margin-top: var(--space-16)`, soit 64 px, calibres pour un pied de
     page en quatre colonnes ou cette marge separe deux blocs larges. Sur
     telephone les colonnes sont empilees : ces 64 px tombent sous la derniere
     chose du bloc de marque. Et cette derniere chose etait le lien LinkedIn,
     jusqu'a ce que pied-bas-mobile.js le deplace en bas ce matin — les sceaux
     ont herite du vide qui suivait le LinkedIn, plus la marge propre du
     LinkedIn qui, elle, est partie avec lui. */
  .site-footer__bottom { margin-top: 24px; }
  .site-footer__badges { margin-bottom: 0; }
}

@media (max-width: 760px) {
  /* ── E. DEUX RANGEES DE PASTILLES DEVIENNENT DES FRISES ──────────────────
     Gabriel, deux demandes du meme jour et du meme ordre :
       « dans la section industrias clave, fais que tous ces boutons soient sur
         une ligne horizontale et qu'ils defilent comme les bandes blanches et
         les logos »
       « les cards des heros sont beaucoup trop longues ; les boutons du style
         SOC Management ISO 9001 etc, mets-les sur une ligne horizontale et
         fais-les defiler, dans chaque card des heros »

     MESURE AVANT. Les onze secteurs s'empilaient sur QUATRE rangees, 130 px de
     capitales rouges sous le titre de la section. Les pastilles des cartes de
     heros faisaient 63 px sur quatre des six cartes et 98 px sur ZeroTrust,
     dans une carte qui en fait 655 : c'est le second poste apres l'image.

     LA MECANIQUE est dans frises-defilantes.js, y compris la raison pour
     laquelle elle n'est pas ecrite dans le HTML comme celle des bandes de
     logos, et le cas ou le defilement se coupe de lui-meme. Ce bloc ne fait
     que regler l'intervalle, la duree et le corps. */

  /* La frise des secteurs va d'un bord de l'ecran a l'autre, comme les deux
     bandes de logos : c'est `100vw` plus la compensation de gouttiere, le meme
     couple que `#alianzas` a la ligne 14271. C'est ce qui fait qu'une frise se
     lit comme une bande et non comme un contenu de colonne. */
  .marquee--secteurs {
    width: 100vw;
    margin-inline: calc(50% - 50vw);
  }
  .industries__sectors.secteurs--defile,
  .industries__sectors.is-ligne {
    display: flex;
    flex-wrap: nowrap;
    gap: 8px;
    padding-inline: 20px;
  }
  /* 38 s POUR UNE PISTE DE ~2 400 px, ET C'EST UN CALCUL. L'animation ne
     parcourt que la moitie de la piste, environ 1 200 px : a 38 s cela fait
     31 px/s, la vitesse exacte de la bande de clients depuis son reglage du
     06/09 (85 s pour une course de 2 624 px). Les trois frises de la page
     defilent donc a la meme allure, ce qui est la condition pour qu'elles se
     lisent comme un seul dispositif et non comme trois trouvailles. */
  .industries__sectors.secteurs--defile { animation-duration: 38s; }

  /* La pastille reste lisible mais cesse de crier : le corps descend d'un cran
     et l'interlettrage se resserre, comme partout ailleurs sur telephone. Les
     capitales sont gardees — c'est ce qui les distingue d'une liste de liens.
     `nowrap` est indispensable : « Sector público » se couperait en deux et la
     frise perdrait sa ligne unique. */
  .industries__sector {
    padding: 5px 10px;
    font-size: 9px;
    letter-spacing: 0.05em;
    white-space: nowrap;
  }
  .industries__sector .dot { width: 5px; height: 5px; }

  /* LA FRISE DES CARTES DE HEROS reste dans la carte, elle : une pastille qui
     sortirait du cadre passerait sous le bord arrondi et sous l'ombre. Seul
     l'estompage des bords, herite de `.marquee`, dit qu'il y a une suite. */
  .marquee--chips { width: 100%; }
  .practice__chips.chips--defile,
  .practice__chips.is-ligne {
    display: flex;
    flex-wrap: nowrap;
    justify-content: flex-start;
    gap: 6px;
  }
  /* 26 s POUR UNE PISTE DE ~600 px : la course vaut 300 px, donc 11,5 px/s.
     TROIS FOIS PLUS LENT QUE LES DEUX AUTRES FRISES, ET C'EST VOULU. Une bande
     pleine largeur qui defile a 31 px/s se regarde passer ; la meme vitesse
     dans une carte de 270 px de large ferait traverser une pastille en neuf
     secondes, six fois en parallele, juste sous un texte qu'on est en train de
     lire. Le mouvement doit se remarquer une fois, pas retenir l'oeil. */
  .practice__chips.chips--defile { animation-duration: 26s; }
  .practice__chip { white-space: nowrap; }
}


/* ══ LA BANDE DU CONSTAT PASSE AU CYAN                     2026-09-08 ═══════
   Gabriel : « les parties en rouge de cette petite section — El ataque
   automatizado por IA ya es casi instantáneo. / Nuestra respuesta también. /
   Hablar con el CSIRT — fais-les en bleu ».

   DEUX ROUGES ETAIENT EN JEU, ET UN SEUL SE VOYAIT AU REPOS : la seconde
   ligne, « Nuestra respuesta también », en --color-primary-lift ; et l'encre
   plus la bordure du bouton AU SURVOL, dans le meme lift. Les deux passent,
   sinon le survol aurait ramene du rouge dans une bande devenue cyan.

   LE BLEU N'EST PAS CHOISI, IL EST DEJA LA. --color-csirt (#06B6D4) est la
   couleur de persona du CSIRT dans le systeme, et cette bande se termine
   precisement par « Hablar con el CSIRT ». La phrase et le bouton parlent donc
   de la meme chose et le disent maintenant avec la meme couleur ; un bleu
   quelconque aurait ajoute une teinte de plus a une palette qui en a six.

   CONTRASTE, MESURE SUR LE NOIR REEL DE CETTE SECTION (#000, la mesure du
   06/09 donne une luminance de fond nulle au 90e centile) :
       rouge lift #EF4444    5,58:1   (ce qui partait)
       cyan      #06B6D4     8,57:1   (ce qui arrive)
   Le seuil est de 3 ici — 30 px en gras est du texte large. Le cyan passe donc
   avec plus de marge que le rouge qu'il remplace, et il se detache toujours
   nettement du blanc de la premiere ligne (20,07:1). C'est ce qui compte dans
   ce bloc : l'oeil doit lire le constat, PUIS la reponse.

   PAS DANS UN `@media` : une couleur n'est pas une version. La consigne
   « uniquement le telephone » porte sur les mises en page, et cette bande est
   la meme sur les deux.

   TROIS ETATS EN UNE JOURNEE, ET C'EST GABRIEL QUI TRANCHE LE TROISIEME.
   Le matin je posais ces regles hors de tout `@media` en decidant seul qu'« une
   couleur n'est pas une version » ; le soir je les bornais au telephone pour
   rendre au bureau son etat d'origine, en laissant la question ouverte ; et
   Gabriel repond : « pour la version ordinateur, nuestra respuesta tambien doit
   aller en bleu comme la version mobile ». Elles sont donc globales, et cette
   fois sur son mot.
   Le contraste avait ete mesure aux deux largeurs avant le premier essai :
   8,57:1 pour le cyan contre 5,58:1 pour le rouge, seuil de 3 a cette taille. */
.anillos__bascule-respuesta {
  color: var(--color-csirt, #06B6D4);
}
.anillos__cta .btn-secondary:hover,
.anillos__cta .btn-secondary:focus-visible {
  color: var(--color-csirt-soft);
  border-color: var(--color-csirt);
  background: color-mix(in srgb, var(--color-csirt) 8%, transparent);
}

@media (max-width: 760px) {
  /* ── F. LE MENU DEROULE PERD SON LIBELLE « IDIOMA » ──────────────────────
     Gabriel : « dans le menu deploye, retirer Idiomas et mets FR EN ES au
     milieu comme les autres boutons ASHA CSIRT ».
     Le libelle et le selecteur etaient aux deux bouts d'un
     `justify-content: space-between` : le mot a gauche, les trois langues
     collees a droite, seule chose du tiroir a n'etre pas centree. Les trois
     langues prennent la place du bloc entier et se centrent comme les deux
     boutons qui les suivent. Deux lettres suffisent a dire ce que le libelle
     annoncait. */
  .mobile-menu__lang-label { display: none; }
  .mobile-menu__lang { justify-content: center; }

  /* ── G. LES HEROS DE PAGE PRENNENT LA GRAMMAIRE DE LA HOME ───────────────
     Gabriel : « aligne tous les boutons des differents heros de toutes les
     pages au meme style que les deux boutons de la hero de la home page ».
     La home a une plaque rouge et un lien flechee ; les cinq heros de page
     avaient encore deux plaques. Les valeurs sont celles de la home, reprises
     par le meme selecteur — c'est le bloc B qui les porte, ce bloc-ci n'ajoute
     que la cible.
     LE SOL A ETE VERIFIE AVANT : ces heros sont tous sombres, ce que dit deja
     `.btn-secondary { color: var(--color-fg) }` dans le systeme. L'encre claire
     du lien y tient donc, ce qui n'aurait pas ete vrai sur un sol clair. */
  .page-hero__actions .btn-secondary {
    padding: 9px 4px !important;
    border: 0;
    border-bottom: 1px solid rgba(255, 255, 255, 0.15);
    border-radius: 0 !important;
    background: none;
    box-shadow: none;
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    color: rgba(241, 245, 249, 0.85);
    font-weight: 600;
    align-self: flex-start;
    transition: color 200ms var(--ease-out),
                border-color 200ms var(--ease-out),
                transform 200ms var(--ease-out);
  }
  .page-hero__actions .btn-secondary:hover,
  .page-hero__actions .btn-secondary:focus-visible {
    color: var(--color-fg);
    background: none;
    border-bottom-color: rgba(255, 255, 255, 0.5);
    transform: translateX(3px) !important;
    box-shadow: none;
  }

  /* ── H. LES TROIS METRIQUES DE « NOSOTROS » EN RANGEE QUI DEFILE ─────────
     Gabriel : « cette partie dans nosotros — 12+ Años de experiencia / 80+
     Clientes satisfechos / 215+ Proyectos realizados — fais en sorte que ce
     soit sur la meme ligne horizontale et qu'on puisse scroller vers la droite
     pour voir l'info suivante ».

     MEME DISPOSITIF QUE LES SIX HEROS, a la valeur pres, et c'est deliberé :
     le site n'a besoin que d'UNE grammaire de rangee defilante. Carte a 88 %
     de la largeur pour que la tranche de la suivante se voie, ancrage au bord
     gauche, et `scroll-padding-inline` sans lequel l'ancrage annule le
     rembourrage du conteneur (piege paye le 07/09 sur les heros).

     `height: auto` EST LA POUR LA MEME RAISON QUE SUR LES CARTES DE HEROS :
     une grille de deux colonnes devient un flex a hauteur indefinie, et toute
     hauteur declaree — meme retombee sur `auto` — empeche `align-items:
     stretch` d'egaliser. Sans cette ligne, les trois metriques auraient les
     trois hauteurs de leurs legendes.

     LES FILETS CHANGENT DE SENS. En grille, ils separaient une colonne de
     l'autre (droite sur les impairs) et une rangee de l'autre (bas sur les
     deux premieres). En rangee il n'y a plus qu'un voisin, a gauche : c'est le
     seul filet qui garde un sens. Les deux autres sont annules, `!important`
     compris, sinon le premier garderait un filet a droite au milieu de rien. */
  .metrics--editorial {
    display: flex;
    grid-template-columns: none;
    flex-wrap: nowrap;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scroll-snap-type: x mandatory;
    scroll-padding-inline: var(--container-px);
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    gap: 0;
    margin-inline: calc(-1 * var(--container-px));
    padding-inline: var(--container-px);
  }
  .metrics--editorial::-webkit-scrollbar { display: none; }
  .metrics--editorial > .metric {
    flex: 0 0 88%;
    scroll-snap-align: start;
    height: auto;
    padding: var(--space-6) var(--space-5);
  }
  .metrics--editorial > .metric:last-child { margin-right: var(--container-px); }
  .metrics--editorial .metric:nth-child(odd) { border-right: 0 !important; }
  .metrics--editorial .metric:nth-child(-n+2) { border-bottom: 0 !important; }
  .metrics--editorial .metric + .metric { border-left: 1px solid var(--color-border) !important; }
  /* 64 px de chiffre, c'est le plancher du `clamp` d'origine et il ne se
     declenche jamais sur telephone : 9vw n'y vaut que 35 px. Dans une carte de
     88 % ces 64 px passent, mais ils ecrasent la legende qui les suit. 48 px
     gardent au chiffre son role de titre sans qu'il occupe la moitie de la
     carte. */
  .metrics--editorial .metric__num { font-size: 48px !important; }
}

@media (max-width: 760px) {
  /* ── I. LES TROIS RANGEES D'« ALIANZAS ESTRATÉGICAS » DEFILENT SEULES ────
     Gabriel, en deux temps le meme jour : d'abord « fais la fonction defile
     vers la droite pour trois sous-sections », puis « fais defiler
     AUTOMATIQUEMENT Nuestros cuatro fantasticos, Alianzas especializadas et
     Nuestro rango con cada fabricante ». La seconde demande remplace la
     premiere, et ce bloc a ete reecrit plutot que complete : laisser les deux
     dispositifs sur les memes rangees aurait donne un conteneur qu'on fait
     glisser au doigt PENDANT qu'une animation le translate.

     MESURE AVANT : les quatre fantastiques s'empilaient sur deux rangees de
     200 px, les cinq alianzas specialisees sur trois rangees, les cinq niveaux
     de partenariat sur CINQ rangees de 150 px — 1 640 px pour la sous-section,
     un ecran et demi de logos.

     ELLES RESTENT DANS LA COLONNE, sans le `100vw` des bandes de la home, et
     c'est une contrainte de la page : sur nosotros un rail de navigation occupe
     la gouttiere (voir la ligne 14268, ou la meme question s'etait posee pour
     #alianzas). Une piste pleine largeur passerait dessous. L'estompage des
     bords, herite de `.marquee`, suffit a dire qu'il y a une suite.

     TROIS VITESSES, ET C'EST LA HAUTEUR QUI LES DICTE. La regle du jour est
     celle de la bande de clients : environ 31 px/s pour une frise pleine
     largeur, trois fois moins dans une carte de heros. Ici les trois rangees
     sont larges mais PORTENT DU TEXTE a lire — un niveau de partenariat, une
     note. On se cale donc entre les deux, d'autant plus lentement que la carte
     dit plus de choses : les logos seuls a ~22 px/s, les niveaux a ~14. La
     course vaut la moitie de la piste, d'ou les durees.

     LA MECANIQUE — doublement de la suite, `aria-hidden` sur les copies, arret
     si la suite tient deja — est dans frises-defilantes.js, avec la raison pour
     laquelle elle n'est pas ecrite dans le HTML comme celle des bandes de
     logos. */
  .marquee--f4,
  .marquee--nichos,
  .marquee--niveaux {
    width: 100%;
    /* PAS D'ESTOMPAGE SUR CES TROIS RANGEES, ET C'EST LE « DEGRADE BIZARRE »
       QUE GABRIEL SIGNALE. `.marquee` porte un masque
       `linear-gradient(90deg, transparent 0%, #000 6%, #000 94%, transparent)`
       qui fait entrer et sortir les items en fondu. Il est juste pour les
       bandes de la home, ou les items sont des logos detoures sur un fond
       continu : le fondu n'y touche que du vide.
       Ici les items sont des CARTES OPAQUES — plaques blanches pour les quatre
       fantastiques, plaques teintees a filet pour les niveaux. Le masque
       s'applique a la carte elle-meme : sur les 21 premiers pixels de la
       rangee, la plaque blanche de CrowdStrike se dissout dans le noir de la
       section. Ce n'est pas un degrade de decor, c'est une carte a moitie
       effacee, et ca se lit comme un defaut de rendu.
       Sans masque, la carte est coupee NET au bord de la boite : c'est le rendu
       normal d'un carrousel, et il dit « il y en a d'autres » au lieu de dire
       « quelque chose ne va pas ».
       Les deux autres frises gardent leur estompage : les pastilles de secteurs
       et celles des cartes de heros n'ont pas de plaque, le fondu n'y mord que
       sur du texte deja sortant. */
    mask-image: none;
    -webkit-mask-image: none;
  }

  .fantastic4__row.f4--defile,
  .fantastic4__row.is-ligne,
  #alianzas .alliances__row.nichos--defile,
  #alianzas .alliances__row.is-ligne,
  #alianzas .partner-levels.niveaux--defile,
  #alianzas .partner-levels.is-ligne {
    display: flex;
    flex-wrap: nowrap;
    grid-template-columns: none;
    justify-content: flex-start;
    align-items: stretch;
    gap: 12px;
    margin: 0;
    padding: 0;
    list-style: none;
  }
  /* 40 s ET NON 23, ET C'EST UNE ESTIMATION CORRIGEE PAR LA MESURE.
     Le premier reglage partait d'« une piste d'environ 1 000 px » ; elle en
     fait 2 016 — quatre plaques de 240 px, doublees, plus les intervalles —
     donc une course de 1 008 px. A 23 s cela donnait 44 px/s : une plaque
     traversait l'ecran en neuf secondes, plus vite que la bande de clients
     de la home pour une frise trois fois plus etroite. 40 s ramenent a
     25 px/s, l'allure des deux rangees qui la suivent. */
  .fantastic4__row.f4--defile { animation-duration: 40s; }
  /* ~22 px/s : cinq cartes, piste d'environ 1 200 px, course 600. */
  #alianzas .alliances__row.nichos--defile { animation-duration: 27s; }
  /* ~14 px/s : ces cartes portent un niveau et une note d'une ligne et demie ;
     a la vitesse des logos, la note sortait du cadre avant d'etre lue. */
  #alianzas .partner-levels.niveaux--defile { animation-duration: 60s; }

  /* DES LARGEURS EN PIXELS, ET SURTOUT PAS EN POURCENTAGE — piege paye a la
     mesure. Premiere version : `flex: 0 0 62%`, la valeur qui marche pour les
     rangees qu'on fait glisser au doigt. Mais une piste de marquee est en
     `width: max-content` : sa largeur vient de ses enfants, et un enfant en
     pourcentage la demande en retour. Le navigateur ne refuse pas, il resout
     — et tres mal. Mesure : la piste des quatre fantastiques annoncait
     17 563 px pour quatre plaques, et comme `.fantastic4__item` porte un
     `aspect-ratio: 16/9`, la rangee faisait 1 229 px de HAUT. Le controle
     passait toutes ses assertions : une ligne, des copies, une animation, des
     hauteurs egales. Toutes vraies, et le resultat inutilisable.
     En pixels il n'y a plus de circularite : la piste additionne des largeurs
     connues.
       240 px  la plaque de logo, 135 px de haut avec son rapport 16/9
       170 px  la carte d'alliance, sur les 240 du bureau
       290 px  la carte de niveau, qui porte trois lignes de texte */
  .fantastic4__row > .fantastic4__item { flex: 0 0 240px; width: 240px; height: auto; }
  #alianzas .alliances__row > .alliance-card { flex: 0 0 170px; width: 170px; height: 88px; }
  #alianzas .partner-levels > .partner-level { flex: 0 0 290px; width: 290px; height: auto; }
}

@media (max-width: 760px) {
  /* ── J. TOUTES LES PHRASES D'INTRODUCTION A LA TAILLE DE CELLE DE LA HERO ─
     Gabriel : « la taille de texte de la hero de la home page "Los que rebasan
     las herramientas convencionales…" est la bonne taille ; regarde dans tout
     le site que tous les textes du meme type aient la meme taille ».

     LA REFERENCE MESUREE : `.hero__support--lede` fait 14 px / 1,5, pose
     explicitement le 07/09. Tout le reste de cette famille tombait sur
     `var(--text-lg)`, qui vaut 15 px dans l'echelle telephone — un pixel
     d'ecart, invisible seul, mais qui se lit des qu'une lede de section suit
     un ecran plus loin celle de la hero.

     LE RELEVE, A 390 px, SUR LES SEPT PAGES :
         lede de la hero            14 px    x1   (la reference)
         lede de hero de page       15 px    x6   toutes les pages interieures
         lede de section            15 px   x15   cinq pages
         note d'alianzas            15 px    x1   (c'est une .section-lede)
         texte de panneau           15 px   x12   index et nosotros
         description de heros       16 px    x6   metodologia
     Les six familles ci-dessus jouent le meme role : une phrase qui explique
     ce que le titre juste au-dessus annonce. Elles passent toutes a 14 px / 1,5.

     CE QUI N'Y PASSE PAS, ET POURQUOI. `.practice__desc` fait 12 px : c'est du
     texte DANS une carte, pas sous un titre, et les cartes de heros ont leur
     propre echelle depuis le 07/09 — l'aligner a 14 px rallongerait les six
     cartes que Gabriel vient de faire raccourcir. `.metric__caption` fait 12 px
     pour la meme raison. Ces deux-la sont un autre registre, pas un oubli.

     L'INTERLIGNE SUIT LA TAILLE, ET C'EST LE POINT QU'ON RATE FACILEMENT : ces
     familles etaient a 1,6, la reference est a 1,5. Garder 1,6 sur un corps
     reduit aurait donne des paragraphes plus aeres que celui de la hero, donc
     visiblement differents malgre une taille identique. C'est le rapport des
     deux qui fait qu'un texte « se ressemble », pas la seule taille.

     `.page-hero__lede` A BESOIN DE DEUX CLASSES : une regle a une classe existe
     deja plus haut (ligne 2878) et une autre a deux classes la cible sur les
     heros de la Liga (ligne 2670). Le selecteur ci-dessous en porte deux, ce
     qui suffit a passer devant les deux sans `!important`. */
  .page-hero .page-hero__lede,
  .section-head .section-lede,
  .section-lede,
  .solpanel__pane-text,
  .method__body .method__desc {
    font-size: 14px;
    line-height: 1.5;
  }
}

@media (max-width: 760px) {
  /* ── K. LA BANDE DE CERTIFICATIONS DE « NOSOTROS » ───────────────────────
     Gabriel : « dans la partie certificaciones, retire "Marcos de referencia y
     estándares" et mets au milieu "Certificación ISO/IEC 27001:2022, ATR" ».

     « AU MILIEU » A ETE TRANCHE PAR LA MESURE, parce que la phrase pouvait
     vouloir dire deux choses : centrer le sceau, ou le placer en position
     centrale des trois. Releve a 390 px : `.cert-strip` est une grille de DEUX
     colonnes de 169 px, donc deux rangees pour trois sceaux —
         rangee 1  FIRST [x=21]   ISO 9001 [x=202]
         rangee 2  ISO 27001 [x=21]   et rien a cote
     Le troisieme sceau est seul sur sa rangee, cale a gauche, avec 169 px de
     vide a sa droite. Il n'y a pas de « position centrale » a occuper dans une
     grille paire : ce qu'on voit, c'est un orphelin desaligne. « Au milieu »
     est donc le centrage, et c'est ce qui est fait.

     LE SELECTEUR DIT LA CONDITION PLUTOT QUE LE RANG : `:last-child` combine a
     `:nth-child(odd)` ne s'applique QUE si le nombre de sceaux est impair,
     c'est-a-dire seulement quand il y a vraiment un orphelin. Ajouter un
     quatrieme sceau un jour remplirait la seconde rangee, et cette regle
     s'eteindrait d'elle-meme au lieu de centrer un sceau qui a un voisin. */
  .cert-strip > .cert-card:last-child:nth-child(odd) {
    grid-column: 1 / -1;
    justify-self: center;
    width: 100%;
    max-width: 169px;
  }

  /* Le libelle part sur telephone seulement : la consigne du moment porte sur
     cette version, et la distinction qu'il annonce — ce a quoi ASHA S'ALIGNE,
     par opposition a ce qu'ASHA DETIENT juste au-dessus — reste utile sur un
     ecran large ou les deux rangees se voient d'un coup. Sur telephone elles
     sont a deux ecrans l'une de l'autre : le libelle n'oppose plus rien, il
     annonce juste des logos qu'on voit deja. */
  .about-frameworks .frameworks__label { display: none; }
}

@media (max-width: 760px) {
  /* ── L. LE SECONDAIRE PASSE SOUS LE PRIMAIRE, CENTRE SUR LUI ─────────────
     Gabriel : « mets le bouton Conocer el sistema ASHA juste centre sur le
     bouton Hablar con un experto ; dans toutes les heros cela doit etre pareil,
     le bouton principal en haut, le bouton secondaire en bas et centre par
     rapport au bouton principal ».

     POURQUOI ILS S'ETAIENT MIS COTE A COTE : en devenant un lien, le secondaire
     est passe de 189 a 139 px de large. Les deux tenaient alors sur une ligne de
     350 px et `flex-wrap: wrap` les y a mis, sans que personne le demande.
     C'est un effet de bord de la transformation en lien, pas une intention.

     `width: fit-content` FAIT TOUT LE TRAVAIL. La rangee etant en colonne, sa
     largeur se cale sur son plus large enfant — le bouton primaire — et
     `align-items: center` centre le lien dans cette largeur. Le bloc, lui,
     reste cale a gauche sur le titre. Sans `fit-content`, un conteneur pleine
     largeur aurait centre le primaire aussi, et le primaire doit rester aligne
     sur le titre au-dessus.

     `align-self: flex-start` DU BLOC B EST RETIRE ICI : il avait ete pose pour
     empecher le lien de s'etirer a toute la largeur, ce que `align-items:
     center` fait desormais, et il annulerait le centrage demande. */
  .hero .hero__actions,
  .page-hero__actions {
    flex-direction: column;
    flex-wrap: nowrap;
    align-items: center;
    width: fit-content;
  }
  .hero .hero__actions .btn-secondary,
  .page-hero__actions .btn-secondary { align-self: center; }

  /* ── M. LE CORRIDOR REVIENT DERRIERE LE PERSONNAGE ───────────────────────
     Gabriel : « change la position de l'embleme pour faire en sorte qu'elle
     soit derriere chaque heros » — precise ensuite : « l'image qu'il y a
     derriere chaque heros dans la version ordinateur, il faut juste la
     replacer pour que l'embleme soit pres du heros ».

     CE QU'EST CETTE IMAGE : le « corridor », un fond de section par persona
     (assets/images/bg/corridor/*.webp). Chacun porte une SPHERE LUMINEUSE d'un
     cote et un couloir de particules qui s'en echappe. Sur ordinateur la sphere
     est cadree derriere le personnage — c'est le reglage du 22/08, avec deux
     fichiers retournes pour cela.

     POURQUOI ELLE N'ETAIT PLUS LA SUR TELEPHONE, mesure faite :
       — l'image est en `cover` sur une section de 390 x 1129 px, donc mise a
         l'echelle par la HAUTEUR : 2489 px de large dont on ne voit que 390,
         soit 16 % ;
       — son cadrage etait `center 62 %`, ce qui montre la bande CENTRALE de
         l'image, la ou il n'y a rien : la sphere est a 12 % ou 87 % ;
       — et le voile `linear-gradient(180deg, band-bg 0 %, band-bg 38 %,
         transparent 66 %)` peint du NOIR PLEIN sur les 38 premiers pour cent de
         la section. Le personnage, lui, est a 33 % (centre mesure a 375 px sur
         1129). La sphere aurait donc ete cachee la meme si elle avait ete
         cadree juste.
     Trois raisons pour un meme resultat : rien derriere le personnage.

     LE CADRAGE EST CALCULE, PAS TATONNE. Mesure : la figure est centree
     horizontalement et son centre vertical tombe entre 367 et 387 px du haut
     de la section, sur les six personas et de 360 a 412 px de large — donc a
     10 px pres, ce qui est stable. La sphere est a 42 % de la hauteur de
     l'image et l'image fait 1600 x 900.
         hauteur imposee H telle que 0,42 H = 375     ->  H = 893 px
         largeur correspondante   893 x 16/9          ->  1587 px
         abscisse de la sphere    0,12 x 1587 = 190   ou  0,87 x 1587 = 1381
     En ancrant l'image en haut de la section et en decalant de `50 % moins
     l'abscisse de la sphere`, la sphere tombe exactement au centre horizontal
     de la section, a 375 px du haut : sur le personnage.

     LA HAUTEUR IMPOSEE REND LE CADRAGE INDEPENDANT DE LA SECTION, et c'est ce
     qui le rend fiable : les six sections font de 1097 a 1402 px selon la
     longueur de leur texte et la langue. Avec `cover`, chacune aurait mis la
     sphere ailleurs.

     LE VOILE DEVIENT RADIAL. Un degrade lineaire ne peut pas a la fois montrer
     le tiers haut et cacher le reste ; une ellipse centree sur le personnage
     fait exactement cela, et elle efface au passage les bords de l'image.

     TROIS PERSONAS ONT LEUR SPHERE A GAUCHE, TROIS A DROITE, et ce n'est pas
     arbitraire : asha, ngsoc et zerotrust pointent un fichier dont la sphere
     est a 12 % ; ctem, csirt et grc un fichier a 87 % — pour ctem et zerotrust
     ce sont les versions retournees du 22/08. Mesure refaite sur les huit
     fichiers du dossier avant d'ecrire ces valeurs. */
  /* LES DEUX DECLARATIONS DE `--sphere` SONT SUR LE MEME POIDS, ET C'EST
     OBLIGATOIRE. Premiere version : la valeur par defaut etait posee sur
     `.method--dark.method--media-start[data-persona]` (deux classes) et
     l'exception sur `.method--dark[data-persona="ctem"]` (une classe). Mesure :
     csirt calculait encore `calc(50% - 190px)`, l'exception ne passait pas.
     La variable est donc posee ici, a une classe et un attribut, et les trois
     personas a sphere droite la redefinissent juste apres au meme poids —
     l'ordre de declaration tranche alors, comme partout dans cette feuille. */
  .method--dark[data-persona] { --sphere: 190px; }   /* sphere a 12 % */
  .method--dark[data-persona="ctem"],
  .method--dark[data-persona="csirt"],
  .method--dark[data-persona="grc"] { --sphere: 1381px; }   /* sphere a 87 % */

  .method--dark.method--media-start[data-persona],
  .method--dark.method--media-end[data-persona] {
    background-size: auto, auto 893px;
    background-position: 50% 0, calc(50% - var(--sphere)) 0;
    background-image:
      radial-gradient(320px 300px at 50% 375px,
        transparent 18%,
        color-mix(in srgb, var(--band-bg) 72%, transparent) 62%,
        var(--band-bg) 100%),
      var(--corridor);
  }
}

@media (max-width: 760px) {
  /* ── N. BOLSA DE TRABAJO : LES QUATRE AIRES DEFILENT ─────────────────────
     Gabriel : « dans la page bolsa de trabajo, fais le systeme de scroll vers
     la droite pour les differentes cards des differents postes ; supprime de
     cette page la photo qu'on voit apres le formulaire ».

     MESURE AVANT : les quatre cartes d'aires s'empilaient en une colonne,
     chacune avec son icone, son titre et trois lignes de description, soit
     198 px piece et 810 px de section pour quatre intitules — Ingenieria,
     PMO, Comercial, Administracion. En rangee, la section tient dans un ecran.

     MEME GRAMMAIRE QUE LES CINQ AUTRES RANGEES DU JOUR, a la valeur pres : la
     carte prend 82 % de la largeur, un peu moins que les 88 % des heros parce
     qu'elle porte moins de texte et que la tranche de la suivante doit se voir.
     Et le meme `height: auto` que partout : `.about-card` ne declare pas de
     hauteur, mais l'egalisation par `align-items: stretch` est ce qui evite
     quatre hauteurs differentes selon la longueur des descriptions. */
  .about-cards.about-cards--4 {
    display: flex;
    grid-template-columns: none;
    flex-wrap: nowrap;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scroll-snap-type: x mandatory;
    scroll-padding-inline: var(--container-px);
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    gap: 12px;
    margin-inline: calc(-1 * var(--container-px));
    padding-inline: var(--container-px);
    padding-bottom: 6px;
  }
  .about-cards.about-cards--4::-webkit-scrollbar { display: none; }
  .about-cards.about-cards--4 > .about-card {
    flex: 0 0 82%;
    scroll-snap-align: start;
    height: auto;
  }
  .about-cards.about-cards--4 > .about-card:last-child { margin-right: var(--container-px); }

  /* LA PHOTO APRES LE FORMULAIRE S'EN VA. Elle est declaree DECOR dans le HTML
     — `alt` vide et `aria-hidden` — donc rien ne se perd a la retirer : aucun
     lecteur d'ecran ne l'annoncait, et aucune information n'y est portee que le
     texte ne dise. Sur ordinateur elle remplit la colonne de droite du
     formulaire et garde tout son sens ; sur telephone la grille passe en une
     colonne et la photo tombe SOUS le formulaire, ou elle n'accompagne plus
     rien : 530 px d'image entre le bouton d'envoi et le pied de page.
     `display: none` et non un retrait du HTML : la consigne du moment porte sur
     la version telephone. */
  #bolsa-form .bolsa-photo { display: none; }
}

@media (max-width: 760px) {
  /* ── O. LES SIX HEROS REVIENNENT DANS LA HERO DE metodologias ────────────
     Gabriel : « fais apparaitre les 6 super-heros en arriere-plan de la page
     dans cette hero ».

     ILS ETAIENT MASQUES EN DEUX TEMPS, et les deux regles avaient leur raison :
     sous 1100 px, `.liga-row__fig:not(--capitana) { display: none }` ne gardait
     que la capitane parce que six figures y devenaient « une haie de
     silhouettes de 60 px de large » ; sous 700 px, `.liga-row { display: none }`
     retirait meme celle-la. C'est ce second seuil que Gabriel renverse.

     LA TAILLE EST CALCULEE POUR QUE LES SIX TIENNENT, pas choisie a l'oeil.
     Mesure des six fichiers, tous hauts de 1520 px : leurs largeurs cumulees
     valent 2,77 fois leur hauteur commune (43 + 56 + 68 + 31 + 39 + 40 pour
     100 px de haut). Avec cinq intervalles de −18 px :
         2,77 H − 90 = 380      ->  H = 170 px
     170 px de haut donnent donc 381 px de rangee, qui tient dans 390 sans
     rogner GRC a droite ni CTEM a gauche.

     L'INTERVALLE PASSE DE −40 A −18 px. Le chevauchement franc du bureau
     (jusqu'a −96) fait lire les six comme un groupe ; a 170 px de haut il les
     empile au point qu'on ne distingue plus que trois silhouettes. −18 px
     laisse chacune se lire tout en gardant le groupe.

     0,38 D'OPACITE, ET C'EST LE TITRE QUI COMMANDE. Le bureau est a 0,72, la
     capitane seule a 0,50 sous 1100 px. Ici les figures passent DERRIERE un
     titre de 30 px et une lede de 14 : ce sont elles qui doivent ceder. Le
     halo de couleur de chacune reste, c'est lui qui les identifie a cette
     taille plus que leur silhouette. */
  .liga-row { display: flex; }
  .liga-row__fig:not(.liga-row__fig--capitana) { display: block; }
  .liga-row {
    justify-content: center;
    /* CENTREES DANS LA HAUTEUR, ET PLUS COLLEES AU BAS. Gabriel : « tu peux
       centrer les heros dans la hero de la page metodologias ».
       Horizontalement elles l'etaient deja — mesure : la rangee va de x5 a x385
       sur un ecran de 390. C'est la VERTICALE qui les tenait en bas : la regle
       du bureau porte `align-items: flex-end`, pensee pour une hero ou les six
       figures font 454 px et posent leurs pieds sur le bord de la bande. A
       234 px dans une hero de 680, ce meme ancrage les laissait dans le tiers
       bas, sous les deux commandes, avec le tiers haut vide.
       `center` les remet au milieu du cadre. Elles passent alors derriere la
       lede plutot que derriere les boutons : a 0,38 d'opacite c'est un fond,
       et la lede est en blanc plein a 20:1. */
    /* REDESCENDUES, MAIS PAS COLLEES AU BORD. Gabriel : « redescends les heros
       de la hero de la page metodologias et mets-les un peu plus a gauche ».
       Trois etats successifs, et celui-ci est entre les deux precedents :
           `flex-end`  figures de 523 a 757, pieds sur le bord de la bande, et
                       le vide de la hero rempli — l'etat d'origine du bureau ;
           `center`    figures de 300 a 534, symetriques, mais 199 px de hero
                       vide sous elles, ce que j'avais signale ;
           ici        `flex-end` plus 100 px de retrait bas : de 423 a 657.
       Elles redescendent de 123 px sans revenir se coller, et leurs pieds
       tombent dans la zone de fondu du masque de la rangee — qui commence a
       82 % de sa hauteur, soit y 635 — donc l'atterrissage reste doux. */
    align-items: flex-end;
    /* 12 px APRES 100, quatrieme etat de ce reglage. Gabriel : « descends
       beaucoup les heros de la hero de metodologias ». Les figures passent de
       423-657 a 511-745, soit 88 px plus bas, et reviennent presque au bord de
       la bande — l'etat d'origine du bureau, a douze pixels pres.
       Ces douze pixels ne sont pas un reste : ils gardent les pieds a
       l'interieur de la zone de fondu du masque de la rangee, qui commence a
       82 % de sa hauteur. A zero, la derniere ligne de pixels serait tranchee
       net par le bord de la section. */
    padding-bottom: 12px;
    /* UN PEU PLUS A GAUCHE, ET CA SE PAIE SUR CTEM. La rangee fait 380 px dans
       un cadre de 390 : il n'y a que 5 px de jeu de chaque cote. Decaler de
       22 px vers la gauche sort donc CTEM de 17 px — sa cape, sur les 132 px de
       large de sa figure, soit 13 % de la plus large des six. C'est le prix du
       geste et il n'y a pas d'autre monnaie : a moins de rapetisser les six, ce
       que la demande precedente venait d'ecarter.
       Le decalage passe par un rembourrage DROIT et non par une marge : la
       rangee reste centree dans son cadre, et c'est le cadre qui se resserre.
       346 px de cadre pour 380 de rangee -> −17 a 363.
       PUIS 80 px, second decalage demande : 310 px de cadre pour 380 de rangee,
       donc de −35 a 345. CTEM sort de 35 px, soit 26 % de ses 132 px de large.
       C'est le quart de la figure la plus large, et c'est la limite que je
       signale : au-dela, ce n'est plus une cape qui depasse, c'est un
       personnage coupe en deux. */
    padding-right: 80px;
    /* `gap` REFUSE LES VALEURS NEGATIVES, ET C'EST LA LECON DE CE REGLAGE.
       J'ai ecrit `gap: -18px` puis `gap: -40px` en croyant resserrer la
       rangee ; mesure au navigateur : `column-gap` calcule vaut 0px dans les
       deux cas. La propriete borne les negatifs a zero, sans erreur ni
       avertissement. Le chevauchement se fait donc par une MARGE NEGATIVE entre
       voisins, ci-dessous, qui elle accepte les negatifs.
       A SIGNALER, PAS CORRIGE : le reglage du bureau porte
       `gap: clamp(-96px, -4.4vw, -40px)` et tombe dans le meme piege — les six
       figures n'y chevauchent donc pas comme le commentaire le decrit. Hors
       consigne du moment, qui ne porte que sur le telephone.

       −40 px ET NON −18, ET C'EST CE QUI PAIE LES FIGURES PLUS GRANDES.
       Gabriel : « tu peux augmenter la taille des heros de la hero de la page
       metodologias ». La largeur de la rangee vaut 2,77 fois la hauteur des
       figures — la somme mesuree de leurs six rapports — moins cinq
       intervalles. A intervalle constant, grandir de 40 px de haut coute 111 px
       de large, qu'on n'a pas. On les prend donc sur le chevauchement :
           170 px de haut, intervalle −18 : 2,77 x 170 − 90  = 381 px
           210 px de haut, intervalle −40 : 2,77 x 210 − 200 = 382 px
       Meme largeur de rangee, figures 24 % plus grandes. Le chevauchement plus
       franc les rapproche aussi de la lecture du bureau, ou il va jusqu'a
       −96 px et fait lire les six comme un groupe plutot qu'une frise. */
    gap: 0;
  }
  /* LE CHEVAUCHEMENT, PAR MARGE ET NON PAR GOUTTIERE. Mesure des six largeurs
     rendues a 390 px : 132 + 120 + 98 + 91 + 81 + 58 = 580 px pour un ecran de
     390. Sans chevauchement, CTEM et GRC sortaient de 95 px chacun, coupes par
     l'`overflow: hidden` de la hero. Cinq marges de −40 px ramenent la rangee a
     380 px, soit 5 px de marge de chaque cote. */
  .liga-row__fig + .liga-row__fig { margin-left: -40px; }
  /* LES SIX HAUTEURS SONT PER-PERSONA, ET IL FAUT LES REPRENDRE UNE PAR UNE.
     Un `height: 210px` sur `.liga-row__fig` ne faisait rien : six regles de la
     ligne 17444 posent une hauteur par persona sur
     `.page-hero--liga .liga-row__fig[data-persona="x"]`, soit deux classes et
     un attribut. Mesure apres coup : les figures etaient toujours a 110-157 px.

     ET CES SIX VALEURS NE SONT PAS INTERCHANGEABLES : 38 / 36,5 / 34,5 / 33 /
     31,5 / 30,5 vw forment un etagement voulu, qui donne de la PROFONDEUR au
     groupe — NGSOC devant, GRC au fond. Les aplatir a une valeur unique aurait
     fait grandir les six et perdu l'etagement. Elles sont donc toutes
     multipliees par le meme facteur, 1,58, ce qui garde les rapports.

     LE FACTEUR VIENT DE LA LARGEUR DISPONIBLE, calculee sur les six rapports
     mesures des fichiers (0,391 pour NGSOC, 0,432 ASHA, 0,559 CSIRT, 0,399
     ZeroTrust, 0,678 CTEM, 0,311 GRC) :
         largeur de rangee = somme(hauteur x rapport) − 5 intervalles
     Avec l'intervalle a −40 px et une cible de 380 px de rangee sur un ecran de
     390, il faut 580 px de largeurs cumulees. Les six valeurs ci-dessous les
     donnent : 91 + 98 + 120 + 81 + 132 + 58 = 580.
     Les bornes `min(80%, 748px, ...)` restent en place et ne mordent pas : 80 %
     d'une hero de 680 px valent 544, la valeur en vw commande partout. */
  .page-hero--liga .liga-row__fig[data-persona="ngsoc"]     { height: min(80%, 748px, 60vw); }
  .page-hero--liga .liga-row__fig[data-persona="asha"],
  .page-hero--liga .liga-row__fig--capitana                 { height: min(80%, 716px, 58vw); }
  .page-hero--liga .liga-row__fig[data-persona="csirt"]     { height: min(80%, 678px, 55vw); }
  .page-hero--liga .liga-row__fig[data-persona="zerotrust"] { height: min(80%, 650px, 52vw); }
  .page-hero--liga .liga-row__fig[data-persona="ctem"]      { height: min(80%, 622px, 50vw); }
  .page-hero--liga .liga-row__fig[data-persona="grc"]       { height: min(80%, 604px, 48vw); }

  /* ── AR. LES SIX PASTILLES DE CONSTELLATION A LA TAILLE DU BOUTON ────────
     Gabriel : « les cards CTEM CSIRT ASHA NGSOC ZeroTrust GRC dans la hero de
     metodologias, tu peux les faire de meme taille que le bouton Conocer
     metodologias ».
     Le bouton fait 32,3 px : 8 px de rembourrage haut et bas, 11 px de corps a
     1,3 d'interligne, 1 px de filet de chaque cote. Les pastilles reprennent
     les trois valeurs a l'identique — elles etaient a 9 px de rembourrage et
     12 px de corps, soit 37 px. Leur rembourrage lateral suit celui du bouton
     plutot que le 16/14 asymetrique du bureau, qui existait pour laisser
     respirer un point de 10 px devenu 8. */
  .liga-constellation__node {
    padding: 8px 14px;
    font-size: 11px;
    line-height: 1.3;
    gap: 8px;
  }
  .liga-constellation { gap: 10px 14px; }
  /* L'INTERLIGNE DU LIBELLE, ET C'EST LUI QUI FAISAIT LES 2,3 px MANQUANTS.
     Mesure : pastille 30 px contre bouton 32,3, pour un rembourrage, un corps
     et un filet identiques. La difference etait dans la hauteur de LIGNE du
     contenu — le libelle porte son propre interligne, plus serre que le 1,3 du
     bouton. On le lui donne, et les deux boites se calculent pareil :
     14,3 de ligne + 16 de rembourrage + 2 de filet = 32,3 px.
     C'est la cause qu'on corrige, pas la hauteur : un `min-height` chiffre
     aurait derive des que le bouton change.
     LE CORPS AUSSI, second tour : l'interligne seul donnait 33,6 px, parce que
     le libelle garde son propre corps de 12 px (ligne 17187, la regle qui
     ramene les petits titres a 12 sur telephone). 1,3 x 12 = 15,6 et non 14,3.
     Le libelle prend donc les DEUX valeurs du bouton, corps et interligne. */
  .liga-constellation__label { font-size: 11px; line-height: 1.3; }
  .liga-row__fig img,
  .liga-row__fig--capitana img { opacity: 0.38; }

  /* ── P. LE BOUTON DE « QUIÉNES SOMOS » SE CENTRE ─────────────────────────
     Gabriel : « centre le bouton contactanos dans la section quienes somos ».
     Il fermait la colonne de texte, cale a gauche sous le dernier paragraphe.
     `margin-inline: auto` sur un element de largeur naturelle suffit ; il faut
     le passer en `flex` pour que la marge automatique ait prise, un `inline-flex`
     restant dans le flux du texte. */
  .who__cta {
    display: flex;
    width: fit-content;
    margin-inline: auto;
  }

  /* ── Q. LA DEVISE ENTRE LES DEUX PARAGRAPHES, CENTREE ────────────────────
     Gabriel : « place "How things should be done." entre les deux paragraphes
     du texte de la section et centre-le au milieu de la page ».
     Le deplacement est fait par devise-mobile.js — et il deplace le NOEUD, pas
     seulement l'ordre visuel, parce que c'est l'ordre de LECTURE qui etait en
     cause : le premier paragraphe finit par « … se transformó en el lema : »,
     il annonce la devise. Le detail est dans le fichier.
     Ce qui reste ici est l'habillage : centrage, et de l'air au-dessus et en
     dessous pour qu'elle se lise comme une citation entre deux paragraphes et
     non comme un titre de l'un des deux. */
  .essence-body p.essence-motto--intercalee {
    text-align: center;
    margin: clamp(18px, 4vw, 28px) 0;
    /* 26 px : la devise fait `clamp(32px, 3.6vw, 60px)`, donc 32 px sur
       telephone — plus gros que le titre de section a 24 px, ce qui la ferait
       passer pour le titre du bloc. A 26 px elle reste la voix la plus forte du
       paragraphe sans depasser le titre au-dessus. */
    font-size: 26px;
    line-height: 1.15;
  }

  /* ── R. « CUÉNTENOS SU PROYECTO » SE CENTRE ET RESPIRE ───────────────────
     Gabriel : « centre le bouton Cuentenos su proyecto dans la section casos
     de exito et mets-le un peu plus en bas, il est trop colle aux informations
     du haut ».
     Ce lien a ete deplace en fin de section le 07/09 ; il a herite du
     `margin-bottom: 6px` qui servait a poser sa ligne de base sur celle du
     titre quand il vivait DANS l'en-tete de section, a cote de lui. A la fin
     d'une section cette valeur n'a plus d'objet et le collait a la carte du
     dessus. Il devient un bloc de largeur naturelle, centre par marges
     automatiques, avec 28 px d'air au-dessus. */
  #casos-exito .section-cta {
    display: flex;
    width: fit-content;
    margin: 28px auto 0;
  }
}

@media (max-width: 760px) {
  /* ── S. LE TITRE DU CTA DESCEND, LE VIDE SOUS LUI SE FERME ───────────────
     Gabriel : « dans le CTA de la home, "¿Está preparado para el próximo
     ataque?" est trop en haut, descends un peu, il y a de l'espace vide entre
     cela et le bouton ; pareil pour les autres CTA ».

     LE VIDE EST FAIT DE DEUX MARGES, MESUREES : 56 px entre le bas du titre et
     le haut des actions, soit `margin-bottom: 24px` sur le titre PLUS
     `margin-top: 32px` sur le bloc d'actions. Ni l'une ni l'autre ne se voyait
     seule ; c'est leur somme qui creusait un trou plus haut que le titre
     lui-meme (42 px).

     ET LE TITRE DESCEND SANS QU'ON LE DEPLACE. La carte est un flex en colonne
     avec `justify-content: center` : refermer l'ecart raccourcit le bloc, et le
     bloc raccourci se recentre — le titre gagne donc la moitie de ce qui a ete
     retire. 56 px d'ecart tombent a 22, le bloc perd 34 px, le titre descend de
     17. C'est exactement le geste demande, obtenu en retirant du vide plutot
     qu'en ajoutant un decalage.

     Mesure attendue apres : section de 251 px sur la home au lieu de 285, et
     les trois CTA restent identiques entre eux — c'etait la demande du matin. */
  .final-cta--poster .final-cta__title { margin-bottom: 12px; }
  .final-cta--poster .final-cta__actions { margin-top: 10px; }

  /* ── T. LES TROIS HEROS DE PAGE MONTRENT LEUR EMBLEME ────────────────────
     Gabriel : « l'image de la hero de bolsa de trabajo est mal positionnee,
     elle devrait etre plus vers la gauche pour qu'on voie l'embleme en
     arriere-plan », puis « de meme pour les pages asha csirt et la page
     contacto ».

     LA MESURE DIT POURQUOI ON NE LE VOYAIT PAS, ET ELLE VAUT POUR LES TROIS.
     Chaque fond fait 1440 x 810 et porte son motif lumineux A DROITE :
         hero-dispersion       (bolsa)     x ~ 77 %
         hero-soleil-embleme   (csirt)     x ~ 72 %
         hero-lever-plat       (contacto)  x ~ 77 %
     Sur telephone la hero fait environ 390 x 430 px : `cover` cale donc sur la
     HAUTEUR et l'image devient 765 px de large, dont on ne voit que 390, soit
     51 %. Avec `object-position: center`, cette fenetre couvre les 24 a 75 % de
     l'image — l'embleme, a 72-77 %, tombe juste dehors. Il n'etait pas mal
     cadre : il etait coupe.

     96 % ET NON 100 %. A 96 % la fenetre couvre les 47 a 98 % de l'image et
     l'embleme se retrouve vers 55 % de l'ecran, donc au milieu du cadre. A
     100 % on collerait le bord droit du fichier, et ce bord est vide — la
     dispersion y retombe a une luminance nulle : on aurait gagne l'embleme et
     ramene une bande noire avec lui.

     LA QUATRIEME PAGE N'EST PAS CONCERNEE, verifie avant d'ecrire la regle :
     hero-vague-bouclier (nosotros) a son motif a 52 %, deja au centre. La regle
     ne vise donc que les trois pages nommees, et non `.page-hero__bg-img` en
     general — sur nosotros elle aurait deplace un motif qui etait a sa place.

     `center` EN VERTICAL, ET C'EST SANS EFFET, donc sans risque : la fenetre
     fait toute la hauteur de l'image sur ce format, il n'y a rien a rogner
     verticalement. La valeur est ecrite pour que la declaration soit complete.

     LE SELECTEUR PASSE PAR LA HERO ET NON PAR LE <body>, qui ne porte aucune
     classe sur ces trois pages — seul nosotros a `page-nosotros`. Les heros,
     elles, sont distinguees : `--careers` sur bolsa, `--contact` sur csirt ET
     contacto, `--about` sur nosotros. Deux classes suffisent donc a viser les
     trois pages nommees et a laisser nosotros de cote. */
  .page-hero--careers .page-hero__bg-img,
  .page-hero--contact .page-hero__bg-img { object-position: 96% center; }
}

@media (max-width: 760px) {
  /* ── U. L'AVIS DE CONFIDENTIALITE SE COLLE AU COPYRIGHT ──────────────────
     Gabriel : « tu peux coller le Aviso de privacidad avec ASHA Solution 2026,
     todos los derechos reservados ».
     Le bloc annoncait deja 4 px d'intervalle, et il en mesurait 20 : le <p> du
     copyright porte un `margin-bottom: 16px` du style de base, qui s'ajoute au
     gap de la colonne. Un `gap` ne remplace pas les marges, il s'y ajoute —
     c'est le piege classique du flex, et il ne se voit pas dans la regle qu'on
     vient d'ecrire.
     A NOTER : ce n'est pas le placement choisi ce matin dans les trois
     propositions (« sous les sceaux, avant le filet ») ; cette demande-ci le
     remplace, l'avis reste sous le copyright. */
  .site-footer__bottom.pied-bas--mobile p { margin-bottom: 0; }

  /* ── V. LES TITRES DES SEPT HEROS S'ALIGNENT SUR CELUI DE LA HOME ────────
     Gabriel : « aligne la position des titres de tous les heros avec celle de
     la hero de la home page, qui est la reference ».

     LE RELEVE, A 390 px, DIT L'ECART : le titre tombe a 213 px du haut de la
     hero sur la home, et a 197, 200, 247, 263, 297 et 299 px sur les six
     autres. Quatre-vingt-dix pixels d'ecart entre la plus haute et la plus
     basse, sur des pages qu'on parcourt a la suite.

     LA CAUSE N'EST PAS UN REGLAGE MAIS UNE MECANIQUE. Ces heros sont des flex
     en `align-items: center` avec un `min-height` de 714 a 720 px : leur
     contenu est CENTRE dans cette hauteur. Or ce contenu mesure de 312 px
     (aviso) a 547 px (nosotros) selon la longueur de la lede et le nombre de
     boutons. Plus le bloc est court, plus il descend. Aucune valeur de
     rembourrage ne pouvait aligner sept pages dont le contenu varie de 235 px.

     ON PASSE DONC DU CENTRAGE A L'ANCRAGE EN HAUT. Le titre tombe alors a
     `padding-top` + la hauteur de la pastille et de sa marge, deux valeurs
     fixes et mesurees : 37 px de pastille et 16 px de marge, soit 53. Pour
     retrouver les 213 px de la home il faut donc 160 px de rembourrage haut.
     C'est arithmetique et ca ne depend plus de la longueur du texte.

     136 ET NON 160, ET C'EST LA MESURE QUI TRANCHE. Le calcul ci-dessus
     donnait 160 ; les sept titres sont alors tombes a 237 px, soit 24 de
     trop, et surtout LES SIX PAGES INTERIEURES ETAIENT ENFIN D'ACCORD
     ENTRE ELLES — c'etait le point difficile, et il etait regle. Ce qui
     surplombe le titre ne fait donc pas 53 px mais 77 une fois le bloc
     ancre en haut. La decomposition importe peu puisque l'ecart est
     constant : 160 - 24 = 136.

     ET LE `min-height` TOMBE AVEC, sinon le contenu ancre en haut laisserait
     jusqu'a 250 px de vide sous lui dans une hauteur imposee. Chaque hero fait
     desormais la hauteur de son contenu, ce qui regle du meme coup la demande
     suivante sur metodologias.

     Deux classes au selecteur : `.page-hero--league` et `.page-nosotros
     .page-hero` posent chacune un `min-height` a deux classes, il faut ce
     poids pour passer devant. */
  .page-hero.page-hero--league,
  .page-nosotros .page-hero {
    min-height: 0;
    align-items: flex-start;
    padding-top: 136px;
    /* 24 px ET NON 40, ET C'EST POUR nosotros. Le releve apres l'ancrage en
       haut : la sous-navigation entre entierement sous la hero sur cinq pages
       — 123 px de marge sur metodologias, ce qui etait la demande — mais elle
       depassait encore de 10 px sur nosotros, dont le contenu de hero est le
       plus long du site (547 px contre 312 a 515 ailleurs). Elle depassait
       deja avant, de 33 px : ce n'est pas une regression, c'est le meme defaut
       sur une autre page. Seize pixels de rembourrage bas en moins le reglent
       partout, et ils ne manquent nulle part : la sous-navigation vient juste
       apres et fait elle-meme la rupture visuelle.
       PUIS A ZERO le meme jour, voir la note du rembourrage haut juste
       au-dessus : c'est ce qui ramene nosotros a la hauteur de la home.
       PUIS A 8 px, APRES REGARD. A zero, le lien « Ver metodologías » de
       nosotros et son filet bas venaient toucher la sous-navigation : la seule
       page ou le rembourrage bas se voit est justement celle dont le contenu
       depasse le plancher. Huit pixels lui rendent son air et coutent 8 px de
       hauteur sur cette page seule — 691 contre 680, un ecart de 1,2 % qui ne
       se lit pas, quand un lien colle a la barre se lit tout de suite. */
    padding-bottom: 8px;
  }

  /* ── W. LA DEVISE RETROUVE SES ENCRES, ET SON ACCENT PASSE AU ROUGE ──────
     Gabriel : « tu peux faire le "should be done." en couleur rouge ».

     ET IL Y AVAIT UN DEFAUT A CORRIGER AVANT, DE MON FAIT DE CE MATIN : en
     deplacant la devise de `.essence-lead` vers `.essence-body`, je lui ai
     fait perdre toutes ses regles de couleur, qui visaient
     `.essence-lead p.essence-motto`. Elle tombait donc sur `.essence-body p`,
     c'est-a-dire `--color-muted`. Mesure : #94A3B8 sur telephone, du GRIS,
     accent compris, quand le bureau affiche #F8FAFC et un accent colore. Le
     deplacement d'un noeud emporte ses selecteurs de contexte : c'est a
     verifier chaque fois, et je ne l'avais pas fait.

     LES DEUX ENCRES SONT DONC REPOSEES ICI. Le corps de la devise reprend le
     blanc du bureau. L'accent passe au rouge, en --color-primary-lift : c'est
     le token du systeme pour du rouge en TEXTE sur sol sombre, mesure a 5,05:1
     sur le noir de cette section, contre 4,35:1 pour le rouge plein. Le seuil
     est de 3 ici — 26 px en gras est du texte large — donc les deux passent, et
     on prend celui qui est prevu pour.
     SUR ORDINATEUR L'ACCENT RESTE BLEU : la consigne du moment ne porte que sur
     le telephone. A dire si Gabriel veut le rouge partout. */
  .essence-body p.essence-motto--intercalee { color: var(--color-fg); }
  .essence-body p.essence-motto--intercalee .accent { color: var(--color-primary-lift); }

  /* ── X. LA BANDE DES METRIQUES PERD SON CADRE ET SON VIDE ────────────────
     Gabriel : « pour la bande avec 12 80 215, pas la peine d'avoir des lignes
     grises qui cadrent, aussi il y a trop d'espace blanc vide ».

     LES DEUX FILETS SONT CEUX DE LA GRILLE D'ORIGINE : `.metrics--editorial`
     porte un `border-top` et un `border-bottom` a rgba(16,16,16,0.12), poses
     quand les metriques formaient un tableau de deux colonnes sur toute la
     largeur. Devenues une rangee qui defile, ces deux traits ne cadrent plus
     rien : ils soulignent un conteneur dont on ne voit qu'un tiers.

     LE VIDE, MESURE : la section fait 353 px pour une rangee de 225, soit
     128 px de blanc — 64 en haut et 64 en bas, le rembourrage standard des
     sections. Il passe a 28, ce qui laisse la bande respirer sans faire d'elle
     un intervalle. La section tombe a 281 px.

     LE FILET ENTRE CARTES RESTE, ET C'EST VOULU : la carte suivante n'apparait
     qu'a 12 % de sa largeur au bord droit de l'ecran ; ce trait vertical est ce
     qui dit qu'il y en a une autre. Sans lui, la rangee a l'air de finir la. */
  .metrics--editorial {
    border-top: 0;
    border-bottom: 0;
  }
  .page-nosotros #trayectoria {
    padding-top: 28px;
    padding-bottom: 28px;
  }

  /* ── Y. LE RACCORD DES FRISES : LA GOUTTIERE PASSE DANS LES ITEMS ────────
     Gabriel : « il y a un bug dans la section alianzas estrategicas, les logos
     ne defilent pas comme il faut » et « le defilement n'est pas en boucle dans
     industrias clave, je voudrais qu'il soit en boucle ».

     LES DEUX ONT LA MEME CAUSE, ET ELLE EST ARITHMETIQUE. L'animation translate
     la piste de −50 %. Pour que le raccord soit invisible, cette moitie doit
     valoir EXACTEMENT un jeu d'items. Avec `gap`, ce n'est jamais le cas : une
     piste de 2n items porte 2n−1 gouttieres, donc la moitie de la piste vaut un
     jeu MOINS une demi-gouttiere. Mesure des cinq frises, ecart entre la
     translation et le debut du second jeu :
         secteurs      piste 2145, moitie 1073, jeu 1057   ->  saut de 16 px
         fantastiques  piste 2004, moitie 1002, jeu 1008   ->  saut de  6 px
         nichos        piste 1808, moitie  904, jeu  910   ->  saut de  6 px
         niveaux       piste 3008, moitie 1504, jeu 1488   ->  saut de 16 px
     Les secteurs cumulaient en plus un `padding-inline: 20px` que j'avais pose
     pour eloigner la premiere pastille du bord — 40 px de plus dans la piste,
     qui ne comptent dans aucun jeu. Il part : dans une frise qui tourne, il n'y
     a pas de premiere pastille, et l'estompage des bords fait ce travail.

     LA CORRECTION : la gouttiere quitte le conteneur et devient une marge
     DROITE sur chaque item, la derniere comprise. La piste vaut alors
     2n x (largeur + gouttiere), et sa moitie exactement n x (largeur +
     gouttiere) : le raccord tombe au pixel. C'est aussi pour ca que la frise
     des pastilles de heros etait la seule juste — elle tient sur trois items
     et son ecart de 2 px passait inapercu.

     A SIGNALER, PAS CORRIGE ICI : la bande de clients de la home a le meme
     defaut, 15 px de saut toutes les 85 secondes, sur ordinateur comme sur
     telephone. Elle n'est pas dans la demande et le geste sortirait de la
     version telephone. La mesure est la si Gabriel veut la meme correction. */
  .industries__sectors.secteurs--defile,
  .industries__sectors.is-ligne {
    gap: 0;
    padding-inline: 0;
  }
  .industries__sectors.secteurs--defile > *,
  .industries__sectors.is-ligne > * { margin-right: 8px; }

  .practice__chips.chips--defile,
  .practice__chips.is-ligne { gap: 0; }
  .practice__chips.chips--defile > *,
  .practice__chips.is-ligne > * { margin-right: 6px; }

  .fantastic4__row.f4--defile,
  .fantastic4__row.is-ligne,
  #alianzas .alliances__row.nichos--defile,
  #alianzas .alliances__row.is-ligne,
  #alianzas .partner-levels.niveaux--defile,
  #alianzas .partner-levels.is-ligne { gap: 0; }
  .fantastic4__row.f4--defile > *,
  .fantastic4__row.is-ligne > *,
  #alianzas .alliances__row.nichos--defile > *,
  #alianzas .alliances__row.is-ligne > *,
  #alianzas .partner-levels.niveaux--defile > *,
  #alianzas .partner-levels.is-ligne > * { margin-right: 12px; }

  /* ── Z. LES MOTS DES CARTES DE HEROS ACCELERENT ──────────────────────────
     Gabriel : « tu peux augmenter la vitesse de defilement des mots dans les
     cards des heros de la home page ».
     26 s donnaient 12 px/s, un tiers de la vitesse des autres frises — un
     choix assume ce matin pour ne pas retenir l'oeil sous un texte qu'on lit.
     Gabriel tranche l'autre sens. 14 s donnent 22 px/s, l'allure des rangees
     d'alianzas, et la pastille traverse sa carte en douze secondes au lieu de
     vingt-deux. */
  .practice__chips.chips--defile { animation-duration: 14s; }

  /* LES PASTILLES SE RESSERRENT DE DEUX PIXELS, ET C'EST UN CALCUL DE 12 px.
     Les cartes de heros viennent de passer a 100 % de la colonne : leur boite
     de pastilles fait 300 px. La premiere carte — SOC Management, ISO 9001,
     ISO 27001 — en demande 312. Douze pixels de trop, donc une frise qui doit
     defiler pour montrer douze pixels : du mouvement pour rien, et un raccord
     qui se verrait sur une piste aussi courte. Deux pixels de rembourrage en
     moins de chaque cote sur trois pastilles rendent exactement ces 12 px : la
     suite tient, la rangee reste fixe, et rien n'est coupe.
     Les cinq autres cartes demandent de 622 a 1 209 px : elles defilent
     toujours, ce que `frises-defilantes.js` decide carte par carte. */
  .practice__chip { padding-inline: 5px; }

  /* ── AA. LA CARTE DU CTA : PLUS ETROITE, PLUS HAUTE, PLUS SERREE ─────────
     Gabriel : « le CTA de la home est trop large, raccourcis-le un peu des
     cotes, je parle de la card a l'interieur, et il est trop court en hauteur,
     ajoute-lui ; le bouton Hablar con un experto et Agendar una sesion ne sont
     pas assez proches, il est trop en bas le bouton Agendar una sesion ».

     LA CARTE, C'EST `.final-cta__inner` : c'est elle qui porte le filet, le
     rayon et le degrade. Mesure : 390 px de large a 0 px du bord de la
     section, donc collee aux deux cotes, pour 163 px de haut. Elle prend
     18 px de marge de chaque cote — 354 px — et son rembourrage vertical
     revient a 22 px, celui que ma passe de ce matin avait mis a zero pour
     resserrer la section.

     LES DEUX EQUERRES DE LA CARTE SUIVENT : 60 px de branche a 16 px des bords
     dans une carte de 207 px, elles se rejoignaient presque. 32 px a 12 px.

     LES DEUX COMMANDES SE RAPPROCHENT, ET LE VIDE N'ETAIT PAS OU IL SEMBLAIT.
     L'ecart mesure entre le bas du bouton et le haut du lien fait 22 px, mais
     le lien porte 15 px de rembourrage HAUT — poses le 2026-08-XX pour tenir sa
     cible tactile a 44 px sans toucher au corps du texte. Le blanc reel entre
     les deux libelles fait donc 37 px. On rend au lien le meme dispositif qu'aux
     boutons : un rembourrage de 7 px et un rectangle de touche invisible qui
     deborde de 8 px. 7 + 7 + 14,3 + 16 = 44,3 px de cible, et le blanc visible
     tombe a 10 + 7 = 17 px. */
  .final-cta--poster .final-cta__inner {
    margin-inline: 18px;
    padding-top: 22px;
    padding-bottom: 22px;
  }
  .final-cta--poster .final-cta__inner::before,
  .final-cta--poster .final-cta__inner::after { width: 32px; height: 32px; }
  .final-cta--poster .final-cta__inner::before { top: 12px; left: 12px; }
  .final-cta--poster .final-cta__inner::after { bottom: 12px; right: 12px; }
  .final-cta--poster .final-cta__actions { gap: 10px; }
  .final-cta__link {
    position: relative;
    padding: 7px 4px;
  }
  .final-cta__link::after {
    content: '';
    position: absolute;
    inset: -8px 0;
  }

  /* ── AB. L'IMAGE DE LA HERO DE bolsa REVIENT VERS LA DROITE ──────────────
     Gabriel : « mets l'image de la hero de la page bolsa de trabajo un peu plus
     vers la droite ».
     Elle etait a 96 %, la valeur posee pour les trois pages a embleme decale.
     Un pourcentage PLUS PETIT deplace l'image vers la droite — c'est le meme
     contre-intuitif que la video de la hero de la home : le pourcentage designe
     le point de l'IMAGE qu'on aligne, pas un deplacement. A 86 % la fenetre
     couvre les 42 a 93 % du fichier, et la dispersion, centree sur 77 %, se
     retrouve vers 68 % de l'ecran au lieu de 55.
     LES DEUX AUTRES PAGES NE BOUGENT PAS : csirt et contacto viennent d'etre
     reglees et Gabriel ne les cite pas. Leur regle est donc separee de celle-ci
     au lieu d'etre partagee. */
  .page-hero--careers .page-hero__bg-img { object-position: 86% center; }
}

@media (max-width: 760px) {
  /* ── AD. INDUSTRIAS CLAVE : LE VIDE SOUS LE TITRE ────────────────────────
     Gabriel : « dans la section industrias clave il y a un espace qui n'est pas
     normal entre le titre et le texte ».

     C'EST UNE MARGE DEVENUE ORPHELINE, ET ELLE EST DE MON FAIT. `.industries__head`
     portait `margin-bottom: 48px` parce qu'elle contenait DEUX choses : le bloc
     titre et la liste des onze secteurs. Cette liste est partie entre les deux
     images il y a une heure, a la demande precedente ; la marge est restee et
     s'ajoute au `margin-bottom: 16px` du titre. Mesure : 66 px entre le bas du
     titre et la ligne des 95 %, pour un en-tete qui ne contient plus qu'un
     bloc. 16 px la ramenent a 32, l'intervalle normal entre un titre et son
     texte sur cette page. */
  .industries__head { margin-bottom: 16px; }

  /* ── AE. LA CARTE DU CTA SE RESSERRE ENCORE ──────────────────────────────
     Gabriel : « dans la home page tu peux reduire un peu la largeur de la
     card ». Elle etait passee de 390 a 354 px il y a une heure ; 28 px de marge
     la mettent a 334. Les equerres de section restent a 14 px des bords, donc
     elles encadrent maintenant la carte au lieu de la toucher. */
  .final-cta--poster .final-cta__inner { margin-inline: 28px; }

  /* ── AF. LES PASTILLES DES SEPT HEROS S'EN VONT ──────────────────────────
     Gabriel : « retire "Sobre ASHA Solution" de la hero nosotros et toutes les
     cards similaires dans toutes les heros des differentes pages ».
     Ce sont les six pastilles de hero de page — Sobre ASHA Solution, La Liga
     ASHA, Hablemos, Hablemos · ASHA CSIRT, Únete al equipo, Legal · Documento
     oficial — plus celle de la home, deja masquee ce matin. Les sept heros
     n'ont donc plus qu'un titre, une lede et leurs commandes.

     ET LE REMBOURRAGE HAUT SUIT, SINON L'ALIGNEMENT DEMANDE IL Y A UNE HEURE
     SE CASSE. Le titre tombait a `padding-top` + 77 px de pastille = 136 + 77
     = 213, la valeur de la home. Sans pastille, il ne reste que le
     rembourrage : il passe donc a 213 pour que les sept titres restent au meme
     endroit. C'est la meme arithmetique, avec un terme en moins. */
  .page-hero__eyebrow { display: none; }

  /* ── AG. LES SEPT HEROS A LA HAUTEUR DE CELLE DE LA HOME ─────────────────
     Gabriel : « je veux que toutes les heros de toutes les pages aient la meme
     taille que la hero de la home page ».
     Releve avant : 680 px sur la home, et 472, 476, 549, 574, 675, 707 sur les
     six autres — la hauteur suivait la longueur du texte, chaque page arrivant
     avec un pli different.
     ON REPREND L'EXPRESSION DE LA HOME, PAS SA VALEUR : `max(520px,
     calc(100svh - 164px))`, ou 164 px est la somme de l'en-tete et de la
     sous-navigation. Un chiffre en dur aurait fige 680 px, juste pour un
     iPhone 12 et faux partout ailleurs ; l'expression suit l'ecran comme la
     home, et les sept plis tombent au meme endroit sur tous les telephones.
     `svh` et non `vh` : la barre d'adresse mobile fait varier `vh`. */
  .page-hero.page-hero--league,
  .page-nosotros .page-hero {
    min-height: max(520px, calc(100svh - 164px));
    /* 189 ET NON 213, LA PASTILLE PARTIE. Le calcul disait : plus de pastille,
       donc le titre tombe au rembourrage. Mesure : 237 px, soit 24 de trop, et
       les six pages a nouveau d'accord entre elles. Il reste donc 24 px
       au-dessus du titre que le releve d'element en element ne montre pas — une
       gouttiere de grille ou une marge non repliee dans `.container`. L'ecart
       etant constant sur les six, on le retire du rembourrage : 213 - 24 = 189.
       C'est la troisieme fois aujourd'hui que ce reglage se fait par ecart
       mesure et non par decomposition ; la decomposition n'est pas necessaire
       tant que l'ecart est le meme partout, et il l'est.

       PUIS 112, ET LE BON REPERE EST LA FENETRE. Gabriel : « regarde bien a
       quelle hauteur est le titre de la hero dans la home page et fais pareil
       pour tous les titres ». Mon controle lisait la distance du titre au haut
       de SA hero — 213 px partout, donc aligne. Depuis le haut de la FENETRE,
       ce que l'oeil voit, il est a 213 px sur la home et a 290 sur les six
       autres : la hero de la home commence a y=0 et passe SOUS l'en-tete colle,
       les heros de page commencent a y=77, sous lui. Les 77 px de l'en-tete
       sont donc a retirer : 189 - 77 = 112, et les sept titres tombent a
       213 px de la fenetre.

       LE REMBOURRAGE BAS TOMBE A ZERO, ET C'EST POUR nosotros SEUL. Cinq heros
       sur six sont plus courts que le plancher de 680 px : leur rembourrage bas
       ne se voit pas, l'espace libre etant sous le contenu de toute facon.
       nosotros est la seule dont le contenu depasse — lede de quatre lignes et
       deux commandes empilees — et elle finissait a 731 px, 51 de trop. A
       189/0 elle tombe a 683, soit 3 px du plancher. Zero ne coute donc rien
       ailleurs et donne la seule page qui posait probleme. */
    padding-top: 112px;
  }

  /* ── AH. LA LEDE DES HEROS PREND LE BLANC DE LA HOME ─────────────────────
     Gabriel : « est-ce que tu peux aligner la taille du texte de la hero et sa
     couleur, la reference est le texte blanc de la hero de la home page ».
     LA TAILLE ETAIT DEJA ALIGNEE, mesure faite : 14 px / 21 px de hauteur de
     ligne sur les sept pages, depuis la passe sur les ledes de ce matin. C'est
     la COULEUR qui differait, et d'un cran seulement : #F8FAFC sur la home,
     #94A3B8 sur les six autres. Sur le sombre des heros, cela fait 20,07:1
     contre 6,17:1 — les deux passent, mais la lede des pages interieures se lit
     comme un commentaire quand celle de la home porte la promesse. */
  .page-hero .page-hero__lede { color: var(--color-fg); }

  /* ── AI. LES COPIES DE FRISE ETAIENT INVISIBLES ──────────────────────────
     Gabriel : « dans la section Alianzas estrategicas les defilements
     automatiques ne sont pas en boucle, fais-le ».

     ET IL AVAIT RAISON CONTRE MA MESURE. Le controle du raccord annoncait 0 px
     d'ecart sur les cinq frises, donc une boucle exacte. Elle l'est. Mais la
     SECONDE MOITIE DE LA PISTE NE S'AFFICHAIT PAS : ces items sont des cibles
     du reveal GSAP, qui leur pose `opacity: 0` EN LIGNE au chargement puis les
     anime a 1 quand la section entre a l'ecran. Mon script les duplique avec
     `cloneNode(true)`, qui recopie l'attribut `style` — donc les copies
     heritent d'un `opacity: 0` fige, et GSAP ne les animera jamais : il a
     capture ses cibles au chargement, avant qu'elles n'existent. Un jeu
     visible, un jeu invisible : la frise semble s'arreter puis repartir.

     POURQUOI MES HARNAIS NE L'ONT PAS VU, ET C'EST LA VRAIE LECON : ils
     injectaient `body *{opacity:1!important}` pour contourner le reveal quand
     on saute dans la page. Cette injection rendait les copies visibles, donc
     effacait exactement le defaut qu'elle aurait du reveler. Un contournement
     de harnais peut cacher le bug qu'on cherche.

     LA CORRECTION EST CSS ET NON JS, et c'est le choix le plus sur : plutot que
     de nettoyer le style en ligne des copies — ce qui laisserait un demi-instant
     ou un jeu est visible et l'autre pas pendant le reveal — on retire ces
     rangees du reveal. Une frise qui defile n'a rien a gagner a apparaitre en
     fondu, et `!important` est ici necessaire pour battre un style en ligne. */
  .industries__sectors > *,
  .fantastic4__row > *,
  #alianzas .alliances__row > *,
  #alianzas .partner-levels > * {
    opacity: 1 !important;
    transform: none !important;
    translate: none !important;
  }

  /* ── AJ. LES TROIS FRISES D'ALIANZAS ACCELERENT ──────────────────────────
     Gabriel : « et augmente la vitesse de defilement ».
     De 25, 34 et 25 px/s a 42, 46 et 42. La course vaut la moitie de la piste :
     1 008 px pour les quatre plaques, 910 pour les cinq cartes d'alliance,
     1 510 pour les cinq niveaux. */
  .fantastic4__row.f4--defile { animation-duration: 24s; }
  #alianzas .alliances__row.nichos--defile { animation-duration: 20s; }
  #alianzas .partner-levels.niveaux--defile { animation-duration: 36s; }

  /* ── AK. LE CORRIDOR DES HEROS : PLUS GRAND, MOINS VOILE ─────────────────
     Gabriel : « l'image en fond des heros dans metodologias est toujours pas
     bien placee et pour certains a disparu ».

     DEUX DEFAUTS, ET LE SECOND EXPLIQUE « DISPARU ». Le cadrage etait juste —
     la sphere tombe bien a 5 a 9 px du centre de la figure sur les six, mesure
     refaite. Mais le VOILE etouffait tout : l'ellipse ne laissait le fond
     intact que dans un rayon de 18 % de 320 px, soit 57 px, et le ramenait au
     noir de la bande a 62 %. Une fenetre claire de 114 px de large pour une
     figure de 240. Sur les personas dont le corridor est chaud — ASHA en rouge
     — il en restait une lueur ; sur NGSOC, dont le corridor est argente sur une
     bande noire, il n'en restait rien. D'ou « pour certains a disparu » : ce
     n'etait pas un fichier manquant, c'etait un voile trop serre sur un fond
     peu contraste.

     LA SPHERE GRANDIT D'UN TIERS. La hauteur imposee passe de 893 a 1 200 px,
     ce qui porte l'image a 2 133 px de large et la sphere a environ 400 px de
     diametre au lieu de 300. Le calcul de position se refait avec :
         sphere en y   0,42 x 1200 = 504 px du haut de l'image
         on la veut a  375 px du haut de la section
         ancrage y  =  375 - 504 = -129 px
         sphere en x   0,12 x 2133 = 256 px   ou   0,87 x 2133 = 1856 px
     `calc(50% - 256px)` amene donc la sphere au centre horizontal exact.

     ET LE VOILE S'OUVRE. La zone intacte passe a 45 % d'un rayon de 420 px,
     soit 189 px — la largeur de la figure entiere — et la retombee au noir se
     fait a 100 % au lieu de 62. Le corridor redevient ce qu'il est sur
     ordinateur : une lueur derriere le personnage, pas un halo devine. */
  /* `--sphere` EST POSEE A UNE CLASSE ET UN ATTRIBUT, PAS DEUX, et c'est le
     meme piege que la premiere fois : la valeur par defaut doit avoir le MEME
     poids que les trois exceptions, sinon elles ne passent pas. Ecrite sur
     `.method--dark.method--media-start[data-persona]` (deux classes), elle
     battait `.method--dark[data-persona="ctem"]` (une classe) et csirt gardait
     la valeur de gauche. Deja paye il y a deux heures. */
  .method--dark[data-persona] { --sphere: 256px; }
  .method--dark[data-persona="ctem"],
  .method--dark[data-persona="csirt"],
  .method--dark[data-persona="grc"] { --sphere: 1856px; }

  .method--dark.method--media-start[data-persona],
  .method--dark.method--media-end[data-persona] {
    background-size: auto, auto 1200px;
    background-position: 50% 0, calc(50% - var(--sphere)) -129px;
    background-image:
      radial-gradient(420px 340px at 50% 375px,
        transparent 45%,
        color-mix(in srgb, var(--band-bg) 58%, transparent) 78%,
        var(--band-bg) 100%),
      var(--corridor);
  }
}

@media (max-width: 760px) {
  /* ── AL. LA PASTILLE DE HERO : DEUX CLASSES, PAS UNE ─────────────────────
     La regle du bloc AF ne s'appliquait pas : `.page-hero__eyebrow` vaut une
     classe, et `.page-hero--league .page-hero__eyebrow` (ligne 2675) en vaut
     deux. Mesure : la pastille restait en `inline-flex` sur les six pages et le
     titre a 290 px au lieu de 213 — exactement les 77 px de la pastille. Le
     selecteur en porte donc deux. */
  .page-hero .page-hero__eyebrow,
  .page-hero--league .page-hero__eyebrow { display: none; }

  /* ── AM. INDUSTRIAS : LE RESTE DU VIDE ───────────────────────────────────
     La marge de l'en-tete etait passee de 48 a 16 px, et il restait 62 px entre
     le titre et la ligne des 95 %. Le compte : 16 px de marge du titre, 16 de
     marge de l'en-tete, et 30 de marge haute sur `.industries__coverage` —
     trois marges qui s'additionnent parce qu'aucune ne se replie a travers un
     conteneur en grille. On annule celle du milieu et on ramene celle du bas a
     12 : 16 + 0 + 12 = 28 px, l'intervalle d'un titre a son texte. */
  .industries__head { margin-bottom: 0; }
  /* LES DEUX MARGES RESTANTES TOMBENT. Apres l'annulation de la marge de
     l'en-tete il restait 46 px entre le bas du titre et le haut du texte, dont
     16 de marge du titre, 12 de marge du texte, et 18 qu'aucun releve d'element
     en element ne montre — une gouttiere de la grille de l'en-tete ou une marge
     non repliee. On retire les deux marges qu'on maitrise, ce qui ramene
     l'intervalle a 24 px. Le titre est declare a l'interieur de `#industrias`
     pour ne pas toucher les onze autres titres de section de la page. */
  /* 16 px, LA VALEUR DES SEPT AUTRES SECTIONS DE LA PAGE, mesuree une par une :
     problema, versus, sistema, soluciones, operacion, casos-exito et presencia
     ont tous 16 px entre leur titre et leur texte. Industrias en avait 6 apres
     ma passe precedente — et je croyais y avoir mis 24. L'ecart vient de ce que
     je mesurais : `getBoundingClientRect` comptait le `translateY` du reveal
     GSAP, encore en cours. La mise en page, elle, donnait 6. C'est ce que
     Gabriel voit comme « pas respecte ».
     La marge est portee par le TEXTE et non par le titre : c'est ainsi que les
     sept autres sections la portent, via `.section-lede`. */
  /* ── AS. LES QUATRE INTERVALLES DE LA SECTION, RELEVES UN PAR UN ─────────
     Gabriel : « regarde les differents espacements entre les elements de la
     section Industrias Clave pour etre sur que cela respecte bien ».

     LE RYTHME DE LA PAGE, MESURE SUR LES HUIT SECTIONS DE LA HOME :
         rembourrage de section      64 / 64 px
         pastille -> titre                 16 px
         titre -> texte d'intro            16 px
         bloc d'en-tete -> contenu         48 px   (problema, versus, sistema,
                                                    soluciones, casos-exito)
     Industrias tenait les trois premiers et manquait le quatrieme : ZERO pixel
     entre la ligne des 95 % et la grille des cartes. Le contenu commencait
     donc collé au texte qui l'annonce, alors que les cinq autres sections
     laissent 48 px a cet endroit.

     ET C'ETAIT MON FAIT, une heure plus tot. Les 48 px vivaient dans le
     `margin-bottom` de `.industries__head` ; en le mettant a zero pour resserrer
     l'intervalle titre -> texte, j'ai emporte avec lui l'air qui separait
     l'en-tete du contenu. Les deux intervalles etaient portes par la meme
     declaration alors qu'ils ne disent pas la meme chose.
     Ils sont donc separes : 16 px en marge HAUTE du texte, 48 en marge BASSE.
     `var(--space-12)` et non 48 en dur, c'est le token que `.section-head`
     utilise pour ce meme intervalle a la ligne 996. */
  .industries__coverage {
    margin-top: 16px;
    margin-bottom: var(--space-12);
  }
  #industrias .industries__head .section-title { margin-bottom: 0; }

  /* ── AN. LES CARTES DE HEROS PRENNENT TOUTE LA LARGEUR ───────────────────
     Gabriel : « fais que les cards des heros dans la section nuestro modelo
     prennent toute la largeur et qu'on ne voie pas une partie de la card
     suivante ».
     88 % avaient ete choisis pour que la tranche de la carte voisine dise qu'il
     y a une suite. Cet indice n'est plus necessaire : la reglette coloree posee
     au-dessus le dit mieux, en montrant AUSSI combien il y en a et ou l'on est.
     La carte passe donc a 100 % de la colonne, et l'intervalle de 12 px suffit
     a ce qu'aucune voisine n'affleure. */
  .practices__grid--six > .practice--card { flex: 0 0 100%; }

  /* ── AO. LA REGLETTE DE « LA PROBLEMÁTICA » PREND LA FORME DE LA REFERENCE
     Gabriel, capture de CrowdStrike a l'appui : « fais-les fins et carres comme
     cette reference ; de base c'est [gris] et ca devient rouge en fonction du
     scroll ».

     CE QUE FAIT LA REFERENCE, mesure sur sa capture ramenee en px CSS : trois
     filets plats de 3 px de haut, a angles VIFS, separes de 20 px, dont un seul
     est rouge — l'actif. Pas de fond, pas de bordure, pas de rayon.

     ELLE NE TOUCHE QUE LA REGLETTE DES SYMPTOMES. Celle des six heros garde ses
     pilules aux couleurs de persona : Gabriel l'a validee le 07/09 en demandant
     explicitement qu'elle parle la langue des eyebrows, et une pastille par
     hero y porte une information que trois filets identiques ne porteraient
     pas. Le selecteur passe donc par `.symptoms__pager`, la classe que seule la
     reglette de cette section porte.

     L'ENCRE ETEINTE EST MESUREE, PAS REPRISE DE LA CAPTURE. La reference pose
     du blanc plein sur un fond rouge sombre ; ici le sol est `data-sol="1"`,
     un gris tres sombre, et du blanc plein ferait quatre filets aussi presents
     que l'actif. A 30 % il rend 2,2:1 contre le sol — assez pour se voir comme
     un repere, pas assez pour rivaliser avec le rouge de l'actif, qui rend
     4,3:1. Un repere n'est pas du texte : le seuil de 4,5 ne s'y applique pas,
     c'est le RAPPORT entre eteint et allume qui doit se lire, et il est de 2. */
  .symptoms__pager .practices__pager-item {
    height: 3px;
    border-radius: 0;
    border: 0;
    background: color-mix(in srgb, var(--color-fg) 30%, transparent);
  }
  .symptoms__pager .practices__pager-item.is-actif {
    background: var(--color-primary);
    border: 0;
  }
  /* La cible tactile se recalcule sur la nouvelle epaisseur : 3 + 2 x 21 = 45. */
  .symptoms__pager .practices__pager-item::after { inset: -21px 0; }
  /* 20 px d'intervalle, comme la reference : a 8 px, quatre filets de 3 px se
     lisaient comme une seule ligne pointillee. */
  .symptoms__pager { gap: 20px; }

  /* ── AP. LA REGLETTE DES SIX HEROS PREND LA MEME FORME ───────────────────
     Gabriel : « les petits rectangles de scroll pour la problematica ont bien
     reussi, fais de meme pour la section nuestro modelo avec les differentes
     couleurs ».
     Meme geometrie que celle des symptomes — filets de 3 px, angles vifs, ni
     fond ni bordure ni rayon — et les six couleurs conservees, qui sont
     l'information propre a cette reglette : chaque barre dit QUEL heros, pas
     seulement combien il y en a.
     L'ETEINTE EST A 32 % ET NON A 12 %, et c'est la difference avec la version
     en pilule qu'elle remplace. Une pilule eteinte se lisait par son FILET, qui
     portait 55 % de la couleur ; un filet plat n'a que son fond. A 12 %, les
     six barres disparaissaient sur le sol clair de cette section. A 32 % elles
     se voient toutes, et l'active, pleine, garde trois fois leur presence.
     Les tokens restent les `-ink`, assombris pour ce sol clair : l'argent de
     NGSOC en couleur pleine y etait invisible, mesure du 07/09. */
  .practices__pager .practices__pager-item {
    height: 3px;
    border-radius: 0;
    border: 0;
    background: color-mix(in srgb, var(--persona, var(--color-fg)) 32%, transparent);
  }
  .practices__pager .practices__pager-item.is-actif {
    background: var(--persona, var(--color-fg));
    border: 0;
  }
  /* 3 + 2 x 21 = 45 px sous le doigt, comme les filets des symptomes. */
  .practices__pager .practices__pager-item::after { inset: -21px 0; }
  /* 12 px et non 20 : six barres au lieu de quatre sur la meme largeur. Les
     deux reglettes a quatre barres gardent les 20 px de la reference. */
  .practices__pager:not(.symptoms__pager):not(.areas__pager) { gap: 12px; }
  .areas__pager { gap: 20px; }

  /* LES DEUX REGLES DES SYMPTOMES SONT REPOSEES ICI, ET C'EST UNE QUESTION
     D'ORDRE. Elles valent deux classes, comme celles des heros juste au-dessus,
     et a poids egal c'est la derniere declaration qui gagne : la barre active
     des symptomes prenait donc `var(--persona, var(--color-fg))`, et comme ces
     barres n'ont pas de persona, elle tombait sur le BLANC. Mesure : #F8FAFC au
     lieu du rouge. Redeclarees apres, elles reprennent la main. */
  /* ── AQ. LA REGLETTE DES AIRES DE CARRIERE, EN ROUGE ─────────────────────
     Gabriel : « tu peux faire le meme fonctionnement avec les petits rectangles
     dans la section Áreas de carrera, en rouge ».
     Elle rejoint la regle des symptomes plutot que d'en recevoir une copie :
     meme forme, meme encre eteinte, meme rouge actif, et un seul endroit a
     changer si la forme evolue. Les deux sections sont sur un sol sombre —
     `data-sol="1"` pour les deux — donc la meme encre eteinte y rend le meme
     contraste, et le rouge actif garde ses trois fois leur presence.
     `.areas__pager` porte aussi `.practices__pager` dans le HTML : c'est ce qui
     lui donne la geometrie commune, et c'est aussi pourquoi cette regle doit
     etre declaree APRES celle des heros, a poids egal. */
  .symptoms__pager .practices__pager-item,
  .areas__pager .practices__pager-item {
    background: color-mix(in srgb, var(--color-fg) 30%, transparent);
  }
  .symptoms__pager .practices__pager-item.is-actif,
  .areas__pager .practices__pager-item.is-actif {
    background: var(--color-primary);
  }
}

@media (max-width: 760px) {
  /* ── AT. L'IMAGE ET LA VIDEO DU HERO SE SUPERPOSENT ENFIN ────────────────
     Gabriel : « il y a un bug, quand la page se charge dans la hero de la home
     page on voit une autre image et non la video directement ».

     CE N'EST PAS UNE AUTRE IMAGE, C'EST LA MEME MAL CADREE. Releve dans WebKit
     (le moteur de Safari iOS) au chargement puis a `readyState 4` :
         image   opacite 0,30   object-position 68 %   top    0   hauteur 680
         video   opacite 1,00   object-position 74 %   top  −36   hauteur 716
     L'image est le repli du hero, et son fichier est l'image d'arrivee EXACTE
     de l'animation — c'est ecrit dans le HTML depuis le 04/09. Elle devrait
     donc etre indistinguable de la derniere frame. Elle ne l'etait pas : trois
     reglages sur quatre differaient, et la bascule donnait un bouclier qui
     saute de 6 % de largeur, remonte de 36 px et triple de luminosite. C'est
     ce saut que Gabriel lit comme « une autre image ».

     LES QUATRE VALEURS SONT DONC RECOPIEES DE LA VIDEO. Y COMPRIS L'OPACITE, et
     c'est le seul point qui demandait une verification plutot qu'un alignement
     aveugle : le 0,30 (l. 8368) a ete pose le 11/08 pour que « ataques
     sofisticados » ne tombe pas en rouge sur l'arche rouge du cadenas — avec un
     cadrage a 68 %, qui amenait cette arche derriere le titre. Deux choses ont
     change depuis. Le cadrage : a 72 % l'arche n'est plus sous le titre. Et le
     voile : `.hero__scrim` passe en degrade VERTICAL sous 900 px (l. 8341) et
     couvre le haut a 0,72 d'alpha, au-dessus du visuel. La preuve est en ligne
     depuis un mois — la video occupe ce meme emplacement a opacite PLEINE et le
     titre s'y lit. Le motif du retrait a disparu avec le cadrage qui le causait.

     LE FILTRE PART AUSSI : la video n'en porte aucun, l'image portait
     `saturate(1.05) contrast(1.05)`. Un ecart de saturation entre deux images
     censees etre la meme se voit exactement au moment de la bascule. */
  .hero__bg-img {
    object-position: 72% center;
    top: -36px;
    height: calc(100% + 36px);
    opacity: 1;
    filter: none;
  }

  /* ── AU. LA VIDEO GLISSE ENCORE VERS LA DROITE ───────────────────────────
     Gabriel : « tu peux mettre la video de la hero de la home page un peu plus
     a droite ». Cinquieme decalage : 84, 80, 78, 76, 74, et 72 maintenant.

     LE PRIX, RECALCULE SUR LA GEOMETRIE ACTUELLE et non repris de la table du
     bloc precedent — la hero a change de hauteur depuis, donc l'echelle de
     `cover` avec elle. Boite 390 x 716, source 1920 x 1080 : l'echelle vaut
     716/1080 = 0,663 et l'image s'affiche sur 1273 px de large, dont 390 se
     voient. Bouclier releve a l'image : x de 1200 a 1620.
         a 74 %  la fenetre couvre x 985..1574 dans la source -> 46 px du
                 bouclier sortent a droite, 11 % de ses 420 px
         a 72 %  elle couvre       x 959..1547              -> 73 px, 17 %
     Le pas coute donc 27 px de plus, et C'EST LE DERNIER QUE JE FERAIS SANS
     REDISCUTER : a 70 % on passerait le quart du bouclier hors cadre.
     L'image de repli reprend la meme valeur juste au-dessus, sinon la bascule
     du correctif AT redeviendrait visible. */
  .hero__bg-video { object-position: 72% center; }
}

/* ── AV. LE SURVOL NE MET PLUS LES BANDES EN PAUSE AU TOUCHER ──────────────
   Gabriel : « les deux bandes blanches ne defilent pas sur iPhone ».

   `.marquee:hover .marquee__track { animation-play-state: paused }` (l. 4548)
   est juste sur un poste de travail : on survole une bande pour lire un logo,
   elle s'arrete. Sur un ecran tactile, `:hover` se pose AU TOUCHER et y RESTE
   — c'est le comportement de Safari iOS depuis toujours, et rien ne le leve
   avant un toucher ailleurs. Un doigt qui effleure une bande en faisant
   defiler la page l'arrete donc pour de bon, sans aucun signal.
   Reproduit dans WebKit : apres 1,6 s de survol, `animation-play-state` passe
   a `paused` et la piste ne bouge plus d'un pixel.

   CE BLOC N'EST PAS BORNE A 760 px, ET C'EST VOULU. La condition qui compte
   n'est pas la largeur mais le POINTEUR : une tablette a 900 px a le meme
   defaut, un navigateur de bureau retreci a 500 px n'en a aucun et doit garder
   sa pause. `(hover: hover) and (pointer: fine)` decrit exactement « un
   dispositif capable de survoler sans toucher ». L'affichage sur ordinateur
   est donc rendu a l'identique : la seconde regle repose la premiere, mot pour
   mot, la ou elle a un sens. */
.marquee:hover .marquee__track { animation-play-state: running; }
@media (hover: hover) and (pointer: fine) {
  .marquee:hover .marquee__track { animation-play-state: paused; }
}

@media (max-width: 760px) {
  /* ── AW. LE CORRIDOR : UN POURCENTAGE DANS `background-position` N'EST PAS
         UN DECALAGE ──────────────────────────────────────────────────────────
     Gabriel : « l'image de fond de chaque section dans la page metodologia est
     mal placee, on devrait voir la partie ou il y a l'embleme » — puis « on ne
     voit pas l'image en arriere-plan pour grc et csirt ».

     LES DEUX PHRASES ONT LA MEME CAUSE, ET C'EST UNE ERREUR DE MA PART, DEUX
     FOIS DE SUITE (blocs M et AK). J'ai ecrit `calc(50% - var(--sphere))` en
     lisant « le centre, moins l'abscisse de la sphere ». Ce n'est pas ce que
     fait la propriete. Dans `background-position`, UN POURCENTAGE ALIGNE LE
     POINT P % DE L'IMAGE SUR LE POINT P % DE LA BOITE :
         bord gauche de l'image = P/100 x (largeur boite − largeur image)
     Avec une boite de 390 et une image de 2 133, `50 %` place donc le bord
     gauche a −871 px — et le `− var(--sphere)` du calc s'AJOUTE a ces −871 au
     lieu de partir du centre. Releve au navigateur :
         --sphere  256 px  ->  bord gauche −1 128, bande source visible
                               1 128..1 518, la sphere est a 256 : HORS CADRE
         --sphere 1856 px  ->  bord gauche −2 728, et l'image finit a −595 :
                               ELLE EST ENTIEREMENT HORS DE L'ECRAN
     D'ou les deux plaintes d'un coup : sur asha, ngsoc et zerotrust on voyait
     la bande centrale de l'image, celle ou il n'y a rien ; sur ctem, csirt et
     grc — les trois a `--sphere: 1856px` — on ne voyait RIEN DU TOUT. Gabriel
     nomme csirt et grc, ctem est dans le meme cas.

     LES VALEURS DE `--sphere` SONT JUSTES, ELLES, ET JE LES AI RE-MESUREES
     avant de les accuser. Carte de luminance des huit fichiers en 160 x 90 :
         asha 12,5 %   ctem 13,1 %   ngsoc 13,1 %   zerotrust-mirror 12,5 %
         csirt 86,2 %  ctem-mirror 86,2 %  grc ~86 %  zerotrust 86,9 %
     en y, le pic est a 41,1 a 42,2 % sur les huit. Les 12 % / 87 % / 42 %
     heritees du 24/08 tiennent, a un demi-point pres. La faute etait dans
     l'expression, pas dans la mesure.
     (Un premier releve au canvas m'a donne « 48 a 64 % » et m'a fait croire le
     contraire pendant dix minutes : son seuil a 80 % du maximum attrapait les
     particules speculaires dispersees dans toute l'image, pas la sphere. Le
     nombre de pixels retenus le disait — 6 264 sur ngsoc contre 830 sur asha.)

     LA FORME CORRECTE, ET POURQUOI ELLE EST SUR CETTE FORME. On veut le point
     `sx` de l'image au centre de la boite. Avec `50 %` l'image arrive centree,
     son propre centre (Iw/2 = 1 066,5) sur celui de la boite ; il suffit alors
     de la faire glisser de la distance qui separe son centre de sa sphere :
         bord gauche = 0,5(W − Iw) + Iw/2 − sx = W/2 − sx
     Le W disparait de l'expression : LE CADRAGE EST DONC INDEPENDANT DE LA
     LARGEUR DE L'ECRAN, ce qu'aucune valeur en dur ne donnerait. Verifie a
     320 px (bord gauche −96, sphere a 160 = 320/2) comme a 390 (−61, sphere a
     195). Les six sections tombent au centre horizontal, sur le personnage.

     LE BUREAU N'A PAS CE DEFAUT, verifie avant de generaliser : il ecrit
     `background-position: center, 12% 46%` (l. 13695), un pourcentage SEUL.
     Et c'est l'idiome juste pour ce qu'il veut — le point 12 % de l'image
     arrive au point 12 % de la boite, la ou se tient son personnage. C'est
     parce que le personnage est CENTRE sur telephone, et non colle a un bord,
     que le meme idiome n'y suffit pas et qu'un calc est necessaire. */
  .method--dark.method--media-start[data-persona],
  .method--dark.method--media-end[data-persona] {
    background-position: 50% 0, calc(50% + 1066.5px - var(--sphere)) -129px;
  }

  /* ── AX. ZEROTRUST ET GRC SE DECOLLENT DE LEUR VOISINE, ET GRANDISSENT ───
     Gabriel : « dans la hero de metodologias, grc est trop colle a gauche,
     deplace-le plus a droite, pareil zerotrust, et je voudrais qu'ils soient un
     peu plus grands ces deux-la ».

     CE QUE « COLLE A GAUCHE » DESIGNE, mesure a l'appui : les six figures se
     chevauchent d'une marge NEGATIVE CONSTANTE de −40 px, alors que leurs
     largeurs vont de 132 px (ctem) a 58 (grc). Le meme chevauchement mange donc
     30 % de la premiere et 69 % de la derniere. Releve avant :
         ctem      x −35..97   132 large    csirt      x  57..177   120
         asha      x 137..235   98          ngsoc      x 195..286    91
         zerotrust x 246..327   81          grc        x 287..345    58
     Les deux dernieres sont litteralement plaquees sur leur voisine de gauche :
     40 px des 81 de zerotrust passent sous ngsoc, 40 des 58 de grc sous
     zerotrust. C'est ce que Gabriel voit, et « deplace-le plus a droite »
     veut dire « rends-lui son espace », pas « pousse toute la rangee ».

     LE BUDGET EST FERME, ET C'EST LUI QUI FIXE LES VALEURS. La rangee tient
     entre deux bornes que j'ai deja annoncees : son bord gauche ne descend pas
     sous −35 px (au-dela, ce n'est plus la cape de ctem qui depasse mais un
     personnage tronque — le quart de la plus large des six), et son bord droit
     ne franchit pas l'ecran. Largeur disponible : 425 px. Or agrandir deux
     figures ET reduire leur chevauchement coute environ 76 px. Il faut donc les
     prendre, et le seul endroit ou elles existent est le chevauchement des
     TROIS PREMIERES PAIRES — la ou une figure large peut ceder 12 px de plus
     sans devenir illisible. D'ou cinq marges au lieu d'une :
         −52  −52  −34   pour ctem→csirt, csirt→asha, asha→ngsoc
         −24  −22        pour ngsoc→zerotrust, zerotrust→grc
     et les 45 px de vide qui restaient a droite rendus par le rembourrage,
     80 -> 42 px, qui remet le bord gauche a −35 exactement.

     APRES, ET C'EST LE CONTROLE QUI COMPTE — la largeur VISIBLE de chacune,
     c'est-a-dire ce qu'aucune voisine ne recouvre (l'ordre de peinture suit le
     DOM, sauf asha qui porte `z-index: 1` et passe au-dessus de ses deux
     voisines) :
                     avant   apres
         ctem          57      45      les deux plus larges paient
         csirt         80      68
         asha          98      98      la capitane est intouchee
         ngsoc         11      33      +200 %
         zerotrust     41      71      +73 %
         grc           58      68      et 28 px plus a droite
     Quatre figures sur six y gagnent, les deux qui perdent sont celles qui en
     avaient le plus.

     TOUT EST EN vw, ET C'EST CE QUI REND LA COMPOSITION STABLE. Premiere
     version en pixels fixes : elle passait a 390 mais laissait le bord gauche
     a −41 px a 412 px de large, contre −27 a 360 — parce que les six LARGEURS
     suivent la largeur d'ecran (elles derivent de hauteurs en vw) tandis que
     des marges en px, non. La rangee changeait donc de proportions d'un
     telephone a l'autre, et a 412 elle frolait la borne du harnais. En vw, les
     deux termes suivent la meme echelle : le bord gauche vaut −8,99 % de la
     largeur et le droit 98,2 % a TOUTE largeur. Verifie a 320, 360, 390 et
     412 px. Les valeurs a 390 px sont entre parentheses. */
  .liga-row { padding-right: 10.77vw; }                                /*  42 px */
  .liga-row__fig[data-persona="csirt"]     { margin-left: -13.33vw; }  /* −52 px */
  /* asha SEULE, PAR SON ATTRIBUT ET NON PAR `--capitana` : cette classe ne
     vaut qu'un selecteur, donc 0,1,0, et elle perdrait contre
     `.liga-row__fig + .liga-row__fig` qui en vaut deux. L'attribut la met a
     0,2,0, a egalite, et l'ordre tranche. */
  .liga-row__fig[data-persona="asha"]      { margin-left: -13.33vw; }  /* −52 px */
  .liga-row__fig[data-persona="ngsoc"]     { margin-left:  -8.72vw; }  /* −34 px */
  .liga-row__fig[data-persona="zerotrust"] { margin-left:  -6.15vw; }  /* −24 px */
  .liga-row__fig[data-persona="grc"]       { margin-left:  -5.64vw; }  /* −22 px */

  /* LES DEUX HAUTEURS MONTENT DE 16 %, ET L'ETAGEMENT SURVIT. Les six valeurs
     forment une profondeur voulue — ngsoc devant a 60vw, grc au fond a 48 —
     que j'avais dit ne pas aplatir. Ici Gabriel demande explicitement les deux
     dernieres plus grandes, donc l'ecart se resserre : 60 / 58 / 55 / 60 / 50 /
     56. Zerotrust rejoint ngsoc au premier plan et grc passe devant ctem, ce
     qui est le sens de la demande — ces deux-la etaient au fond ET rognees.
     Les largeurs qui en decoulent, sur les rapports mesures des fichiers
     (0,399 pour zerotrust, 0,310 pour grc) : 93 et 68 px au lieu de 81 et 58.
     Deux classes et un attribut, comme les six regles qu'elles remplacent —
     sinon elles ne passeraient pas. */
  .page-hero--liga .liga-row__fig[data-persona="zerotrust"] { height: min(80%, 650px, 60vw); }
  .page-hero--liga .liga-row__fig[data-persona="grc"]       { height: min(80%, 604px, 56vw); }
}

@media (max-width: 760px) {
  /* ── AY. LE CORRIDOR RETROUVE SA RESOLUTION, ET LA SOURCE VIENT DE GABRIEL
     Gabriel, trois fois : « l'image en arriere plan des heros dans la page
     metodologias est en mauvaise qualite, un peu pixelise », puis « elle est
     encore plus pixelisee alors que je t'avais dit de l'ameliorer », puis
     « je te redonne l'image de base si cela peut t'aider, reduis la taille de
     l'image si cela peut aider ».

     C'ETAIT LA SEULE CHOSE QUI MANQUAIT. `hero-04_corridor.png` fait
     3 840 x 2 160, soit 2,4 fois la largeur des fichiers qui etaient en service.
     La bande visible sur telephone vaut 18,3 % de la largeur de l'image et
     s'affiche sur 1 170 px d'appareil a DPR 3 :
         1 600 px de source  ->  292 px dans la bande  ->  agrandissement 4,00x
         3 840 px de source  ->  702 px dans la bande  ->  agrandissement 1,66x
     Un quart de la pixelisation, et zero credit depense — j'allais proposer une
     montee d'echelle par IA, elle n'a plus d'objet.

     ET L'IMAGE EST RECADREE, pour la raison que Gabriel autorisait sans le
     savoir. Une premiere version servait les 3 840 px entiers : la nettete etait
     la, mais elle faisait DECODER 8,3 MEGAPIXELS PAR SECTION, six fois par page,
     pour un fond affiche sur 0,4 megapixel. Le poids du fichier n'est pas le
     seul cout d'une image, le decodage en est un, et il se paie en memoire et en
     temps sur un telephone. Comme la formule de cadrage amene la sphere au
     centre de la section, la bande visible ne fait que 702 px de source : on
     garde 1 440 px autour du globe et on jette le reste, que rien ne montre
     jamais sous 760 px.
         pleine largeur   8,3 Mpx a decoder   1 009 Ko   agrandissement 1,66x
         recadree         3,1 Mpx a decoder     802 Ko   agrandissement 1,66x
     Recadrer ne change pas la densite, donc la nettete est identique : c'est du
     decodage et du poids en moins, pour rien en moins a l'ecran.

     LA COLORISATION EST MESUREE, PAS DEVINEE. La source est ROUGE, globe releve
     a 86,9 % en x et 42,2 % en y. Comparaison pixel a pixel avec les six
     fichiers en service, sur les seuls pixels franchement colores — saturation
     > 0,5, luminosite 0,10 a 0,75 : les particules blanches ont une teinte de
     bruit, et les inclure m'avait donne un premier releve incoherent, 356 deg
     pour ctem la ou son fichier lit 24.
         asha        source retournee   teinte    0 deg  sat x1,000  lum x1,000
         ctem        source directe     teinte  +23 deg  sat x0,970  lum x1,015
         ngsoc       source retournee   teinte +213 deg  sat x0,109  lum x1,750
         csirt       source directe     teinte +188 deg  sat x0,978  lum x1,012
         zerotrust   source retournee   teinte +269 deg  sat x0,976  lum x1,000
         grc         source directe     teinte +140 deg  sat x0,980  lum x1,016
     Cinq sont de PURES ROTATIONS DE TEINTE, ce qui explique que les particules
     blanches restent blanches : tourner la teinte d'un pixel desature ne le
     change pas. NGSOC est a part, quasi desature et beaucoup plus clair — c'est
     l'argente du persona, et c'est pour ca que son corridor se voyait moins.
     CONTROLE APRES FABRICATION, chaque fichier pleine largeur ramene a 1 600 px
     et compare a celui qu'il remplace : ecart moyen d'1 unite sur 255, mediane
     0,3 a 1,0, neuvieme decile 2 a 4. Ce sont les memes images, en plus grand.

     LES DEUX VALEURS DE `--sphere` CHANGENT, ET C'EST LA CONSEQUENCE DU
     RECADRAGE. Elles disent ou est le globe EN PIXELS AFFICHES, et la coupe ne
     fait plus 2 133 px de large mais 800 (1 440 de source a l'echelle
     1200/2160). Releve : le globe tombe a 520 px dans les coupes directes et a
     280 dans les retournees. La demi-largeur passe donc de 1 066,5 a 400 dans la
     formule, qui reste la meme : `50 % + demi-largeur - sphere` amene le globe
     au centre horizontal, independamment de la largeur d'ecran.
     Verification : a 390 px, coupe directe, bord gauche = 0,5(390 - 800) - 120
     = -325, et le globe tombe a 520 - 325 = 195. Soit le centre exact.

     L'ANCRAGE VERTICAL RESTE A -129 px, valeur validee. Le globe est a 42,2 % de
     1 200, soit 506 px, donc il tombe a 377 px du haut de la section quand le
     voile est centre sur 375. Deux pixels d'ecart, et je ne touche pas a une
     valeur que Gabriel a regardee.

     SEUL LE TELEPHONE REcOIT CES FICHIERS. Sur ordinateur le corridor s'affiche
     entier et a une bien plus petite echelle — `background-position: 12% 46%`
     sans agrandissement — il y est net, et une coupe de 1 440 px ne couvrirait
     pas sa largeur. D'ou six redeclarations ici, et non un remplacement des
     fichiers d'origine. */
  .method--dark[data-persona="asha"] {
    --corridor: url('../assets/images/bg/corridor/asha-hd.webp');
    --sphere: 280px;
  }
  .method--dark[data-persona="ctem"] {
    --corridor: url('../assets/images/bg/corridor/ctem-hd.webp');
    --sphere: 520px;
  }
  .method--dark[data-persona="ngsoc"] {
    --corridor: url('../assets/images/bg/corridor/ngsoc-hd.webp');
    --sphere: 280px;
  }
  .method--dark[data-persona="csirt"] {
    --corridor: url('../assets/images/bg/corridor/csirt-hd.webp');
    --sphere: 520px;
  }
  .method--dark[data-persona="zerotrust"] {
    --corridor: url('../assets/images/bg/corridor/zerotrust-hd.webp');
    --sphere: 280px;
  }
  .method--dark[data-persona="grc"] {
    --corridor: url('../assets/images/bg/corridor/grc-hd.webp');
    --sphere: 520px;
  }

  /* LA DEMI-LARGEUR SUIT LA COUPE : 400 px et non 1 066,5. Le reste de
     l'expression est celui du bloc AW, avec sa demonstration — un pourcentage
     dans `background-position` aligne le point P % de l'IMAGE sur le point P %
     de la BOITE, donc `50 %` centre l'image et il ne reste qu'a la faire glisser
     de la distance entre son centre et son globe. Le W disparait de l'equation :
     le cadrage ne depend pas de la largeur d'ecran. */
  .method--dark.method--media-start[data-persona],
  .method--dark.method--media-end[data-persona] {
    background-position: 50% 0, calc(50% + 400px - var(--sphere)) -129px;
  }
}

@media (min-width: 761px) {
  /* ── BA. LE SECOND BOUTON DES HEROS PREND LE STYLE DU TELEPHONE ───────────
     Gabriel : « sur la version ordinateur, le bouton de la hero de la home page
     "Conocer el sistema ASHA" doit avoir le meme style que la version mobile,
     pareil pour les seconds boutons des autres heros des differentes pages ».

     CE QUI CHANGE : la seconde plaque devient un lien souligne. Une hero portait
     deux aplats de meme poids, donc deux actions de meme rang alors qu'il y en a
     une principale. C'est exactement la grammaire du CTA final du site, ou un
     seul aplat rouge porte l'action et le second choix se donne en lien : les
     deux extremites de la page se mettent a parler pareil, sur les deux
     affichages maintenant.

     `@media (min-width: 761px)` ET NON UNE REGLE GLOBALE, et c'est une question
     d'ordre. Les regles du telephone vivent aux lignes 19978 et 20233 ; une
     regle globale ecrite ici, en fin de feuille, les battrait a poids egal et
     imposerait au telephone les valeurs du bureau. Les deux paliers sont donc
     disjoints : chacun garde ses valeurs, et il n'y a pas de cascade a
     arbitrer.

     CE QUE JE NE CHANGE PAS : la DISPOSITION. Sur telephone le lien passe sous
     le bouton et se centre, parce que la rangee y est une colonne. Sur
     ordinateur la rangee reste une rangee et le lien garde sa place a droite de
     la plaque — c'est le style qui etait demande, pas le placement, et cette
     ligne unique est la lecture juste de « le meme style ». A dire plutot qu'a
     decider : si Gabriel veut aussi le lien SOUS le bouton sur ordinateur,
     c'est une ligne de plus.

     LE REMBOURRAGE VERTICAL RESTE CELUI DU BUREAU. Le telephone force
     `padding: 9px 4px` pour que la boite fasse les 32 px de son bouton ; ici la
     plaque voisine fait 48 a 52 px, et imposer 9 px desalignerait les deux
     lignes de base. Seul le rembourrage HORIZONTAL est reprise, parce que
     `.btn-pill` pose 28 px en `!important` (l. 4315) et que le texte du lien
     serait rentre de 28 px par rapport au titre et au bouton. */
  .hero .hero__actions .btn-secondary,
  .page-hero__actions .btn-secondary {
    padding-inline: 4px !important;
    border: 0;
    border-bottom: 1px solid rgba(255, 255, 255, 0.15);
    border-radius: 0 !important;
    background: none;
    box-shadow: none;
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    color: rgba(241, 245, 249, 0.85);
    font-weight: 600;
    transition: color 200ms var(--ease-out),
                border-color 200ms var(--ease-out),
                transform 200ms var(--ease-out);
  }
  .hero .hero__actions .btn-secondary:hover,
  .hero .hero__actions .btn-secondary:focus-visible,
  .page-hero__actions .btn-secondary:hover,
  .page-hero__actions .btn-secondary:focus-visible {
    color: var(--color-fg);
    background: none;
    border-bottom-color: rgba(255, 255, 255, 0.5);
    /* Le glissement lateral du CTA, et non la montee des plaques : un lien qui
       se souleve n'a pas de plaque a soulever. */
    transform: translateX(3px) !important;
    box-shadow: none;
  }
}

@media (max-width: 760px) {
  /* ── BB. LA HERO DE LA HOME GRANDIT DE 60 px, LE SECOND HEADER PASSE SOUS
         LA LIGNE ─────────────────────────────────────────────────────────────
     Gabriel : « recalibre quelque chose, il faut agrandir la hero de la home
     page pour faire en sorte que le second header soit pile cache a la
     limite ».

     LES 60 px SONT EXACTS, PAS APPROCHES, ET ILS SONT LES MEMES SUR TOUS LES
     TELEPHONES. La hauteur valait `calc(100svh - 164px)`, et ce 164 se
     decompose — le commentaire de la ligne 18913 le dit : 104 px de bande
     blanche + 54 de sous-navigation + 6 de marge. La sous-navigation etait donc
     ENTIEREMENT VISIBLE par construction, ce qui etait l'intention d'aout.
     Releve a trois formats, et le nombre ne bouge pas :
         390 x 844   bord haut de la sous-nav a y784, fenetre 844 -> 60 px vus
         360 x 800   y740, fenetre 800                          -> 60 px vus
         412 x 915   y855, fenetre 915                          -> 60 px vus
     C'est constant parce que la hauteur est en `svh` : le bas de la hero tombe
     toujours a `fenetre - 164`, et la sous-nav 104 px plus bas, donc a
     `fenetre - 60`. Retirer les deux termes qui la decrivent — 54 + 6 — amene
     son bord haut PILE sur la ligne de flottaison.

     CE QUI RESTE VISIBLE : la bande blanche, entiere, du bas de la hero jusqu'a
     la limite de l'ecran. C'est elle qui devient le dernier element vu, et la
     sous-navigation apparait au premier geste de defilement.

     LES SIX AUTRES HEROS SUIVENT, parce que Gabriel demande la meme taille pour
     toutes. Elles commencent a y=77, sous l'en-tete colle, donc leur propre
     sous-navigation depassera de 27 px (77 - 104 + 54). Les deux demandes se
     contredisent sur ce point precis — « la sous-nav de la home pile cachee » et
     « toutes les heros de la meme taille » — et l'ordre dans lequel Gabriel les
     a posees tranche : c'est la home qui est calibree, les autres s'alignent
     sur sa taille. A dire, pas a decider seul. */
  .hero {
    min-height: max(520px, calc(100vh - 104px)) !important;
    min-height: max(520px, calc(100svh - 104px)) !important;
  }
  .page-hero.page-hero--league,
  .page-nosotros .page-hero {
    min-height: max(520px, calc(100svh - 104px));
  }

  /* ── BC. LES SEPT TITRES A LA MEME HAUTEUR, A TOUTES LES LARGEURS ─────────
     Gabriel : « dans la version mobile les titres de toutes les heros ne sont
     plus a la meme hauteur, je te rappelle que je t'avais dit de les aligner a
     la meme hauteur que le titre de la hero de la home page ».

     ILS L'ETAIENT A 390 px, ET NULLE PART AILLEURS. C'est ce que le releve
     montre, et c'est ce qui rendait le defaut invisible pour moi :
         390 x 844   home 213, les six autres 213   — d'accord
         360 x 800   home 191, les six autres 213   — 22 px d'ecart
         412 x 915   home 259, les six autres 213   — 46 px d'ecart
     J'avais calibre au pixel sur un iPhone 12 et conclu que c'etait aligne. Ce
     n'etait vrai qu'a cette largeur.

     LA CAUSE EST UNE DIFFERENCE DE MECANIQUE VERTICALE, relevee element par
     element :
         `.hero`      flex, `align-items: center`     — contenu CENTRE
         `.page-hero` flex, `align-items: flex-start` — contenu ANCRE EN HAUT
     Un contenu centre se place a la moitie de l'espace restant, donc sa
     position depend de la hauteur de la hero ET de la longueur de son propre
     texte. Un contenu ancre en haut tombe toujours au meme endroit.

     ET C'EST POURQUOI C'EST LA HOME QUI CHANGE DE MECANIQUE, alors que Gabriel
     la designe comme reference. Aligner les six autres SUR un contenu centre
     est impossible : leurs blocs internes mesurent 494, 410 et d'autres valeurs
     selon la longueur de leur lede, donc leur centre tombe ailleurs sur chaque
     page et a chaque largeur. Aucune valeur de rembourrage ne peut suivre ca.
     L'ancrage haut, lui, donne la meme hauteur a tous les titres, sur toutes
     les pages et a toutes les largeurs. La reference reste la home : c'est sa
     VALEUR de 213 px qui est conservee, c'est sa facon de l'atteindre qui
     change.

     LE REMBOURRAGE EST CALCULE, PAS CHERCHE. Dans la home, le titre est le
     premier enfant de `.hero__col-left`, elle-meme dans `.hero__inner` qui
     porte `padding-top: 77px` — la hauteur de l'en-tete colle, sous lequel
     cette hero passe. Le titre tombe donc a `rembourrage de la hero + 77`.
     Pour 213 : 213 - 77 = 136 px. Les six autres gardent leurs 112 px, qui
     donnent 77 + 112 + 24 de marge = 213. Sept titres a 213, quelle que soit la
     hauteur de la hero.

     CE QUE ca COUTE, ET IL FAUT LE DIRE : le contenu de la home ne flotte plus
     au milieu de sa hero, il se pose en haut. Avec la hero agrandie a
     `100svh - 104px`, l'espace qui etait partage en deux passe entierement en
     dessous du contenu — la ou se trouvent deja la ligne de sceaux ISO et le
     repere de defilement, qui s'y repartissent. */
  .hero {
    align-items: flex-start;
    padding-top: 136px;
  }
}

/* -- BD. LE BOUTON DE REFUS DU CONSENTEMENT LISIBLE SUR TOUT FOND -----------
   Lighthouse telephone : contraste insuffisant sur « En este momento no ».
   Le bouton est en --color-muted-lift (#A0AEC2) sur le verre de la banniere,
   rgba(23,23,23,0.82). Sur le noir d'une page c'est 8,4:1. Mais la banniere est
   FIXEE EN BAS, et sur telephone elle tombe sur la bande blanche des logos : le
   verre devient un gris #616161 et le texte descend a 2,75:1, sous les 4,5
   requis pour du 14 px. Mesure sur les pixels rendus, aux deux largeurs :
       fond rendu      #A0AEC2 (avant)   #E2E8F0 (apres)
       telephone         2,75:1            5,02:1
       ordinateur        8,37:1           15,29:1
   PUIS LE BLANC, ET LE SURVOL CHANGE DE SIGNAL. #E2E8F0 passait a 5,02:1 sur
   mon releve (fond #616161, 14 px), mais Lighthouse en ligne le lit a 3,91:1 :
   son fond est #717273 — la banniere n'est pas au meme endroit selon la hauteur
   d'ecran, donc pas sur le meme gris de la bande — et le texte est a 12 px sur
   telephone, ou le seuil est 4,5. Un gris clair ne tient pas sur un fond qui
   varie ; le blanc (--color-fg) tient a 5,3:1 sur le pire des deux. Comme le
   survol passait deja au blanc, il ne pouvait plus se distinguer : il se signale
   desormais par un souligne, ce qui est plus juste pour un bouton en texte nu.
   Regle globale : le defaut ne depend pas de la largeur mais de ce qui passe
   sous la banniere. */
.consent__refus { color: var(--color-fg); }
.consent__refus:hover,
.consent__refus:focus-visible { color: var(--color-fg); text-decoration: underline; text-underline-offset: 3px; }
