/* Feuille unique, écrite à la main. Les couleurs passent toutes par les propriétés
   personnalisées ci-dessous — les valeurs littérales ailleurs sont un défaut. Les quatre
   teintes du dégradé sont celles du logo, et ne servent qu'à ce qui l'entoure. */

:root {
  --fond: #06090f;
  --fond-haut: #0b1119;
  --surface: #111823;
  --surface-hi: #18202c;
  --bord: #1e2836;
  --bord-vif: #2b3a4e;

  --texte: #e6edf3;
  --doux: #90a0b4;
  --pale: #5d6c7d;

  /* Les trois teintes du logo, relevées sur le fichier lui-même : le valknut va de `#7f00ff`
     à `#e100ff`. Tout ce qui l'entoure — lueur, anneaux, titre, filets — en sort, sans quoi
     la scène jurerait avec la marque qu'elle met en valeur. */
  --violet: #7f00ff;
  --accent: #a800ff;
  --magenta: #e100ff;

  --ok: #3fb950;
  --alerte: #d29922;
  --grave: #f85149;

  --degrade: linear-gradient(90deg, var(--violet), var(--accent), var(--magenta));
  --degrade-diag: linear-gradient(135deg, var(--violet), var(--magenta));

  --rayon: 14px;
  --page: 1200px;

  color-scheme: dark;
}

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

html { scroll-behavior: smooth; height: 100%; }

/* `min-height` et non `height` : une hauteur fixe borne le bloc conteneur de la barre à un
   écran, et `position: sticky` cesse de coller dès qu'on descend plus bas — la barre repart
   alors avec le contenu, au milieu de la page. */
body {
  min-height: 100%;
  margin: 0;
  background: var(--fond);
  color: var(--texte);
  font: 16px/1.6 ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", sans-serif;
  -webkit-font-smoothing: antialiased;
  display: flex;
  flex-direction: column;
}

/* ⚠️ Pas d'`overflow-x: hidden` sur `body` : ça en ferait un conteneur de défilement, et la
   barre en `position: sticky` cesserait alors de coller — elle repart avec le contenu, sans
   qu'aucune règle ne semble en cause. Ce qui pourrait déborder est borné là où il naît. */

h1, h2 { margin: 0; font-weight: 600; }
a { color: inherit; }

.skip { position: absolute; left: -9999px; }
.skip:focus {
  left: 12px; top: 12px; z-index: 100;
  padding: 8px 12px;
  background: var(--surface-hi);
  border: 1px solid var(--accent);
  border-radius: 8px;
}

/* ── Barre ───────────────────────────────────────────────────────────────────────────── */

.barre {
  position: sticky;
  top: 0;
  z-index: 20;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 14px clamp(16px, 4vw, 48px);
  background: color-mix(in srgb, var(--fond) 82%, transparent);
  backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--bord);
}

/* Le filet reprend le dégradé du logo : c'est la seule couleur franche de la page. */
.barre::after {
  content: "";
  position: absolute;
  inset: auto 0 -1px 0;
  height: 1px;
  background: var(--degrade);
  opacity: .4;
}

.barre__marque {
  display: flex;
  align-items: center;
  gap: 10px;
  font-weight: 600;
  letter-spacing: .04em;
}

.barre__lien {
  padding: 7px 16px;
  border: 1px solid var(--bord-vif);
  border-radius: 999px;
  font-size: .9rem;
  text-decoration: none;
  color: var(--doux);
  transition: color .15s ease, border-color .15s ease, background .15s ease;
}

.barre__lien:hover,
.barre__lien:focus-visible {
  color: var(--texte);
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 12%, transparent);
}

/* ── Scène ───────────────────────────────────────────────────────────────────────────── */

.scene {
  position: relative;
  /* `svh` et non `vh` : sur mobile, `vh` compte la barre d'adresse rétractée, et la scène
     déborde d'autant tant qu'elle est déployée. */
  min-height: calc(100svh - 60px);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: clamp(40px, 8vh, 90px) clamp(16px, 4vw, 48px) clamp(60px, 10vh, 110px);
  text-align: center;
  isolation: isolate;
  /* La lueur et la grille sont peintes en pseudo-éléments débordants : elles se coupent ici,
     et non sur le corps du document. */
  overflow: hidden;
}

