/* components.css — boot, cursor, hero, work, build, homelab, stack, contact, exit */

/* ============ BOOT ============ */
.boot { display: none; }
.js .boot {
  position: fixed;
  inset: 0;
  z-index: var(--z-boot);
  display: flex;
  align-items: center;
  justify-content: center;
  background: #0b0b0b;
  color: var(--dark-fg);
}
.boot__box { min-width: min(420px, 80vw); }
.boot__line { color: var(--dark-muted); }
.boot__line:first-child { color: var(--dark-fg); }
.boot__gap { line-height: 1; }
.boot__pct { color: var(--dark-fg); margin-top: 1em; }
.boot__ready {
  color: var(--accent);
  opacity: 0;
  transform: scaleX(1);
}
.boot__wipe {
  position: absolute;
  inset: 0;
  background: var(--bg);
  transform: scaleY(0);
  transform-origin: center bottom;
}

/* ============ CURSOR ============ */
.cursor { display: none; }
.js .cursor.is-on { display: block; }
.cursor {
  position: fixed;
  inset: 0;
  z-index: var(--z-cursor);
  pointer-events: none;
}
.cursor__dot {
  position: absolute;
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--accent);
  transform: translate(-50%, -50%);
}
.cursor__ring {
  position: absolute;
  width: 36px; height: 36px;
  border: 1px solid var(--fg);
  border-radius: 50%;
  transform: translate(-50%, -50%);
  display: flex;
  align-items: center;
  justify-content: center;
}
.cursor__label {
  position: absolute;
  top: calc(100% + 8px);
  left: 50%;
  transform: translateX(-50%);
  font-size: .5625rem;
  white-space: nowrap;
  color: var(--fg);
  opacity: 0;
}
.cursor.has-label .cursor__label { opacity: 1; }
.cursor.has-label .cursor__ring { width: 52px; height: 52px; }
/* capitoli scuri (homelab / exit): ring e label in chiaro, come il chrome */
.cursor__ring,
.cursor__label {
  transition: border-color .4s var(--ease-out-quart), color .4s var(--ease-out-quart),
    opacity .25s, width .3s var(--ease-out-quart), height .3s var(--ease-out-quart);
}
body.on-dark .cursor__ring { border-color: var(--dark-fg); }
body.on-dark .cursor__label { color: var(--dark-fg); }

/* ============ HERO ============ */
.chapter--hello .chapter__inner {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  row-gap: var(--space-sm);
}
.hero-top {
  display: flex;
  justify-content: space-between;
  color: var(--muted);
}
.hero-lead {
  position: relative;
  z-index: 2;
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: end;
  gap: var(--space-md);
}
.hero-title {
  font-size: clamp(3.8rem, 11.5vw, 10.5rem);
  font-weight: 500;
  line-height: .82;
  letter-spacing: -.065em;
  text-transform: uppercase;
  user-select: none;
}
.hero-title__line { display: block; overflow: hidden; }
.hero-title__line--indent { margin-left: .9em; }
.hero-title__word {
  display: inline-block;
  will-change: transform;
  /* alone del colore del bg: invisibile sulla carta, separa il testo dalla λ scura */
  text-shadow: 0 0 2px rgba(232, 230, 223, .75), 0 0 14px rgba(232, 230, 223, .35);
}
/* lockup del nome: a destra del titolo grande, allineato alla baseline;
   la λ 3D piccola vive nel canvas fixed dietro questo blocco */
