/* NODARIS — the public identity layer.
   Every value comes from tokens.css, which is generated from the frozen identity.
   No hex, no px size and no duration is typed by hand in this file.

   Two laws govern this stylesheet:
     1. NOTHING HERE IS EVIDENCE. The grid, the traces, the pulses and the instrument panel
        are geometry. They carry no number, no identifier and no measurement, so no visitor
        can read them as a claim about a real network.
     2. NOTHING HERE OUTRANKS THE TEXT. Every decorative layer sits behind the content, is
        excluded from the accessibility tree, and stops moving under prefers-reduced-motion. */

.pubblico {
  background: var(--color-bg-deep);
  min-height: 100%;
  /* the identity layer is fixed and full-bleed; the page itself must never slide sideways */
  overflow-x: clip;
}

/* ==================================================== the identity field (decorative) */
.campo-identita {
  position: fixed; inset: 0; z-index: 0; pointer-events: none;
  overflow: hidden;
}
/* the drafting field: a technical grid, not a texture */
.campo-griglia {
  position: absolute; inset: -10%;
  background-image:
    linear-gradient(to right, var(--color-bg-grid) var(--border-width-hairline), transparent 0),
    linear-gradient(to bottom, var(--color-bg-grid) var(--border-width-hairline), transparent 0);
  background-size: var(--space-12) var(--space-12), var(--space-12) var(--space-12);
  /* fades out downward so the grid frames the hero and then gets out of the way of reading */
  -webkit-mask-image: linear-gradient(to bottom, black 0%, transparent 92%);
  mask-image: linear-gradient(to bottom, black 0%, transparent 92%);
  animation: deriva var(--motion-ambient) linear infinite;
}
@keyframes deriva {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(calc(var(--space-12) * -1), calc(var(--space-12) * -1), 0); }
}
/* one restrained bloom, top right, behind the instrument */
.campo-bagliore {
  position: absolute; top: calc(var(--space-12) * -2); right: -10%;
  width: min(1100px, 92vw); height: min(1100px, 92vw);
  background: radial-gradient(circle at 50% 50%,
              var(--color-interaction-accent-trace) 0%, transparent 62%);
  opacity: var(--opacity-stale);
}
/* The traces live in the OUTER field. The mask keeps them off the reading column, because
   a decorative line crossing a sentence is a decorative line that has become a defect. */
.campo-tracce {
  position: absolute; inset: 0; width: 100%; height: 100%;
  -webkit-mask-image: linear-gradient(to right, transparent 0%, transparent 34%, black 64%, black 100%);
  mask-image: linear-gradient(to right, transparent 0%, transparent 34%, black 64%, black 100%);
}
.campo-tracce .tracce path {
  fill: none; stroke: var(--color-interaction-accent-trace);
  stroke-width: var(--stroke-link-access);
}
.campo-tracce .nodi rect {
  fill: none; stroke: var(--color-interaction-accent-trace);
  stroke-width: var(--stroke-group);
}
.campo-tracce .impulso circle {
  fill: var(--color-interaction-accent); opacity: var(--opacity-stale);
}

/* ================================================================== page frame */
.pub {
  position: relative; z-index: 1;
  max-width: 1180px; margin: 0 auto;
  padding: var(--space-6) var(--space-4) var(--space-12);
}
.pub .spazio { flex: 1; }
.pub header.top {
  display: flex; align-items: center; gap: var(--space-3);
  margin-bottom: var(--space-12);
  padding-bottom: var(--space-3);
  border-bottom: var(--border-width-hairline) solid var(--color-border-subtle);
  min-width: 0;
}
.pub .marchio {
  display: flex; align-items: center; gap: var(--space-2);
  color: var(--color-text-primary); text-decoration: none;
}
.pub .wordmark {
  font-weight: var(--font-weight-bold);
  letter-spacing: var(--font-tracking-wordmark); font-size: var(--font-size-lg);
}
.pub .indice {
  font-size: var(--font-size-micro); letter-spacing: var(--font-tracking-label);
  color: var(--color-text-muted); white-space: nowrap;
  padding-left: var(--space-3);
  border-left: var(--border-width-hairline) solid var(--color-border-default);
}

