/* ==========================================================================
   www.oxmo.org — feuille de style unique
   ==========================================================================

   AUCUNE RESSOURCE EXTERNE. Pas de CDN, pas de police distante, pas d'image
   hebergee ailleurs. C'est ce qui permet la CSP « default-src 'self' » posee
   par conf.d/01-oxmo.org.conf sur cette page et sur /assets/ : la moindre
   @import vers un tiers la ferait echouer, et le symptome serait une page nue
   sans la moindre erreur cote serveur.

   La maquette appelait IBM Plex chez Google Fonts. Les .woff2 sont ici, dans
   fonts/, sous-ensembles latin et latin-ext seulement -- 159 Kio pour huit
   fichiers, la ou les jeux complets en font plus de quatre cents.

   ---------------------------------------------------------------------------
   DEUX THEMES, COMME CHEZ tools, ip ET dns
   ---------------------------------------------------------------------------
   La maquette n'avait qu'un fond noir. La bascule jour/nuit a ete ajoutee le
   2026-08-19, avec LA MEME MECANIQUE que les trois voisins -- assets/theme.js,
   l'attribut data-theme sur <html>, le choix garde en localStorage -- pour que
   la bascule se comporte pareil d'un site a l'autre du domaine.

   Le defaut suit donc le systeme, comme chez eux : clair de base, sombre sous
   prefers-color-scheme. Ce n'est PAS ce que faisait la maquette, qui etait
   noire pour tout le monde ; c'est le prix de la coherence avec les voisins.
   Pour rendre le sombre au visiteur qui n'a rien choisi, il suffirait
   d'echanger les deux palettes ci-dessous.

   CHAQUE JETON DEFINI EN CLAIR DOIT L'ETRE EN SOMBRE, et reciproquement. Le
   sombre est redefini a DEUX endroits, et les deux sont necessaires :
     - @media (prefers-color-scheme: dark), garde par :not([data-theme="light"])
     - :root[data-theme="dark"]
   Sans le premier, un visiteur qui n'a jamais touche a la bascule reste en
   clair alors que son systeme est en sombre. Sans le second, la bascule ne
   peut pas forcer le sombre. La garde :not([data-theme="light"]) est ce qui
   permet a la bascule de forcer le CLAIR chez quelqu'un dont le systeme est en
   sombre -- sans elle, le media query l'emporterait.

   ---------------------------------------------------------------------------
   CETTE PAGE NE SUIT PAS LA CHARTE DE tools, ip ET dns
   ---------------------------------------------------------------------------
   Les trois voisins sont plats, carres et gris : ils tiennent leur charte du
   theme « 2010 - gris » du forum, et le verificateur de dns compare ses jetons
   a ceux de ip, nom par nom. Rien de tout cela ne s'applique ici : l'accueil
   est une vitrine, pas un quatrieme outil. Seule la MECANIQUE de la bascule
   est partagee, pas les couleurs.

   La seule chose qu'il leur emprunte, ce sont LES VIGNETTES : elles sont
   dessinees dans les couleurs des sites qu'elles annoncent (#cbcbcb, #efefef,
   #646464), ce qui les fait lire comme des apercus et non comme du decor.
   Elles vivent dans inc/vignettes.php, pas ici.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Les polices
   -------------------------------------------------------------------------- */