.hero-name {
  text-align: right;
  font-size: clamp(1.4rem, 3.4vw, 2.8rem);
  font-weight: 500;
  line-height: .95;
  letter-spacing: -.03em;
  text-transform: uppercase;
  user-select: none;
  text-shadow: 0 0 2px rgba(232, 230, 223, .75), 0 0 14px rgba(232, 230, 223, .35);
}
.hero-name span { display: block; }
.hero-statement {
  grid-column: 1;
  max-width: 46ch;
  margin-top: 1.3em;
  font-size: clamp(1.05rem, 1.8vw, 1.5rem);
  font-weight: 500;
  letter-spacing: -.015em;
  line-height: 1.35;
  text-wrap: balance;
  text-shadow: 0 0 2px rgba(232, 230, 223, .75), 0 0 14px rgba(232, 230, 223, .35);
}
/* "system properties": i fatti chiave di chi sono, in righe mono */
.hero-meta {
  position: relative;
  z-index: 2;
  display: grid;
  gap: .75em;
  max-width: 54rem;
  font-size: .75rem;
  text-shadow: 0 0 2px rgba(232, 230, 223, .75), 0 0 14px rgba(232, 230, 223, .35);
}
.hero-meta > div {
  display: flex;
  justify-content: space-between;
  gap: var(--space-md);
  border-bottom: 1px solid var(--line);
  padding-bottom: .55em;
}
.hero-meta dt { color: var(--muted); }
.hero-meta dd { text-align: right; }
.hero-meta .status-dot { margin-right: .45em; }
.hero-bottom {
  position: relative;
  z-index: 2;
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--space-md);
}
.hero-bottom__meta { color: var(--muted); }
.scroll-cue {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: .8em;
  color: var(--muted);
}
.scroll-cue__line {
  display: block;
  width: 1px; height: 42px;
  background: var(--fg);
  transform-origin: top center;
  animation: cue-grow 2.6s var(--ease-in-out) infinite;
}

/* ============ WORK ============ */
.work-head { padding-top: 7svh; }
.work-list {
  list-style: none;
  margin-top: 3svh;
  border-top: 1px solid var(--line);
}
.work-row {
  display: grid;
  grid-template-columns: 3.5rem 1fr auto 2.5rem;
  align-items: center;
  gap: var(--space-md);
  width: 100%;
  min-height: 19svh;
  padding: var(--space-sm) 0;
  border-bottom: 1px solid var(--line);
  text-align: left;
  transition: transform .5s var(--ease-out-expo);
  transform-origin: left center;
}
.work-row__index { color: var(--muted); }
.work-row__name {
  font-size: clamp(1.8rem, 4.6vw, 4.2rem);
  font-weight: 500;
  letter-spacing: -.045em;
  line-height: 1;
  text-transform: uppercase;
  transition: transform .6s var(--ease-out-expo);
}
.work-row__tag {
  display: inline-block;
  font-size: .625rem;
  letter-spacing: .08em;
  color: var(--muted);
  vertical-align: super;
}
.work-row__meta {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: .4em;
  color: var(--muted);
}
.work-row__status { font-size: .5625rem; }
.work-row__status--active { color: var(--accent); }
.work-row__arrow {
  font-size: 1.6rem;
  justify-self: end;
  color: var(--muted);
  transition: transform .5s var(--ease-out-expo), color .3s;
}
@media (hover: hover) {
  .work-row:hover { transform: scaleY(.96); }
  .work-row:hover .work-row__name { transform: translateX(2vw); }
  .work-row:hover .work-row__arrow { transform: translate(4px, -4px); color: var(--accent); }
}

/* floating preview */
.work-preview {
  position: fixed;
  top: 0; left: 0;
  z-index: 30;
  pointer-events: none;
  opacity: 0;
}
.work-preview__card {
  position: relative;
  width: 320px;
  height: 220px;
  background: var(--dark);
  color: var(--dark-fg);
  border: 1px solid var(--dark-line);
  padding: 18px;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  gap: .4em;
  overflow: hidden;
  will-change: transform;
}
.work-preview__id { color: var(--accent); }
.work-preview__name {
  font-size: 1.4rem;
  font-weight: 500;
  letter-spacing: -.03em;
  line-height: 1;
}
.work-preview__tech { color: var(--dark-muted); }
.work-preview__scan {
  position: absolute;
  inset: 0;
  background: repeating-linear-gradient(0deg, transparent 0 3px, rgba(232,230,223,.04) 3px 4px);
}

/* readout della sequenza deck: nascosto di default (lista normale),
   appare solo in deck mode */
.work-deck { display: none; }