/* ======================================================================= hero */
.eroe {
  display: grid; grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr);
  gap: var(--space-8); align-items: center;
  margin-bottom: var(--space-12);
}
.eroe-testo { min-width: 0; }

/* THE PRODUCT CATEGORY. Not metadata: the machine identifying itself, revealed by a scan
   rather than faded in. Two lines, because the category has two halves and a professional
   should be able to read either one alone and still be told the truth. */
.categoria {
  margin: 0 0 var(--space-4);
  font-family: var(--font-family-mono);
  text-transform: uppercase; letter-spacing: var(--font-tracking-label);
  line-height: 1.25;
}
.categoria .cat-riga {
  display: block; position: relative;
  font-size: clamp(var(--font-size-md), 2.4vw, var(--font-size-xl));
  color: var(--color-interaction-accent);
  white-space: nowrap;
  /* the scan reveal: the line is uncovered left to right, never typed character by
     character — a fake terminal is exactly the kind of theatre the identity forbids */
  clip-path: inset(0 100% 0 0);
  animation: scansiona var(--motion-reveal) var(--motion-easing) forwards;
}
.categoria .cat-secondaria {
  color: var(--color-text-secondary);
  animation-delay: var(--motion-standard);
}
.categoria .cat-riga::before {
  content: ""; position: absolute; left: calc(var(--space-3) * -1); top: 0; bottom: 0;
  width: var(--border-width-emphasis);
  background: var(--color-interaction-accent-dim);
}
@keyframes scansiona {
  from { clip-path: inset(0 100% 0 0); }
  to   { clip-path: inset(0 0 0 0); }
}

.pub h1 {
  font-size: clamp(var(--font-size-xl), 5.4vw, var(--font-size-display));
  line-height: 1.1; max-width: 18ch; margin: 0 0 var(--space-4);
  letter-spacing: -0.01em;
}
.pub .sommario {
  font-size: var(--font-size-md); color: var(--color-text-secondary);
  max-width: 62ch; margin: 0 0 var(--space-6); line-height: 1.55;
}
.eroe-azioni { margin: 0; display: flex; gap: var(--space-3); flex-wrap: wrap; }

/* ------------------------------------------------- the decorative instrument */
.eroe-strumento { min-width: 0; display: flex; justify-content: center; }
.pannello {
  width: 100%; max-width: 420px;
  background: var(--color-bg-sunken);
  border: var(--border-width-hairline) solid var(--color-border-default);
  box-shadow: var(--elevation-glow);
  /* a lightweight parallax driven by the pointer; JS sets the two custom properties and
     nothing else, so the effect costs one transform and dies with reduced motion */
  transform: perspective(1200px)
             rotateX(calc(var(--inclina-y, 0) * 1deg))
             rotateY(calc(var(--inclina-x, 0) * 1deg));
  transition: transform var(--motion-large) var(--motion-easing);
}
.pannello-testa {
  display: flex; gap: var(--space-1); align-items: center;
  padding: var(--space-2) var(--space-3);
  border-bottom: var(--border-width-hairline) solid var(--color-border-default);
}
.pannello-testa .punto {
  width: var(--icon-size-sm); height: var(--border-width-emphasis);
  background: var(--color-border-strong);
}
.pannello-testa .punto:first-child { background: var(--color-interaction-accent-dim); }
.pannello-disegno { display: block; width: 100%; height: auto; }
.pannello-disegno .rete line {
  stroke: var(--color-topology-link-default); stroke-width: var(--stroke-link-access);
  opacity: var(--opacity-stale);
}
.pannello-disegno .scatole rect {
  fill: var(--color-topology-node-device); stroke: var(--color-topology-node-stroke);
  stroke-width: var(--stroke-group);
}
.pannello-disegno .scatole rect:first-child {
  stroke: var(--color-interaction-accent);
}
.pannello-disegno .scansione {
  stroke: var(--color-interaction-accent); stroke-width: var(--stroke-link-access);
  opacity: var(--opacity-grid);
  animation: scorri var(--motion-ambient) linear infinite;
}
@keyframes scorri {
  from { transform: translateY(0); }
  to   { transform: translateY(240px); }
}