@font-face {
	font-family: 'IBM Plex Mono';
	font-style: normal;
	font-weight: 400;
	font-display: swap;
	src: url(fonts/plex-mono-400-latin-ext.woff2) format('woff2');
	unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
	font-family: 'IBM Plex Mono';
	font-style: normal;
	font-weight: 400;
	font-display: swap;
	src: url(fonts/plex-mono-400-latin.woff2) format('woff2');
	unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
	font-family: 'IBM Plex Mono';
	font-style: normal;
	font-weight: 500;
	font-display: swap;
	src: url(fonts/plex-mono-500-latin-ext.woff2) format('woff2');
	unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
	font-family: 'IBM Plex Mono';
	font-style: normal;
	font-weight: 500;
	font-display: swap;
	src: url(fonts/plex-mono-500-latin.woff2) format('woff2');
	unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
	font-family: 'IBM Plex Mono';
	font-style: normal;
	font-weight: 600;
	font-display: swap;
	src: url(fonts/plex-mono-600-latin-ext.woff2) format('woff2');
	unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
	font-family: 'IBM Plex Mono';
	font-style: normal;
	font-weight: 600;
	font-display: swap;
	src: url(fonts/plex-mono-600-latin.woff2) format('woff2');
	unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
	font-family: 'IBM Plex Sans';
	font-style: normal;
	font-weight: 400;
	font-display: swap;
	src: url(fonts/plex-sans-400-latin-ext.woff2) format('woff2');
	unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
	font-family: 'IBM Plex Sans';
	font-style: normal;
	font-weight: 400;
	font-display: swap;
	src: url(fonts/plex-sans-400-latin.woff2) format('woff2');
	unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
	font-family: 'IBM Plex Sans';
	font-style: normal;
	font-weight: 500;
	font-display: swap;
	src: url(fonts/plex-sans-400-latin-ext.woff2) format('woff2');
	unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
	font-family: 'IBM Plex Sans';
	font-style: normal;
	font-weight: 500;
	font-display: swap;
	src: url(fonts/plex-sans-400-latin.woff2) format('woff2');
	unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
	font-family: 'IBM Plex Sans';
	font-style: normal;
	font-weight: 600;
	font-display: swap;
	src: url(fonts/plex-sans-400-latin-ext.woff2) format('woff2');
	unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
	font-family: 'IBM Plex Sans';
	font-style: normal;
	font-weight: 600;
	font-display: swap;
	src: url(fonts/plex-sans-400-latin.woff2) format('woff2');
	unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
	font-family: 'IBM Plex Sans';
	font-style: normal;
	font-weight: 700;
	font-display: swap;
	src: url(fonts/plex-sans-400-latin-ext.woff2) format('woff2');
	unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
	font-family: 'IBM Plex Sans';
	font-style: normal;
	font-weight: 700;
	font-display: swap;
	src: url(fonts/plex-sans-400-latin.woff2) format('woff2');
	unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* --------------------------------------------------------------------------
   2. Jetons — theme clair
   --------------------------------------------------------------------------
   Le clair n'est pas un noir inverse : l'accent #f4a184 de la maquette, pose
   sur du blanc, tombe a 1,6:1 et devient illisible. Le clair prend donc
   #c25a33, la terre cuite des directions claires de la meme maquette, qui
   passe 4,5:1 sur le fond creme. Les DEUX doivent rester lisibles : c'est le
   seul jeton dont la valeur claire n'est pas une variation de la sombre.

   Les triplets --*-rgb existent pour assets/app.js : la toile compose ses
   couleurs avec des alphas calcules, elle ne peut pas se contenter d'une
   couleur finie.
   -------------------------------------------------------------------------- */
:root {
	color-scheme: light dark;

	--fond:        #eae6e1;
	--fond-rgb:    234, 230, 225;
	--fond-bande:  #e2ddd6;
	--bande-rgb:   226, 221, 214;
	--texte:       #191512;
	--texte-doux:  #2f2823;
	--attenue:     #4a423b;
	--faible:      #6b6259;
	--tres-faible: #85796f;

	--filet:       #cfc8c0;
	--bord:        #b3aba1;
	--toile-rgb:   25, 21, 18;
	--champ:       #ffffff;

	--accent:      #c25a33;
	--accent-rgb:  194, 90, 51;
	--accent-txt:  #ffffff;
	--accent-doux: rgba(194, 90, 51, .07);

	--ok:          #1f7a4d;
	--ok-fond:     rgba(31, 122, 77, .09);
	--ko:          #a8121f;
	--ko-fond:     rgba(168, 18, 31, .08);
	--inconnu:     #8a847d;

	--police:      'IBM Plex Sans', system-ui, -apple-system, sans-serif;
	--mono:        'IBM Plex Mono', ui-monospace, SFMono-Regular, monospace;

	--large:       1240px;
	--marge:       28px;
}

/* --------------------------------------------------------------------------
   2 bis. Jetons — theme sombre, la palette d'origine de la maquette
   -------------------------------------------------------------------------- */
@media (prefers-color-scheme: dark) {
	:root:not([data-theme="light"]) {
		--fond:        #08090a;
		--fond-rgb:    8, 9, 10;
		--fond-bande:  #0b0c0d;
		--bande-rgb:   11, 12, 13;
		--texte:       #f2f0ee;
		--texte-doux:  rgba(242, 240, 238, .8);
		--attenue:     rgba(242, 240, 238, .62);
		--faible:      rgba(242, 240, 238, .45);
		--tres-faible: rgba(242, 240, 238, .32);

		--filet:       rgba(255, 255, 255, .12);
		--bord:        rgba(255, 255, 255, .18);
		--toile-rgb:   255, 255, 255;
		--champ:       rgba(0, 0, 0, .35);

		--accent:      #f4a184;
		--accent-rgb:  244, 161, 132;
		--accent-txt:  #14100e;
		--accent-doux: rgba(244, 161, 132, .06);

		--ok:          #7ee2a8;
		--ok-fond:     rgba(126, 226, 168, .08);
		--ko:          #f4736b;
		--ko-fond:     rgba(244, 115, 107, .08);
		--inconnu:     #8a8f96;
	}
}

:root[data-theme="dark"] {
	--fond:        #08090a;
	--fond-rgb:    8, 9, 10;
	--fond-bande:  #0b0c0d;
	--bande-rgb:   11, 12, 13;
	--texte:       #f2f0ee;
	--texte-doux:  rgba(242, 240, 238, .8);
	--attenue:     rgba(242, 240, 238, .62);
	--faible:      rgba(242, 240, 238, .45);
	--tres-faible: rgba(242, 240, 238, .32);

	--filet:       rgba(255, 255, 255, .12);
	--bord:        rgba(255, 255, 255, .18);
	--toile-rgb:   255, 255, 255;
	--champ:       rgba(0, 0, 0, .35);

	--accent:      #f4a184;
	--accent-rgb:  244, 161, 132;
	--accent-txt:  #14100e;
	--accent-doux: rgba(244, 161, 132, .06);

	--ok:          #7ee2a8;
	--ok-fond:     rgba(126, 226, 168, .08);
	--ko:          #f4736b;
	--ko-fond:     rgba(244, 115, 107, .08);
	--inconnu:     #8a8f96;
}

/* --------------------------------------------------------------------------
   3. Base
   -------------------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }

html { scroll-behavior: smooth; }

body {
	margin: 0;
	background: var(--fond);
	color: var(--texte);
	font-family: var(--police);
	font-size: 16px;
	line-height: 1.5;
	-webkit-font-smoothing: antialiased;

	/* CLIP ET NON HIDDEN — LA CAUSE DU BOGUE DU 2026-08-19.
	 *
	 * overflow-x: hidden fait de <body> un CONTENEUR DE DEFILEMENT : le
	 * navigateur en deduit un overflow-y: auto implicite. Le
	 * position: sticky du bloc des quatre paliers se colle alors a ce
	 * conteneur et non plus a la fenetre. Symptome observe en remontant
	 * depuis le bas de la page : un ecran noir a la place des paliers, le
	 * premier bloc de site tronque, et un retour a la normale au bout de
	 * trois ou quatre secondes -- le temps que le navigateur finisse de
	 * repeindre une zone qu'il croyait a une autre place.
	 *
	 * overflow-x: clip coupe le debordement horizontal SANS creer de
	 * conteneur de defilement. C'est le remplacant exact, et le sticky
	 * retrouve la fenetre pour reference. Ne jamais le repasser a hidden.
	 */
	overflow-x: clip;
}

