/* ── valezconsulting ──────────────────────────────────────────────────
   La feuille de la vitrine — et la base commune des deux sites : le portail
   familial (newtownvillage.com) la charge aussi, puis y ajoute portail.css
   (la porte, la sidebar, la scène, les transitions). Une retouche ici se voit
   donc des deux côtés. */

:root {
  --bg: #0a0b0e;
  --bg-lift: #0e1015;
  --text: #e9eaee;
  --muted: #979dab;
  --faint: #757c8e;   /* 4,71:1 sur --bg : au-dessus du seuil AA (4,5) */
  --panel: rgba(255, 255, 255, 0.028);
  --panel-hover: rgba(255, 255, 255, 0.055);
  --border: rgba(255, 255, 255, 0.075);
  --border-strong: rgba(255, 255, 255, 0.16);

  /* Un seul accent : la ponctuation de la marque, le focus, les filets. */
  --accent: #d99a5b;

  /* Ne servent QUE l'état des services — jamais la décoration. */
  --ok: #4ac295;
  --down: #e5706b;
  --unknown: #5b616e;

  /* Un empattement pour les titres, une linéale pour le texte, un
     chasse-fixe pour tout ce qui est machine (statut, codes, latences). */
  --serif: ui-serif, Charter, "Iowan Old Style", Georgia, "Times New Roman", serif;
  --sans: ui-sans-serif, -apple-system, "SF Pro Text", "Segoe UI", Inter, Roboto, sans-serif;
  --mono: ui-monospace, "SF Mono", SFMono-Regular, Menlo, monospace;

  --wrap: 1080px;
  --pad: 32px;
}

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

/* L'attribut hidden doit gagner : toute règle d'auteur qui pose un display
   (ex. .side-close { display: grid }) écrase sinon le display:none du navigateur. */
[hidden] { display: none !important; }

html { color-scheme: dark; scroll-behavior: smooth; }

body {
  background: var(--bg);
  color: var(--text);
  font-family: var(--sans);
  font-size: 16px;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  overflow-x: hidden;
}

/* Une seule nappe, immobile : de la profondeur, pas un décor. */
body::before {
  content: "";
  position: fixed;
  inset: -30vh 0 auto 0;
  height: 80vh;
  z-index: -1;
  background: radial-gradient(60% 50% at 50% 0%, rgba(217, 154, 91, 0.07), transparent 70%);
  pointer-events: none;
}

::selection { background: rgba(217, 154, 91, 0.28); }

/* Un seul anneau de focus pour tout le document. */
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 4px;
}

.skip {
  position: absolute;
  left: -9999px;
  top: 8px;
  z-index: 100;
  padding: 10px 16px;
  background: var(--bg-lift);
  border: 1px solid var(--border-strong);
  border-radius: 8px;
  color: var(--text);
  text-decoration: none;
}
.skip:focus { left: 12px; }

/* ── En-tête ───────────────────────────────────────────────────────── */

.top {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 24px;
  flex-wrap: wrap;
  max-width: var(--wrap);
  width: 100%;
  margin: 0 auto;
  padding: 34px var(--pad) 0;
}

/* La marque : capitales, chasse ouvert, VALEZ appuyé et CONSULTING léger — sans
   ce contraste, quinze capitales d'affilée deviennent illisibles.

   Le HTML reste en minuscules : c'est le CSS qui capitalise, les lecteurs
   d'écran prononcent donc le nom au lieu de l'épeler.

   .brand ne porte PAS de taille — c'est ce qui lui permet d'apparaître au fil
   d'un paragraphe sans le faire exploser. La taille appartient à l'endroit où la
   marque est posée. */
.brand {
  font-family: var(--sans);
  font-weight: 700;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--text);
  text-decoration: none;
  white-space: nowrap;
}
.brand .thin { font-weight: 300; color: var(--muted); }

.top .brand {
  font-size: clamp(1.25rem, 2.6vw, 1.7rem);
  line-height: 1;
}
/* Au fil du texte, deux corrections optiques. Une capitale occupe toute la
   hauteur d'ascendante là où le texte autour ne remplit que sa hauteur d'œil :
   à corps égal, le mot ressort donc sans être plus gros. D'où 0.9em (en em, pour
   qu'il suive le corps de la phrase), et un cran de chasse en moins — 0.15em y
   deviendrait de la dentelle. */