/* ================================================================== sections */
.pub section { margin-top: var(--space-12); }
.pub h2 {
  font-size: var(--font-size-xl); margin-bottom: var(--space-3);
  display: flex; align-items: baseline; gap: var(--space-3);
}
.pub h2::before {
  content: ""; width: var(--space-4); height: var(--border-width-emphasis);
  background: var(--color-interaction-accent); flex: 0 0 auto;
}
.pub h3 { font-size: var(--font-size-base); margin-bottom: var(--space-1); }

.prove {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  gap: var(--border-width-hairline); background: var(--color-border-subtle);
  border: var(--border-width-hairline) solid var(--color-border-default);
}
.prove div {
  background: var(--color-bg-raised); padding: var(--space-4) var(--space-3);
  transition: background var(--motion-standard) var(--motion-easing);
}
.prove div:hover { background: var(--color-bg-overlay); }
.prove .n {
  font-family: var(--font-family-mono); font-size: var(--font-size-xl);
  display: block; color: var(--color-text-primary);
}
.prove .k {
  font-size: var(--font-size-micro); text-transform: uppercase;
  letter-spacing: var(--font-tracking-label); color: var(--color-text-muted);
}

.catena {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: var(--space-3);
}
.catena div {
  border-left: var(--border-width-emphasis) solid var(--color-interaction-accent-dim);
  padding-left: var(--space-3);
  transition: border-color var(--motion-standard) var(--motion-easing);
}
.catena div:hover { border-left-color: var(--color-interaction-accent); }
.catena .passo-n {
  display: block; font-size: var(--font-size-micro);
  letter-spacing: var(--font-tracking-label); color: var(--color-text-muted);
}
.catena p { color: var(--color-text-muted); font-size: var(--font-size-xs); margin: 0; }

.limite {
  border: var(--border-width-hairline) solid var(--color-border-strong);
  border-left-width: var(--border-width-emphasis);
  border-left-color: var(--color-status-warning);
  padding: var(--space-4);
  background: var(--color-bg-raised);
}

.cornice {
  border: var(--border-width-hairline) solid var(--color-border-default);
  background: var(--color-bg-sunken);
}
.cornice .barra-finta {
  display: flex; gap: var(--space-2); padding: var(--space-2) var(--space-3);
  border-bottom: var(--border-width-hairline) solid var(--color-border-default);
  font-family: var(--font-family-mono); font-size: var(--font-size-micro);
  color: var(--color-text-muted);
}
.cornice img { display: block; width: 100%; height: auto; }

.pub footer {
  position: relative; z-index: 1;
  margin-top: var(--space-12); padding-top: var(--space-4);
  border-top: var(--border-width-hairline) solid var(--color-border-subtle);
  color: var(--color-text-muted); font-size: var(--font-size-xs);
  display: flex; gap: var(--space-4); flex-wrap: wrap;
}

/* ============================================================ public controls */
.pub .btn {
  height: auto; min-height: var(--density-control-height);
  padding: var(--space-2) var(--space-4);
  text-decoration: none;
}
.pub .btn.grande {
  min-height: var(--density-row-standard);
  padding: var(--space-3) var(--space-6);
  font-size: var(--font-size-md); font-weight: var(--font-weight-medium);
}
.pub .btn.primario {
  background: var(--color-interaction-accent); color: var(--color-text-inverse);
  border-color: var(--color-interaction-accent); font-weight: var(--font-weight-medium);
  box-shadow: var(--elevation-glow);
  transition: background var(--motion-micro) var(--motion-easing),
              box-shadow var(--motion-micro) var(--motion-easing),
              transform var(--motion-micro) var(--motion-easing);
}
.pub .btn.primario:hover { background: var(--color-interaction-link); }
.pub .btn.primario:active { transform: translateY(var(--border-width-hairline)); }
.pub .btn:not(.primario) {
  border-color: var(--color-border-strong); background: var(--color-bg-raised);
  transition: border-color var(--motion-micro) var(--motion-easing),
              background var(--motion-micro) var(--motion-easing);
}
.pub .btn:not(.primario):hover {
  border-color: var(--color-interaction-accent-dim);
  background: var(--color-bg-overlay);
}

