/* NubieCloud — socle d'actifs des sites vitrines. Servi a /_nubie/base.css
 *
 * CE FICHIER PORTE LA QUALITE DU PRODUIT, pas le modele.
 *
 * Avec un modele a poids ouverts, le systeme de design ne fait plus seulement le
 * plancher de qualite : il fait aussi le plafond. Plus ce fichier travaille, moins le
 * gout du modele compte -- et c'est ce qui rend l'offre tenable sans modele de pointe.
 *
 * TROIS CONTRAINTES QUI EXPLIQUENT CHAQUE CHOIX CI-DESSOUS :
 *
 * 1. AUCUNE URL EXTERNE. Pas de Google Fonts, pas de CDN, pas d'image distante. C'est
 *    la liste blanche implicite : le modele ne peut referencer que ce que la plateforme
 *    heberge. Les piles de polices sont donc systeme -- ce qui, sur le marche vise, est
 *    aussi le bon choix technique : aucun telechargement, rendu immediat.
 *
 * 2. LE PREMIER RENDU EST SANS PHOTO. L'utilisateur decrit son activite, choisit une
 *    direction et obtient un site AVANT d'avoir rien televerse. Ce n'est pas un cas
 *    degrade, c'est le chemin principal -- d'ou les motifs CSS et les compositions
 *    typographiques ci-dessous, qui doivent avoir l'air VOULUS et non vides.
 *
 * 3. MOBILE D'ABORD. Le marche visé consulte au telephone. Les styles de base sont donc
 *    ceux du petit ecran, et les requetes elargissent.
 */

/* --------------------------------------------------------------------------- *
 * Jetons — la direction artistique les surcharge, rien d'autre
 * --------------------------------------------------------------------------- */

/* --------------------------------------------------------------------------- *
 * LA POLICE, AUTO-HEBERGEE -- ajoutee le 2026-10-31.
 *
 * POURQUOI ELLE ARRIVE SI TARD, et pourquoi c'est le plus gros levier du socle. Les
 * sites etaient sur des piles SYSTEME : `system-ui` donne Roboto sur Android, Segoe sur
 * Windows. Aucun jeu de couleurs ni d'espacements ne compense la texture du texte, et le
 * texte occupe plus de surface que le fond. Mesure sur les deux references fournies par
 * l'utilisateur : stripe.com emploie `sohne-var` (variable, auto-hebergee) et apura --
 * notre propre produit -- emploie Onest. Aucune des deux n'est sur une pile systeme.
 *
 * ET CE N'ETAIT PAS INTERDIT. `verifier_aucune_ressource_distante` refuse une URL
 * seulement si elle porte un SCHEMA (`https:`, `//`). Une police servie depuis `_nubie/`
 * est la notre, meme origine : elle passe. Je l'avais ecartee par analogie avec « aucune
 * URL externe », sans verifier -- et les trois raisons de cette garde sont toutes
 * preservees : aucune dependance a un tiers, aucune adresse IP de visiteur qui fuit,
 * aucun contenu qui change du jour au lendemain.
 *
 * INTER VARIABLE, SOUS-ENSEMBLE LATIN : 48 432 octets, soit MOINS que la Sohne de
 * Stripe (58 852). Un seul fichier pour toutes les graisses de 100 a 900, donc une seule
 * requete. Les 28 caracteres francais verifies un par un -- accents, cedille, oe, euro,
 * guillemets, tiret cadratin : aucun manquant. Licence SIL OFL : auto-hebergement et
 * usage commercial permis.
 *
 * LE NOM DU FICHIER PORTE UNE VERSION (`-1`), et c'est ce qui autorise le cache long.
 * Le chemin du socle est FIXE et sans version -- c'est pourquoi `base.css` est en cache
 * COURT : un an y figerait un socle perime. Une police ne change jamais de contenu sous
 * le meme nom ; en changer changera le nom du fichier, comme pour un media remplace.
 *
 * `font-display: swap` : le texte s'affiche tout de suite dans la pile de secours puis
 * bascule. Sur une connexion lente -- le public vise -- `block` laisserait la page muette
 * plusieurs secondes. */
