/* ===========================================================
   uyoop.css - feuille du site, reconstruction 25-26/08/2026.
   Les jetons viennent de brand/tokens.yaml et restent inchanges.
   Une regle n'existe ici que si une page la porte : tools/check-site.py
   sort en erreur sur toute classe orpheline, dans les deux sens.
   =========================================================== */

:root {
  /* >>> BLOC GENERE depuis brand/tokens.yaml. NE PAS EDITER A LA MAIN.
     Edition   : 2026.08
     Empreinte : sha256:28bbe16609c8eec425eceddc3adddb73d1d884d46e4a865de5bc1313c8577399
     Regenerer : uhub-core/scripts/gen-tokens-css.py
     Verifier  : uhub-core/scripts/gen-tokens-css.py --check
     Une valeur changee ici sera ecrasee au prochain passage, et --check la
     refusera avant. Elle se change dans tokens.yaml. */

  /* Fonds et textes */
  --bg-deep:        #000000;
  --bg-primary:     #050505;
  --text-primary:   #ffffff;
  --text-secondary: #a1a1aa;
  --text-muted:     #8a8a98;
  --border:         #222222;

  /* Accent */
  --accent:         #00ff00;
  --accent-dim:     #00cc88;

  /* Les quatre couleurs de la marque */
  --net: #00ffff;
  --com: #ff00ff;
  --biz: #ffaa00;
  --org: #ff0000;

  /* <<< FIN DU BLOC GENERE */

  /* Hors bloc : une SURFACE, pas un jeton de marque. tokens.yaml nomme des
     couleurs, il ne connait pas les traitements de surface du site. */
  --border-glass:   rgba(255, 255, 255, 0.06);

  /* Typographies */
  --font-brand:   'Comfortaa', sans-serif;
  --font-display: 'Space Grotesk', sans-serif;
  --font-body:    'Inter', sans-serif;

  /* Rayons. Transposition directe des trois rayons du losange de marque,
     releves dans brand/logo/uhub-logo-v1.svg :
       exterieur  rx 26.458 sur un cote de 230  ->  11.50 %
       median     rx 15.824 sur un cote de 200  ->   7.91 %
       interieur  rx  6.203 sur un cote de 175  ->   3.54 %
     Le rapport est conserve : 20 / 13.8 / 6.2, arrondi a 20 / 14 / 6.
     Les deux derniers retombent sur l'echelle de uhub-core (base.css:40-42). */
  /* Le logotype est un TRACE, pas du texte : sa largeur est une LONGUEUR, et
     tout le bloc de tete en decoule. X, le fut du u, vaut 0.02813 de cette
     largeur, releve sur le contour de Comfortaa 600. C'est ce rapport qui a
     identifie la graisse : la planche d'Alan donne 0.02817, le 600 rend
     0.02813, le 700 rend 0.03082. Espace de protection : 3X, mesures sur la
     BOITE du logo, du bas des descendantes au haut des capitales. */
  --logo-width: min(620px, calc(100vw - 2 * var(--marge-tete)));
  --logo-x: 0.02813;
  --slogan-scale: 0.044623;
  --slogan-offset: 0.08590;

  --r-lg: 20px;
  --r-md: 14px;
  --r-sm: 6px;

  /* Largeurs */
  --w-prose: 880px;

  /* Echelle de texte */
  /* ---------------------------------------------------------------
     L'ECHELLE. Sept niveaux, des nombres ENTIERS, et un interligne qui
     retombe toujours sur un multiple de 4 px.

     Pourquoi ca change tout : l'ancienne echelle rendait 12 / 13,6 / 15,2 /
     16,8 / 18,4 / 22,4 / 25,6 / 35,2. Aucune de ces valeurs n'avait ete
     CHOISIE, c'etaient des restes de division de rem decimaux. Quatre pas
     se tenaient a 10 % les uns des autres, que l'oeil ne distingue pas, et
     les interlignes ne retombaient sur aucun rythme commun : la page
     vibrait d'un bloc a l'autre.

     Reference : le type scale du GOV.UK Design System (16, 19, 24, 27, 36,
     48, 80), sept niveaux entiers dont tous les interlignes sont des
     multiples de 5. On garde le principe, pas les valeurs.

     ⛔ LE BLOC DE TETE N'EST PAS DANS CETTE ECHELLE. Le logotype est un
     trace, le slogan se cale sur SA largeur (--logo-width x --slogan-scale),
     d'apres les mesures prises sur les planches d'Alan. Ne jamais y brancher
     une taille de texte.
     --------------------------------------------------------------- */
  --t-label: 0.75rem;      /* 12 px  etiquettes en capitales, tracking large */
  --t-meta:  0.875rem;     /* 14 px  menu, pied de page, dates, notes        */
  --t-small: 1rem;         /* 16 px  texte secondaire : cartes, encart, liens */
  --t-body:  1.1875rem;    /* 19 px  TEXTE COURANT, l'ancre : il ne bouge pas */
  --t-lead:  1.5rem;       /* 24 px  chapo et titres d'encart                */
  /* Le coefficient vw compte plus que le plafond : a 1135 px de fenetre,
     3.2vw rendait 36 px et le plafond de 44 ne servait jamais. Un titre long
     ecrasait la page sans qu'aucune valeur ecrite ne l'explique. */
  --t-h3:    clamp(1.5rem, 2.1vw, 1.875rem);  /* 24 -> 30 px */
  --t-h2:    clamp(1.75rem, 2.6vw, 2.25rem);  /* 28 -> 36 px */

  /* Les interlignes, sans unite pour rester proportionnels. Chacun tombe
     sur un multiple de 4 px a la taille de son niveau. */
  --lh-label: 1.3333;   /* 12 -> 16 */
  --lh-meta:  1.4286;   /* 14 -> 20 */
  --lh-small: 1.5;      /* 16 -> 24 */
  --lh-body:  1.6842;   /* 19 -> 32 */
  --lh-lead:  1.3333;   /* 24 -> 32 */
  --lh-title: 1.2;
  --t-fl-2xl:  clamp(1.9rem, 4.6vw, 3.1rem);

  /* Hauteur de la barre, une seule valeur pour toute la page */
  --h-barre: 72px;

  /* La marque et le slogan ont exactement la meme largeur.
     Mesure faite dans les fichiers de police servis par ce site :
       « uyoop » en Comfortaa 700, interlettrage 0.06em  ->  3.51400 em de large
       le slogan en Space Grotesk 300, interlettrage 0.30em -> 22.15200 em de large
     Rapport 22.15200 / 3.51400 = 6.303927. Toute retouche de l'un des deux
     interlettrages, de la graisse ou du texte du slogan invalide ce nombre :
     le recalculer plutot que l'ajuster a l'oeil. */
  --rapport-marque: 6.303927;

  /* La marque et le slogan font tous deux 22.152 em de large, c'est la raison
     d'etre du rapport ci-dessus. Leur largeur en pixels vaut donc exactement
     22.152 x --taille-slogan, et il suffit de tenir CE nombre sous la largeur
     disponible pour qu'aucun des deux ne deborde.
     Le diviseur est 24 et non 22.152 : les 8 pour cent d'ecart sont la marge
     de respiration a gauche et a droite du bloc.
     ⛔ Aucun terme en rem ici. Un rem depend de la taille de police reglee par
     le visiteur sur son appareil ; avec un reglage « grande police » sur
     Android, le plafond montait et la marque sortait de l'ecran. Mesure faite
     sur telephone le 26/08/2026. Le logotype se dimensionne sur la fenetre,
     jamais sur une preference systeme. */
  --marge-tete: clamp(20px, 4vw, 48px);
  --taille-slogan: min(22.4px, calc((100vw - 2 * var(--marge-tete)) / 24));
}
/* --- Socle -------------------------------------------------- */
*, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }
html { scroll-behavior: smooth; }
/* --- Lien d'evitement ---------------------------------------
   Premier element focusable de la page : il mene droit a <main>, sans
   retraverser l'entete et la navigation a chaque page, au clavier comme
   au lecteur d'ecran.
   ⛔ Ni display:none ni visibility:hidden : l'un et l'autre le sortiraient
   de l'ordre de tabulation, donc le rendraient inatteignable. On le sort
   du cadre, et le focus le ramene. */
