@charset "utf-8";
/* ══════════════════════════════════════════════════════════════════════════
   MESSA A REGISTRO — base.css
   Beatrice Pirani · portfolio · sito statico, zero dipendenze.

   Questo file possiede, per contratto (CONTRATTO.md §0.1):
     · il reset e i token (§ palette, § tipografia del SISTEMA)
     · le classi tipografiche .display / .testo / .lead / .dati
     · la primitiva .riga-titolo (Riga di piombo + Fuori registro)  §8
     · l'apparato di prestampa: .didascalia §10, .segnatura §12,
       .barra-colore §17, .filo §13
     · i filtri §7, la testata §2, il righello §3
     · il colophon §18 e il piede §19
     · skip link, .visivamente-nascosto, stampa

   Questo file NON tocca: insegna/hero, disco, opera/lastra, riga, fascia,
   rail, indice, scheda progetto, bio. Sono di layout.css + motion.css.

   Regola di scrittura rispettata ovunque: si anima SOLO transform, opacity,
   clip-path, background-color (e color, che è paint puro come background-color
   ed è prescritto dal SISTEMA per la Passata di colore sulla didascalia).
   Mai width/height/top/left/margin/padding/font-size.
   ══════════════════════════════════════════════════════════════════════════ */


/* ═══════════════════════════════════════════════════════ 1 · RESET ═══════ */

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

/* Azzeramento sobrio: solo i margini, che sono l'unica eredità del browser
   che entra in conflitto con un ritmo verticale dichiarato. */
html, body,
h1, h2, h3, h4, h5, h6,
p, figure, figcaption, blockquote,
dl, dd, ol, ul, pre { margin: 0; }

ol, ul { padding: 0; }
/* Le liste con classe sono strutture (righello, contatori, tag): niente pallini.
   Una lista senza classe è prosa e resta una lista vera. */
ol[class], ul[class] { list-style: none; }

html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  /* Lo scroll ancorato deve fermarsi sotto la testata sticky, mai dietro. */
  scroll-padding-top: calc(var(--testata-h) + var(--sp-3));
  /* Nessuno smooth-scroll dirottato via JS: qui è nativo, e si spegne
     insieme a tutto il resto del movimento. */
  scroll-behavior: auto;
}
@media (prefers-reduced-motion: no-preference) {
  html { scroll-behavior: smooth; }
}

body {
  min-height: 100dvh;
  background-color: var(--carta);
  color: var(--inchiostro);
  font-family: var(--f-testo);
  font-size: var(--t-body);
  line-height: var(--lh-body);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

img, picture, video, canvas, svg { display: block; max-width: 100%; }
/* `height:auto` sta a specificità 0,0,1: qualunque regola di layout.css
   sull'immagine della lastra (`.lastra > img{height:100%}`) la batte. */
img { height: auto; }

input, button, textarea, select { font: inherit; color: inherit; letter-spacing: inherit; }
button { background: none; border: 0; padding: 0; }

h1, h2, h3, h4, h5, h6, p, li, dt, dd, figcaption { overflow-wrap: break-word; }
h1, h2, h3, h4, h5, h6 { font-size: inherit; font-weight: inherit; }

table { border-collapse: collapse; }
hr { border: 0; border-top: var(--hair); }

/* Il focus non si rimuove mai. Questo è il default globale: ogni componente
   che lo ridisegna lo fa con un sostituto visibile in --rosso-ink. */
:focus-visible {
  outline: 2px solid var(--rosso-ink);
  outline-offset: 3px;
}
/* Rimuoviamo solo l'anello UA sul focus non-tastiera dei contenitori
   programmaticamente focalizzabili (la scheda, la pista del rail). */
[tabindex="-1"]:focus:not(:focus-visible) { outline: none; }

/* Link di prosa: --rosso-ink (5.79:1), mai --rosso. */
a { color: var(--rosso-ink); text-decoration-thickness: 1px; text-underline-offset: 0.18em; }
a:hover, a:focus-visible { color: var(--rosso-fondo); }

::selection { background: var(--rosso-ink); color: var(--foglio); }


/* ══════════════════════════════════════════ 2 · TOKEN (dal SISTEMA) ══════ */
/* I due blocchi che seguono sono copiati alla lettera da SISTEMA.md,
   commenti compresi: quei commenti sono la documentazione del progetto
   e vivono qui, non in un file a parte. */

/* ============================================================
   MESSA A REGISTRO — token cromatici
   7 token su 10 sono campionati dal file logo o ne sono derivati
   diretti. La palette non e' una scelta: e' un prelievo.
   Contrasti calcolati su --carta (luminanza relativa 0.881).
   ============================================================ */
:root{

  /* --- I DUE BIANCHI. Decisione strutturale dell'intero sistema. --- */
  --carta:   #F2F0EC; /* Fondo pagina, UNICO. Avorio impercettibile, 4% sotto il
                         bianco puro. Esiste per una ragione verificata sui
                         provini, non per gusto: la brochure Hotel Gambrinus e'
                         bianco su bianco con orchidee a tratto grigio chiarissimo,
                         e Miramare, QTM, ATBV, ANMCO e le carte AlmaDiploma hanno
                         fondo bianco puro. Su un sito bianco il loro perimetro
                         sanguinerebbe e sembrerebbero immagini rotte.
                         NON scurire oltre #F2F0EC: sopra vira in beige e il sito
                         diventa vintage. */
  --foglio:  #FFFFFF; /* Bianco puro riservato ESCLUSIVAMENTE al passe-partout su
                         cui poggia ogni opera, alla scheda progetto e al lightbox.
                         Non e' mai fondo pagina ne' fondo di sezione: e' un
                         oggetto che si stacca dalla carta di un valore e
                         restituisce a ogni pezzo il suo bordo foglio.
                         Rapporto foglio/carta = 1.135:1 → la hairline
                         --registro sotto e' OBBLIGATORIA, non decorativa. */
  --velina:  #E7E4DF; /* Campiture di servizio: hover dei filtri, fondo dei rail
                         orizzontali, separatori pesanti, blocchi didascalia
                         lunghi. Mai sotto un'immagine. */

  /* --- NEUTRI, campionati dal file logo --- */
  --registro:   #B2B1B1; /* Grigio del logo. Hairline 1px, crocini di registro,
                            tacche del righello, griglia dichiarata della hero,
                            numeri di segnatura non informativi.
                            1.90:1 su carta → VIETATO come testo, sempre e solo
                            linea o riempimento non informativo. */
  --grafite:    #444141; /* Antracite del logo. TUTTO il testo piccolo: metadati,
                            didascalie, misure in mm, navigazione, mono.
                            8.96:1 su carta → AAA anche a 11px. */
  --inchiostro: #1B1A1A; /* Display e corpo. Non nero puro: il nero assoluto e'
                            gia' dentro la brochure Briganti Ceramiche e deve
                            restare suo. 14.9:1 su carta. */
  --notte:      #141313; /* UN SOLO blocco scuro in tutto il sito (colophon +
                            contatti), per chiudere la scrollata e far cambiare
                            respiro alla pagina. Mai una seconda occorrenza. */

  /* --- I TRE ROSSI. Non decorazione: tre stati della stessa materia,
         perche' una materia ha spessore e deve poter arretrare. --- */
  --rosso:       #EF2F2C; /* MATERIA. Solo campiture piene: disco della hero,
                             bullet della numerazione, lamina sotto la lastra in
                             hover. 3.64:1 su carta → mai testo sotto 32px,
                             mai bordi di testo, mai icone informative.
                             Tetto misurabile: <2% della superficie di ogni
                             schermata, tranne il primo frame della hero. */
  --rosso-ink:   #B81C19; /* INCHIOSTRO. L'unico rosso autorizzato a essere
                             piccolo: link, underline, numerazione progetti,
                             stati hover, focus ring. 5.79:1 su carta → AA a
                             qualunque corpo. Ogni testo rosso passa da qui. */
  --rosso-fondo: #7E1210; /* RITIRATA. Sostituisce --rosso quando il piano confina
                             con un lavoro navy+oro (Mediobanca Christmas,
                             Cervia IN), teal (bollo #CERVIA.net, AIAS, Hotel
                             Kiss) o rosso-ciano (banner Viale Ironman), dove
                             #EF2F2C vibra e si legge come errore di stampa.
                             Usato anche per stati premuti e ombre di rosso. */

  /* --- IL COLORE DEI LAVORI, MAI DELLA SHELL --- */
  --dominante: var(--registro); /* Iniettata inline per-progetto dal campo
                                   `color` del manifest. Vive in due soli posti:
                                   le 23 tacche del righello e la barra di
                                   controllo colore in fondo alla scheda
                                   progetto. Il sito non inventa mai un colore:
                                   lo cita. */

  /* --- SUPERFICI DERIVATE (non aggiungono tinte) --- */
  --hair:        1px solid var(--registro);
  --hair-attiva: 1px solid var(--rosso-ink);
}