@font-face {
  font-family: "NubieSans";
  src: url("/_nubie/inter-var-1.woff2") format("woff2-variations");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

:root {
  /* Couleur. Une direction redefinit ces six variables et change tout le site. */
  --nubie-fond: #fffdf9;
  --nubie-fond-alt: #f4efe6;
  --nubie-encre: #1c1917;
  --nubie-encre-doux: #57534e;
  --nubie-accent: #9a3412;
  /* LA COULEUR DU TEXTE **SUR** L'ACCENT, et c'est une PAIRE, pas un supplement.
   *
   * Le bouton ecrivait `color: var(--nubie-fond)` -- il empruntait le fond de la PAGE
   * comme couleur de texte. Ca marche par chance sur les quatre directions actuelles,
   * et rien ne le garantit : une direction dont l'accent et le fond sont tous deux
   * clairs donnerait un bouton illisible, SANS qu'aucune verification ne le voie.
   *
   * C'est la convention de shadcn/ui, lue a la source le 2026-10-08 : chaque couleur de
   * fond va par paire avec son `-foreground`. Un test calcule desormais le contraste
   * WCAG des deux paires de chaque direction. */
  --nubie-accent-encre: #fffdf9;
  --nubie-trait: #e7e0d5;

  /* Typographie. Piles systeme : aucun telechargement, aucune URL externe. */
  --nubie-titre: "NubieSans", system-ui, -apple-system, sans-serif;
  --nubie-texte: "NubieSans", system-ui, -apple-system, sans-serif;

  /* Echelle fluide. clamp() evite les requetes media pour la taille du texte. */
  --nubie-t-xxl: clamp(2.5rem, 9vw, 5.5rem);
  --nubie-t-xl: clamp(1.9rem, 6vw, 3.2rem);
  --nubie-t-l: clamp(1.3rem, 3.5vw, 1.75rem);
  --nubie-t-m: clamp(1rem, 2.2vw, 1.125rem);
  --nubie-t-s: 0.875rem;

  /* Espace. Une seule echelle, employee partout. */
  --nubie-e-1: 0.5rem;
  --nubie-e-2: 1rem;
  --nubie-e-3: 1.5rem;
  --nubie-e-4: 2.5rem;
  --nubie-e-5: 4rem;
  --nubie-e-6: 6rem;

  --nubie-rayon: 0.75rem;
  --nubie-mesure: 62ch;      /* longueur de ligne lisible */
  --nubie-gouttiere: 1.25rem;

  /* --------------------------------------------------------------------------- *
   * GRAISSES, INTERLETTRAGE ET INTERLIGNE -- ajoutes le 2026-10-08.
   *
   * POURQUOI ILS ARRIVENT SI TARD. Une direction artistique ne pouvait changer que
   * SIX COULEURS ET DEUX FAMILLES DE POLICE. L'echelle des tailles, le rayon et les
   * espacements etaient deja des jetons, mais les graisses et l'interlettrage etaient
   * ecrits EN DUR dans les regles ci-dessous -- il n'existait aucun jeton de graisse
   * dans tout le socle.
   *
   * Or ce qu'on reconnait comme « moderne » tient surtout a ces leviers-la : des
   * graisses tranchees, un interlettrage serre sur les grands titres, un contraste fort
   * entre les tailles. Une direction ne pouvait donc toucher a RIEN de ce qui compte,
   * et les quatre etaient quatre variations de couleur sur une seule ossature.
   *
   * LES VALEURS CI-DESSOUS SONT CELLES QUI S'APPLIQUAIENT DEJA. Cette etape ne change
   * rien a l'ecran : elle rend seulement modifiable ce qui ne l'etait pas. C'est
   * verifiable, et ca a ete verifie -- les deux sites publies rendent a l'identique.
   * --------------------------------------------------------------------------- */

  /* `bold` est ce que le navigateur applique a h1-h3 par defaut. Les piles systeme
   * (SF Pro, Roboto, Noto) sont variables : toute valeur de 100 a 900 est disponible
   * sans charger un octet. */
  --nubie-gras-titre: bold;
  --nubie-gras-accroche: 400;
  --nubie-gras-texte: 400;

  --nubie-serre-xxl: -0.02em;
  --nubie-serre-xl: -0.01em;
  --nubie-serre-l: 0;
  /* Le sur-titre du heros : large a dessein, c'est ce qui le fait lire comme une
   * etiquette et non comme du texte. */
  --nubie-serre-sur: 0.14em;

  --nubie-hauteur-titre: 1.1;
  --nubie-hauteur-texte: 1.65;

  /* Le bouton. Son rayon est un levier a part du rayon general : une direction peut
   * vouloir des cartes douces et un bouton carre, ou l'inverse. `999px` est une
   * pilule -- la valeur qui s'appliquait deja. */
  --nubie-gras-action: 600;
  --nubie-rayon-action: 999px;

  /* Le grand chiffre : c'est LUI qui porte l'effet « page composee » dans une
   * direction sans photo, donc sa graisse est un levier a part entiere.
   *
   * LE DEFAUT EST CELUI QUI S'APPLIQUAIT DEJA, pas celui que je trouve meilleur.
   * `.nubie-chiffre__valeur` est un `<div>` : il HERITAIT de 400 et d'un interlettrage
   * normal. Lui donner `bold` et `-0.01em` au passage aurait change l'apparence des
   * sites publies pendant une etape dont toute la valeur est de ne RIEN changer -- et
   * ma propre verification l'a attrape. Le choix de le rendre gras appartient a la
   * refonte des directions, ou il sera voulu et visible. */
  --nubie-gras-chiffre: var(--nubie-gras-texte);
  --nubie-serre-chiffre: normal;

  /* --------------------------------------------------------------------------- *
   * LES NIVEAUX -- ajoutes le 2026-10-31, et c'est le manque le plus structurel.
   *
   * MESURE SUR LES DEUX REFERENCES DE L'UTILISATEUR. Le systeme de stripe.com compte
   * 491 jetons, le notre 36. Et apura -- notre propre produit, donc le gout de
   * l'utilisateur demontre -- porte QUATRE gris de texte, TROIS filets et TROIS rayons
   * la ou nous en avions deux, un et un.
   *
   * CE QUE DEUX GRIS INTERDISENT : tout texte est soit l'encre, soit le gris moyen.
   * Aucune hierarchie fine n'est exprimable, donc une legende, un libelle et un
   * paragraphe ont le MEME poids -- et une page dont tout a le meme poids parait plate,
   * quelle que soit la palette. Ce n'etait un probleme ni de couleur ni de motif :
   * c'etait un probleme de GRANULARITE.
   *
   * Les defauts sont derives de l'encre existante, pas inventes : chaque niveau
   * s'eclaircit vers le fond. Une direction les redefinit comme le reste. */

  /* Quatre niveaux de texte. `encre` affirme, `doux` accompagne, `tiers` situe,
   * `faible` ne fait que ne pas disparaitre -- une mention, une unite. */
  --nubie-encre-tiers: #78716c;
  --nubie-encre-faible: #a8a29e;

  /* Trois niveaux de filet. `trait` separe deux blocs, `trait-doux` suggere une limite,
   * `separateur` ne fait que rythmer une liste. Un seul niveau obligeait a choisir entre
   * un cadre trop present et pas de cadre du tout. */
  --nubie-trait-doux: #efebe4;
  --nubie-separateur: #f5f2ed;

  /* Trois niveaux de rayon, releves sur apura : badge 5 px, bouton 7, carte 10. Un seul
   * rayon donne le meme arrondi a une etiquette de 18 px et a une carte de 400 -- ce que
   * la doc de design d'Anthropic designe comme un signe de page generee. */
  --nubie-rayon-badge: 0.3125rem;
  --nubie-rayon-carte: 0.625rem;
}

/* --------------------------------------------------------------------------- *
 * Reinitialisation — minimale, et seulement ce qui sert
 * --------------------------------------------------------------------------- */

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

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

body {
  background: var(--nubie-fond);
  color: var(--nubie-encre);
  font-family: var(--nubie-texte);
  font-size: var(--nubie-t-m);
  font-weight: var(--nubie-gras-texte);
  line-height: var(--nubie-hauteur-texte);
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3 {
  font-family: var(--nubie-titre);
  font-weight: var(--nubie-gras-titre);
  line-height: var(--nubie-hauteur-titre);
  text-wrap: balance;
}
h1 { font-size: var(--nubie-t-xxl); letter-spacing: var(--nubie-serre-xxl); }
h2 { font-size: var(--nubie-t-xl); letter-spacing: var(--nubie-serre-xl); }
h3 { font-size: var(--nubie-t-l); letter-spacing: var(--nubie-serre-l); }

p { text-wrap: pretty; }
img, svg, video { display: block; max-width: 100%; height: auto; }
ul, ol { padding-inline-start: 1.1rem; }

a { color: inherit; text-decoration-thickness: 1px; text-underline-offset: 0.2em; }

/* Visible au clavier. Non negociable : c'est la seule facon de naviguer pour
 * certaines personnes, et un `outline: none` sans remplacement les enferme. */
:focus-visible { outline: 2px solid var(--nubie-accent); outline-offset: 3px; }

/* --------------------------------------------------------------------------- *
 * Primitives de mise en page
 * --------------------------------------------------------------------------- */

/* --------------------------------------------------------------------------- *
 * Navigation -- ajoutee le 2026-10-08, et elle vient d'un manque CONSTATE.
 *
 * Le socle n'offrait aucune navigation. Sur le site d'un macon, le modele en a donc
 * invente une : `.menu` en `position: fixed`, plus un `.content { margin-top: 60px }`
 * pour pousser la page sous la barre. Ce 60px est un calcul A LA MAIN -- la barre
 * mesurait ~56px -- et surtout : fixe, elle sort du flux, donc ses six liens passant a
 * la ligne sur un telephone la font grandir et RECOUVRIR le contenu.
 *
 * `position: sticky` resout tout ca sans qu'aucun nombre ne soit calcule : la barre
 * reste DANS le flux, donc elle reserve sa propre hauteur, quelle qu'elle soit. C'est
 * la seule difference entre les deux proprietes, et c'est toute la difference.
 *
 * `flex-wrap` plutot qu'un menu replie : six liens courts tiennent sur deux lignes au
 * telephone, et deux lignes lisibles valent mieux qu'un bouton a decouvrir.
 *
 * `z-index: 10` et non 1000 : rien d'autre ne se superpose dans une page de ce socle,
 * et une valeur demesuree est une dette pour qui ajoutera un jour un element au-dessus.
 * --------------------------------------------------------------------------- */

.nubie-nav {
  position: sticky;
  top: 0;
  z-index: 10;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--nubie-e-1) var(--nubie-e-3);
  padding: var(--nubie-e-1) var(--nubie-gouttiere);
  background: var(--nubie-fond);
  border-bottom: 1px solid var(--nubie-trait);
  font-size: var(--nubie-t-s);
}
.nubie-nav a { color: inherit; text-decoration: none; }
.nubie-nav a:hover { color: var(--nubie-accent); }

/* Sans ca, un lien d'ancre amene la section SOUS la barre collante. Pose sur la
 * section et non en `scroll-padding` sur `html` : seules les cibles d'ancre en ont
 * besoin, et c'est sans effet quand il n'y a pas de navigation. */
.nubie-section { scroll-margin-block-start: 4.5rem; }

.nubie-section { padding-block: var(--nubie-e-5); padding-inline: var(--nubie-gouttiere); }
.nubie-section--serre { padding-block: var(--nubie-e-4); }
.nubie-section--alt { background: var(--nubie-fond-alt); }

/* La gouttiere est posee UNE fois, en padding-inline. Jamais un `padding`
 * raccourci qui remettrait les cotes a zero. */
.nubie-contenu { max-width: var(--nubie-mesure); margin-inline: auto; }
.nubie-contenu--large { max-width: 72rem; margin-inline: auto; }

.nubie-pile { display: flex; flex-direction: column; gap: var(--nubie-e-3); }
.nubie-pile--serree { gap: var(--nubie-e-1); }

.nubie-grille {
  display: grid;
  gap: var(--nubie-e-3);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 16rem), 1fr));
}