.skip-link {
  position: absolute;
  top: -100%;
  left: 0;
  z-index: 200;
  padding: 0.8rem 1.4rem;
  background: var(--accent);
  color: var(--bg-deep);
  font-family: var(--font-display);
  font-size: var(--t-meta);
  letter-spacing: 0.06em;
  text-decoration: none;
}
.skip-link:focus { top: 0; }
body {
  font-family: var(--font-body);
  background: var(--bg-deep);
  color: var(--text-primary);
  line-height: 1.6;
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
}
a { color: inherit; text-decoration: none; }
img { max-width: 100%; height: auto; display: block; }
ul, ol { list-style: none; }
/* Le « u » de la marque porte l'accent, partout. */
.u { color: var(--accent); }
/* La marque en cours de phrase garde sa police. */
.brand { font-family: var(--font-brand); font-weight: 700; letter-spacing: 0.06em; }
/* Un parcours au clavier doit se voir. */
a:focus-visible, summary:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
}
/* ===========================================================
   BARRE, commune a toutes les pages
   =========================================================== */
.topbar {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: var(--h-barre);
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
  padding: 0 clamp(1.25rem, 4vw, 3rem);
  background: rgba(0, 0, 0, 0.72);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border-bottom: 1px solid var(--border-glass);
}
.topbar-brand {
  font-family: var(--font-brand);
  font-size: var(--t-lead);
  font-weight: 700;
  letter-spacing: 0.12em;
}
/* Le menu occupe l'espace libre et se range a droite, le logo ferme la barre. */
.topbar-nav {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: clamp(1rem, 2.5vw, 2rem);
  flex: 1;
}
.topbar-logo {
  width: 28px;
  height: 28px;
  flex-shrink: 0;
}
.topbar-nav a {
  font-family: var(--font-display);
  font-size: var(--t-meta);
  letter-spacing: 0.08em;
  color: var(--text-secondary);
  padding: 0.35rem 0;
  border-bottom: 1px solid transparent;
  transition: color 0.2s, border-color 0.2s;
}
.topbar-nav a:hover { color: var(--text-primary); border-bottom-color: var(--accent); }
.topbar-nav a[aria-current="page"] {
  color: var(--text-primary);
  border-bottom-color: var(--accent);
}
/* Le depliant natif remplace le menu sur les ecrans etroits, sans script. */
.topbar-drawer { display: none; position: relative; }
.topbar-drawer summary {
  list-style: none;
  cursor: pointer;
  width: 40px;
  height: 40px;
  display: grid;
  place-items: center;
  /* Sans rang explicite, le bouton passe SOUS le voile : le panneau est
     positionne, le bouton ne l'etait pas, donc le panneau et son ombre se
     peignaient par dessus lui. */
  position: relative;
  z-index: 2;
}
.topbar-drawer summary::-webkit-details-marker { display: none; }
.topbar-burger,
.topbar-burger::before,
.topbar-burger::after {
  content: "";
  display: block;
  width: 22px;
  height: 2px;
  background: var(--text-primary);
  border-radius: 1px;
  transition: transform 0.25s, top 0.25s, background 0.25s;
}
.topbar-burger { position: relative; }
.topbar-burger::before { position: absolute; top: -7px; }
.topbar-burger::after  { position: absolute; top: 7px; }
/* Ouvert, les trois traits deviennent une croix : le bouton dit ce qu'il fait.
   Le trait du milieu s'efface, les deux autres se croisent au centre. */