/* --- deck cinematica: i progetti si avvicendano in uno stage unico mentre
   il chapter resta pinnato (hold 220svh, scrub in js/animations.js).
   Stesse condizioni del matchMedia in workDeck(): fuori da qui — no-JS,
   no-gsap, reduced-motion, touch, viewport stretto — resta la lista
   verticale di link, invariata. */
@media (hover: hover) and (pointer: fine) and (min-width: 961px) {
  .js.gsap .chapter--work { --chapter-hold: 220svh; }
  .js.gsap .chapter--work .chapter__inner { display: flex; flex-direction: column; }
  .js.gsap .work-list {
    flex: 1;
    min-height: 0;
    position: relative;
    margin-top: 2svh;
    border-top: 0;
  }
  .js.gsap .work-list > li { position: absolute; inset: 0; }
  /* pre-scrub: in primo piano solo la prima card (le altre le rivela gsap) */
  .js.gsap .work-list > li + li .work-row { opacity: 0; }
  .js.gsap .work-row {
    position: relative;
    height: 100%;
    min-height: 0;
    grid-template-columns: 4.5rem 1fr auto 3rem;
    align-content: center;
    /* lo scrub pilota transform/opacity inline: niente transizioni CSS */
    transition: none;
    pointer-events: none;
  }
  .js.gsap .work-row.is-front { pointer-events: auto; }
  .js.gsap .work-row__name { font-size: clamp(2.2rem, 6vw, 5.4rem); }
  /* tagline e tech vivono negli attributi data-* (aggiornati da app.js):
     resi visibili in deck mode senza markup aggiuntivo */
  .js.gsap .work-row::before,
  .js.gsap .work-row::after { position: absolute; bottom: var(--space-md); }
  .js.gsap .work-row::before {
    content: attr(data-tagline);
    left: calc(4.5rem + var(--space-md));
    max-width: 44ch;
    font-size: .95rem;
    line-height: 1.55;
    letter-spacing: 0;
    text-transform: none;
    color: var(--muted);
  }
  .js.gsap .work-row::after {
    content: attr(data-tech);
    right: 0;
    font-family: var(--font-mono);
    font-size: .75rem;
    letter-spacing: .1em;
    color: var(--muted);
  }
  .js.gsap .work-deck {
    display: flex;
    justify-content: center;
    gap: .5em;
    padding-top: var(--space-sm);
    color: var(--muted);
    letter-spacing: .14em;
  }
  .js.gsap .work-deck__cur { color: var(--accent); }
}

/* ============ BUILD ============ */
.build-head { padding-top: 7svh; }
.build-cards {
  margin-top: 4svh;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-md);
  perspective: 1200px;
}
.build-card {
  position: relative;
  border: 1px solid var(--line);
  background: var(--bg);
  padding: var(--space-md);
  min-height: 38svh;
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
  transform-style: preserve-3d;
  transition: transform .6s var(--ease-out-expo);
}
.build-card__num { color: var(--muted); }
.build-card__title {
  font-size: clamp(1.6rem, 2.6vw, 2.4rem);
  font-weight: 500;
  letter-spacing: -.04em;
}
.build-card__desc { color: var(--fg); max-width: 32ch; font-size: .95rem; }
.build-card__list { margin-top: auto; color: var(--muted); line-height: 1.9; }
.build-card__cross {
  position: absolute;
  top: var(--space-md); right: var(--space-md);
  color: var(--muted);
  font-family: var(--font-mono);
}

/* marquee */
.marquee {
  position: absolute;
  left: 0; right: 0;
  bottom: calc(var(--page-padding) * .9);
  overflow: hidden;
  opacity: .5;
}
.marquee__track {
  display: flex;
  white-space: nowrap;
  width: max-content;
  will-change: transform;
}
.marquee__track .mono { font-size: .75rem; letter-spacing: .2em; }

/* ============ HOMELAB ============ */
/* chapter full-bleed scuro e OPACO: per tutta la durata del percorso
   interno (e durante le transizioni) la card precedente non deve mai
   trasparire — né dai bordi, né quando lo stage scala in uscita */