.nubie-rang { display: flex; flex-wrap: wrap; gap: var(--nubie-e-2); align-items: center; }

/* --------------------------------------------------------------------------- *
 * Compositions SANS PHOTO — le coeur du socle
 *
 * Chacune remplace une image par de la typographie, de la couleur ou un motif CSS.
 * C'est ce qui fait qu'un site sans photo a l'air VOULU et non vide.
 * --------------------------------------------------------------------------- */

/* Heros typographique : le nom de l'activite occupe l'ecran. Aucune image. */
.nubie-heros {
  min-height: min(78svh, 40rem);
  display: grid;
  align-content: center;
  gap: var(--nubie-e-3);
  padding-block: var(--nubie-e-6);
  padding-inline: var(--nubie-gouttiere);
}
.nubie-heros__sur {
  /* Un VRAI badge, et c'est la seule decision de design de ce lot : `rayon-badge`
     n'avait aucun composant a qui appartenir, donc il restait une promesse que rien
     ne pouvait tenir. Un surtitre en pastille est l'idiome des deux references
     mesurees, et il ne coute aucun telechargement. */
  display: inline-flex;
  align-items: center;
  padding: 0.2rem 0.6rem;
  background: var(--nubie-fond-alt);
  border-radius: var(--nubie-rayon-badge);
  font-size: var(--nubie-t-s);
  letter-spacing: var(--nubie-serre-sur);
  text-transform: uppercase;
  color: var(--nubie-encre-tiers);
}
.nubie-heros__accroche {
  font-size: var(--nubie-t-l);
  font-weight: var(--nubie-gras-accroche);
  color: var(--nubie-encre-doux);
  max-width: 48ch;
}