.topbar-drawer[open] summary .topbar-burger { background: transparent; }
.topbar-drawer[open] summary .topbar-burger::before {
  top: 0;
  transform: rotate(45deg);
  background: var(--accent);
}
.topbar-drawer[open] summary .topbar-burger::after {
  top: 0;
  transform: rotate(-45deg);
  background: var(--accent);
}
/* Depliant ouvert : la page passe derriere un voile a 50 pour cent, le panneau
   du menu n'a aucun fond.
   ⛔ Le voile ne peut PAS etre un enfant en position:fixed. La barre porte un
   backdrop-filter, ce qui fait d'elle le bloc conteneur de ses descendants
   fixes : un inset:0 se resout alors sur la barre de 72 px, pas sur la fenetre.
   L'ombre portee, elle, n'est pas bornee par le bloc conteneur. Un etalement de
   100vmax couvre donc toute la fenetre, sans script et sans element en plus. */
.topbar-drawer[open] nav {
  box-shadow: 0 0 0 100vmax rgba(0, 0, 0, 0.8);
}
.topbar-drawer nav {
  position: absolute;
  top: calc(100% + 0.9rem);
  right: 0;
  min-width: 210px;
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  padding: 0.6rem;
  background: #000000;
  /* Le panneau est noir plein sur une page voilee a 70 pour cent, donc presque
     noire elle aussi : sans ce filet, il ne se detacherait plus de son fond. */
  border: 1px solid var(--border);
  border-radius: var(--r-md);
}
.topbar-drawer nav a {
  font-family: var(--font-display);
  font-size: var(--t-small);
  color: var(--text-secondary);
  padding: 0.6rem 0.75rem;
  border-radius: var(--r-sm);
}
.topbar-drawer nav a:hover { color: var(--text-primary); background: rgba(255, 255, 255, 0.05); }
.topbar-drawer nav a[aria-current="page"] { color: var(--accent); }
/* ===========================================================
   TETE DE L'ACCUEIL - un ecran plein, puis le corps
   =========================================================== */
.hero {
  min-height: 100svh;
  padding: var(--h-barre) var(--marge-tete) 0;
  text-align: center;
  position: relative;
  overflow: hidden;
}
/* La signature est calee au milieu du hero. Les deux autres reperes de hauteur,
   les metiers et la portee, sont morts avec l'ancien hero en texte : depuis
   09/2026 le mot est un trace, pas une chaine de caracteres. */
.hero-signature {
  position: absolute;
  left: 50%;
  width: 100%;
  padding: 0 var(--marge-tete);
  z-index: 1;
}
.hero-signature { top: 50%; transform: translate(-50%, -50%); }
/* Le logo en filigrane, au centre, sans gener la lecture. */
.hero-watermark {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: clamp(300px, 48vw, 620px);
  opacity: 0.05;
  pointer-events: none;
  z-index: 0;
}
.hero-tagline {
  font-family: var(--font-display);
  font-size: calc(var(--logo-width) * var(--slogan-scale));
  margin-top: calc(var(--logo-width) * var(--slogan-offset));
  line-height: 1;
  font-weight: 300;
  letter-spacing: 0.3em;
  margin-right: -0.3em;
  text-transform: uppercase;
  /* Un slogan replie vaut mieux qu'un slogan coupe : le retour a la ligne
     reste possible, meme s'il ne se produit pas de 320 a 1440 px. */
  white-space: normal;
  color: var(--text-secondary);
}
/* Le repere de descente : la page continue sous le premier ecran. */
.hero-scroll {
  position: absolute;
  bottom: 1.5rem;
  left: 50%;
  transform: translateX(-50%);
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  /* Zero, et les respirations s'ecrivent la ou elles ont un sens : un gap
     uniforme ecarte autant les deux moities d'une phrase que le verbe. */
  gap: 0;
  font-family: var(--font-display);
  font-size: var(--t-label);
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--text-muted);
}
.hero-scroll span { line-height: 1.75; }
/* Le verbe porte l'action : couleur pleine quand le reste du bloc est attenue. */
.hero-scroll .hero-scroll-verb {
  margin-top: 0.85rem;
  color: var(--text-primary);
}
/* ⛔ Cette ligne degradee est le DERNIER enfant. Tout span ajoute au bloc se
   pose avant elle, jamais apres. */
.hero-scroll span:last-child {
  margin-top: 0.7rem;
  width: 1px;
  height: 26px;
  background: linear-gradient(to bottom, var(--text-muted), transparent);
}
/* ===========================================================
   TETE DES PAGES INTERIEURES
   =========================================================== */
.page-head {
  padding: calc(var(--h-barre) + clamp(3.5rem, 10vh, 6rem)) clamp(1.25rem, 4vw, 3rem) clamp(2.5rem, 6vh, 4rem);
  border-bottom: 1px solid var(--border-glass);
}
.page-logo {
  width: 62px;
  height: 62px;
  margin-bottom: 1.25rem;
}
.page-title {
  font-family: var(--font-display);
  font-size: var(--t-fl-2xl);
  font-weight: 600;
  line-height: 1.1;
  margin-bottom: 1.25rem;
}
.page-lead {
  font-size: var(--t-lead);
  line-height: var(--lh-lead);
  color: var(--text-secondary);
  max-width: var(--w-prose);
}
/* ===========================================================
   CORPS COMMUN
   =========================================================== */
.section { padding: clamp(3.5rem, 9vh, 6.5rem) clamp(1.25rem, 4vw, 3rem); }
.section--alt { background: var(--bg-primary); }
/* ⛔ UNE SEULE LARGEUR POUR TOUT LE SITE (CJ, 14/09/2026 : « la meme largeur
   que le reste, partout »). Il y avait deux colonnes : les blocs reservaient
   1180 px et leur contenu en occupait 880, soit 300 px de vide mort a droite,
   A L'INTERIEUR du bloc. Le bloc etait centre, son contenu ne l'etait pas :
   la page penchait a gauche sur 26 blocs et six pages.
   Le modificateur `--wide` et la liste de quinze selecteurs qui rattrapait la
   largeur enfant par enfant sont supprimes : ils reparaient un ecart qui n'a
   plus lieu d'etre. */
