/* ═══════════════════════════════════════════════════════════════════════════
   style.v2.css — la porte d'entrée de d4xw.com (index.php).

   Même identité visuelle que /public.php et /shop.php : fond noir, phosphore
   vert, Fira Code, scanlines, et le nuage de points en décor. Avant, cette
   page vivait sur un fond gris #222 sans rapport avec le reste : le visiteur
   changeait de site en cliquant sur « Entrée ».

   ⚠️ Le nom du fichier porte sa version. Le site est derrière Cloudflare : un
   statique qui change de CONTENU sans changer de NOM continue d'être servi
   périmé pendant des heures. Modifier ce fichier = le renommer (style.v3.css)
   et répercuter le <link> dans index.php.
   L'ancien style.css est laissé en place volontairement : c'est le retour
   arrière immédiat (rien ici n'est suivi par git).
   ═══════════════════════════════════════════════════════════════════════════ */

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

html { height: 100%; }

body {
	min-height: 100%;
	background-color: #0a0a0a;
	color: #fff;
	font-family: "Fira Code", ui-monospace, monospace;
	/* Obligatoire depuis le passage à la police auto-hébergée : le lien Google
	   d'avant ne servait QUE la graisse 500, la variable va de 400 à 600 et
	   retomberait sur 400 — tout le texte maigrissait. */
	font-weight: 500;
	-webkit-text-size-adjust: 100%;
	overflow-x: hidden;
}

/* ── Le nuage de points, derrière tout le reste ──────────────────────────────
   `fixed` : il habite la page au lieu de défiler avec elle. Jamais entre le
   doigt et un lien — la porte privée est un Ctrl+clic sur la signature et un
   appui long sur le titre, il ne faut rien qui intercepte. */
#d4-cloud {
	position: fixed;
	inset: 0;
	width: 100%;
	height: 100%;
	z-index: 0;
	pointer-events: none;
}

/* Halo central : détache le nuage du noir pur sans éclaircir la page. */
.glow {
	position: fixed;
	left: 50%;
	top: 50%;
	width: min(78vw, 78vh);
	height: min(78vw, 78vh);
	transform: translate(-50%, -50%);
	background: radial-gradient(circle, rgba(119, 255, 136, .055), transparent 62%);
	pointer-events: none;
	z-index: 0;
}

/* Scanlines : la signature D4, gardée très discrète pour ne pas manger les
   points du nuage. */
body::before {
	content: "";
	position: fixed;
	inset: 0;
	background: repeating-linear-gradient(
		0deg, transparent, transparent 2px,
		rgba(0, 0, 0, .10) 2px, rgba(0, 0, 0, .10) 4px
	);
	pointer-events: none;
	z-index: 2;
}

/* ── Colonne d'accueil ──────────────────────────────────────────────────────
   Un seul écran, jamais de défilement : titre, sous-titre, la zone où le nuage
   respire, puis la porte. */
.landing {
	position: relative;
	z-index: 1;
	min-height: 100vh;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: flex-start;
	padding: 3.2rem 1.2rem 4.4rem;
}

/* ── Titre glitché ──────────────────────────────────────────────────────── */
.TextGlitch {
	--TextGlitch-blendSize: .08em;
	--TextGlitch-blendColorA: #77f8;
	--TextGlitch-blendColorB: #ff68;

	position: relative;
	color: #fff;
	line-height: 1em;
	letter-spacing: -.1ch;
	/* Borné : à 8vw sec, « D4 » faisait 300 px sur un écran 4K et 31 px sur un
	   téléphone. */
	font-size: clamp(3.4rem, 11vw, 9rem);
	font-family: "Fira Code", ui-monospace, monospace;
	font-weight: 500;
	/* Le nuage passe derrière : sans cette ombre, les points traversent les
	   lettres et le titre se met à grésiller pour de mauvaises raisons. */
	text-shadow: 0 2px 34px rgba(0, 0, 0, .95);
}

.TextGlitch::after {
	display: none;
	content: "";
	position: absolute;
	left: 100%;
	bottom: 0;
	width: .7ch;
	height: 1em;
	margin-left: .35ch;
	border-radius: 2px;
	background-color: currentColor;
	animation: cursorAnim 1s ease infinite;
}
@keyframes cursorAnim {
	0% { opacity: .5; }
	45% { opacity: .5; }
	55% { opacity: 0; }
	100% { opacity: 0; }
}

.TextGlitch-clip {
	position: relative;
	display: flex;
	align-items: baseline;
}
.TextGlitch-clip + .TextGlitch-clip {
	position: absolute;
	top: 0;
}
.TextGlitch:not( .TextGlitch-blended ) .TextGlitch-clip + .TextGlitch-clip {
	display: none;
}

.TextGlitch-word {
	margin: 0;
	white-space: nowrap;
}