/* --------------------------------------------------------------------------- *
 * LA PROFONDEUR -- remplace les quatre MOTIFS le 2026-10-31.
 *
 * TROIS DES QUATRE ETAIENT DES TRAMES REPETEES : filets verticaux tous les 2,5 rem,
 * grille de points tous les 1,5 rem, rayures en biais tous les 1,5 rem. C'est l'idiome
 * « subtle pattern » des annees 2010, et l'utilisateur l'a rejete sans detour devant un
 * apercu : « le background avec les barre, je supporte pas ».
 *
 * LA DIFFERENCE DE PRINCIPE : une trame se COMPTE. L'oeil percoit le pas de 2,5 rem et
 * lit « fond d'ecran ». Une variation CONTINUE ne se compte pas, donc elle passe pour de
 * la lumiere. Aucune des quatre regles ci-dessous ne se repete.
 *
 * ET PERSONNE NE LES AVAIT CHOISIES. Chaque direction portait un champ `motif` --
 * `artisan` prescrivait les filets verticaux -- que l'ecran du choix ne montrait JAMAIS
 * (`DirectionCard` n'en dit pas un mot) et qu'une garde exigeait ensuite de poser. Le
 * client choisissait une palette et heritait d'une trame sans l'avoir vue ni demandee.
 * Meme famille que les autres defauts de ce produit : une decision consequente prise en
 * son nom, invisible au moment du choix. Le champ `motif` disparait donc de
 * `Direction` : la profondeur appartient au socle, pas a la couleur. */