.block { max-width: var(--w-prose); margin: 0 auto; }
.heading {
  font-family: var(--font-display);
  font-size: var(--t-h2);
  font-weight: 600;
  line-height: var(--lh-title);
  margin-bottom: 1.75rem;
}
/* Un titre qui ouvre sa section n'a pas besoin de marge haute ; un titre qui
   en enchaine une autre dans le meme bloc, si. */
.heading:not(:first-child) { margin-top: 3.25rem; }
/* Un titre qui porte un logo : le logo se range a gauche et le titre garde sa
   ligne de base, sans casser la largeur de lecture. */
/* ⛔ Les marges du titre appartiennent au BLOC, pas au titre. Un flex centre
   sur la boite MARGE COMPRISE : laissees sur le titre, les 3.25rem de
   `.heading:not(:first-child)` decalaient le logo de la moitie, 26 px mesures.
   Et cette regle de marge haute tire ici sur un cas pour lequel elle n'a pas
   ete ecrite, le titre n'etant deuxieme que parce que le logo est premier. */
.heading-logo {
  display: flex;
  align-items: center;
  gap: 1.4rem;
  max-width: var(--w-prose);
  margin-top: 3.25rem;
  margin-bottom: 1.75rem;
}
.heading-logo-img {
  width: 54px;
  height: 54px;
  flex-shrink: 0;
}
.heading-logo .heading { margin-top: 0; margin-bottom: 0; }
.subheading {
  font-family: var(--font-display);
  font-size: var(--t-h3);
  font-weight: 500;
  line-height: var(--lh-title);
  margin: 2.75rem 0 1rem;
}
.lead {
  font-size: var(--t-lead);
  line-height: var(--lh-lead);
  margin-bottom: 2rem;
}
.prose {
  font-size: var(--t-body);
  line-height: var(--lh-body);
  color: var(--text-secondary);
  margin-bottom: 1.5rem;
}
.prose--small { font-size: var(--t-small); color: var(--text-muted); }
.closing {
  margin-top: 2.5rem;
  padding-top: 1.75rem;
  border-top: 1px solid var(--border);
  font-family: var(--font-display);
  font-size: var(--t-lead);
  font-weight: 500;
  line-height: 1.5;
}
kbd {
  font-family: var(--font-display);
  font-size: 0.85em;
  padding: 0.1em 0.45em;
  color: var(--text-primary);
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
}
.link { color: var(--accent-dim); border-bottom: 1px solid rgba(0, 204, 136, 0.35); }
.link:hover { color: var(--accent); border-bottom-color: var(--accent); }
/* --- Cesure de bloc ----------------------------------------
   Chaque section s'annonce par une etiquette precedee d'un operateur colore.
   Geste repris de la page du 24/08 (style.css:1249) : il donne au lecteur un
   repere de position sans ajouter une ligne de prose. */
.eyebrow {
  font-family: var(--font-display);
  font-size: var(--t-meta);
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 1.25rem;
}
.eyebrow-op {
  font-weight: 400;
  margin-right: 0.8em;
  letter-spacing: 0;
  opacity: 0.8;
}
.eyebrow-op--net { color: var(--net); }
.eyebrow-op--com { color: var(--com); }
.eyebrow-op--biz { color: var(--biz); }
.eyebrow-op--org { color: var(--org); }
/* Le filet de separation entre deux sections : quatre points, les quatre
   couleurs de la marque, dans l'ordre fige de uColors. */
.divider {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 0 clamp(1.25rem, 4vw, 3rem);
}
.divider::before,
.divider::after {
  content: "";
  flex: 1;
  max-width: 200px;
  height: 1px;
  background: linear-gradient(to right, transparent, rgba(255, 255, 255, 0.16), transparent);
  margin: 0 1.1rem;
}
.divider-dot {
  width: 5px;
  height: 5px;
  border-radius: 50%;
  opacity: 0.75;
}
.divider-dot--net { background: var(--net); }
.divider-dot--com { background: var(--com); }
.divider-dot--biz { background: var(--biz); }
.divider-dot--org { background: var(--org); }
/* --- Encart ------------------------------------------------- */
.callout {
  padding: 1.75rem;
  background: rgba(255, 255, 255, 0.022);
  border: 1px solid var(--border-glass);
  border-radius: var(--r-lg);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
}
.callout-head {
  display: flex;
  align-items: center;
  gap: 0.85rem;
  margin-bottom: 1.1rem;
}
.callout-glyph { width: 38px; height: 38px; flex-shrink: 0; }
/* ⛔ Il partageait sa taille avec `.prose` : meme jeton, donc deux roles
   differents au meme corps. L'oeil ne pouvait pas les hierarchiser. */