.chapter--homelab {
  height: auto;
  background: var(--dark);
  /* banda scura sotto il chapter: copre il card-gap trasparente in cima a
     CONTACT durante la transizione (dietro c'è la card STACK pinnata) */
  box-shadow: 0 var(--card-gap) 0 0 var(--dark);
}
.homelab-track { height: 420svh; position: relative; }
.homelab-stage {
  position: sticky;
  top: 0;
  height: 100svh;
  overflow: hidden;
  margin: var(--card-gap);
  margin-top: 0;
  border: 1px solid var(--dark-line);
  background: var(--dark);
  color: var(--dark-fg);
}
.homelab-track { margin: 0 var(--card-gap); }
.homelab-stage { margin: 0; }
#homelab-canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  touch-action: pan-y;
}
.homelab-labels {
  position: absolute;
  inset: 0;
  pointer-events: none;
  overflow: hidden;
}
.hl-label {
  position: absolute;
  transform: translate(-50%, -100%);
  text-align: center;
  color: var(--dark-fg);
  font-size: .625rem;
  transition: opacity .3s;
  will-change: transform;
}
.hl-label small {
  display: block;
  color: var(--dark-muted);
  font-size: .5625rem;
}
.homelab-ui { position: absolute; inset: 0; pointer-events: none; }
.homelab-ui .hl-btn, .homelab-ui .corner { pointer-events: auto; }
.homelab-head {
  position: absolute;
  top: 9svh;
  left: var(--page-padding);
  max-width: 40rem;
}
.homelab-step {
  font-size: clamp(2.2rem, 6vw, 5rem);
  font-weight: 500;
  line-height: .9;
  letter-spacing: -.05em;
  text-transform: uppercase;
  display: flex;
  flex-direction: column;
  gap: .3em;
}
.homelab-step__idx { color: var(--dark-muted); letter-spacing: .12em; }
.homelab-sub { margin-top: 1em; color: var(--dark-muted); }
.homelab-actions {
  position: absolute;
  right: var(--page-padding);
  top: 9svh;
  display: flex;
  flex-direction: column;
  gap: 1em;
  align-items: flex-end;
}
.hl-btn {
  color: var(--dark-fg);
  letter-spacing: .12em;
  padding: .4em 0;
  transition: color .3s;
}
.hl-btn:hover, .hl-btn.is-on { color: var(--accent); }
.homelab-hint {
  position: absolute;
  bottom: calc(var(--page-padding) * .9);
  left: 50%;
  transform: translateX(-50%);
  color: var(--dark-muted);
  letter-spacing: .12em;
}

/* scheda nodo */
.node-card {
  position: absolute;
  right: var(--page-padding);
  bottom: calc(var(--page-padding) * 1.2);
  z-index: 5;
  width: min(340px, calc(100vw - 2 * var(--page-padding)));
  background: var(--dark-2);
  border: 1px solid var(--dark-line);
  padding: var(--space-md);
  color: var(--dark-fg);
}
.node-card__close {
  position: absolute;
  top: .6rem; right: .8rem;
  font-size: 1rem;
  color: var(--dark-muted);
}
.node-card__close:hover { color: var(--accent); }
.node-card__kind { color: var(--accent); }
.node-card__name {
  font-size: 1.8rem;
  font-weight: 500;
  letter-spacing: -.03em;
  margin: .2em 0 .8em;
  text-transform: uppercase;
}
.node-card__meta { display: grid; gap: .7em; color: var(--dark-muted); }
.node-card__meta div {
  display: flex;
  justify-content: space-between;
  border-bottom: 1px solid var(--dark-line);
  padding-bottom: .5em;
}
.node-card__meta dd { color: var(--dark-fg); text-align: right; }
.node-card__desc { margin-top: 1em; font-size: .85rem; color: var(--dark-muted); }