/* Deux fonds superposés, purement décoratifs : une grille technique, et une lueur qui la
   décolore vers le centre. Ils sont posés en pseudo-éléments pour n'ajouter aucun nœud. */
.scene::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -2;
  background-image:
    linear-gradient(var(--bord) 1px, transparent 1px),
    linear-gradient(90deg, var(--bord) 1px, transparent 1px);
  background-size: 64px 64px;
  opacity: .35;
  /* La grille s'efface sur les bords : sans ce masque elle coupe net, et le bas de page
     ressemble à une capture tronquée. */
  mask-image: radial-gradient(ellipse 80% 60% at 50% 40%, #000 30%, transparent 100%);
}

.scene::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background:
    radial-gradient(ellipse 60% 45% at 50% 30%, color-mix(in srgb, var(--accent) 14%, transparent), transparent 70%),
    radial-gradient(ellipse 50% 40% at 70% 60%, color-mix(in srgb, var(--magenta) 10%, transparent), transparent 70%);
}

/* ── L'astre : le logo et ce qui tourne autour ───────────────────────────────────────── */

.astre {
  position: relative;
  width: clamp(220px, 34vh, 320px);
  aspect-ratio: 1;
  display: grid;
  place-items: center;
  margin-bottom: clamp(20px, 4vh, 40px);
}

.astre__halo,
.astre__anneau {
  position: absolute;
  inset: 0;
  border-radius: 50%;
}

.astre__halo {
  background: radial-gradient(circle, color-mix(in srgb, var(--accent) 30%, transparent), transparent 62%);
  filter: blur(26px);
  animation: respire 5s ease-in-out infinite;
}

/* Le balayage : un dégradé conique tourné, découpé en anneau par un masque. Un `border` ne
   saurait pas porter un dégradé qui tourne avec lui. */