a { color: inherit; text-decoration: none; }

::selection { background: var(--accent); color: var(--accent-txt); }

/* Le contour de focus est VISIBLE ET UNIFORME. La maquette n'en avait aucun :
   sur un fond noir, un focus par defaut est invisible, et la page devient
   inutilisable au clavier sans que rien ne le signale. */
:focus-visible {
	outline: 2px solid var(--accent);
	outline-offset: 3px;
	border-radius: 3px;
}

/* Lu par les lecteurs d'ecran, jamais affiche. */
.hors-ecran {
	position: absolute;
	width: 1px; height: 1px;
	margin: -1px; padding: 0;
	overflow: hidden;
	clip: rect(0 0 0 0);
	clip-path: inset(50%);
	white-space: nowrap;
	border: 0;
}

/* Le lien d'evitement : cache jusqu'a ce qu'on l'atteigne au clavier. Il
   compte double ici, ou 320vh de defilement separent le haut de page du
   premier contenu utile. */
.saut {
	position: absolute;
	left: -9999px;
	z-index: 100;
	padding: 12px 18px;
	background: var(--accent);
	color: var(--accent-txt);
	font-family: var(--mono);
	font-size: 13px;
}
.saut:focus { left: 12px; top: 12px; }

.kicker {
	margin: 0;
	font-family: var(--mono);
	font-size: 12px;
	letter-spacing: .22em;
	text-transform: uppercase;
	color: var(--faible);
}
.kicker-accent { color: var(--accent); letter-spacing: .2em; font-size: 11px; }

/* --------------------------------------------------------------------------
   3 bis. La toile de fond
   --------------------------------------------------------------------------
   UNE SEULE, FIXE, DERRIERE TOUTE LA PAGE. Il y en avait une enfermee dans le
   bloc colle du haut : ses cercles concentriques s'arretaient net a la fin de
   ce bloc, et la liste des sites -- opaque -- posait une ligne de separation
   franche en travers de la page. La toile couvre desormais la fenetre entiere
   et ne s'interrompt nulle part ; ce sont les PANNEAUX qui deviennent
   translucides pour la laisser passer.

   Elle ne doit rien intercepter : un canvas plein ecran en z-index 0 avale
   sinon tous les clics de la page.
   -------------------------------------------------------------------------- */
.fond-toile {
	position: fixed;
	inset: 0;
	width: 100%;
	height: 100%;
	z-index: 0;
	pointer-events: none;
}

/* Tout le contenu passe AU-DESSUS de la toile. Sans cette regle, seuls les
   elements deja positionnes le feraient, et le reste disparaitrait derriere. */
.entete, .bandeau-langue, .scrub, main, .bande, .pied { position: relative; z-index: 1; }
.entete { z-index: 30; }

/* --------------------------------------------------------------------------
   4. L'en-tete
   -------------------------------------------------------------------------- */
.entete {
	position: fixed;
	top: 0; left: 0; right: 0;
	z-index: 30;
	display: flex;
	align-items: center;
	gap: 16px;
	padding: 14px var(--marge);
	background: linear-gradient(rgba(var(--fond-rgb), .94), rgba(var(--fond-rgb), 0));
}

/* La marque reprend la forme des trois voisins : une icone, le nom du site en
   gras, puis le domaine attenue. Ici le nom du site EST « www » -- c'est le
   sous-domaine de l'accueil, au meme titre que « tools » ou « dns » chez eux. */
.marque {
	display: inline-flex;
	align-items: center;
	gap: 9px;
	font-size: 16px;
	letter-spacing: -.01em;
	font-weight: 400;
}
.marque svg { width: 19px; height: 19px; display: block; color: var(--accent); }
.marque b { font-weight: 700; }
.tld { color: var(--faible); }

.nav {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 6px;
	margin-left: auto;
}

/* Une seule geometrie pour TOUT ce que porte la barre : meme hauteur, meme
   rayon, meme graisse. La bascule de langue en etait sortie -- coins a 5 px au
   milieu de pilules a 999 px, sans bordure -- et se lisait comme une piece
   rapportee. Le rayon et la hauteur sont fixes ici, une fois. */
.nav-lien, .langues, .theme-bascule {
	height: 34px;
	border-radius: 999px;
	border: 1px solid var(--bord);
}

.nav-lien {
	display: inline-flex;
	align-items: center;
	font-family: var(--mono);
	font-size: 11.5px;
	letter-spacing: .14em;
	text-transform: uppercase;
	padding: 0 14px;
	transition: background-color .18s ease, color .18s ease, border-color .18s ease;
}
.nav-lien:hover { background: var(--texte); color: var(--fond); border-color: var(--texte); }