/* ============================================================
   TOKEN DI STRUTTURA E DI MOVIMENTO
   ============================================================ */
:root{
  --max:      1680px;
  --margine:  clamp(20px, 5vw, 88px);   /* STATICO. Mai animato: animare il
                                           margine e' animare il layout. */
  --gutter:   clamp(14px, 1.6vw, 26px); /* STATICO, stessa ragione. */
  --pad:      clamp(14px, 1.4vw, 28px); /* passe-partout attorno all'opera */
  --riga:     clamp(280px, 42vh, 560px);      /* ALTEZZA UNICA di ogni lastra */
  --riga-bassa: calc(var(--riga) * 0.42);     /* solo fasce ultra-wide ratio>3 */

  /* ritmo verticale, base 8px, scala non lineare */
  --sp-1:8px;  --sp-2:16px; --sp-3:24px;  --sp-4:40px;
  --sp-5:64px; --sp-6:104px; --sp-7:168px; --sp-8:272px;

  /* curve: quattro, non di piu' */
  --e-entrata: cubic-bezier(.16, 1, .30, 1);   /* ingressi, decelerazione lunga */
  --e-scatto:  cubic-bezier(.20, .80, .20, 1); /* micro-interazioni, meccanico */
  --e-piombo:  cubic-bezier(.19, 1, .22, 1);   /* righe di titolo che si assestano */
  --e-tendina: cubic-bezier(.70, 0, .20, 1);   /* transizione di vista, in-out */

  --d-micro:  180ms;
  --d-corta:  380ms;
  --d-media:  560ms;
  --d-lunga:  720ms;
  --d-vista:  640ms;
}

/* ============================================================
   MESSA A REGISTRO — tipografia
   DUE famiglie, TRE ruoli. Zero CDN, zero @font-face, zero byte.
   Il carattere del sito viene dalla SCALA e dal tracking negativo,
   non da un font esotico.

   Perche' un grottesco di sistema: la B del marchio e' un grottesco
   geometrico pesantissimo e Helvetica Neue/Arial e' esattamente la
   famiglia da cui discende. La B della hero e' letteralmente la
   stessa lettera del logo ridisegnata dal font di sistema.

   Perche' NON un serif nel corpo (correzione alla direzione di
   partenza): il materiale e' gia' saturo di serif e script eleganti
   — Gambrinus, Golden New Year di Piero Milano, Val d'Orcia,
   Portico Zambeccari, Mediobanca. Una voce serif nell'interfaccia
   ci competerebbe contro invece di ospitarli. Il corpo resta nella
   stessa famiglia del display, a peso 400: una famiglia, due pesi,
   nessuna gara col contenuto.

   Perche' il monospaziato: non e' un vezzo tech, e' una citazione
   verificabile. I provini di AlmaDiploma portano crocini di registro
   e barra di controllo colore CMYK; la tavola Agenti Immobiliari
   Online e' una "BOZZA ESECUTIVO / CLIENTE / INFORMAZIONI LAVORO".
   Il sito eredita quel linguaggio di prestampa e lo usa per i dati.
   ============================================================ */