.callout-title {
  font-family: var(--font-display);
  font-size: var(--t-lead);
  line-height: var(--lh-lead);
  font-weight: 500;
}
.callout p {
  font-size: var(--t-small);
  line-height: 1.7;
  color: var(--text-secondary);
}
.callout p + p { margin-top: 0.85rem; }
/* --- Calendrier condense ------------------------------------ */
.timeline { display: grid; gap: 0.85rem; margin-bottom: 1.5rem; }
.reg-item {
  display: grid;
  /* Largeur prise sur le texte le plus long, « depuis le 1er septembre 2026 »,
     pas sur une valeur ronde : a 160 px il se coupait en deux. */
  grid-template-columns: minmax(150px, 200px) 1fr;
  gap: 0.3rem 1.5rem;
  padding-bottom: 0.85rem;
  border-bottom: 1px solid var(--border);
  align-items: start;
}
.reg-when {
  font-family: var(--font-display);
  font-size: var(--t-meta);
  font-weight: 500;
  letter-spacing: 0.04em;
  color: var(--accent);
}
.reg-text { font-size: var(--t-small); line-height: var(--lh-small); color: var(--text-secondary); }
/* --- Tarifs -------------------------------------------------- */
.prices { display: grid; gap: 0; margin-bottom: 1.5rem; }
.price {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 0.3rem 1.5rem;
  padding: 1rem 0;
  border-bottom: 1px solid var(--border);
  align-items: baseline;
}
.price-name { font-size: var(--t-small); }
.price-value {
  font-family: var(--font-brand);
  font-size: var(--t-body);
  font-weight: 700;
  color: var(--accent);
  white-space: nowrap;
}
.price-note {
  grid-column: 1 / -1;
  font-size: var(--t-meta);
  line-height: 1.6;
  color: var(--text-muted);
}
.list { display: grid; gap: 0.7rem; margin-bottom: 1.5rem; }
.card .list { margin-bottom: 0; }
.card .list li { font-size: var(--t-small); }
.list li {
  position: relative;
  padding-left: 1.15rem;
  font-size: var(--t-small);
  line-height: 1.6;
  color: var(--text-secondary);
}
.list li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.62em;
  width: 5px;
  height: 5px;
  background: var(--accent-dim);
  transform: rotate(45deg);
}
.button {
  display: inline-block;
  margin-top: 1rem;
  padding: 0.85rem 1.6rem;
  font-family: var(--font-display);
  font-size: var(--t-small);
  letter-spacing: 0.06em;
  color: var(--accent);
  border: 1px solid var(--accent-dim);
  border-radius: var(--r-md);
  transition: background 0.25s, color 0.25s, box-shadow 0.25s;
}
.button:hover {
  background: var(--accent);
  color: #000000;
  box-shadow: 0 0 24px rgba(0, 255, 0, 0.22);
}
/* --- Les dates posees --------------------------------------- */
.milestones {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1.75rem 1.5rem;
  margin-bottom: 2.5rem;
  padding-bottom: 2.5rem;
  border-bottom: 1px solid var(--border);
}
.milestone { display: flex; flex-direction: column; gap: 0.3rem; }
.milestone-year {
  font-family: var(--font-brand);
  font-size: var(--t-lead);
  font-weight: 700;
  color: var(--accent);
}
.milestone-text { font-size: var(--t-small); line-height: 1.5; color: var(--text-secondary); }
/* --- Grilles de cartes -------------------------------------- */
.grid { display: grid; gap: 1.25rem; }
.grid:not(:last-child) { margin-bottom: 2rem; }
.grid--2 { grid-template-columns: repeat(2, 1fr); }
.grid--3 { grid-template-columns: repeat(3, 1fr); }
.grid--4 { grid-template-columns: repeat(4, 1fr); }
/* La carte porte le rayon exterieur du losange de marque. Le filet colore
   n'est pas une bordure : c'est un trait pose en tete, qui s'etend au survol.
   Reprise du geste de la page du 24/08 (style.css:478). */
.card {
  position: relative;
  overflow: hidden;
  padding: 1.6rem 1.5rem 1.5rem;
  background: rgba(255, 255, 255, 0.022);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border: 1px solid var(--border-glass);
  border-radius: var(--r-lg);
  display: flex;
  flex-direction: column;
  transition: border-color 0.35s, transform 0.35s, background 0.35s;
}
.card::before {
  content: "";
  position: absolute;
  top: 0;
  left: 18%;
  right: 18%;
  height: 2px;
  border-radius: 0 0 2px 2px;
  background: var(--border);
  opacity: 0.65;
  transition: opacity 0.35s, left 0.35s, right 0.35s;
}
.card:hover {
  transform: translateY(-2px);
  background: rgba(255, 255, 255, 0.035);
  border-color: rgba(255, 255, 255, 0.12);
}
.card:hover::before { opacity: 1; left: 8%; right: 8%; }
/* La carte s'ouvre par UNE ligne : le symbole de marque et son libelle cote a
   cote, comme dans la tete de l'accueil. Le symbole est servi depuis brand/
   sans retouche. */