/* CONTACT mene a une page de CE site, pas a un site voisin : il doit pouvoir
   s'allumer en « page courante », ce que les quatre autres ne peuvent jamais
   faire. D'ou l'accent, qui dit « ici », et non un cinquieme bouton identique
   dans une rangee ou il serait le seul a ne jamais reagir. */
.nav-lien-interne {
	border-color: var(--accent);
	color: var(--accent);
}
.nav-lien-interne:hover { background: var(--accent); color: var(--accent-txt); border-color: var(--accent); }
.nav-lien[aria-current="page"] {
	background: var(--accent);
	color: var(--accent-txt);
	border-color: var(--accent);
}

/* Deux moities dans une seule pilule, du meme dessin que les boutons voisins.
   overflow: hidden pour que la moitie active epouse l'arrondi. */
.langues {
	display: inline-flex;
	align-items: stretch;
	overflow: hidden;
	margin-left: 4px;
}
.langues a {
	display: inline-flex;
	align-items: center;
	padding: 0 12px;
	font-family: var(--mono);
	font-size: 11.5px;
	font-weight: 600;
	letter-spacing: .12em;
	text-transform: uppercase;
	color: var(--faible);
	transition: background-color .18s ease, color .18s ease;
}
.langues a + a { border-left: 1px solid var(--bord); }
.langues a[aria-current="true"] { background: var(--accent); color: var(--accent-txt); }
.langues a:not([aria-current]):hover { background: var(--accent-doux); color: var(--texte); }

/* La bascule de theme. hidden tant que JavaScript n'a pas tourne : sans lui
   elle ne ferait rien, et un bouton mort est pire qu'un bouton absent. */
.theme-bascule {
	display: inline-grid;
	place-items: center;
	width: 34px;
	padding: 0;
	background: transparent;
	color: var(--faible);
	cursor: pointer;
	transition: background-color .18s ease, color .18s ease, border-color .18s ease;
}
.theme-bascule:hover { color: var(--texte); border-color: var(--texte); }
.theme-bascule svg { width: 16px; height: 16px; display: block; }

/* L'icone montre LA DESTINATION, pas l'etat courant : en clair on propose la
   lune. Les deux glyphes sont dans le HTML, la feuille choisit lequel est
   visible -- sans quoi il faudrait du JavaScript pour permuter le balisage, et
   l'icone serait fausse pendant le premier rendu. Meme procede que chez tools,
   ip et dns. */
.theme-bascule .i-sun  { display: none; }
.theme-bascule .i-moon { display: block; }
@media (prefers-color-scheme: dark) {
	:root:not([data-theme="light"]) .theme-bascule .i-sun  { display: block; }
	:root:not([data-theme="light"]) .theme-bascule .i-moon { display: none; }
}
:root[data-theme="dark"] .theme-bascule .i-sun  { display: block; }
:root[data-theme="dark"] .theme-bascule .i-moon { display: none; }

/* La ligne qui propose l'autre langue. Elle PROPOSE : elle ne remplace pas la
   page et ne la recharge pas -- c'est un lien, pas une modale. */
.bandeau-langue {
	position: relative;
	z-index: 25;
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: center;
	gap: 14px;
	padding: 66px var(--marge) 10px;
	font-size: 14px;
	color: var(--attenue);
}
.bandeau-langue a {
	font-family: var(--mono);
	font-size: 12px;
	letter-spacing: .1em;
	text-transform: uppercase;
	color: var(--accent);
	border-bottom: 1px solid var(--accent);
	padding-bottom: 2px;
}

/* --------------------------------------------------------------------------
   5. Les quatre paliers
   --------------------------------------------------------------------------
   Le bloc mesure 320vh, ce qu'on voit est colle en haut. app.js calcule la
   progression et allume un palier a la fois.

   SANS JAVASCRIPT, LES QUATRE PALIERS SONT VISIBLES ET EMPILES. C'est le
   defaut, et .js-scrub -- pose par app.js sur <html> -- est ce qui bascule
   vers la superposition. Un blocage de script ne doit pas rendre la page
   muette : trois quarts du texte d'introduction disparaitraient.
   -------------------------------------------------------------------------- */
.scrub { position: relative; }

.scrub-collant {
	display: grid;
	gap: 40px;
	padding: 120px var(--marge) 80px;
	max-width: var(--large);
	margin: 0 auto;
	text-align: center;
}

.scrub-mots  { display: grid; gap: 40px; }
.scrub-hint  { display: none; }

.titre-geant {
	margin: 14px 0 0;
	font-size: clamp(40px, 9vw, 130px);
	line-height: .92;
	letter-spacing: -.04em;
	font-weight: 700;
	text-wrap: balance;
}
.titre-grand {
	margin: 0 auto;
	max-width: 22ch;
	font-size: clamp(26px, 5vw, 68px);
	line-height: 1.04;
	letter-spacing: -.03em;
	font-weight: 700;
	text-wrap: balance;
}
.titre-accent { color: var(--accent); }
.titre-moyen {
	margin: 0 auto;
	max-width: 24ch;
	font-size: clamp(22px, 3.6vw, 50px);
	line-height: 1.12;
	letter-spacing: -.025em;
	font-weight: 700;
	text-wrap: balance;
}

/* La mise en scene, uniquement quand le script tourne. */
.js-scrub .scrub { height: 320vh; }

.js-scrub .scrub-collant {
	position: sticky;
	top: 0;
	height: 100vh;
	display: block;
	overflow: hidden;
	padding: 0;
	max-width: none;
}

.js-scrub .scrub-mots {
	position: absolute;
	inset: 0;
	display: grid;
	place-content: center;
	gap: 0;
	padding: 0 var(--marge);
	pointer-events: none;
}