:root{
  --f-display: "Helvetica Neue", Helvetica, "Liberation Sans", Arial, system-ui, sans-serif;
  --f-testo:   var(--f-display);
  --f-dati:    ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", "Courier New", monospace;

  /* scala: rapporto ~1.33 nei gradi bassi, che si apre a ~2.1 verso
     l'alto. Il rapporto fra --t-hero e --t-mono e' ~18:1: e' il salto,
     non il font, a produrre il carattere. Nessuna taglia intermedia
     ambigua fra --t-lead e --t-l: due mondi separati. */
  --t-mono: clamp(0.6875rem, 0.655rem + 0.16vw, 0.8125rem); /* 11 → 13px */
  --t-cap:  clamp(0.75rem,   0.715rem + 0.18vw, 0.875rem);  /* 12 → 14px */
  --t-body: clamp(1rem,      0.95rem  + 0.26vw, 1.1875rem); /* 16 → 19px */
  --t-lead: clamp(1.25rem,   1.10rem  + 0.75vw, 1.75rem);
  --t-l:    clamp(1.75rem,   1.35rem  + 2.00vw, 3.25rem);   /* titoli sezione */
  --t-xl:   clamp(2.75rem,   1.60rem  + 5.80vw, 7rem);      /* titolo progetto */
  --t-hero: clamp(3.4rem,    1.20rem  + 11.2vw, 15rem);     /* BEATRICE/PIRANI */

  --lh-hero: .84;  --lh-title: .92;  --lh-lead: 1.28;  --lh-body: 1.58;
  --tr-hero: -0.045em; --tr-title: -0.028em; --tr-lead: -0.015em;
  --tr-body: 0;        --tr-dati:  0.16em;
}

/* --- RUOLO 1 · DISPLAY. Solo maiuscole naturali del nome proprio,
       mai text-transform:uppercase su un titolo lungo. --- */
.display{
  font-family: var(--f-display);
  font-weight: 800;
  font-synthesis-weight: none;
  color: var(--inchiostro);
  text-wrap: balance;
}
.display--hero { font-size: var(--t-hero); line-height: var(--lh-hero);  letter-spacing: var(--tr-hero); }
.display--xl   { font-size: var(--t-xl);   line-height: var(--lh-title); letter-spacing: var(--tr-title); }
.display--l    { font-size: var(--t-l);    line-height: var(--lh-title); letter-spacing: var(--tr-title); font-weight: 700; }

/* --- RUOLO 2 · TESTO. Stessa famiglia, peso 400. --- */
.testo{
  font-family: var(--f-testo);
  font-weight: 400;
  font-size: var(--t-body);
  line-height: var(--lh-body);
  letter-spacing: var(--tr-body);
  color: var(--inchiostro);
  max-width: 62ch;
}
.lead{
  font-family: var(--f-testo);
  font-weight: 400;
  font-size: var(--t-lead);
  line-height: var(--lh-lead);
  letter-spacing: var(--tr-lead);
  color: var(--grafite);
  max-width: 44ch;
}

/* --- RUOLO 3 · DATI. L'apparato di prestampa: cliente, anno, tecnica,
       formato reale, numerazione. Cifre tabulari perche' le colonne di
       numeri si allineino da sole anche dove non c'e' una linea. --- */
.dati{
  font-family: var(--f-dati);
  font-weight: 500;
  font-size: var(--t-mono);
  line-height: 1.35;
  text-transform: uppercase;
  letter-spacing: var(--tr-dati);
  font-variant-numeric: tabular-nums;
  color: var(--grafite); /* MAI --registro: 1.90:1 non passa AA */
}
/* --t-mono (11–13px) con tracking .16em e' al limite: consentito solo per
   etichette di massimo tre parole. Qualunque metadato piu' lungo sale a
   --t-cap. Regola dura, verificata su monitor non calibrato. */
.dati--lungo{ font-size: var(--t-cap); letter-spacing: 0.12em; }

/* VIETATO: transform: scaleX() per simulare un condensato che i font di
   sistema non hanno. Le aste si deformano e si vede al primo sguardo.
   Se serve compattezza si stringe il tracking fino a -0.045em e ci si
   ferma li'. */

/* --- Nota di collaborazione. L'attribuzione dei lavori sviluppati per conto
       di uno studio terzo: compare nella testa del progetto e sotto la
       descrizione nella scheda.

       NON e' .dati e non puo' esserlo: e' una frase di venticinque parole e
       la regola qui sopra chiude il maiuscoletto a tre. E' un ruolo di testo
       in tono minore — corpo --t-cap, corsivo, grafite — con una stanghetta
       che la stacca dal claim senza aprire un riquadro. Il corsivo qui non
       enfatizza: segna che la voce cambia, e la voce che parla e' l'autrice
       sul proprio lavoro, non il lavoro. --- */
.nota-collaborazione{
  font-family: var(--f-testo);
  font-style: italic;
  font-weight: 400;
  font-size: var(--t-cap);
  line-height: 1.5;
  color: var(--grafite);   /* 8.9:1 su --carta: il corpo piccolo non scende sotto */
  max-width: 58ch;
  margin: 0;
  padding-inline-start: var(--sp-2);
  border-inline-start: var(--hair);
}

/* --- Token locali di base: non tinte, non scala. Solo misure di shell
       che devono essere leggibili anche da layout.css. --- */
:root{
  --testata-h: 56px;  /* CONTRATTO §2 — altezza fissa della testata sticky */

  /* Scala dei piani, DICHIARATA UNA VOLTA SOLA e qui, nel file che carica per
     primo. layout.css la legge e non la ridefinisce: due scale in due file
     producevano una testata sticky sopra la scheda modale. L'ordine è
     l'argomento del sistema: il lavoro (--z-indice) passa sempre davanti al
     rosso (--z-disco); la scheda copre la testata; lo skip link copre tutto. */
  --z-disco:   1;
  --z-indice:  2;
  --z-testata: 40;
  --z-scheda:  60;
  --z-salta:   200;
}


/* ═══════════════════════ 3 · COMPLEMENTI ALLE CLASSI TIPOGRAFICHE ═══════ */
/* Le classi .display/.testo/.lead/.dati e le loro varianti arrivano intatte
   dal blocco qui sopra. Quello che segue è ciò che serve per farle vivere
   in pagina: ritmo dei paragrafi, la riga di titolo, il collegamento. */

.testo > p + p { margin-top: var(--sp-3); }
.testo :is(strong, b) { font-weight: 700; }
.testo :is(em, i) { font-style: italic; }