.card-row {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  margin-bottom: 0.85rem;
}
.card-glyph {
  width: 32px;
  height: 32px;
  flex-shrink: 0;
}
.card-row .card-name { margin-top: 0; }
.card-key {
  font-family: var(--font-display);
  font-size: var(--t-body);
  font-weight: 300;
  letter-spacing: 0.14em;
  display: block;
}
.card-name {
  font-family: var(--font-display);
  font-size: var(--t-label);
  font-weight: 400;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--text-primary);
  display: block;
  margin-top: 0.5rem;
  line-height: 1.35;
}
.card-field {
  font-family: var(--font-display);
  font-size: 0.7rem;
  font-weight: 300;
  letter-spacing: 0.10em;
  color: var(--text-muted);
  display: block;
  margin-bottom: 1rem;
}
.card-text {
  font-size: var(--t-small);
  line-height: 1.65;
  color: var(--text-secondary);
  display: block;
}
.card-fact {
  display: block;
  margin-top: auto;
  padding-top: 0.9rem;
  border-top: 1px solid var(--border);
  font-size: var(--t-meta);
  line-height: 1.6;
  color: var(--text-muted);
}
.card--net::before { background: var(--net); }
.card--com::before { background: var(--com); }
.card--biz::before { background: var(--biz); }
.card--org::before { background: var(--org); }
.card--net .card-key { color: var(--net); }
.card--com .card-key { color: var(--com); }
.card--biz .card-key { color: var(--biz); }
.card--org .card-key { color: var(--org); }
/* --- Ce qui arrive, date par date --------------------------- */
.issues { display: grid; gap: 1.1rem; margin-bottom: 2rem; }
.issue {
  display: grid;
  grid-template-columns: minmax(130px, 170px) 1fr;
  gap: 0.4rem 1.5rem;
  padding-bottom: 1.1rem;
  border-bottom: 1px solid var(--border);
}
.issue-date {
  font-family: var(--font-display);
  font-size: var(--t-small);
  font-weight: 500;
  color: var(--accent);
  letter-spacing: 0.04em;
}
.issue-name {
  font-family: var(--font-display);
  font-size: var(--t-small);
  font-weight: 500;
}
.issue-text {
  grid-column: 2;
  font-size: var(--t-small);
  line-height: 1.65;
  color: var(--text-secondary);
}
.sources {
  margin-top: 2rem;
  font-size: var(--t-label);
  line-height: 1.8;
  color: var(--text-muted);
}
/* --- Deux colonnes qui se repondent ------------------------- */
.pair { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 2rem; }
.pair-who {
  font-family: var(--font-display);
  font-size: var(--t-small);
  font-weight: 500;
  color: var(--accent);
  margin-bottom: 1rem;
  padding-bottom: 0.6rem;
  border-bottom: 1px solid var(--border);
}
/* --- Tableau de specifications ------------------------------ */
.specs { display: grid; gap: 0; margin-bottom: 1.5rem; }
.spec {
  display: grid;
  grid-template-columns: minmax(150px, 230px) 1fr;
  gap: 0.35rem 1.5rem;
  padding: 0.85rem 0;
  border-bottom: 1px solid var(--border);
}
.spec-name {
  font-family: var(--font-display);
  font-size: var(--t-meta);
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--text-muted);
}
.spec-value { font-size: var(--t-small); line-height: 1.6; color: var(--text-secondary); }
/* --- Coordonnees -------------------------------------------- */
.coords { display: grid; gap: 0; margin-bottom: 2rem; }
.coords-row {
  display: grid;
  grid-template-columns: minmax(120px, 180px) 1fr;
  gap: 0.35rem 1.5rem;
  padding: 0.9rem 0;
  border-bottom: 1px solid var(--border);
  align-items: baseline;
}
.coords-label {
  font-family: var(--font-display);
  font-size: var(--t-meta);
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--text-muted);
}
.coords-value { font-size: var(--t-body); line-height: 1.5; }
/* --- Pages legales ------------------------------------------ */
.legal-updated {
  font-family: var(--font-display);
  font-size: var(--t-meta);
  letter-spacing: 0.05em;
  color: var(--text-muted);
  margin-bottom: 2.5rem;
  padding-bottom: 1.25rem;
  border-bottom: 1px solid var(--border);
}
/* --- Bandeau de sobriete -----------------------------------
   Meme phrase, meme place, sur les six pages : juste au dessus du pied. */
.banner-body { padding: 0 clamp(1.25rem, 4vw, 3rem) clamp(2rem, 5vh, 3rem); }
.banner-body .block { max-width: var(--w-prose); }
.banner {
  /* Largeur de lecture, comme la prose et les encarts. Mais centre, parce que
     le bandeau appartient a la CLOTURE de la page avec le pied, pas au corps :
     le bord gauche du corps ne bouge jamais, la cloture est centree, et les
     deux regles se lisent au lieu de se contredire. */
  max-width: var(--w-prose);
  margin: 0 auto;
  padding: 1.1rem 1.5rem;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.9rem;
  background: rgba(255, 255, 255, 0.022);
  border: 1px solid var(--border-glass);
  border-radius: var(--r-lg);
  font-family: var(--font-display);
  font-size: var(--t-small);
  line-height: 1.4;
}
.banner-glyph { width: 30px; height: 30px; flex-shrink: 0; }
/* ===========================================================
   PIED DE PAGE, commun a toutes les pages
   =========================================================== */
.footer {
  padding: clamp(2.5rem, 6vh, 4rem) clamp(1.25rem, 4vw, 3rem) 2rem;
  border-top: 1px solid var(--border-glass);
  background: var(--bg-primary);
}
/* Le pied se lit comme une seule composition centree. Pousser trois blocs aux
   extremites sous un contenu centre donnait une page qui paraissait non
   maitrisee. */
.footer-top {
  max-width: var(--w-prose);
  margin: 0 auto 1.75rem;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1.25rem;
}
.footer-brand {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  font-family: var(--font-brand);
  font-size: var(--t-lead);
  font-weight: 700;
  letter-spacing: 0.12em;
}
.footer-logo { width: 30px; height: 30px; }
.footer-nav {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.75rem 1.75rem;
  font-family: var(--font-display);
  font-size: var(--t-meta);
  letter-spacing: 0.06em;
}
.footer-nav a { color: var(--text-secondary); }
.footer-nav a:hover { color: var(--accent); }
.footer-legal {
  max-width: var(--w-prose);
  margin: 0 auto;
  padding-top: 1.5rem;
  border-top: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.45rem;
  text-align: center;
  font-size: var(--t-label);
  line-height: 1.6;
  color: var(--text-muted);
}
.footer-contact {
  margin-top: 0.9rem;
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  font-family: var(--font-display);
  font-size: var(--t-meta);
  letter-spacing: 0.06em;
  color: var(--text-secondary);
}
.footer-dot { width: 17px; height: 17px; }
.footer-legal a { color: var(--accent-dim); }
.footer-legal a:hover { color: var(--accent); }
/* ===========================================================
   ECRANS ETROITS
   =========================================================== */

/* =============================================================
   LE LOGOTYPE, LES ONGLETS, LE CALENDRIER
   Objets introduits par la refonte de la page d'accueil (09/2026).
   ============================================================= */

/* Le mot est une image, donc il ne peut pas deborder. Le h1 l'entoure et ne
   rend rien : il porte la structure du document, l'image porte alt="uyoop". */