.TextGlitch-blend {
	position: absolute;
	top: 0;
	opacity: 0;
	transition: .1s;
	transition-property: opacity;
}
.TextGlitch-blendA {
	color: var( --TextGlitch-blendColorA );
	margin: calc( var( --TextGlitch-blendSize ) * -1 ) 0 0 var( --TextGlitch-blendSize );
	mix-blend-mode: darken;
}
.TextGlitch-blendB {
	color: var( --TextGlitch-blendColorB );
	margin: var( --TextGlitch-blendSize ) 0 0 calc( var( --TextGlitch-blendSize ) * -1 );
	mix-blend-mode: color-burn;
}
.TextGlitch-blended .TextGlitch-blend {
	opacity: .4;
}

/* La zone où le nuage respire : vide de contenu, c'est volontaire. Le moteur
   (assets/d4-cloud.v5.js) lit ce rectangle pour se centrer et se dimensionner
   — pas un seul chiffre en dur côté JS. `flex:1` : elle prend ce qui reste,
   donc le globe est grand sur un grand écran et la page ne déborde jamais. */
.stage {
	flex: 1 1 auto;
	width: 100%;
	min-height: 170px;
}

/* ── La porte ───────────────────────────────────────────────────────────── */
.enter-btn {
	position: relative;
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: .55em;
	padding: 1em 2.8em;
	border: 1px solid rgba(119, 255, 136, .22);
	/* Fond franc : le bouton passe au-dessus du nuage, le texte doit toujours
	   gagner contre les points qui bougent derrière. */
	background: rgba(9, 9, 9, .78);
	-webkit-backdrop-filter: blur(7px);
	backdrop-filter: blur(7px);
	color: rgba(119, 255, 136, .7);
	font-family: inherit;
	text-decoration: none;
	cursor: pointer;
	overflow: hidden;
	/* Deux animations qui ne se marchent pas dessus : l'une l'opacité et la
	   propriété `translate`, l'autre l'ombre. Le survol garde `transform` pour
	   lui — une animation en `forwards` écrase toujours un `transform` déclaré
	   normalement, c'est ce qui rendait l'ancien effet de survol inopérant. */
	animation: enter-in .8s ease .7s backwards,
	           enter-pulse 3.8s ease-in-out 1.6s infinite;
	transition: border-color .25s, color .25s, background .25s, transform .25s;
}
/* Barre d'accent à gauche, comme les cartes de /public.php. */
.enter-btn::after {
	content: "";
	position: absolute;
	left: 0; top: 15%;
	height: 70%; width: 2px;
	background: rgba(119, 255, 136, .55);
	transform: scaleY(0);
	transform-origin: top;
	transition: transform .25s;
}
.enter-btn:hover,
.enter-btn:focus-visible {
	border-color: rgba(119, 255, 136, .6);
	background: rgba(12, 12, 12, .88);
	color: rgba(119, 255, 136, 1);
	transform: translateY(-3px);
	outline: none;
}
.enter-btn:hover::after,
.enter-btn:focus-visible::after { transform: scaleY(1); }
.enter-btn:hover .enter-txt,
.enter-btn:focus-visible .enter-txt { animation: card-glitch .2s steps(1) 3; }

.enter-txt {
	font-size: clamp(.85rem, 2.2vw, 1rem);
	letter-spacing: .3em;
	text-indent: .3em;
	text-transform: uppercase;
}
.enter-sub {
	font-size: .6rem;
	letter-spacing: .2em;
	text-indent: .2em;
	text-transform: uppercase;
	color: rgba(255, 255, 255, .28);
	transition: color .25s;
}
.enter-btn:hover .enter-sub,
.enter-btn:focus-visible .enter-sub { color: rgba(255, 255, 255, .5); }