/* --- 3.1 · RIGA DI TITOLO (CONTRATTO §8, vocabolario #4 "Riga di piombo").
       Le righe sono spezzate per parole dal generatore; qui dentro c'è il
       testo reale, non un'etichetta di ricambio. --- */
.riga-titolo{
  display: block;
  transform-origin: 0% 100%;
}

/* Stato di partenza. Vive SOLO con .con-js e SOLO sotto un contenitore che
   riceverà davvero .e-dentro: se il contenitore non porta data-obs
   (è il caso del nome della hero, animato da motion.css alla comparsa),
   la riga nasce già al suo posto e non viene mai nascosta.
   `html.senza-js` non nasconde nulla, mai — CONTRATTO §20. */
.con-js [data-obs]:not(.e-dentro) > .riga-titolo{
  opacity: 0;
  transform: translateY(0.92em) rotate(1.2deg);
  /* La maschera segue esattamente la traslazione: entrambe partono dal
     100% dell'altezza di riga e arrivano a 0 con la stessa curva, quindi
     restano in fase. Il lato alto è allargato di .34em perché accenti e
     ascendenti non vengano tagliati (line-height .92 < 1). */
  clip-path: inset(-0.34em -0.06em 100% 0);
  will-change: transform, clip-path, opacity;
}

/* fill-mode `backwards` e non `both`: a corsa finita le proprietà tornano
   al valore dichiarato (opacity 1, nessuna trasformata, nessuna maschera).
   Con `both` l'animazione resterebbe a vincere sulla cascata per sempre. */
.con-js [data-obs].e-dentro > .riga-titolo{
  animation: piombo var(--d-vista) var(--e-piombo) backwards;
  animation-delay: calc(var(--i-riga, 0) * 70ms);
}

/* Lo stagger per riga: --i è scritto solo dentro i gruppi [data-stagger],
   e i titoli non lo sono. Qui la posizione della riga basta e avanza. */
.riga-titolo:nth-child(1) { --i-riga: 0; }
.riga-titolo:nth-child(2) { --i-riga: 1; }
.riga-titolo:nth-child(3) { --i-riga: 2; }
.riga-titolo:nth-child(4) { --i-riga: 3; }

/* Il nome della hero non ha data-obs: entra a tempo, 300ms dopo il carico,
   con lo stesso identico gesto. Le hairline della griglia partono a 0ms. */
.con-js .display--hero > .riga-titolo{
  animation: piombo var(--d-vista) var(--e-piombo) backwards;
  animation-delay: calc(300ms + var(--i-riga, 0) * 70ms);
}

@keyframes piombo{
  from{ opacity: 0; transform: translateY(0.92em) rotate(1.2deg); clip-path: inset(-0.34em -0.06em 100% 0); }
  to  { opacity: 1; transform: translateY(0)      rotate(0deg);   clip-path: inset(-0.34em -0.06em -0.35em 0); }
}

/* --- 3.2 · FUORI REGISTRO. Tre occorrenze in tutto il sito, mai due
       visibili insieme (insegna · apertura · colophon). La copia rossa è
       un ::before che legge data-eco: nessun testo duplicato nel DOM,
       nessuna doppia lettura da screen reader. --- */
.riga-titolo--fuori{
  position: relative;
  isolation: isolate;
}
.riga-titolo--fuori::before{
  /* `/ ""` è il testo alternativo del contenuto generato: toglie il ::before
     dall'albero di accessibilità. Senza, la copia rossa viene letta e il
     titolo risulta duplicato («Beatrice Pirani Pirani»), che è esattamente
     ciò che il CONTRATTO §0.5 dichiara di voler evitare. Dove la sintassi non
     è supportata la dichiarazione è invalida e il ::before non viene generato:
     la copia rossa non si stampa, come già senza JS e con movimento ridotto. */
  content: attr(data-eco) / "";
  position: absolute;
  inset: 0;
  z-index: -1;
  color: var(--rosso);
  opacity: .9;
  transform: translate(6px, 4px);
  pointer-events: none;
  /* La stampa mal registrata rientra e svanisce: 820ms, come da SISTEMA. */
  transition: transform 820ms var(--e-piombo), opacity 820ms var(--e-piombo);
}
/* Rientro sotto il contenitore osservato (apertura, colophon)… */
.con-js [data-obs].e-dentro > .riga-titolo--fuori::before{
  transform: translate(0, 0);
  opacity: 0;
}
/* …e a tempo nella hero, che non è osservata. */
.con-js .display--hero > .riga-titolo--fuori::before{
  animation: fuori-registro 820ms var(--e-piombo) 300ms both;
  transition: none;
}
@keyframes fuori-registro{
  from{ transform: translate(6px, 4px); opacity: .9; }
  to  { transform: translate(0, 0);     opacity: 0; }
}
/* Senza JS la copia rossa non ha modo di rientrare: non si stampa affatto,
   invece di restare fuori registro per sempre. */
.senza-js .riga-titolo--fuori::before{ content: none; }

/* Delle tre occorrenze del Fuori registro due sono al sicuro (l'insegna a
   --t-hero, min 54px; il colophon a --t-xl, min 44px). La seconda vive su
   .apertura__titolo, che è .display--l: `1.35rem + 2vw` raggiunge i 32px solo
   a 520px di viewport. Sotto, la copia rossa sarebbe testo in --rosso
   (3.64:1) a meno di 32px — il divieto è esplicito. --rosso-ink è 5.79:1 e
   il SISTEMA lo autorizza a qualunque corpo. */
@media (max-width: 519.98px){
  .display--l > .riga-titolo--fuori::before{ color: var(--rosso-ink); }
}

/* --- 3.3 · COLLEGAMENTO. Link testuale ricorrente (azione del progetto,
       contatto della bio, social e navigazione della scheda). Sottolineatura
       che si disegna con scaleX da sinistra, identica su hover e focus. --- */
.collegamento{
  position: relative;
  color: var(--inchiostro);
  text-decoration: none;
  display: inline-flex;
  align-items: baseline;
  gap: 0.6em;
  transition: color var(--d-micro) var(--e-scatto);
}
.collegamento::after{
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: -0.14em;
  height: 1px;
  background-color: var(--rosso-ink);
  transform: scaleX(0);
  transform-origin: 0 50%;
  transition: transform var(--d-micro) var(--e-scatto);
}
.collegamento:hover,
.collegamento:focus-visible{ color: var(--rosso-ink); }
.collegamento:hover::after,
.collegamento:focus-visible::after{ transform: scaleX(1); }
.collegamento .dati{ color: inherit; }