/* manifesto testuale */
.homelab-manifest {
  position: absolute;
  left: var(--page-padding);
  bottom: calc(var(--page-padding) * 1.2);
  z-index: 5;
  width: min(430px, calc(100vw - 2 * var(--page-padding)));
  max-height: 55svh;
  overflow: auto;
  background: var(--dark-2);
  border: 1px solid var(--dark-line);
  padding: var(--space-md);
  color: var(--dark-muted);
  display: none;
}
.homelab-manifest.is-open { display: block; }
.homelab-manifest__title { color: var(--dark-fg); margin-bottom: 1em; }
.homelab-manifest ul { list-style: none; }
.homelab-manifest > ul > li { margin-bottom: 1em; }
.homelab-manifest > ul > li > ul { margin: .4em 0 0 1em; display: grid; gap: .35em; }
.homelab-manifest strong { color: var(--dark-fg); font-weight: 400; }
.homelab-manifest .srv { color: var(--accent); }
.homelab-manifest__links { margin-top: 1em; border-top: 1px solid var(--dark-line); padding-top: 1em; }

/* senza JS / senza WebGL: manifesto sempre visibile, canvas spento */
html:not(.js) .homelab-track,
.no-webgl .homelab-track { height: auto; }
html:not(.js) .homelab-stage,
.no-webgl .homelab-stage { position: relative; height: auto; min-height: 100svh; }
html:not(.js) #homelab-canvas,
.no-webgl #homelab-canvas,
html:not(.js) .homelab-labels,
.no-webgl .homelab-labels { display: none; }
html:not(.js) .homelab-manifest,
.no-webgl .homelab-manifest {
  display: block;
  position: relative;
  left: auto; bottom: auto;
  margin: var(--space-lg) var(--page-padding);
  max-height: none;
}
html:not(.js) .homelab-hint,
.no-webgl .homelab-hint,
html:not(.js) .homelab-actions,
.no-webgl .homelab-actions { display: none; }

/* ============ STACK ============
   Pipeline SOURCE → RUNTIME → DEPLOY: hairline continua con un nodo per
   stage. Il nodo dello stage centrale è esattamente sotto la hairline che
   porta il wire dentro il chapter (::before su .chapter__inner, left 50%).
   Il pacchetto accento (js/stack.js) percorre la linea e accende uno stage
   alla volta; senza JS / reduced-motion / touch tutto resta statico. */
/* cue di continuità: il wire "entra" nel chapter — hairline statica che
   scende dal bordo superiore verso l'header (CSS puro, monocromo) */
.chapter--stack .chapter__inner::before,
.chapter--homelab .homelab-stage::before {
  content: "";
  position: absolute;
  top: 0;
  left: 50%;
  width: 1px;
  height: 8svh;
  background: var(--line);
  pointer-events: none;
}
.chapter--homelab .homelab-stage::before {
  z-index: 2;
  background: var(--dark-line);
}
.stack-head { padding-top: 7svh; }
.stack-list {
  position: relative;
  margin-top: 12svh;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-md);
}
/* la linea della pipeline */
.stack-list::before {
  content: "";
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 1px;
  background: var(--line);
}
.stack-list__col {
  position: relative;
  padding-top: var(--space-md);
  transition: opacity .45s var(--ease-out-quart);
}
/* nodo: quadratino centrato sulla linea, sopra lo stage */
.stack-list__col::before {
  content: "";
  position: absolute;
  top: -3.5px;
  left: 50%;
  width: 7px; height: 7px;
  transform: translateX(-50%);
  background: var(--fg);
  transition: background .3s;
}
.stack-stage__label {
  display: flex;
  gap: .5em;
  margin-bottom: .6em;
  letter-spacing: .14em;
  transition: color .3s;
}
.stack-stage__num { color: var(--muted); transition: color .3s; }
.stack-list__col h3 { color: var(--muted); margin-bottom: 1em; }
.stack-list__col ul { list-style: none; }
.stack-list__col li {
  padding: .35em 0;
  border-bottom: 1px solid var(--line);
  font-size: clamp(1.15rem, 2vw, 1.7rem);
  font-weight: 500;
  letter-spacing: -.02em;
  line-height: 1.25;
  text-transform: uppercase;
}
/* cycling (solo JS): uno stage attivo alla volta, gli altri attenuati;
   l'accento segna lo stage attivo (indicatore di stato) */