@keyframes enter-in {
	from { opacity: 0; translate: 0 8px; }
	to   { opacity: 1; translate: 0 0; }
}
@keyframes enter-pulse {
	0%, 100% { box-shadow: 0 0 0 0 rgba(119, 255, 136, 0); }
	50%      { box-shadow: 0 0 34px -6px rgba(119, 255, 136, .18); }
}
@keyframes card-glitch {
	0%   { transform: translate(0); color: #fff; }
	33%  { transform: translate(-2px, 1px); color: #77f8; clip-path: inset(20% 0 40% 0); }
	66%  { transform: translate(2px, -1px); color: #ff68; clip-path: inset(55% 0 10% 0); }
	100% { transform: translate(0); color: inherit; clip-path: none; }
}

/* ── Signature ──────────────────────────────────────────────────────────────
   Invisible par défaut : c'est la porte privée (Ctrl+A la révèle, Ctrl+clic
   ouvre le mot de passe). Elle doit rester CLIQUABLE, donc au-dessus des
   scanlines (z-index 2) — pas de pointer-events: none ici. */
.signature {
	position: fixed;
	bottom: 8px;
	left: 0;
	width: 100%;
	z-index: 5;
	text-align: center;
	font-family: inherit;
	font-size: 11px;
	letter-spacing: .12em;
	color: transparent;
	user-select: none;
	cursor: default;
}
.signature.revealed {
	color: rgba(255, 255, 255, .22);
	cursor: pointer;
	animation: sig-glitch .6s ease forwards;
}
@keyframes sig-glitch {
	0%   { color: rgba(255,255,255,0);    transform: translate(0);       text-shadow: none; }
	10%  { color: rgba(119,255,136,.6);   transform: translate(-2px, 0); text-shadow: 2px 0 #ff6688, -2px 0 #77ffff; }
	20%  { color: rgba(255,255,255,.22);  transform: translate(2px, 0);  text-shadow: none; }
	35%  { color: rgba(255,100,200,.5);   transform: translate(-1px, 0); text-shadow: 3px 0 #77f8; }
	50%  { color: rgba(255,255,255,.22);  transform: translate(0);       text-shadow: none; }
	70%  { color: rgba(119,255,255,.4);   transform: translate(1px, 0);  text-shadow: -2px 0 #ff68; }
	100% { color: rgba(255,255,255,.22);  transform: translate(0);       text-shadow: none; }
}

/* ── Modal mot de passe ─────────────────────────────────────────────────── */
.pw-modal {
	display: none;
	position: fixed;
	inset: 0;
	background: rgba(0, 0, 0, .8);
	align-items: center;
	justify-content: center;
	z-index: 9999;
}
.pw-modal.active {
	display: flex;
}
.pw-box {
	background: #0d0d0d;
	border: 1px solid rgba(119, 255, 136, .25);
	box-shadow: 0 0 30px rgba(119, 255, 136, .08), inset 0 0 20px rgba(0,0,0,.5);
	padding: 2.5em 3.5em;
	display: flex;
	flex-direction: column;
	gap: 1.2em;
	min-width: 300px;
	font-family: inherit;
}
.pw-label {
	font-size: .95em;
	letter-spacing: .15em;
	color: rgba(119, 255, 136, .7);
}
.pw-input {
	background: transparent;
	border: none;
	border-bottom: 1px solid rgba(119, 255, 136, .3);
	color: #fff;
	font-family: inherit;
	font-size: 1.4em;
	letter-spacing: .5em;
	text-align: center;
	outline: none;
	padding: .3em 0;
	transition: border-color .2s;
}
.pw-input:focus {
	border-bottom-color: rgba(119, 255, 136, .8);
}
.pw-error {
	font-size: .8em;
	letter-spacing: .1em;
	color: rgba(255, 100, 100, .8);
	min-height: 1em;
}
.pw-input.shake {
	animation: pw-shake .35s ease;
}
@keyframes pw-shake {
	0%, 100% { transform: translateX(0); }
	20%, 60% { transform: translateX(-7px); }
	40%, 80% { transform: translateX(7px); }
}
.pw-submit {
	background: transparent;
	border: 1px solid rgba(119, 255, 136, .25);
	color: rgba(119, 255, 136, .6);
	font-family: inherit;
	font-size: .8em;
	letter-spacing: .25em;
	padding: .6em 1.2em;
	cursor: pointer;
	align-self: center;
	transition: border-color .2s, color .2s;
}
.pw-submit:hover, .pw-submit:active {
	border-color: rgba(119, 255, 136, .7);
	color: rgba(119, 255, 136, 1);
}

/* ── Animations réduites : on garde la page, on enlève le mouvement ─────── */
@media (prefers-reduced-motion: reduce) {
	.enter-btn { animation: none; }
	.enter-btn:hover .enter-txt,
	.enter-btn:focus-visible .enter-txt { animation: none; }
}

/* ── Mobile : ce bloc doit RESTER en dernier, sinon la cascade l'annule
      (régression déjà vécue sur ARIsMAP). ─────────────────────────────────── */
@media (max-width: 640px) {
	.landing { padding: 2.6rem 1.1rem 3.6rem; }
	.stage { min-height: 150px; }
	.enter-btn { padding: 1em 2.2em; width: 100%; max-width: 320px; }
}

/* Téléphone couché. Mesuré sur un viewport de 303 px de haut (un iPhone SE
   couché, barres du navigateur déduites) : la page débordait de 61 px et la
   porte tombait sous la ligne de flottaison. Tout ce qui est en hauteur se
   resserre, le titre se cale sur la hauteur plutôt que sur la largeur, et la
   zone du nuage devient négociable — mais pas en dessous de 44 px : sous 40 px
   le moteur cesse de se caler dessus et va dessiner le nuage par-dessus le
   texte. */
@media (max-height: 520px) {
	.landing { padding: 1.2rem 1.1rem 1.6rem; }
	.TextGlitch { font-size: clamp(2.2rem, 7vh, 3.4rem); }
	.stage { min-height: 44px; }
	.enter-btn { padding: .7em 2.4em; }
}