/* ═════════════════════════════════ 4 · APPARATO DI PRESTAMPA ════════════ */

/* --- 4.1 · DIDASCALIA DELLA LASTRA (CONTRATTO §10).
       Committente / tecnica / formato reale / anno. Allineata al bordo
       sinistro della lastra e INCHIODATA: mai Deriva, mai parallasse.
       È qui che la misura dichiarata trasforma l'eterogeneità in dato. --- */
.didascalia{
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0 0.55em;
  margin-top: var(--sp-2);
  color: var(--grafite);
  transform: translateX(0);
  /* Passata di colore: 180ms in, 240ms out. Solo transform e color. */
  transition:
    transform 240ms var(--e-scatto),
    color     240ms var(--e-scatto);
}
.didascalia__voce{
  color: inherit;
  white-space: nowrap;
}
/* Il committente è l'unica voce che deve poter andare a capo: nei dati veri
   arriva a «CerviaAmbiente — Centro Ricerche Marine» e a «Società Agricola
   Pracucci Roberto & C.s.s.», più lunghi della lastra che descrivono. Con
   `nowrap` sborda dalla propria opera e stampa sulla didascalia della vicina —
   verificato a schermo sulla prima riga dell'indice. Tecnica, misura e anno
   restano nowrap: sono corti per costruzione e non devono spezzarsi. */
.didascalia__voce--cliente{
  font-weight: 700;
  white-space: normal;
}
/* La misura dichiarata porta sotto di sé una linea di quota: 1px --registro,
   linea e non testo, quindi in regola col contrasto. */
.didascalia__voce--misura{
  border-block-end: var(--hair);
  padding-block-end: 2px;
}
.didascalia__voce:not(:last-child)::after{
  content: "·";
  margin-inline-start: 0.55em;
  letter-spacing: 0;
}
/* La risposta in hover appartiene alla didascalia, quindi la scrive base
   anche se il selettore parte da .opera (CONTRATTO §0.1).
   Su touch `engine.lastreTouch` scrive .e-attiva sulla .lastra — non sulla
   .opera, come lascerebbe intendere il §10 del contratto. La didascalia è la
   sorella successiva della lastra: il selettore di fratellanza copre il caso
   reale senza chiedere modifiche all'engine. */
.opera:hover .didascalia,
.opera:focus-within .didascalia,
.opera.e-attiva .didascalia,
.lastra.e-attiva ~ .didascalia{
  transform: translateX(4px);
  color: var(--inchiostro);
  transition-duration: var(--d-micro);
}

/* --- 4.2 · SEGNATURA (CONTRATTO §12, vocabolario #5).
       I numeri montano come i contatori meccanici di una macchina da stampa.
       Nessun conteggio incrementale: scorre solo la cifra finale.
       Le cifre visibili sono aria-hidden — il valore vero sta nello span
       nascosto — ed è per questo che possono stare in --registro. --- */
.segnatura{
  display: inline-flex;
  align-items: baseline;
  gap: 0.4em;
  font-family: var(--f-dati);
  font-weight: 500;
  font-size: var(--t-l);            /* mai in filigrana, mai a 20rem */
  line-height: 1;
  letter-spacing: 0.02em;
  font-variant-numeric: tabular-nums;
  color: var(--registro);
}
.segnatura__cifre{
  display: inline-flex;
  align-items: flex-end;
}
.cifra{
  display: inline-block;
  overflow: hidden;
  line-height: 1;
  vertical-align: bottom;
}
.cifra__glifo{
  display: block;
  transform: translateY(0);
  transition: transform var(--d-corta) var(--e-scatto);
  transition-delay: calc(var(--i, 0) * 30ms); /* --i decrescente: da destra a sinistra */
}
/* Stato di partenza, gated su .con-js e su un contenitore osservato. */
.con-js [data-obs]:not(.e-dentro) .cifra__glifo{ transform: translateY(100%); }

.segnatura__voce{
  color: var(--grafite);
  letter-spacing: var(--tr-dati);
}

/* Varianti dichiarate dal contratto. */
.segnatura--contatore{
  /* Apertura dell'indice: qui il numero è contenuto, non segnatura di
     servizio → passa a --inchiostro. --registro resta ai numeri muti. */
  color: var(--inchiostro);
  gap: 0.5em;
}
.segnatura--conteggio{           /* testa del rail: "01/14" */
  font-size: var(--t-cap);
  letter-spacing: 0.08em;
  color: var(--grafite);
  gap: 0.1em;
}
.segnatura--compatta{            /* righello sotto 720px */
  font-size: var(--t-cap);
  letter-spacing: 0.08em;
  color: var(--grafite);
  gap: 0;
}

/* --- 4.3 · BARRA DI CONTROLLO COLORE (CONTRATTO §17).
       Due sole occorrenze in tutto il sito: il filo e il fondo della scheda.
       Riporta dati veri letti dal manifest, quindi non è costume. --- */
.barra-colore{
  display: flex;
  align-items: flex-end;
}
.campione{
  display: block;
  min-width: 0;
}
.campione::before{
  content: "";
  display: block;
  background-color: var(--dominante);
  transform: scaleY(1);
  transform-origin: bottom;
  transition: transform 480ms var(--e-scatto);
  transition-delay: calc(var(--i, 0) * 28ms);
}
.con-js [data-obs]:not(.e-dentro) .campione::before{ transform: scaleY(0); }

/* Variante indice: 23 tacche alte 10px, una per progetto. */
.barra-colore--indice{ gap: 1px; }
.barra-colore--indice .campione{ flex: 1 1 0; }
.barra-colore--indice .campione::before{ height: 10px; }