.zone-lede .brand,
.foot .brand {
  font-size: 0.9em;
  letter-spacing: 0.1em;
}
/* Il termine la marque ET le titre : c'est ce qui les relie. */
.brand-dot { color: var(--accent); }

.top-nav {
  display: flex;
  gap: 26px;
  font-size: 0.88rem;
}
.top-nav a {
  color: var(--faint);
  text-decoration: none;
  transition: color 0.18s ease;
}
.top-nav a:hover { color: var(--text); }

/* ── Corps ─────────────────────────────────────────────────────────── */

main {
  max-width: var(--wrap);
  width: 100%;
  margin: 0 auto;
  padding: 0 var(--pad);
  flex: 1;
}

/* Le titre suit la marque de près, sur la même marge : l'œil descend de l'une à
   l'autre comme sur une seule phrase. Ne rien intercaler.
   Plus de max-width sur la section : les domaines occupent toute la colonne. */
.hero { padding: 64px 0 72px; }
.hero h1 {
  font-family: var(--serif);
  font-weight: 500;
  font-size: clamp(2.4rem, 6.4vw, 4.1rem);
  line-height: 1.08;
  letter-spacing: -0.02em;
}
/* Ce qu'on sait faire, en une ligne — pas en quatre paragraphes. */
.skills {
  margin-top: 28px;
  font-family: var(--mono);
  font-size: 0.72rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--faint);
}

/* Les domaines : la substance de l'expertise, en trois colonnes serrées. Le
   gabarit doit tenir dans un écran AVEC le titre d'acte qui suit — c'est la
   contrainte qui borne la longueur des textes, pas une préférence. Étiquettes
   en chasse-fixe cuivré (l'écho du tiret des titres de section), textes en
   voix baissée. Une liste, pas des titres : ce sont des facettes du h1, elles
   n'ont pas à peser dans le plan du document. */
.domains {
  list-style: none;
  margin-top: 46px;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(260px, 100%), 1fr));
  gap: 30px 44px;
}
.domain-name {
  display: block;
  font-family: var(--mono);
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 9px;
}
.domain p {
  color: var(--muted);
  font-size: 0.93rem;
  line-height: 1.6;
  max-width: 38ch;
}

/* Le second acte de la page. Même voix que le titre du hero — empattement,
   point cuivré — un cran en dessous : l'écho suffit, la redite lasserait. */
.part-title {
  font-family: var(--serif);
  font-weight: 500;
  font-size: clamp(1.5rem, 3.4vw, 2.1rem);
  line-height: 1.15;
  letter-spacing: -0.015em;
}
/* Le titre d'acte porte déjà la césure : ce qui le suit se rapproche. */
.part-title + .board { margin-top: 34px; }

/* ── Sections ──────────────────────────────────────────────────────── */

/* Pas de border-top sur la zone : elle ferait doublon avec le filet du titre.
   C'est donc au titre de porter seul la césure — d'où un filet affirmé. */
.zone {
  padding: 54px 0;
  scroll-margin-top: 24px;
}
.zone-title {
  display: flex;
  align-items: center;
  gap: 14px;
  font-family: var(--mono);
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.26em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 30px;
}
.zone-title::before {
  content: "";
  flex: none;
  width: 22px;
  height: 2px;
  background: var(--accent);
}
.zone-title::after {
  content: "";
  flex: 1;
  height: 1px;
  background: linear-gradient(90deg, var(--border-strong), transparent 85%);
}
.zone-lede {
  max-width: 44rem;
  color: var(--muted);
  margin-top: -14px;   /* le zone-title a déjà sa marge basse */
  margin-bottom: 14px;
}
/* La pile, en toutes lettres. */
.stack {
  font-family: var(--mono);
  font-size: 0.72rem;
  letter-spacing: 0.12em;
  color: var(--faint);
  margin-bottom: 34px;
}

/* ── Le terrain : les familles de services ─────────────────────────── */

/* Chaque famille de services est une section de plein rang, avec le même titre
   que Contact : filet cuivré, chasse ouvert. Elles ne sont plus les
   sous-chapitres d'une « Supervision » qui les engloberait — la supervision est
   l'une d'elles, à côté des projets et (une fois la session ouverte) de la
   médiathèque. */