.js-scrub .mot {
	grid-area: 1 / 1;
	opacity: 0;
	transition: opacity .4s ease;
}
.js-scrub .mot-actif { opacity: 1; }

.js-scrub .scrub-hint {
	display: block;
	position: absolute;
	bottom: 26px;
	left: 0; right: 0;
	margin: 0;
	text-align: center;
	font-family: var(--mono);
	font-size: 11px;
	letter-spacing: .22em;
	text-transform: uppercase;
	color: var(--tres-faible);
}

/* --------------------------------------------------------------------------
   6. Les quatre sites
   -------------------------------------------------------------------------- */
/* PAS DE FOND OPAQUE ICI. C'etait la ligne de separation : la liste posait un
   aplat de --fond par-dessus la toile, qui s'arretait donc net a son bord
   superieur. Elle est transparente, la toile continue dessous. */
.sites { position: relative; z-index: 1; }

.site {
	display: grid;
	grid-template-columns: 92px minmax(0, 1fr) minmax(0, .95fr);
	gap: 36px;
	align-items: start;
	max-width: var(--large);
	margin: 0 auto;
	padding: 62px var(--marge);
	border-top: 1px solid var(--filet);
	transition: background-color .2s ease;
}
.sites .site:first-child { border-top: 0; }
.site:hover { background: var(--accent-doux); }

.site-num {
	margin: 8px 0 0;
	font-family: var(--mono);
	font-size: 12px;
	letter-spacing: .18em;
	color: var(--tres-faible);
}

.site-corps { display: grid; gap: 12px; }

.site-titre {
	margin: 0;
	font-size: clamp(28px, 4.4vw, 60px);
	line-height: .98;
	letter-spacing: -.035em;
	font-weight: 700;
	text-wrap: balance;
}

.site-hote {
	margin: 0;
	font-family: var(--mono);
	font-size: 13px;
	letter-spacing: .1em;
	color: var(--accent);
}

.site-desc {
	margin: 0;
	max-width: 52ch;
	font-size: 16.5px;
	line-height: 1.6;
	color: var(--attenue);
	text-wrap: pretty;
}

.site-lien {
	margin: 6px 0 0;
	justify-self: start;
	font-family: var(--mono);
	font-size: 12.5px;
	letter-spacing: .1em;
	text-transform: uppercase;
	border-bottom: 1px solid var(--accent);
	padding-bottom: 4px;
}
.site:hover .site-lien { color: var(--accent); }

/* --------------------------------------------------------------------------
   6 bis. Les tuiles de logo
   --------------------------------------------------------------------------
   Les valeurs viennent de la planche « Logos Oxmo », section « 2a · RETENU » :
   tuile 16/9 en charbon, coins a 20 px, un seul geste au centre. Elles
   remplacent quatre maquettes d'interface dessinees en SVG, qui tenaient lieu
   de vignettes en attendant de vraies marques.

   ELLES NE SUIVENT PAS LE THEME DE LA PAGE. Le charbon et le corail restent
   les memes en clair comme en sombre : un logo ne se reteinte pas selon les
   preferences du lecteur, sans quoi il faudrait deux jeux de dessins et deux
   equilibres a tenir. La tuile est une carte posee sur la page, pas une partie
   de la page -- c'est pourquoi ses couleurs sont ecrites ici en clair et non
   prises aux jetons.
   -------------------------------------------------------------------------- */
.site-vignette {
	--tuile:  #191514;   /* fond de la tuile */
	--lisere: #2F2725;   /* son contour */
	--trait:  #4A403C;   /* les traits neutres du geste */
	--trait2: #3A3230;   /* leur variante en retrait */
	--corail: #E1836B;   /* l'accent des marques */
	--pale:   #EDE7E4;
	--sourd:  #8A5C4E;

	position: relative;
	perspective: 800px;
	aspect-ratio: 16 / 9;
	border: 1px solid var(--lisere);
	border-radius: 20px;
	overflow: hidden;
	background: var(--tuile);
	display: grid;
	place-items: center;
	padding: 32px;
}

/* Le geste occupe le centre, sans jamais deborder de la tuile.
   
   IL S'APPELLE « geste » ET NON « marque ». .marque designe deja la marque de
   l'en-tete -- le globe et www.oxmo.org -- posee en inline-flex avec
   align-items: center. Les tuiles ont porte ce nom une demi-heure : elles
   heritaient de cet alignement, leurs lignes se dimensionnaient sur leur
   contenu au lieu de s'etirer, et la marque de tools s'affichait a 42 px de
   large au lieu de 284. Rien n'etait casse, deux choses sans rapport
   partageaient un nom. */
.geste { display: block; max-width: 100%; max-height: 100%; }

/* -- 01·C  tools : trois rangees, un disque corail au milieu de chacune ---- */
.geste-tools {
	width: 66%;
	display: flex;
	flex-direction: column;
	/* Explicite, et pas seulement parce que c'est le defaut : c'est la valeur
	   dont depend toute la marque. Avec center, chaque ligne se dimensionne sur
	   son contenu et les barres de fin tombent a zero. */
	align-items: stretch;
	gap: 16px;
}
.mt-ligne { display: flex; align-items: center; gap: 12px; }
.mt-amorce, .mt-suite { height: 9px; border-radius: 5px; }
.mt-amorce { background: var(--trait);  flex: none; }
.mt-suite  { background: var(--trait2); flex: 1; }
/* Trois amorces de longueurs differentes : l'entree varie, la sortie garde la
   meme forme. C'est tout le propos d'un outil. */