/* Variante scheda: 6–8 campioni quadrati con l'esadecimale sotto. */
.barra-colore--scheda{
  flex-wrap: wrap;
  gap: var(--sp-2);
  align-items: flex-start;
  border-top: var(--hair);
  padding-top: var(--sp-3);
}
.barra-colore--scheda > .dati{
  flex: 1 0 100%;
  margin-bottom: var(--sp-2);
}
.barra-colore--scheda .campione{ width: clamp(44px, 6vw, 76px); }
.barra-colore--scheda .campione::before{ aspect-ratio: 1; }
.campione__hex{
  display: block;
  margin-top: var(--sp-1);
  color: var(--grafite);
  letter-spacing: 0.06em;
}

/* --- 4.4 · FILO (CONTRATTO §13 e §19).
       Stesso oggetto in due collocazioni: piede della hero e piede del sito.
       Conteggio a sinistra, barra colore al centro, firma a destra. --- */
.filo{
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(120px, 2fr) minmax(0, 1fr);
  align-items: center;
  gap: var(--sp-3);
  border-top: var(--hair);
  padding-top: var(--sp-2);
}
.filo__conteggio{ justify-self: start; }
.filo__firma{ justify-self: end; text-align: right; }

@media (max-width: 719.98px){
  .filo{
    grid-template-columns: 1fr 1fr;
    gap: var(--sp-2) var(--sp-3);
  }
  .filo .barra-colore--indice{ grid-column: 1 / -1; order: -1; }
}

/* --- 4.5 · FILTRI PER CATEGORIA (CONTRATTO §7).
       Hairline + testo. Nessun pulsante rosso pieno, mai: il rosso arriva
       solo su hover e focus, e sempre come --rosso-ink. --- */
.filtri{
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-1);
}
/* L'unica cosa che `.senza-js` nasconde in tutto il sito, e non è contenuto:
   sono comandi. Da quando l'indice è pre-renderizzato i filtri finiscono
   nell'HTML statico come tutto il resto, ma senza JavaScript non filtrano
   niente — otto bottoni che non rispondono al clic sono peggio della loro
   assenza. Il <noscript> accanto dice che ci sono e perché non ci sono. */
.senza-js .filtri{ display: none; }
.filtro{
  display: inline-flex;
  align-items: baseline;
  gap: 0.7em;
  padding: 0.6em 0.95em;
  /* Non `--hair`: quello è il token delle hairline decorative, e a riposo il
     filtro non ha campitura — il rettangolo è l'UNICA cosa che dice che è un
     pulsante. --registro su --carta è 1.88:1, sotto il 3:1 richiesto per i
     confini che identificano un componente. --grafite è il colore del testo
     che sta dentro: stessa voce, 8.88:1. */
  border: 1px solid var(--grafite);
  background-color: transparent;
  color: var(--grafite);
  font-family: var(--f-dati);
  font-weight: 500;
  font-size: var(--t-cap);
  line-height: 1;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  font-variant-numeric: tabular-nums;
  cursor: pointer;
  transition:
    color            var(--d-micro) var(--e-scatto),
    border-color     var(--d-micro) var(--e-scatto),
    background-color var(--d-micro) var(--e-scatto);
}
/* Nessuna opacità sul conteggio: attenuare --grafite lo porta sotto 4.5:1. */
.filtro__n{ color: inherit; }
.filtro:hover,
.filtro:focus-visible{
  color: var(--rosso-ink);
  border-color: var(--rosso-ink);
  background-color: var(--velina);
}
.filtro[aria-pressed="true"]{
  color: var(--inchiostro);
  border-color: var(--inchiostro);
  background-color: var(--velina);
}
.filtro[aria-pressed="true"]:hover,
.filtro[aria-pressed="true"]:focus-visible{
  color: var(--rosso-ink);
  border-color: var(--rosso-ink);
}
.filtro:active{ color: var(--rosso-fondo); border-color: var(--rosso-fondo); }


/* ═══════════════════════════════ 5 · TESTATA STICKY + RIGHELLO ══════════ */

.testata{
  position: sticky;
  top: 0;
  z-index: var(--z-testata);
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--sp-3);
  height: var(--testata-h);
  padding-inline: var(--margine);
  background-color: var(--carta);
}
/* La hairline inferiore compare a fine corsa dello scroll-shrink: prima
   la testata è un vuoto sulla carta, non una barra. */
.testata::after{
  content: "";
  position: absolute;
  inset-inline: 0;
  bottom: 0;
  height: 1px;
  background-color: var(--registro);
  transform: scaleX(1);
  transform-origin: 0 50%;
}
.con-js .testata::after{
  transform: scaleX(0);
  transition: transform var(--d-corta) var(--e-scatto);
}
.con-js .testata.e-dentro::after{ transform: scaleX(1); }

.testata__marchio{
  display: inline-flex;
  align-items: center;
  color: var(--inchiostro);
  text-decoration: none;
}
/* Il pieno tipografico in cui atterra il nome dell'insegna. aria-hidden:
   il testo accessibile del marchio sta nello span nascosto e non dipende
   da nessuna animazione. */
.testata__lettering{
  font-family: var(--f-display);
  font-weight: 800;
  font-size: var(--t-lead);
  line-height: 1;
  letter-spacing: var(--tr-title);
  color: var(--inchiostro);
  opacity: 1;
}
.con-js .testata__lettering{ opacity: 0; }
.con-js .testata.e-dentro .testata__lettering{
  opacity: 1;
  transition: opacity var(--d-corta) var(--e-entrata);
}

.testata__bio{
  position: relative;
  justify-self: end;
  color: var(--grafite);
  text-decoration: none;
  transition: color var(--d-micro) var(--e-scatto);
}
.testata__bio::after{
  content: "";
  position: absolute;
  inset-inline: 0;
  bottom: -0.35em;
  height: 1px;
  background-color: var(--rosso-ink);
  transform: scaleX(0);
  transform-origin: 0 50%;
  transition: transform var(--d-micro) var(--e-scatto);
}
.testata__bio:hover,
.testata__bio:focus-visible{ color: var(--rosso-ink); }
.testata__bio:hover::after,
.testata__bio:focus-visible::after{ transform: scaleX(1); }

/* Dove c'è scroll(): la testata si chiude da sola alla fine della prima
   schermata, senza dipendere da nessuna classe scritta da JS. */