.brand-heading { margin: 0; font-size: 0; line-height: 0; }
.brand-wordmark {
  display: block;
  width: var(--logo-width);
  height: auto;
  margin: 0 auto;
}
/* --- Les quatre poles metiers, en accordeon natif -------------------------
   Des <details name>, donc exclusifs, sans une ligne de script. Un navigateur
   qui ignore l'attribut laisse plusieurs panneaux ouverts : la page reste
   lisible, c'est la seule degradation acceptable. */
.tabs { margin-top: 2.5rem; border-top: 1px solid var(--border); }
.tab { border-bottom: 1px solid var(--border); }
.tab > summary {
  cursor: pointer;
  list-style: none;
  display: flex;
  align-items: center;
  gap: 0.7rem;
  padding: 1.1rem 0.25rem;
  /* Coins hauts seuls, le bas porte le soulignement actif.
     --r-md et non --r-sm : un onglet est une grande surface cliquable, de la
     famille de .bouton. A 6 px sur un bloc de 120 px le rayon ne se lit pas,
     et un rayon qui ne se lit pas vaut un angle droit. */
  border-radius: var(--r-md) var(--r-md) 0 0;
  transition: background 0.15s ease;
}
.tab > summary::-webkit-details-marker { display: none; }
.tab > summary::marker { content: ""; }
.tab > summary:hover { background: rgba(255, 255, 255, 0.03); }
.tab > summary:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.tab-glyph { width: 26px; height: 26px; flex: none; }
.tab-tld { font-family: var(--font-display); font-size: var(--t-small); letter-spacing: 0.02em; }
.tab-net .tab-tld { color: var(--net); }
.tab-com .tab-tld { color: var(--com); }
.tab-biz .tab-tld { color: var(--biz); }
.tab-org .tab-tld { color: var(--org); }
.panel { padding: 0.25rem 0.25rem 1.9rem; max-width: var(--w-prose); }
.panel-text { font-size: var(--t-small); line-height: var(--lh-small); margin-bottom: 1rem; }
.panel-proof {
  font-size: var(--t-small);
  color: var(--text-secondary);
  border-left: 2px solid var(--border);
  padding-left: 0.9rem;
}
/* Ce qui n'est pas fini se dit UNE fois, en bas de zone, sans nommer lequel. */
.panel-note {
  margin-top: 0.55rem;
  padding-left: 0.9rem;
  font-size: var(--t-label);
  font-style: italic;
  color: var(--text-muted);
}
/* La securite n'est pas un pole metier, c'est un pilier : elle a sa ligne
   sous les quatre onglets, pas une case dans l'un d'eux. */
.cross-cutting {
  margin-top: 2.25rem;
  padding-top: 1.4rem;
  border-top: 1px solid var(--border);
  font-size: var(--t-small);
  line-height: var(--lh-small);
  color: var(--text-secondary);
  max-width: var(--w-prose);
}
/* --- Les etiquettes capitales : UNE voix, pas cinq -----------------------
   ⛔ Ce registre portait CINQ tailles (10,88 / 11,52 / 12 / 12 / 13,6) et
   CINQ interlettrages pour un seul et meme objet : une petite etiquette en
   capitales. Deux niveaux suffisent. `.eyebrow` ouvre une section et garde
   son interlettrage large ; toutes les autres parlent d'une seule voix. */
.tab-name,
.panel-field,
.cross-cutting-label,
.reg-status {
  font-family: var(--font-display);
  font-size: var(--t-label);
  letter-spacing: 0.15em;
  text-transform: uppercase;
}
.tab-name            { color: var(--text-secondary); }
.panel-field         { color: var(--text-muted); margin-bottom: 0.7rem; }
.cross-cutting-label { display: block; color: var(--accent-dim); margin-bottom: 0.6rem; }
.reg-status          { display: block; line-height: 1.3; }
/* --- Le calendrier dit un ETAT, pas une echeance -------------------------
   Une echeance devient fausse le lendemain. L'etat, lui, ne se perime pas :
   les 1er et 11 septembre 2026 sont restes ecrits au futur trois jours apres
   etre passes. */
.reg-status--in-force  { color: var(--accent); }
.reg-status--available { color: var(--accent-dim); }
.reg-status--pending   { color: var(--text-muted); }
.reg-since {
  display: block;
  margin-top: 0.3rem;
  font-family: var(--font-display);
  font-size: var(--t-label);
  font-weight: 400;
  letter-spacing: 0.02em;
  line-height: 1.45;
  color: var(--text-muted);
}
/* --- Au large, l'accordeon devient une rangee d'onglets ------------------ */
@media (min-width: 781px) {
  .tabs {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    column-gap: 1.25rem;
    border-top: none;
  }
  /* Le details disparait en tant que boite : son resume et son panneau
     deviennent des cases de la grille. L'ouverture reste geree par le
     navigateur. */
  .tab { display: contents; }
  .tab > summary {
    grid-row: 1;
    flex-direction: column;
    gap: 0.45rem;
    padding: 1.1rem 0.5rem;
    border-bottom: 2px solid var(--border);
    text-align: center;
  }
  .tab[open] > summary { background: rgba(255, 255, 255, 0.04); }
  .tab-net[open] > summary { border-bottom-color: var(--net); }
  .tab-com[open] > summary { border-bottom-color: var(--com); }
  .tab-biz[open] > summary { border-bottom-color: var(--biz); }
  .tab-org[open] > summary { border-bottom-color: var(--org); }
  /* Deux ecritures, et il en faut deux : les navigateurs recents enveloppent
     le contenu dans ::details-content, ce sont eux qui portent la case ; les
     plus anciens promeuvent le div. Un selecteur inconnu n'invalide que sa
     propre regle. */
  .tab::details-content { grid-row: 2; grid-column: 1 / -1; }
  .tab > .panel { grid-row: 2; grid-column: 1 / -1; }
  .panel { padding: 2rem 0 0.5rem; }
}
/* Tablette : quatre colonnes deviennent illisibles sous 1050 px de large. */
@media (max-width: 1050px) {
  .grid--4 { grid-template-columns: repeat(2, 1fr); }
  .heading-logo-img { width: 46px; height: 46px; }
}
@media (max-width: 780px) {
  .topbar-nav { display: none; }
  .topbar-logo { margin-left: auto; }
  .grid--2, .grid--3, .grid--4 { grid-template-columns: 1fr; }
  .milestones { grid-template-columns: repeat(2, 1fr); }
  .topbar-drawer { display: block; }
  .hero {
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    gap: clamp(2rem, 6vh, 3.5rem);
    padding-top: calc(var(--h-barre) + 2rem);
    padding-bottom: 3rem;
  }
  .hero-signature {
    position: static;
    transform: none;
    width: 100%;
    padding-left: 0;
    padding-right: 0;
  }
  .issue { grid-template-columns: 1fr; gap: 0.35rem; }
  .issue-text { grid-column: 1; }
  .spec, .coords-row, .reg-item { grid-template-columns: 1fr; }
  .divider::before, .divider::after { max-width: 60px; margin: 0 0.85rem; }
  .pair { gap: 2.5rem; }
}
/* Tablette et telephone en paysage. Une seule colonne gaspille la largeur :
   une carte de 700 px pour trois lignes de texte se lit mal. */