.stack-list.has-active .stack-list__col:not(.is-active) { opacity: .3; }
.stack-stage.is-active::before { background: var(--accent); }
.stack-stage.is-active .stack-stage__label,
.stack-stage.is-active .stack-stage__num { color: var(--accent); }
/* pacchetto accento sulla linea: resta nascosto finché JS non lo attiva
   (classe .is-on, come rail__packet) */
.stack-packet {
  display: none;
  position: absolute;
  top: -3.5px; left: 0;
  width: 7px; height: 7px;
  background: var(--accent);
  pointer-events: none;
}
.stack-packet.is-on { display: block; }

/* ============ CONTACT ============ */
.contact-head { padding-top: 9svh; }
/* chiusura narrativa: il "processo" del sito è finito, si torna alla shell.
   Monocromo; l'accento è solo sul simbolo del prompt. */
.contact-term {
  margin-top: 3svh;
  display: grid;
  gap: .4em;
  font-size: .8rem;
  color: var(--muted);
}
.contact-term .accent { color: var(--accent); }
.contact-term__line { display: block; }
.contact-term__caret {
  display: inline-block;
  width: .55ch;
  height: 1em;
  margin-left: .5ch;
  vertical-align: -.15em;
  background: currentColor;
  animation: caret-blink 1.1s steps(1) infinite;
}
.contact-mail {
  margin-top: 6svh;
  font-size: clamp(1.5rem, 4.2vw, 3.8rem);
  font-weight: 500;
  letter-spacing: -.04em;
}
.contact-mail a { display: inline-block; }
.contact-links {
  margin-top: var(--space-lg);
  list-style: none;
  display: grid;
  gap: 1.2em;
}
.contact-links__h { color: var(--muted); margin-left: 1em; }

/* ============ EXIT ============ */
.exit-center {
  position: absolute;
  inset: 0;
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-md);
  text-align: center;
}
.exit-lambda {
  font-size: clamp(6rem, 16vw, 14rem);
  font-weight: 500;
  line-height: .8;
  color: var(--dark-fg);
  user-select: none;
  transition: opacity .6s var(--ease-out-quart);
}
/* con WebGL attivo la λ dell'exit è formata dalle particelle del canvas */
body.webgl .exit-lambda { opacity: 0; }
.exit-line { color: var(--accent); letter-spacing: .3em; }
.exit-meta { color: var(--dark-muted); line-height: 2; }
.exit-top { color: var(--dark-fg); margin-top: var(--space-md); display: inline-block; }

/* ============ MENU ============ */
.menu {
  position: fixed;
  inset: 0;
  z-index: var(--z-menu);
  background: #0b0b0b;
  color: var(--dark-fg);
}
.menu__inner {
  height: 100%;
  padding: var(--page-padding);
  display: flex;
  flex-direction: column;
  justify-content: space-between;
}
.menu__kicker { color: var(--dark-muted); }
.menu__list { list-style: none; display: grid; }
.menu__list a {
  display: flex;
  align-items: baseline;
  gap: var(--space-md);
  padding: .35rem 0;
}
.menu__num {
  color: var(--dark-muted);
  transition: transform .4s var(--ease-out-expo), color .3s;
}
.menu__name {
  font-size: clamp(2rem, 6.5vh, 4.5rem);
  font-weight: 500;
  letter-spacing: -.05em;
  line-height: 1;
  transition: transform .4s var(--ease-out-expo), color .3s;
}
.menu__list a:hover .menu__num { transform: translateX(.5em); color: var(--accent); }
.menu__list a:hover .menu__name { transform: translateX(.3em); }
.menu__foot { color: var(--dark-muted); }

/* ============ TOAST ============ */
.toast {
  position: fixed;
  left: 50%;
  bottom: 12svh;
  transform: translateX(-50%);
  z-index: var(--z-menu);
  background: var(--dark);
  color: var(--dark-fg);
  border: 1px solid var(--dark-line);
  padding: 1em 1.4em;
  text-align: center;
  line-height: 1.9;
}
.toast .accent { color: var(--accent); }