.mt-a { width: 26%; }
.mt-b { width: 58%; }
.mt-c { width: 10%; }
.mt-disque {
	height: 18px;
	width: 18px;
	flex: none;
	border-radius: 50%;
	background: var(--corail);
}

/* -- 02·C  ip : le globe marque ------------------------------------------- */
.geste-ip { width: 168px; height: 168px; }

/* -- 03·C  dns : la traduction -------------------------------------------- */
.geste-dns {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 10px;
	font-family: var(--mono);
	line-height: 1;
}
.md-nom     { font-size: 40px; color: var(--pale);   letter-spacing: .02em; }
.md-fleche  { font-size: 30px; color: var(--corail); }
.md-adresse { font-size: 30px; color: var(--sourd);  letter-spacing: .02em; }

/* -- l'archive #france : le canal et ses bornes --------------------------- */
.geste-france {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 14px;
	font-family: var(--mono);
	line-height: 1;
}
.gf-canal  { font-size: 42px; color: var(--pale); letter-spacing: .01em; }
.gf-diese  { color: var(--corail); }
.gf-annees { font-size: 15px; color: var(--sourd); letter-spacing: .22em; }

/* -- le forum : la piece qui tourne --------------------------------------- */
.piece {
	position: relative;
	width: 100%;
	height: 100%;
	transform-style: preserve-3d;
	/* Sans will-change, chaque pas de rotation redessine la couche entiere sur
	   le fil principal. C'est le seul element de la page qui tourne a chaque
	   image de defilement. */
	will-change: transform;
}

.piece-face {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: contain;
	/* Ce qui fait qu'on ne voit jamais le logo en miroir. */
	backface-visibility: hidden;
}

/* Le revers : le meme logo, retourne, donc a l'endroit quand il se presente. */
.piece-dos { transform: rotateY(180deg); }

/* --------------------------------------------------------------------------
   7. Le bandeau a trois cartes
   -------------------------------------------------------------------------- */
/* Translucide, et non transparent : le texte doit rester lisible par-dessus le
   maillage, mais le maillage doit rester perceptible. .92 est le point ou les
   deux tiennent -- verifie sur les deux themes. */
.bande {
	background: rgba(var(--bande-rgb), .92);
	border-top: 1px solid var(--filet);
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: 26px;
	max-width: var(--large);
	margin: 0 auto;
	padding: 84px var(--marge);
}

.carte {
	display: grid;
	gap: 12px;
	align-content: start;
	padding: 28px;
	border: 1px solid var(--filet);
	border-radius: 12px;
}
.carte-accent { background: var(--accent-doux); border-color: var(--accent); }

.carte-titre { margin: 0; font-size: 24px; letter-spacing: -.02em; }
/* Deux lignes VOULUES, et non un repli de mise en page : le titre se lit en
   deux affirmations. Deux <span> plutot qu'un <br> dans le libelle -- aucun
   balisage ne transite par les fichiers de langue. */
.carte-titre span { display: block; }
.carte-corps { margin: 0; font-size: 15.5px; line-height: 1.6; color: var(--attenue); text-wrap: pretty; }

.statut-liste { list-style: none; margin: 4px 0 0; padding: 0; display: grid; gap: 9px; }

.statut-ligne {
	display: flex;
	align-items: center;
	gap: 10px;
	font-family: var(--mono);
	font-size: 12.5px;
	color: var(--texte-doux);
}
.statut-hote { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.statut-etat { flex: 0 0 auto; color: var(--faible); white-space: nowrap; }

/* La pastille est DECORATIVE : l'etat est ecrit a cote en toutes lettres. Une
   couleur seule ne dit rien a qui ne la distingue pas, et « rouge » est
   precisement le cas ou l'information compte. */
.pastille {
	flex: 0 0 auto;
	width: 8px; height: 8px;
	border-radius: 50%;
	background: var(--inconnu);
}
.pastille-ok { background: var(--ok); animation: pulse 2.4s ease-in-out infinite; }
.pastille-ko { background: var(--ko); }
.pastille-inconnu { background: var(--inconnu); }

@keyframes pulse {
	0%, 100% { opacity: .45; }
	50%      { opacity: 1; }
}

.statut-note  { margin: 6px 0 0; font-size: 12.5px; color: var(--tres-faible); }
.statut-panne { color: var(--ko); }

/* --------------------------------------------------------------------------
   8. Le pied
   -------------------------------------------------------------------------- */
.pied {
	background: rgba(var(--bande-rgb), .92);
	border-top: 1px solid var(--filet);
}

.pied-haut {
	max-width: var(--large);
	margin: 0 auto;
	padding: 62px var(--marge) 34px;
	display: grid;
	grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr);
	gap: 54px;
}

.pied-legal { display: grid; gap: 16px; align-content: start; }
.pied-marque { margin: 0; font-size: 18px; font-weight: 700; }
.pied-texte { margin: 0; max-width: 46ch; font-size: 14.5px; line-height: 1.65; color: var(--attenue); text-wrap: pretty; }

.pied-liens { display: flex; flex-wrap: wrap; gap: 8px; }
.pied-liens a {
	font-family: var(--mono);
	font-size: 11.5px;
	letter-spacing: .1em;
	text-transform: uppercase;
	padding: 8px 13px;
	border: 1px solid var(--filet);
	border-radius: 6px;
	color: var(--texte-doux);
	white-space: nowrap;
	transition: border-color .18s ease, color .18s ease;
}
.pied-liens a:hover { border-color: var(--accent); color: var(--accent); }