.astre__anneau--balayage {
  background: conic-gradient(from 0deg,
    transparent 0deg,
    color-mix(in srgb, var(--violet) 70%, transparent) 60deg,
    var(--magenta) 110deg,
    transparent 170deg,
    transparent 360deg);
  mask: radial-gradient(circle, transparent 61%, #000 62%, #000 65%, transparent 66%);
  animation: tourne 9s linear infinite;
}

.astre__anneau--pointille {
  inset: 6%;
  border: 1px dashed color-mix(in srgb, var(--doux) 45%, transparent);
  animation: tourne 40s linear infinite reverse;
}

/* L'anneau fin porte un satellite : le point est un pseudo-élément posé sur sa circonférence,
   et c'est l'anneau qui tourne — le point n'a pas d'animation propre. */
.astre__anneau--fin {
  inset: -8%;
  border: 1px solid color-mix(in srgb, var(--bord-vif) 90%, transparent);
  animation: tourne 22s linear infinite;
}

.astre__anneau--fin::after {
  content: "";
  position: absolute;
  top: -4px;
  left: 50%;
  width: 8px;
  height: 8px;
  margin-left: -4px;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 12px 2px color-mix(in srgb, var(--accent) 70%, transparent);
}

.astre__marque {
  position: relative;
  width: 62%;
  height: auto;
  animation: flotte 6s ease-in-out infinite;
  filter: drop-shadow(0 0 18px color-mix(in srgb, var(--accent) 35%, transparent));
}

@keyframes tourne { to { transform: rotate(360deg); } }
@keyframes flotte {
  0%, 100% { transform: translateY(-5px); }
  50%      { transform: translateY(5px); }
}
@keyframes respire {
  0%, 100% { opacity: .55; transform: scale(.94); }
  50%      { opacity: .95; transform: scale(1.04); }
}

/* ── Titre et texte ──────────────────────────────────────────────────────────────────── */

.scene__titre {
  font-size: clamp(3rem, 11vw, 7rem);
  line-height: 1;
  letter-spacing: -.03em;
  /* Le nom porte le dégradé du logo : le texte est peint par le fond, découpé à la forme des
     lettres. `color: transparent` est ce qui laisse voir ce fond. */
  background: var(--degrade-diag);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.scene__baseline {
  margin: 14px 0 0;
  color: var(--doux);
  font-size: clamp(.9rem, 2.2vw, 1.1rem);
  letter-spacing: .34em;
  text-transform: uppercase;
}

.scene__texte {
  margin-top: clamp(28px, 5vh, 48px);
  max-width: 62ch;
  color: var(--doux);
  text-wrap: pretty;
}

.scene__texte p { margin: 0 0 14px; }

/* ── Portes ──────────────────────────────────────────────────────────────────────────── */

.portes {
  width: 100%;
  max-width: var(--page);
  margin: 0 auto;
  padding: clamp(40px, 8vh, 90px) clamp(16px, 4vw, 48px) clamp(50px, 9vh, 100px);
}

.titre-section {
  font-size: .78rem;
  letter-spacing: .22em;
  text-transform: uppercase;
  color: var(--pale);
  margin-bottom: 26px;
}

.portes__liste {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 16px;
  /* La grille se réorganise sur la largeur disponible, pas sur une taille d'écran devinée. */
  grid-template-columns: repeat(auto-fit, minmax(290px, 1fr));
}

.porte__lien {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 4px;
  height: 100%;
  padding: 24px;
  background: linear-gradient(180deg, var(--surface), var(--fond-haut));
  border: 1px solid var(--bord);
  border-radius: var(--rayon);
  text-decoration: none;
  overflow: hidden;
  transition: border-color .18s ease, transform .18s ease, box-shadow .18s ease;
}

/* Un filet de couleur en haut de carte, révélé au survol : la couleur signale la cible sans
   rien ajouter au balisage. */
.porte__lien::before {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 2px;
  background: var(--degrade);
  opacity: 0;
  transition: opacity .18s ease;
}

.porte__lien:hover,
.porte__lien:focus-visible {
  border-color: var(--bord-vif);
  transform: translateY(-3px);
  box-shadow: 0 18px 40px -24px color-mix(in srgb, var(--accent) 60%, transparent);
}

.porte__lien:hover::before,
.porte__lien:focus-visible::before { opacity: 1; }

.porte__nom { font-weight: 600; font-size: 1.05rem; }
.porte__desc { color: var(--doux); font-size: .95rem; }

/* L'adresse est écrite en clair : sur une page publique, on doit pouvoir lire où mène un lien
   avant de le suivre. */
.porte__adresse {
  margin-top: 14px;
  color: var(--pale);
  font-size: .78rem;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  overflow-wrap: anywhere;
}

/* ── La pile ─────────────────────────────────────────────────────────────────────────── */

.pile {
  width: 100%;
  padding: 0 0 clamp(50px, 9vh, 100px);
}

/* Le titre s'aligne sur la colonne de texte, le bandeau va d'un bord à l'autre : c'est ce
   décalage qui donne l'impression que la pile traverse la page. */
.pile .titre-section {
  max-width: var(--page);
  margin: 0 auto 26px;
  padding: 0 clamp(16px, 4vw, 48px);
}

.bandeau {
  display: flex;
  gap: 56px;
  overflow: hidden;
  /* Les deux extrémités s'effacent : sans ce masque, les logos apparaissent et disparaissent
     d'un coup, et le bandeau ressemble à une liste coupée plutôt qu'à un défilement. */
  mask-image: linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent);
}

.bandeau__piste {
  display: flex;
  flex: 0 0 auto;
  align-items: center;
  gap: 56px;
  list-style: none;
  margin: 0;
  padding: 0;
  animation: defile 70s linear infinite;
}

@keyframes defile {
  /* `-100%` de la piste, pas du bandeau : les deux pistes étant identiques, l'image obtenue
     au bout du compte est exactement celle du départ. */
  to { transform: translateX(calc(-100% - 56px)); }
}

/* Le survol arrête le défilement : de quoi lire un nom sans le poursuivre. */
.bandeau:hover .bandeau__piste { animation-play-state: paused; }

.tech {
  display: flex;
  align-items: center;
  gap: 12px;
  color: var(--pale);
  transition: color .2s ease;
}

.tech:hover { color: var(--texte); }

/* Le logo est un MASQUE, pas une image : la teinte vient d'ici, et le bandeau garde une seule
   couleur quelles que soient celles des marques. `currentColor` le fait suivre le survol. */
.tech__logo {
  width: 28px;
  height: 28px;
  flex: 0 0 auto;
  background: currentColor;
  mask-image: var(--logo);
  mask-size: contain;
  mask-repeat: no-repeat;
  mask-position: center;
}

.tech__nom {
  font-size: .95rem;
  white-space: nowrap;
  letter-spacing: .02em;
}

/* ── Pied ────────────────────────────────────────────────────────────────────────────── */

.pied {
  margin-top: auto;
  border-top: 1px solid var(--bord);
  padding: 22px clamp(16px, 4vw, 48px);
  color: var(--pale);
  font-size: .85rem;
  display: flex;
  flex-wrap: wrap;
  gap: 6px 20px;
  justify-content: center;
}

.pied a { color: var(--doux); text-decoration: none; }
.pied a:hover { color: var(--texte); }
.pied__version { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; }

/* ── Calque de contact ───────────────────────────────────────────────────────────────── */

/* Ouvert par `:target`, donc par un lien : aucune ligne de JavaScript. Corollaire assumé —
   la touche d'échappement ne ferme pas, il faut le fond ou la croix. */
.calque { display: none; }

.calque:target {
  display: grid;
  place-items: center;
  position: fixed;
  inset: 0;
  z-index: 50;
  padding: clamp(12px, 4vw, 32px);
}

.calque__fond {
  position: absolute;
  inset: 0;
  background: color-mix(in srgb, var(--fond) 82%, transparent);
  backdrop-filter: blur(8px);
}

.calque__boite {
  position: relative;
  width: min(100%, 560px);
  max-height: 88vh;
  overflow-y: auto;
  padding: clamp(20px, 4vw, 30px);
  background: var(--surface);
  border: 1px solid var(--bord-vif);
  border-radius: 18px;
  box-shadow: 0 40px 90px -30px #000;
  animation: monte .18s ease-out;
}

@keyframes monte {
  from { opacity: 0; transform: translateY(12px); }
}

.calque__tete {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 16px;
}

.calque__tete h2 { font-size: 1.3rem; }

.calque__fermer {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border: 1px solid var(--bord);
  border-radius: 50%;
  color: var(--doux);
  text-decoration: none;
  transition: color .15s ease, border-color .15s ease;
}

.calque__fermer:hover,
.calque__fermer:focus-visible { color: var(--texte); border-color: var(--accent); }

.calque__texte {
  margin: 0 0 20px;
  color: var(--doux);
  font-size: .95rem;
}

/* L'accusé ne se lit jamais à la seule couleur : le texte dit ce qui s'est passé, la teinte
   ne fait que le confirmer. */
.accuse {
  margin: 0 0 18px;
  padding: 12px 16px;
  background: var(--surface-hi);
  border: 1px solid var(--bord);
  border-left-width: 3px;
  border-radius: 8px;
  font-size: .95rem;
}

.accuse--ok { border-left-color: var(--ok); }
.accuse--limite,
.accuse--champs { border-left-color: var(--alerte); }
.accuse--refus,
.accuse--panne { border-left-color: var(--grave); }

.formulaire { display: grid; gap: 14px; }

.champ { display: grid; gap: 6px; }

.champ__nom { font-size: .8rem; color: var(--doux); letter-spacing: .06em; }

.champ input,
.champ textarea {
  padding: 11px 13px;
  background: var(--fond-haut);
  border: 1px solid var(--bord);
  border-radius: 10px;
  color: var(--texte);
  font: inherit;
  resize: vertical;
}

.champ input:focus-visible,
.champ textarea:focus-visible {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 22%, transparent);
}

.envoyer {
  justify-self: start;
  margin-top: 4px;
  padding: 11px 26px;
  background: var(--degrade-diag);
  border: none;
  border-radius: 10px;
  color: var(--fond);
  font: inherit;
  font-weight: 700;
  cursor: pointer;
  transition: filter .15s ease, transform .15s ease;
}

.envoyer:hover,
.envoyer:focus-visible { filter: brightness(1.12); transform: translateY(-1px); }

/* ── Mouvement ───────────────────────────────────────────────────────────────────────── */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .astre__halo,
  .astre__anneau,
  .astre__marque,
  .calque__boite { animation: none; }
  /* La pile ne défile plus : elle se parcourt à la main, sinon la fin de la liste devient
     inatteignable pour qui a désactivé le mouvement. */
  .bandeau__piste { animation: none; }
  .bandeau { overflow-x: auto; mask-image: none; }
  .bandeau__piste[aria-hidden="true"] { display: none; }
  .porte__lien,
  .envoyer { transition: none; }
  .porte__lien:hover,
  .porte__lien:focus-visible,
  .envoyer:hover { transform: none; }
}