@supports (animation-timeline: scroll()){
  .con-js .testata::after{
    animation: testata-linea linear both;
    animation-timeline: scroll(root block);
    animation-range: 72vh 100vh;
  }
  .con-js .testata__lettering{
    animation: testata-lettering linear both;
    animation-timeline: scroll(root block);
    animation-range: 72vh 100vh;
  }
}
@keyframes testata-linea{
  from{ transform: scaleX(0); }
  to  { transform: scaleX(1); }
}
@keyframes testata-lettering{
  from{ opacity: 0; }
  to  { opacity: 1; }
}
/* Senza scroll() il nome dell'insegna non viaggia: il marchio della testata
   è visibile dal primo frame, come da CONTRATTO §2. E con esso la hairline:
   nessuno scrive .e-dentro su [data-testata] — né l'engine né app.js — quindi
   senza questa regola la testata resterebbe per sempre senza filo inferiore. */
@supports not (animation-timeline: scroll()){
  .con-js .testata__lettering{ opacity: 1; }
  .con-js .testata::after{ transform: scaleX(1); }
}

/* --- 5.1 · RIGHELLO (CONTRATTO §3, vocabolario #7).
       23 tacche = 23 <a> reali. È l'indice, non un ornamento: fa da orologio
       e da mappa nello stesso oggetto. --- */
.righello{
  display: flex;
  align-items: center;
  justify-content: flex-end;
  min-width: 0;
}
.righello__tacche{
  display: flex;
  align-items: flex-end;
  gap: 2px;
}
.tacca{ display: block; }
.tacca__ancora{
  display: flex;
  align-items: flex-end;
  justify-content: center;
  width: 8px;
  height: 26px;               /* bersaglio tattile, il segno resta 1px */
  text-decoration: none;
}
.tacca__segno{
  display: block;
  width: 1px;
  height: 9px;
  background-color: var(--dominante);
  transform: scaleY(1);
  transform-origin: bottom;
  transition:
    transform        240ms var(--e-scatto),
    background-color 240ms var(--e-scatto);
}
/* Attiva: si allunga a 2.4 e passa a --rosso-ink. Sia .e-attiva sul <li>
   (engine.righello) sia [aria-current] sull'<a>: il ramo ARIA copre anche
   il caso in cui l'attributo arrivi come stringa vuota. */
.tacca.e-attiva .tacca__segno,
.tacca__ancora[aria-current] .tacca__segno{
  transform: scaleY(2.4);
  background-color: var(--rosso-ink);
}
.tacca.e-vicina .tacca__segno{
  transform: scaleY(1.6);
  background-color: var(--grafite);
}
.tacca__ancora:hover .tacca__segno,
.tacca__ancora:focus-visible .tacca__segno{
  transform: scaleY(1.6);
  background-color: var(--rosso-ink);
}
.tacca__ancora:focus-visible{ outline-offset: 0; }
/* Progetti fuori dal filtro corrente: la tacca arretra ma non sparisce,
   così il righello non cambia mai lunghezza. */
.tacca.e-esclusa{ opacity: .22; }
.tacca.e-esclusa .tacca__segno{ background-color: var(--registro); }

/* Ingresso: scaleY(0)→1, stagger 28ms. Non dipende da .e-dentro perché
   la testata è in pagina dal primo frame. `backwards`: a corsa finita il
   transform torna alla cascata, altrimenti .e-attiva non potrebbe più
   allungare la tacca. */
.con-js .tacca__segno{
  animation: tacca-entra 480ms var(--e-scatto) backwards;
  animation-delay: calc(var(--i, 0) * 28ms);
}
@keyframes tacca-entra{
  from{ transform: scaleY(0); }
  to  { transform: scaleY(1); }
}

/* Collasso sotto 720px: resta un solo dato, "07/23", che aggiorna con la
   Segnatura. Le 23 tacche escono di scena, non si comprimono. */
.righello__compatto{
  display: none;
  align-items: baseline;
  color: var(--grafite);
}
.righello__totale{ letter-spacing: 0.08em; }

@media (max-width: 719.98px){
  .righello__tacche{ display: none; }
  .righello__compatto{ display: inline-flex; }
  .testata{ gap: var(--sp-2); }
  /* Il link al Metodo resta: è navigazione, non ornamento. */
}


/* ═══════════════════════════════════ 6 · COLOPHON E PIEDE ═══════════════ */
/* --notte compare qui e in nessun altro punto del sito. Chiude la scrollata
   e fa cambiare respiro alla pagina: una seconda occorrenza la annullerebbe. */

.colophon{
  background-color: var(--notte);
  color: var(--foglio);
  padding: var(--sp-7) var(--margine) var(--sp-6);
}

/* Il disco, nel suo terzo stato, chiude la corsa al centro di QUESTO blocco
   (SISTEMA §colophon). È fisso e sta a --z-disco 1, mentre qui non c'era alcun
   z-index: stampava quindi sopra il titolo, e «del prossimo» si leggeva a metà.
   Si alzano i contenuti, non la sezione: `.colophon` ha il fondo opaco --notte,
   e alzare l'intero blocco coprirebbe il disco invece di lasciarlo passare
   dietro le lettere. Con z-index 1 sui soli figli il disco resta sopra il fondo
   e sotto il testo — a parità di livello vince l'ordine di documento, e il
   disco nasce nell'insegna, molto prima di qui.
   Il bianco sul rosso del disco misura 4,1:1: sotto la soglia AA del testo
   corrente, sopra quella del testo grande — e qui sono tutti display. */
.colophon__titolo,
.colophon__contatti,
.colophon__nota{
  position: relative;
  z-index: 1;
}

.colophon .display,
.colophon__titolo{ color: var(--foglio); }
.colophon .dati{ color: var(--registro); } /* su --notte il grigio del logo passa 8.9:1 */
.colophon .lead{ color: var(--registro); }

.colophon__contatti{
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--sp-3);
  margin-top: var(--sp-5);
}
.colophon__link{
  position: relative;
  display: inline-block;
  color: var(--foglio);
  text-decoration: none;
  transition: color var(--d-corta) var(--e-scatto);
}
.colophon__sottolineatura{
  position: absolute;
  left: 0; right: 0; bottom: -0.06em;
  height: 2px;
  background-color: var(--rosso-ink);
  transform: scaleX(0);
  transform-origin: 0 50%;
  transition: transform var(--d-corta) var(--e-scatto);
}
.colophon__link:hover .colophon__sottolineatura,
.colophon__link:focus-visible .colophon__sottolineatura{ transform: scaleX(1); }
.colophon__nota{
  margin-top: var(--sp-5);
  max-width: 44ch;
}
.colophon :focus-visible{ outline-color: var(--foglio); }