/* Le bloc de droite du pied : un rappel vers la page de contact, et non plus
   le formulaire lui-meme -- il vit desormais sur /contact. */
.pied-contact {
	display: grid;
	gap: 12px;
	align-content: start;
	padding: 24px;
	border: 1px solid var(--filet);
	border-radius: 12px;
	background: var(--accent-doux);
}
.pied-contact p { margin: 0; }
.pied-contact-note { font-size: 14px; line-height: 1.55; color: var(--attenue); }

.bouton-accent {
	justify-self: start;
	display: inline-flex;
	align-items: center;
	margin-top: 4px;
	padding: 12px 20px;
	border: 1px solid var(--accent);
	border-radius: 7px;
	background: var(--accent);
	color: var(--accent-txt);
	font-family: var(--mono);
	font-size: 12px;
	font-weight: 600;
	letter-spacing: .12em;
	text-transform: uppercase;
	cursor: pointer;
	transition: background-color .18s ease, color .18s ease;
}
.bouton-accent:hover { background: transparent; color: var(--accent); }

.pied-bas {
	border-top: 1px solid var(--filet);
	padding: 18px var(--marge) 30px;
	display: flex;
	flex-wrap: wrap;
	gap: 12px;
	justify-content: space-between;
	font-family: var(--mono);
	font-size: 11.5px;
	letter-spacing: .06em;
	color: var(--tres-faible);
}

/* --------------------------------------------------------------------------
   9. La page de contact
   --------------------------------------------------------------------------
   Le formulaire a quitte le pied de l'accueil le 2026-08-19 : il y etait au
   bout de 320vh de defilement plus quatre blocs de site, c'est-a-dire nulle
   part. Il a maintenant sa page, son adresse — /contact — et son bouton dans
   la barre.
   -------------------------------------------------------------------------- */
.page-etroite {
	max-width: 760px;
	margin: 0 auto;
	padding: 130px var(--marge) 90px;
	display: grid;
	gap: 22px;
}

.page-titre {
	margin: 0;
	font-size: clamp(34px, 6vw, 68px);
	line-height: .98;
	letter-spacing: -.035em;
	font-weight: 700;
	text-wrap: balance;
}
.page-chapo { margin: 0; font-size: 17px; line-height: 1.6; color: var(--attenue); text-wrap: pretty; }

.retour-accueil {
	justify-self: start;
	font-family: var(--mono);
	font-size: 12px;
	letter-spacing: .12em;
	text-transform: uppercase;
	color: var(--faible);
}
.retour-accueil:hover { color: var(--accent); }

.contact {
	display: grid;
	gap: 12px;
	align-content: start;
	padding: 26px;
	border: 1px solid var(--filet);
	border-radius: 12px;
	background: var(--fond-bande);
}
.contact-note { margin: 0; font-size: 14px; line-height: 1.55; color: var(--attenue); }

.contact-form { display: grid; gap: 12px; }

.contact-champ { display: grid; gap: 6px; }
.contact-champ > span {
	font-family: var(--mono);
	font-size: 11px;
	letter-spacing: .16em;
	text-transform: uppercase;
	color: var(--faible);
}

.contact-form input[type="text"],
.contact-form input[type="email"],
.contact-form textarea {
	width: 100%;
	padding: 11px 13px;
	border: 1px solid var(--bord);
	border-radius: 7px;
	background: var(--champ);
	color: var(--texte);
	font-family: var(--police);
	font-size: 15px;
}
.contact-form textarea { resize: vertical; min-height: 150px; }
.contact-form ::placeholder { color: var(--tres-faible); opacity: 1; }

/* Le pot de miel. Hors ecran ET hors du flux : un humain ne peut ni le voir,
   ni l'atteindre a la tabulation, ni l'entendre. */
.piege {
	position: absolute;
	left: -9999px;
	width: 1px; height: 1px;
	opacity: 0;
}

.captcha {
	display: flex;
	align-items: center;
	gap: 10px;
	flex-wrap: wrap;
	padding-top: 12px;
	border-top: 1px solid var(--filet);
}
.captcha-label {
	font-family: var(--mono);
	font-size: 11px;
	letter-spacing: .16em;
	text-transform: uppercase;
	color: var(--faible);
}
.captcha-somme { font-family: var(--mono); font-size: 15px; }
.captcha input {
	width: 78px;
	padding: 9px 11px;
	border: 1px solid var(--bord);
	border-radius: 7px;
	background: var(--champ);
	color: var(--texte);
	font-family: var(--mono);
	font-size: 15px;
}

/* Le bouton est TOUJOURS actif. La maquette le grisait tant que l'addition
   n'etait pas juste : un bouton desactive ne dit pas POURQUOI, et il ne le
   dira jamais a qui ne voit pas le champ d'a cote. Ici on envoie, et le
   serveur repond en une phrase -- c'est aussi le seul comportement qui tienne
   sans JavaScript. */
.envoyer {
	justify-self: start;
	margin-top: 4px;
	padding: 13px 22px;
	border: 1px solid var(--accent);
	border-radius: 7px;
	background: var(--accent);
	color: var(--accent-txt);
	font-family: var(--mono);
	font-size: 12px;
	font-weight: 600;
	letter-spacing: .12em;
	text-transform: uppercase;
	cursor: pointer;
	transition: background-color .18s ease, color .18s ease;
}
.envoyer:hover { background: transparent; color: var(--accent); }