.board-group {
  padding: 46px 0 0;
  scroll-margin-top: 24px;
}
.board-group:first-child { padding-top: 0; }
.board-grid {
  list-style: none;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(232px, 100%), 1fr));
  gap: 10px;
}

/* Filet fin, fond à peine détaché, aucun relief. Sur la vitrine, la tuile n'est
   PAS cliquable : ni lien, ni curseur, ni survol. Dans le portail, elle le
   devient avec .open (portail.css). */
.tile {
  position: relative;
  display: flex;
  align-items: center;
  gap: 13px;
  padding: 14px 16px;
  border: 1px solid var(--border);
  border-radius: 12px;
  background: var(--panel);
  transition: border-color 0.2s ease, background 0.2s ease;
}
.tile .icon {
  flex: none;
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border-radius: 9px;
  border: 1px solid var(--border);
  color: var(--muted);
}
.tile .icon svg { width: 18px; height: 18px; }
.tile .body { min-width: 0; }

/* Ce que le service FAIT passe devant ; le nom de l'outil derrière, en chasse
   fixe — une référence technique, pas une marque. Le DOM garde .name pour le nom
   de l'outil : c'est lui que la sidebar reprend, et là il redevient la bonne
   étiquette. Ne pas inverser les classes. */
.tile .desc {
  display: block;
  font-weight: 600;
  font-size: 0.92rem;
  line-height: 1.4;
  letter-spacing: -0.005em;
  color: var(--text);
}
.tile .name {
  display: block;
  margin-top: 2px;
  font-family: var(--mono);
  font-size: 0.74rem;
  letter-spacing: 0.04em;
  color: var(--faint);
}

/* ── Les projets : une ligne chacun ────────────────────────────────────
   Une application a un nom, une nature, une pile — et plusieurs environnements.
   D'où une ligne pleine largeur et autant de pastilles que d'environnements,
   chacune étant un service à part entière. */
.board-rows { grid-template-columns: 1fr; }

.project-row {
  display: flex;
  align-items: center;
  gap: 16px;
  flex-wrap: wrap;
  padding: 16px 18px;
  border: 1px solid var(--border);
  border-radius: 12px;
  background: var(--panel);
}
.project-row .icon {
  flex: none;
  display: grid;
  place-items: center;
  width: 38px;
  height: 38px;
  border-radius: 10px;
  border: 1px solid var(--border);
  color: var(--accent);
}
.project-row .icon svg { width: 20px; height: 20px; }
/* La ligne projet porte du TEXTE, pas une étiquette : le corps prend la largeur
   qu'il faut, et les pastilles s'alignent en haut plutôt qu'au centre — sur trois
   lignes de description, un centrage vertical les ferait flotter au milieu de nulle
   part. Le reste de la rangée reste centré (.project-row { align-items: center }),
   ce sont les pastilles seules qui remontent. */
.project-body {
  flex: 1 1 22rem;
  min-width: 0;
}
.project-name {
  display: block;
  font-weight: 600;
  font-size: 1rem;
  letter-spacing: -0.005em;
}
.project-desc {
  display: block;
  margin-top: 2px;
  /* Une mesure, pas une bannière : au-delà de ~62 caractères, l'œil ne retrouve
     plus le début de la ligne suivante. */
  max-width: 62ch;
  font-size: 0.86rem;
  line-height: 1.5;
  color: var(--muted);
}
.project-desc i {
  font-style: italic;
  color: var(--text);
}
.project-stack {
  display: block;
  margin-top: 7px;
  font-family: var(--mono);
  font-size: 0.7rem;
  line-height: 1.5;
  letter-spacing: 0.03em;
  color: var(--faint);
}

.envs {
  display: flex;
  flex: none;
  align-self: flex-start;
  gap: 8px;
  flex-wrap: wrap;
}
/* Sous 420 px, le texte du projet passe forcément à la ligne. Plutôt que de
   laisser l'icône seule en haut et les environnements tomber en troisième
   rangée, on empile franchement : icône + nom, puis la description, puis les
   pastilles alignées à gauche. */