.nubie-fond-voute {
  background-image: radial-gradient(
    135% 80% at 50% -25%, var(--nubie-fond-alt) 0%, transparent 62%);
}
.nubie-fond-horizon {
  background-image: linear-gradient(
    to bottom, var(--nubie-fond-alt) 0%, transparent 42%);
}
.nubie-fond-halo {
  background-image: radial-gradient(
    70% 60% at 78% 18%, var(--nubie-fond-alt) 0%, transparent 58%);
}
/* Un filet UNIQUE, en haut. Une ligne qui separe n'est pas une trame qui decore. */
.nubie-fond-bord {
  background-image: linear-gradient(
    to bottom, var(--nubie-trait-doux) 0 1px, transparent 1px);
}

/* Le chiffre : « 15 ans de metier », « ouvert 7j/7 ». Un commerce a presque
 * toujours deux ou trois chiffres a montrer, et c'est un substitut d'image tres
 * efficace parce qu'il porte une information reelle. */
.nubie-chiffre { display: grid; gap: 0.15rem; }
.nubie-chiffre__valeur {
  font-family: var(--nubie-titre);
  font-size: var(--nubie-t-xl);
  font-weight: var(--nubie-gras-chiffre);
  letter-spacing: var(--nubie-serre-chiffre);
  line-height: 1;
  color: var(--nubie-accent);
  font-variant-numeric: tabular-nums;
}
.nubie-chiffre__libelle { font-size: var(--nubie-t-s); color: var(--nubie-encre-tiers); }