.piede{
  background-color: var(--notte);
  color: var(--foglio);
  padding: var(--sp-3) var(--margine) var(--sp-4);
}
.piede .filo{ border-top-color: var(--registro); }
.piede .dati{ color: var(--registro); }
.piede :focus-visible{ outline-color: var(--foglio); }


/* ════════════════════ 7 · SKIP LINK · NASCOSTI · STAMPA ═════════════════ */

/* Primo nodo focusabile del documento. Compare solo quando serve, e con
   :focus (non :focus-visible): deve uscire anche se il focus arriva da JS. */
.salta{
  position: fixed;
  top: 0;
  left: var(--margine);
  z-index: var(--z-salta);
  padding: 0.7em 1.1em;
  background-color: var(--foglio);
  border: var(--hair-attiva);
  border-top: 0;
  color: var(--inchiostro);
  font-family: var(--f-dati);
  font-size: var(--t-cap);
  text-transform: uppercase;
  letter-spacing: 0.12em;
  text-decoration: none;
  transform: translateY(-120%);
  transition: transform var(--d-micro) var(--e-scatto);
}
.salta:focus{ transform: translateY(0); }

/* Contenuto per i soli screen reader: #annunci, le etichette delle tacche,
   i valori reali delle segnature. Mai display:none — sparirebbe anche a loro. */
.visivamente-nascosto{
  position: absolute !important;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* --- 7.1 · MOVIMENTO RIDOTTO. Contenuto COMPLETO e fermo. Nessuna
       animazione di ingresso, nessuna traslazione: restano le transizioni
       di colore, che sono informazione di stato, e i fade brevi. --- */
@media (prefers-reduced-motion: reduce){

  .con-js [data-obs]:not(.e-dentro) > .riga-titolo,
  .con-js [data-obs].e-dentro > .riga-titolo,
  .con-js .display--hero > .riga-titolo{
    animation: none;
    opacity: 1;
    transform: none;
    clip-path: none;
    will-change: auto;
  }
  .con-js [data-obs]:not(.e-dentro) > .riga-titolo{
    opacity: 0;
    transition: opacity 200ms linear;
  }
  /* Fuori registro: con il movimento spento la copia rossa non ha modo di
     rientrare, quindi non si stampa. Lo stato finale è comunque opacity 0. */
  .riga-titolo--fuori::before{ content: none; }

  .con-js [data-obs]:not(.e-dentro) .cifra__glifo{
    transform: none;
    opacity: 0;
  }
  .cifra__glifo{ transition: opacity 200ms linear; }
  .cifra{ overflow: visible; }

  .con-js [data-obs]:not(.e-dentro) .campione::before{
    transform: none;
    opacity: 0;
  }
  .campione::before{ transition: opacity 200ms linear; }

  .con-js .tacca__segno{ animation: none; }
  .tacca__segno{ transition: background-color 200ms linear; }
  .tacca.e-attiva .tacca__segno,
  .tacca__ancora[aria-current] .tacca__segno,
  .tacca.e-vicina .tacca__segno,
  .tacca__ancora:hover .tacca__segno,
  .tacca__ancora:focus-visible .tacca__segno{ transform: none; }
  /* Senza allungamento serve un altro segnale: la tacca attiva raddoppia
     di larghezza in modo statico, non animato. */
  .tacca.e-attiva .tacca__segno,
  .tacca__ancora[aria-current] .tacca__segno{ width: 3px; }

  .didascalia{ transition: color 200ms linear; }
  .opera:hover .didascalia,
  .opera:focus-within .didascalia,
  .opera.e-attiva .didascalia,
  .lastra.e-attiva ~ .didascalia{ transform: none; }

  .con-js .testata::after,
  .con-js .testata__lettering{ animation: none; }
  .con-js .testata::after{ transform: scaleX(1); }
  .con-js .testata__lettering{ opacity: 1; }

  .collegamento::after,
  .testata__bio::after,
  .colophon__sottolineatura{
    transition: opacity 200ms linear;
    transform: scaleX(1);
    opacity: 0;
  }
  .collegamento:hover::after,
  .collegamento:focus-visible::after,
  .testata__bio:hover::after,
  .testata__bio:focus-visible::after,
  .colophon__link:hover .colophon__sottolineatura,
  .colophon__link:focus-visible .colophon__sottolineatura{ opacity: 1; }

  .salta{ transition: none; }
}

/* --- 7.2 · STAMPA. Il portfolio stampato è un elenco di lavori con la loro
       misura dichiarata: sparisce tutto ciò che è navigazione. --- */
@media print{
  @page{ margin: 14mm; }

  :root{
    --carta: #FFFFFF;
    --foglio: #FFFFFF;
    --notte: #FFFFFF;
    --registro: #999999;
  }
  html, body{
    background: #FFFFFF;
    color: #000000;
    font-size: 10.5pt;
  }

  .salta,
  .testata,
  .righello,
  .filtri{ display: none !important; }

  .colophon,
  .piede{
    background: #FFFFFF;
    color: #000000;
    padding-inline: 0;
  }
  .colophon .display,
  .colophon__titolo,
  .colophon__link{ color: #000000; }
  .colophon .dati,
  .colophon .lead,
  .piede .dati{ color: #333333; }

  .didascalia{ color: #000000; }
  .segnatura{ color: #666666; }

  a{ color: #000000; text-decoration: underline; }
  .collegamento::after,
  .colophon__sottolineatura,
  .testata__bio::after{ display: none; }

  /* Nessun movimento in carta: tutto allo stato finale. */
  .riga-titolo,
  .cifra__glifo,
  .campione::before{
    animation: none !important;
    transition: none !important;
    transform: none !important;
    clip-path: none !important;
    opacity: 1 !important;
  }
  .riga-titolo--fuori::before{ content: none; }
}