/* Touch targets follow the INPUT METHOD, not the width: a tablet in landscape is 1024px
   wide and still driven with a thumb. The public controls are primary by definition. */
@media (max-width: 1100px), (pointer: coarse) {
  .pub .btn { min-height: var(--density-row-standard); }
}

/* ================================================================ section reveal */
/* Sections arrive rather than appear. The class is added by IntersectionObserver, so a
   section that never scrolls into view is never hidden from a reader who cannot scroll. */
.rivela.da-rivelare { opacity: 0; transform: translateY(var(--space-4)); }
.rivela.rivelata {
  opacity: 1; transform: none;
  transition: opacity var(--motion-reveal) var(--motion-easing),
              transform var(--motion-reveal) var(--motion-easing);
}

/* Print and forced-colours never scroll: the hidden state must not survive into them. */
@media print, (forced-colors: active) {
  .rivela.da-rivelare { opacity: 1; transform: none; }
  .campo-identita { display: none; }
}

/* ==================================================================== responsive */
@media (max-width: 900px) {
  .eroe { grid-template-columns: 1fr; gap: var(--space-6); }
  /* the instrument is decoration: on a phone the text takes the whole first viewport */
  .eroe-strumento { display: none; }
  .pub { padding: var(--space-4) var(--space-3) var(--space-8); }
  .pub header.top { margin-bottom: var(--space-8); }
  .pub .indice { display: none; }
  .pub section { margin-top: var(--space-8); }
  .categoria .cat-riga { white-space: normal; }
  /* the field keeps the grid and the bloom; the traces go, because at this width there is
     no outer field left for them to live in */
  .campo-tracce { display: none; }
}
@media (max-width: 420px) {
  .pub .btn.grande { width: 100%; justify-content: center; }
}

/* ================================================================ reduced motion */
/* Not merely faster: the ambient field and the pulses STOP, and every reveal starts done. */
@media (prefers-reduced-motion: reduce) {
  .campo-griglia, .pannello-disegno .scansione { animation: none; }
  .campo-tracce .impulso { display: none; }
  .categoria .cat-riga { animation: none; clip-path: none; }
  .pannello { transform: none; transition: none; }
  .rivela.da-rivelare { opacity: 1; transform: none; }
}

/* ---- V2: the public face carries the same mark and the same plane -------
   The entry surface is where "this is NODARIS" has to land in one glance, and
   it must do it without becoming a splash screen that delays work. */
.top .marchio-svg .nm-nodo { transition: filter var(--motion-standard) var(--motion-easing); }
.top .marchio:hover .nm-nodo { filter: drop-shadow(var(--elevation-glow)); }
.eroe { position: relative; }
.eroe::before {
  content: ""; position: absolute; inset: 0; pointer-events: none; z-index: 0;
  background-image:
    radial-gradient(ellipse at 50% 40%, transparent 0%, var(--color-bg-base) 68%),
    linear-gradient(var(--color-bg-grid) var(--border-width-hairline), transparent 0),
    linear-gradient(90deg, var(--color-bg-grid) var(--border-width-hairline), transparent 0);
  background-size: cover, 72px 72px, 72px 72px;
}
.eroe > * { position: relative; z-index: 1; }

/* iOS safe area: the public face declares viewport-fit=cover too, so it compensates too. */
body.pubblico {
  padding-left: env(safe-area-inset-left);
  padding-right: env(safe-area-inset-right);
}
body.pubblico .top { padding-top: env(safe-area-inset-top); }