.nubie-carte {
  padding: var(--nubie-e-3);
  background: var(--nubie-fond);
  border: 1px solid var(--nubie-trait);
  /* Une carte a son propre rayon : c'est ce qui permet une hierarchie de formes
     (badge < carte < bouton) au lieu du meme arrondi partout -- l'un des tells
     releves par la liste anti-slop. */
  border-radius: var(--nubie-rayon-carte);
}
/* Une barre d'accent au lieu d'une icone : rien a telecharger, rien a inventer. */
.nubie-carte--accent { border-inline-start: 3px solid var(--nubie-accent); }

/* Horaires : une liste de definitions alignee, lisible au telephone. */
.nubie-horaires { display: grid; gap: var(--nubie-e-1); }
.nubie-horaires__ligne {
  display: flex; justify-content: space-between; gap: var(--nubie-e-2);
  padding-block: 0.35rem;
  /* Un filet REPETE sept fois n'a pas le poids d'une bordure unique : c'est pour
     lui que `separateur` existe. Avec `trait`, les horaires devenaient une grille. */
  border-bottom: 1px dashed var(--nubie-separateur);
}
.nubie-horaires__jour { font-weight: var(--nubie-gras-action); }
.nubie-horaires__heures { color: var(--nubie-encre-tiers); font-variant-numeric: tabular-nums; }

/* Emplacement d'image : ce que remplit une photo televersee plus tard.
 * Sans photo, il garde un motif et un rapport de forme -- donc la page ne saute
 * pas quand l'image arrive. */
.nubie-emplacement {
  aspect-ratio: 4 / 3;
  max-width: 100%;
  border-radius: var(--nubie-rayon);
  background-color: var(--nubie-fond-alt);
  background-image: radial-gradient(var(--nubie-trait) 1.2px, transparent 1.2px);
  background-size: 1.5rem 1.5rem;
  overflow: hidden;
}
.nubie-emplacement > img { width: 100%; height: 100%; object-fit: cover; }

/* --------------------------------------------------------------------------- *
 * Actions — tel:, mailto:, wa.me. Jamais un formulaire.
 * --------------------------------------------------------------------------- */

.nubie-action {
  display: inline-flex; align-items: center; gap: 0.5rem;
  /* 44px de haut : la cible tactile minimale recommandee. */
  min-height: 2.75rem;
  padding: 0.65rem 1.25rem;
  border-radius: var(--nubie-rayon-action);
  font-weight: var(--nubie-gras-action);
  text-decoration: none;
  background: var(--nubie-accent);
  color: var(--nubie-accent-encre);
  transition: transform 160ms ease, opacity 160ms ease;
}
.nubie-action:hover { opacity: 0.9; transform: translateY(-1px); }
.nubie-action--sobre {
  background: transparent; color: var(--nubie-encre);
  border: 1px solid var(--nubie-trait);
}

.nubie-pied {
  padding-block: var(--nubie-e-4);
  padding-inline: var(--nubie-gouttiere);
  border-top: 1px solid var(--nubie-trait);
  font-size: var(--nubie-t-s);
  /* Le gris le plus faible du jeu : des mentions de pied ne doivent pas concurrencer
     le contenu. Contraste verifie a 4,17 sur la direction `verger` -- au-dessus du
     seuil de 3,0 qui s'applique a ce corps, sous 4,5, donc reserve a ce seul usage. */
  color: var(--nubie-encre-faible);
}

/* --------------------------------------------------------------------------- *
 * Apparition au defilement — l'etat initial est ici, la bascule dans motion.js
 *
 * `animation-timeline` et les transitions de vue sont inegalement supportees :
 * on s'en tient a IntersectionObserver plus une classe, qui marche partout.
 * --------------------------------------------------------------------------- */