.retour {
	margin: 0;
	padding: 12px 14px;
	border-radius: 7px;
	font-size: 14.5px;
	line-height: 1.5;
	border: 1px solid;
}
.retour-ok { border-color: var(--ok); color: var(--ok); background: var(--ok-fond); }
.retour-ko { border-color: var(--ko); color: var(--ko); background: var(--ko-fond); }

/* --------------------------------------------------------------------------
   10. Les apparitions
   -------------------------------------------------------------------------- */
.js-scrub [data-reveal] {
	opacity: 0;
	transform: translateY(24px);
	transition: opacity .7s ease, transform .7s ease;
}
.js-scrub [data-reveal].vu { opacity: 1; transform: none; }

/* --------------------------------------------------------------------------
   11. Telephone
   --------------------------------------------------------------------------
   320vh de defilement collant avant le premier contenu utile, c'est trois
   ecrans a franchir sur un telephone pour atteindre la liste des sites. Le
   bloc tombe a 180vh -- app.js lit cette valeur sur l'element, il n'a pas de
   seconde definition a tenir a jour.
   -------------------------------------------------------------------------- */
@media (max-width: 900px) {
	.site {
		grid-template-columns: minmax(0, 1fr);
		gap: 22px;
		padding: 44px var(--marge);
	}
	.site-num { margin: 0; }
	.site-vignette { max-width: 420px; }
	.bande { grid-template-columns: minmax(0, 1fr); gap: 18px; padding: 56px var(--marge); }
	.pied-haut { grid-template-columns: minmax(0, 1fr); gap: 34px; }
}

@media (max-width: 720px) {
	:root { --marge: 18px; }
	.js-scrub .scrub { height: 180vh; }
	.entete { flex-wrap: wrap; gap: 10px; }
	.nav { margin-left: 0; width: 100%; }
	.nav-lien { padding: 0 11px; font-size: 11px; }
	.page-etroite { padding-top: 150px; }
}

/* --------------------------------------------------------------------------
   12. Mouvement reduit
   --------------------------------------------------------------------------
   L'equivalent du reglage « staticMotion » de la maquette, branche sur la
   preference du systeme. La toile se fige sur une image, la parallaxe s'arrete,
   et LES QUATRE PALIERS REDEVIENNENT QUATRE PARAGRAPHES EMPILES : les cacher
   tout en supprimant ce qui permettait de les reveler rendrait la page muette.

   La regle annule .js-scrub : elle vient apres, et porte les memes selecteurs.
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
	html { scroll-behavior: auto; }

	.js-scrub .scrub { height: auto; }
	.js-scrub .scrub-collant {
		position: relative;
		height: auto;
		display: grid;
		gap: 40px;
		padding: 120px var(--marge) 80px;
		max-width: var(--large);
		margin: 0 auto;
		overflow: visible;
	}
	/* La toile reste, FIGEE : app.js dessine une image et ne rappelle pas
	   requestAnimationFrame. Elle couvre le bloc entier, le texte passe
	   au-dessus. */
	.js-scrub .scrub-mots { position: relative; z-index: 1; display: grid; gap: 40px; padding: 0; }
	.js-scrub .mot { grid-area: auto; opacity: 1; }
	.js-scrub .scrub-hint { display: none; }

	.js-scrub [data-reveal] { opacity: 1; transform: none; transition: none; }

	.pastille-ok { animation: none; opacity: 1; }

	/* La piece ne tourne pas : elle reste de face, et app.js n'y touche pas. */
	.piece { transform: none !important; will-change: auto; }

	*, *::before, *::after {
		animation-duration: .001ms !important;
		animation-iteration-count: 1 !important;
		transition-duration: .001ms !important;
		scroll-behavior: auto !important;
	}
}

/* --------------------------------------------------------------------------
   13. Les pages de service — À propos, Vie privée, Mentions légales
   --------------------------------------------------------------------------
   Meme forme que chez tools, ip et dns : un titre, un chapo, puis de la prose
   en sections. Les trois boutons du pied menaient a des ancres mortes ; ils
   ont maintenant des pages, et des adresses traduites (/a-propos et /about,
   /vie-privee et /privacy, /mentions-legales et /legal-notice) parce que ce
   sont des mots et non des sigles.
   -------------------------------------------------------------------------- */
.prose {
	display: grid;
	gap: 18px;
	max-width: 68ch;
}
.prose h2 {
	margin: 22px 0 0;
	font-size: 21px;
	letter-spacing: -.02em;
	line-height: 1.2;
}
.prose p {
	margin: 0;
	font-size: 16.5px;
	line-height: 1.68;
	color: var(--attenue);
	text-wrap: pretty;
}
.prose b { color: var(--texte); font-weight: 600; }
.prose a { color: var(--accent); border-bottom: 1px solid rgba(var(--accent-rgb), .45); }
.prose a:hover { border-bottom-color: var(--accent); }
.prose code {
	font-family: var(--mono);
	font-size: .92em;
	padding: 1px 5px;
	border: 1px solid var(--filet);
	border-radius: 4px;
	background: var(--accent-doux);
	color: var(--texte);
}
.prose ul { margin: 0; padding-left: 20px; display: grid; gap: 8px; }
.prose li { font-size: 16.5px; line-height: 1.6; color: var(--attenue); }

/* Le bloc encadre des pages de service, pour ce qui doit se detacher de la
   prose : une adresse, une mise en garde. */
.encadre {
	padding: 18px 20px;
	border: 1px solid var(--filet);
	border-radius: 10px;
	background: var(--accent-doux);
	display: grid;
	gap: 8px;
}
.encadre p { margin: 0; }