@media (min-width: 521px) and (max-width: 780px) {
  .grid--2, .grid--3, .grid--4 { grid-template-columns: repeat(2, 1fr); }
}
/* Telephone etroit. Deux colonnes de jalons se serrent au point de couper les
   mots ; la mise en page passe en colonne unique, les marges se resserrent, et
   l'echelle de texte descend d'un cran pour rester confortable a la lecture. */
@media (max-width: 520px) {
  .lead { font-size: var(--t-body); }
  .prose { font-size: var(--t-small); }
  .page-lead { font-size: var(--t-body); }
  .callout-title { font-size: var(--t-small); }
  .milestones { grid-template-columns: 1fr; gap: 1.5rem; }
  .section { padding-left: 1.25rem; padding-right: 1.25rem; }
  .page-head { padding-left: 1.25rem; padding-right: 1.25rem; }
  .callout { padding: 1.25rem; }
  .card { padding: 1.35rem 1.25rem 1.25rem; }
  .heading-logo { flex-direction: column; gap: 0.9rem; }
  .heading-logo-img { width: 44px; height: 44px; margin-top: 0; }
  .price { gap: 0.25rem 1rem; }
  .callout-head { align-items: flex-start; }
  .topbar-drawer nav { min-width: min(260px, calc(100vw - 2.5rem)); }
}
/* Ecran court, typiquement un telephone en paysage : le repere de descente
   viendrait chevaucher la ligne de portee, on le retire. */
@media (max-height: 720px) {
  .hero-scroll { display: none; }
}

/* =============================================================
   LE SCHEMA — langage de la marque : losange et circuit imprime
   Le losange n'est pas un polygone a pointes vives : c'est un CARRE
   A COINS ARRONDIS tourne a 45 degres. Rapports releves sur
   brand/logo/uhub-logo-v1.svg, jamais inventes : rx vaut 11,50 %
   du cote pour l'anneau externe, 7,91 % pour le median, 3,54 %
   pour l'interne, et les traits suivent un rapport 4:3:2.
   Les interruptions des anneaux portent des PASTILLES : la marque
   cite le circuit imprime, on garde la citation.
   Les symboles de pole ont leur signature propre, le trait s'eteint
   en tournant (brand/symboles/pole-*.svg).
   ============================================================= */
.diagram { margin: 2.5rem 0 0; }

.diagram-svg {
  display: block;
  width: 100%;
  height: auto;
  overflow: visible;
}

.dg-frame {
  fill: none;
  stroke: var(--border);
  stroke-width: 1;
}
.dg-frame-tag {
  font-family: var(--font-display);
  font-size: 11px;
  letter-spacing: 0.15em;
  fill: var(--text-muted);
}

/* Les pistes, et les pastilles qui les jalonnent. */
.dg-trace {
  fill: none;
  stroke: var(--border);
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.dg-trace--in  { stroke: var(--text-muted); }
.dg-trace--out { stroke: var(--accent-dim); stroke-dasharray: 5 6; }
.dg-pad     { fill: var(--text-muted); }

/* Le visiteur : present, mais attenue. Ce n'est pas lui l'objet. */
.dg-you rect { fill: none; stroke: var(--text-muted); stroke-width: 1.5; }
.dg-you text {
  font-family: var(--font-display);
  font-size: 11px;
  letter-spacing: 0.15em;
  fill: var(--text-muted);
  text-anchor: middle;
}

/* La porte. Seul objet en vert plein : c'est le produit. */
.dg-gate rect {
  fill: none;
  stroke: var(--accent);
  stroke-linecap: round;
}
.dg-gate-label {
  font-family: var(--font-display);
  font-size: 12px;
  letter-spacing: 0.18em;
  fill: var(--text-primary);
  text-anchor: middle;
}
.dg-gate-sub {
  font-family: var(--font-body);
  font-size: 13px;
  fill: var(--text-muted);
  text-anchor: middle;
}

.dg-pole rect { fill: none; stroke-width: 2; }
.dg-pole-tld {
  font-family: var(--font-display);
  font-size: 15px;
  letter-spacing: 0.02em;
}
.dg-pole-txt {
  font-family: var(--font-body);
  font-size: 13px;
  fill: var(--text-secondary);
}

.dg-out {
  font-family: var(--font-body);
  font-size: 13px;
  fill: var(--accent-dim);
}