/* MESURE DU 2026-10-08, ET C'EST LA RAISON DE CE BLOC. L'apparition precedente
 * parcourait 0,75rem -- DOUZE PIXELS -- en 520ms avec une courbe `ease`. Le
 * proprietaire du premier site reel ne la voyait pas du tout, et il avait raison :
 * douze pixels de montee pendant un fondu d'une demi-seconde est en-dessous du seuil
 * ou un mouvement se percoit comme voulu. Pire, un bloc deja dans l'ecran au
 * chargement se revele PENDANT le chargement -- donc invisible par construction.
 *
 * CE QUI CHANGE, ET POURQUOI CHAQUE VALEUR :
 *   - la course passe a 1,5rem (24px) : assez pour se voir, trop peu pour bousculer
 *     la mise en page ou donner le mal des transports ;
 *   - la courbe devient une sortie franche (`cubic-bezier(.16,1,.3,1)`) : le mouvement
 *     part vite et se pose, au lieu de la progression lineaire d'`ease` ;
 *   - un ECHELONNEMENT par `--nubie-retard`, pose par motion.js sur les elements d'un
 *     meme groupe. C'est lui qui fait la difference entre « des blocs qui bougent » et
 *     « une page qui se compose » -- et il ne coute rien, c'est une variable CSS.
 *
 * `will-change` n'est PAS pose : il force une couche de composition par element, et
 * sur les telephones d'entree de gamme vises ca coute plus de memoire que le gain
 * d'animation ne vaut. La bascule ne joue qu'une fois de toute facon. */
.nubie-apparait {
  opacity: 0;
  transform: translateY(1.5rem);
  transition:
    opacity 560ms cubic-bezier(.16, 1, .3, 1) var(--nubie-retard, 0ms),
    transform 640ms cubic-bezier(.16, 1, .3, 1) var(--nubie-retard, 0ms);
}
.nubie-apparait.nubie-vu { opacity: 1; transform: none; }

/* Le mouvement rend certaines personnes malades. Non negociable : sans JavaScript
 * comme avec, le contenu doit etre visible. */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  /* `--nubie-retard` remis a zero avec le reste : un delai sans transition ne sert a
   * rien, et le laisser serait une valeur qui traine. */
  .nubie-apparait { opacity: 1; transform: none; transition: none; --nubie-retard: 0ms; }
  .nubie-action { transition: none; }
}

/* Et si le JavaScript ne s'execute pas du tout, rien ne doit rester invisible.
 * C'est la raison du `.nubie-js` pose par motion.js : l'etat cache n'existe QUE
 * lorsque le script a demarre. */
html:not(.nubie-js) .nubie-apparait { opacity: 1; transform: none; }

/* --------------------------------------------------------------------------- *
 * Elargissements — mobile d'abord, donc ce sont les seules requetes de taille
 * --------------------------------------------------------------------------- */

@media (min-width: 48rem) {
  :root { --nubie-gouttiere: 2.5rem; }
  .nubie-section { padding-block: var(--nubie-e-6); }
}

@media (min-width: 72rem) {
  :root { --nubie-gouttiere: 4rem; }
}

@media print {
  .nubie-apparait { opacity: 1; transform: none; }
  .nubie-action { border: 1px solid currentColor; background: none; color: inherit; }
}

/* --- direction artistique du site --- */
:root {
  --nubie-fond: #09090b;
  --nubie-fond-alt: #18181b;
  --nubie-encre: #fafafa;
  --nubie-encre-doux: #a1a1aa;
  --nubie-accent: #a3e635;
  --nubie-accent-encre: #09090b;
  --nubie-trait: #27272a;
  --nubie-encre-tiers: #86868d;
  --nubie-encre-faible: #66666b;
  --nubie-titre: system-ui, -apple-system, sans-serif;
  --nubie-texte: system-ui, -apple-system, sans-serif;
  --nubie-gras-titre: 700;
  --nubie-gras-texte: 300;
  --nubie-gras-chiffre: 600;
  --nubie-serre-xxl: -0.035em;
  --nubie-serre-xl: -0.02em;
  --nubie-serre-chiffre: -0.02em;
  --nubie-hauteur-titre: 1.05;
  --nubie-rayon: 1.25rem;
}