@media (max-width: 420px) {
  .project-row {
    display: grid;
    grid-template-columns: auto 1fr;
    gap: 10px 12px;
  }
  .project-row .icon { grid-row: 1; }
  .project-body { grid-column: 2; }
  .envs { grid-column: 1 / -1; }
}
/* Une pastille d'environnement porte data-service : donc son propre point de
   statut, et son propre lien une fois la session ouverte. */
.env {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 6px 12px;
  border: 1px solid var(--border);
  border-radius: 999px;
  font-size: 0.78rem;
  color: var(--muted);
  transition: border-color 0.2s ease, background 0.2s ease, color 0.2s ease;
}
.env .dot { position: static; flex: none; }

.board-note {
  display: flex;
  align-items: center;
  gap: 9px;
  flex-wrap: wrap;
  margin-top: 26px;
  font-family: var(--mono);
  font-size: 0.74rem;
  color: var(--faint);
}
.board-sep { opacity: 0.5; }

/* ── Pastilles de statut ───────────────────────────────────────────── */

.dot {
  position: absolute;
  top: 12px;
  right: 12px;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--unknown);
  transition: background 0.3s ease;
}
.board-note .dot,
.live-pill .dot { position: static; flex: none; }
.dot.up   { background: var(--ok); }
.dot.down { background: var(--down); box-shadow: 0 0 8px rgba(229, 112, 107, 0.55); }

.live-pill {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  font-family: var(--mono);
  font-size: 0.72rem;
  color: var(--muted);
  border: 1px solid var(--border);
  background: var(--panel);
  padding: 5px 11px;
  border-radius: 999px;
}

/* ── Contact ───────────────────────────────────────────────────────── */

.contact-lede {
  font-family: var(--serif);
  font-size: 1.45rem;
  line-height: 1.42;
  max-width: 34ch;
  margin-bottom: 28px;
}
.contact-links { display: flex; gap: 12px; flex-wrap: wrap; }

/* ── Boutons ───────────────────────────────────────────────────────── */

.btn {
  display: inline-block;
  padding: 11px 20px;
  border: 1px solid var(--border-strong);
  border-radius: 10px;
  background: var(--panel-hover);
  color: var(--text);
  font: inherit;
  font-size: 0.92rem;
  text-decoration: none;
  cursor: pointer;
  transition: background 0.18s ease, border-color 0.18s ease;
}
.btn:hover { background: rgba(255, 255, 255, 0.1); border-color: var(--accent); }
.btn.ghost { background: none; color: var(--muted); border-color: var(--border); }
.btn.ghost:hover { color: var(--text); }

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

.foot {
  max-width: var(--wrap);
  width: 100%;
  margin: 40px auto 0;
  padding: 22px var(--pad) 34px;
  border-top: 1px solid var(--border);
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  font-family: var(--mono);
  font-size: 0.72rem;
  color: var(--faint);
}
.foot-sep { opacity: 0.5; }

/* Texte pour lecteurs d'écran uniquement (état des services) */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

@media (max-width: 560px) {
  :root { --pad: 20px; }
  .hero { padding: 70px 0 56px; }
  .top-nav { gap: 18px; }
}

/* ── Impression ────────────────────────────────────────────────────────
   La feuille n'existe qu'en sombre : imprimée telle quelle, la page sort en
   texte presque blanc sur papier blanc. On inverse le strict nécessaire et on
   retire ce qui n'a pas de sens sur papier (le lien d'évitement, la
   navigation, la nappe de fond). */
@media print {
  html { color-scheme: light; }
  body { background: #fff; color: #111; }
  body::before { display: none; }
  .skip, .top-nav { display: none !important; }
  .brand, .hero h1, .part-title, .project-name, .tile .desc { color: #111; }
  .brand .thin, .lede, .zone-lede, .project-desc { color: #444; }
  .skills, .stack, .zone-title, .tile .name,
  .project-stack, .board-note, .foot { color: #555; }
  .tile, .project-row, .env { border-color: #bbb; background: none; }
  .brand-dot, .zone-title::before { color: #111; background: #111; }
  a { color: inherit; text-decoration: underline; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation: none !important;
    transition: none !important;
  }
  html { scroll-behavior: auto; }
}
