/* =========================================================
   Card component — normal / hover
   Fonte: assets/Section.png (Card_desktop)
   Token: tokens.css
   ========================================================= */

:root {
  /* Prima 260/180ms: la card ruota di ~4.4 gradi (fra --card-rotate-base e
     --card-rotate-hover, assegnati a caso per card) passando anche per una
     scala — su una rotazione, che l'occhio segue con precisione, farlo in
     260ms con --card-ease-weighted (una ease-out "frontale", il grosso del
     moto nei primi istanti) si leggeva come uno scatto seguito da un
     assestamento, non come un sollevamento continuo. Stessa curva, solo
     piu' tempo per srotolarla. */
  --card-duration-enter: 340ms; /* normal -> hover */
  --card-duration-exit: 220ms;  /* hover -> normal, sempre piu' svelto dell'entrata */
  --card-ease: ease;                                  /* color changes (border, underline) */
  --card-ease-out: cubic-bezier(0.23, 1, 0.32, 1);     /* quick entrances (mark fade-in) */
  --card-ease-weighted: cubic-bezier(0.32, 0.72, 0, 1); /* iOS-like weighted glide, for the main tilt+lift */
  /* Era stata messa a 0.94 per contrastare il tratto che ingrossava
     insieme alla thumb ingrandita — ma la scala e' un transform attorno
     al centro della FOTO (vedi .card__sketch sotto), quindi rimpicciolire
     TUTTO il riquadro attorno a quel centro tira dentro anche i segni
     sul bordo, non solo il tratto: misurato dal vivo, campionando i
     tracciati veri contro il riquadro della foto, con 0.94 nove disegni
     su dieci finivano DENTRO la foto (fino a -17px), non solo a
     sfiorarla. Tornata a 1 = geometria del manifest intatta, che e'
     quella verificata a non toccare mai la card. Se il tratto risultasse
     ancora troppo spesso, va assottigliato nel <path> stesso (o con
     vector-effect: non-scaling-stroke), mai con questa manopola: quella
     sposta anche la posizione, questo no. */
  --sketch-scale: 1;

  /* MANOPOLA — quanto allontanare i segni dalla foto oltre a com'erano
     disegnati. A 1 il disegno sta ESATTAMENTE come nel file di Figma, che
     e' quello che si vuole: la geometria giusta arriva dal manifest, e i
     segni non toccano la card gia' di loro (verificato campionando i
     tracciati veri: nessuno dei quattro la sfiora). Serve solo se un
     disegno futuro nascesse troppo addosso alla card.

     NON e' lo strumento giusto per "stringere lo scarabocchio alla
     card": scala l'INTERO riquadro (fw/fh), quindi anche la parte che
     deve combaciare 1:1 con la foto vera — la foto pero' non si
     rimpicciolisce con lui, quindi anche un ritocco "leggero" (provato
     0.9) mangia il margine calibrato molto piu' in fretta di quanto
     sembri (misurato dal vivo: da un margine minimo di ~2px a
     sovrapposizioni di 15-25px). Per stringere solo lo sbordo, senza
     toccare il riquadro-foto, vedi FATTORE_STRINGI in js/card.js. */
  --sketch-overhang: 1;
  /* Not in Section.png (which specifies the same flat shadow for both states) — added
     so the tilt reads as the image lifting toward the viewer instead of spinning flat. */
  --card-shadow-hover: 0 20px 48px rgba(0, 0, 0, 0.18);
}

* {
  box-sizing: border-box;
}

body {
  margin: 0;
  background: var(--color-grey);
  font-family: var(--font-family-base);
}

.page {
  max-width: 1240px;
  margin: 0 auto;
  padding: var(--space-8) var(--space-6);
}

.card-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  /* Piu' largo di --space-8 puro: respiro fra una thumb e l'altra, senza
     introdurre un token nuovo. Alzato da 1.25 a 1.5 insieme all'aumento
     di misura della card — piu' grande la thumb, piu' vuoto le serve
     intorno perche' non si sentano stipate. */
  gap: calc(var(--space-8) * 1.5);
}

/* ---------- Card ---------- */
/* Responsive breakpoints — Thumb S/M/L/XL/XXL (assets/Thumb brakepoint.png).
   S 320 / M 600 / L 900 / XL 1280 / XXL 1728.
   Mobile-first: base rules are Thumb S (stacked, designed from 320px), each
   min-width tier below swaps in the next size. .card__media is always 16:9
   and .card__image always fills it 100% — one consistent shape at every
   tier, only the max-width grows (never shrinks) at each breakpoint. The
   sketch overlay (.card__sketch) extends beyond .card__image by a fixed %
   on each side to reproduce the original calibration, so marks stay in the
   right spot relative to the image regardless of its rendered size. */

.card {
  display: flex;
  flex-direction: column;
  align-items: center; /* S: centers both the thumb and the text block (same width) as a unit */
  /* Sotto i 600px il titolo sta IMPILATO sotto la thumb (flex-direction
     cambia solo dal tier M in su), non affiancato: e' l'unico caso in cui
     lo sbordo dello scarabocchio ha un bordo di testo proprio li' sotto
     a distanza minima. Il tratto vero (non il riquadro trasparente
     dell'SVG, molto piu' grande) sporge, a seconda del disegno, fra 20 e
     45px oltre il bordo della thumb, misurato su tutto l'arco di
     rotazione mobile — var(--space-3) ne dava solo 12.

     32px era la misura voluta (thumb e titolo devono leggersi come la
     stessa card, non due cose separate), ma da sola non bastava per i
     disegni piu' sporgenti: quelli restano esclusi dal catalogo SOLO
     sotto i 600px (vedi "mobileOk" in assets/sketches/manifest.json e
     assignCardSketches in js/card.js) invece di allargare ancora il
     gap. Il valore giusto per stringere lo sbordo stesso non esiste
     (--sketch-overhang) — misurato dal vivo, su mobile il margine dal
     bordo della FOTO e' gia' ~1px anche senza ritocchi: qualunque
     riduzione ulteriore la fa toccare.

     Portato a 36px insieme all'ingrandimento della thumb (315->352px,
     vedi .card__media sotto): .card__sketch e' dimensionato in
     percentuale di .card__media, quindi lo sbordo di OGNI disegno cresce
     nella stessa proporzione della thumb, non solo quello dei cinque
     gia' esclusi. Ricampionato dal vivo (getBoundingClientRect() dei
     <path>, non del riquadro trasparente dell'SVG, su tutto l'arco di
     rotazione mobile 1.7-2.6deg) ogni disegno ammesso sotto i 600px, col
     caso peggiore che sale da ~26px a 28.94px (card-sketch-06.svg, a
     -2.6deg) — troppo vicino ai 32px vecchi per restare un margine
     affidabile su una regola che non deve MAI fallire. 36px = 32 *
     (352/315), la stessa proporzione con cui e' cresciuta la thumb: il
     margine fra tratto e titolo che era gia' verificato sicuro a 315px
     resta lo stesso margine RELATIVO a 352px (28.94/36 = 0.80, contro
     26/32 = 0.81 prima), invece di un numero scelto a caso. */
  gap: 36px;
  /* overridden per-instance by js/card.js (randomized once per page load) */
  --card-rotate-base: 2.57deg;
  --card-rotate-hover: -1.87deg;
}

.card__media {
  position: relative;
  width: 100%;
  /* Base measured from Thumb brakepoint.png (pixel-grid overlay, not
     eyeballed): box width scales with frame width from ~320px image-px at
     Thumb XL. S and M are both close to that same absolute size in the
     mockup (down-scaled here proportionally) — the image is intentionally
     smaller once text sits beside it (M+) than when it's the full-width
     hero on its own (S). Bumped ~18% past that measured baseline on
     direct request ("più grande"), then back down 5% twice ("ancora
     troppo grande" — net ~+6% over the mockup baseline), same ratio at
     every tier so the proportions the mockup set stay intact.

     Portato a 352px su richiesta diretta del committente ("le thumb su
     mobile sono troppo piccole, le fai più grandi? non è un problema se i
     disegni vengono tagliati leggermente ai lati"): a 390px di finestra
     la colonna disponibile misura 358px (.card-list/.card) e la thumb ne
     occupava solo 315, con 43px vuoti ai lati perche' .card ha
     align-items:center. 352px riempie quasi tutta la colonna, con un
     margine minimo (6px) apposta per non toccare il bordo per un pixel
     di arrotondamento — il permesso riguarda SOLO questo taglio
     orizzontale ai bordi della finestra, non lo sbordo verticale dei
     disegni verso il titolo (vedi il gap qui sotto in .card, che e'
     stato dovuto ricalcolare per la stessa ragione). */
  max-width: 352px;
  aspect-ratio: 16 / 9; /* always — image is always 16:9, at every tier */
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

@media (min-width: 600px) {
  .card { flex-direction: row; align-items: center; gap: var(--space-4); }
  .card__media { max-width: 343px; }

  /* Thumb M and up: alternate image/text sides card by card (checkerboard) */
  .card-list__item:nth-child(even) .card { flex-direction: row-reverse; }
  .card-list__item:nth-child(even) .card__content { text-align: right; }
}

@media (min-width: 900px) {
  .card { gap: var(--space-5); }
  .card__media { max-width: 469px; }

  /* Thumb L: two extra "columns" of side margin so the row doesn't feel oversized */
  .page { padding-inline: var(--space-8); }
}

@media (min-width: 1280px) {
  /* Misurato su assets/pagine/XL.png dentro la colonna reale da 1088px:
     l'immagine (bbox ruotata 483-506px -> box ~490) e il gap ~80px
     lasciano al testo ~520-534px. Il 549+32 precedente veniva dalla
     reference isolata del componente (Thumb brakepoint.png) e in
     colonna stringeva troppo il testo, mandando il titolo a 3 righe
     invece delle 2 della tavola. */
  .card { gap: var(--space-8); }
  .card__media { max-width: 523px; }
}

/* Sopra i 1728 la thumb cresce insieme alla colonna.

   I valori del tier XL sono misurati su assets/pagine/XL.png, canvas 1728,
   dentro la colonna reale da 1088: l'immagine 523, il gap 64, al testo i
   501 che restano. Sopra quella larghezza gli stessi numeri diventano
   FRAZIONI DELLA COLONNA invece di misure assolute, cosi' i tre pezzi
   della riga restano nel rapporto in cui sono stati disegnati, quale che
   sia la larghezza a cui la colonna arriva.

   Agganciati a --container e non alla finestra apposta: quanto la colonna
   cresca lo decide tokens.css (a meta' passo, e con un tetto), e la thumb
   deve seguire QUELLA, non la finestra. Cambiando li' il ritmo, qui non
   c'e' niente da rincorrere.

   Senza tutto questo, allargare la sola colonna avrebbe allargato il
   TESTO e basta: la thumb sarebbe rimasta 523 dentro una riga piu' larga,
   cioe' esattamente il difetto da togliere, con in piu' un titolo lungo
   il doppio dell'immagine.

   A 1728px esatti la colonna vale 1088 e i due conti danno 523 e 64:
   nessuno scalino sulla soglia, la tavola resta riprodotta al pixel. */
@media (min-width: 1728px) {
  .card { gap: calc(var(--container) * 0.0588); }        /* 64/1088 */
  .card__media { max-width: calc(var(--container) * 0.4807); }  /* 523/1088 */
}

.card__image {
  position: relative;
  z-index: 1; /* sopra .card__sketch: i segni devono restare dietro la foto, visibili solo dove sbordano */
  width: 100%; /* always fills .card__media, which is always 16:9 */
  height: 100%;
  border-radius: var(--radius-card);
  /* Piu' sottile del bordo condiviso (--stroke-card-width, 6px — usato
     anche dalle foto del collage About): qui e' scoped alla sola thumb,
     su richiesta diretta, non un cambio di token di sistema.
     (Provata anche una variante "glass" — bordo semitrasparente +
     backdrop-filter blur, come la navbar — scartata dopo prova dal vivo:
     non piaceva.) */
  border: 4px solid var(--stroke-card-color);
  box-shadow: var(--shadow-card);
  /* La copertina la porta l'HTML, con un background-image sull'elemento:
     e' l'unico dato che cambia da una card all'altra, e tenerlo li'
     evita quattro regole gemelle qui dentro.

     NON attraverso una custom property. Ci si era provato, e la pagina
     restava grigia: un url() relativo dentro una custom property si
     risolve rispetto al FOGLIO DI STILE CHE LA USA, non rispetto al
     documento che la dichiara — quindi "assets/copertine/dot.webp",
     scritto nell'index, veniva cercato in "/css/assets/copertine/".
     Uno style inline si risolve rispetto al documento, e il problema
     non esiste.

     Il grigio resta SOTTO, non al posto: e' quello che si vede mentre
     l'immagine si carica, e la card ha gia' la sua forma finita prima
     che arrivi.

     Le copertine sono ritagliate a 16/9, la stessa proporzione di
     .card__media: `cover` non taglia niente, serve solo ad arrivare al
     bordo arrotondato. */
  background-color: var(--color-grey-2);
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  transform: rotate(var(--card-rotate-base)) scale(1);
  /* exit timing (hover -> normal): applies when :hover no longer matches */
  transition:
    border-color var(--card-duration-exit) var(--card-ease),
    transform var(--card-duration-exit) var(--card-ease-weighted),
    box-shadow var(--card-duration-exit) var(--card-ease-weighted);
}

/* Il riquadro dello scarabocchio e' PIU GRANDE della foto e centrato su di
   essa, con la stessa proporzione del disegno che contiene.

   Prima era un inset fisso (-18.13% -6.48%), calibrato su disegni che
   avevano tutti la stessa proporzione. I disegni attuali ne hanno una
   diversa ciascuno (da 1.26 a 1.64): con un riquadro di proporzione fissa
   ognuno veniva rimpicciolito per starci dentro, a scale diverse fra loro
   (0.68-0.78), e i segni — che sono disegnati agli ANGOLI, fuori dalla
   card — finivano tirati sopra la foto e quindi nascosti dietro di lei.

   Ora la geometria arriva dal manifest (assets/sketches/manifest.json):
   ogni voce porta il cardBox, cioe' il riquadro che la foto occupava
   dentro il disegno quando e' stato fatto, misurato sui PNG di
   riferimento. js/card.js lo traduce nelle custom property qui sotto, che
   dimensionano e spostano il riquadro perche' quel cardBox coincida con la
   foto vera. --sketch-overhang resta come ritocco fine sopra la geometria
   misurata. */
.card__sketch {
  position: absolute;
  left: 50%;
  top: 50%;
  /* Dimensioni e scarto arrivano da js/card.js, che li calcola dal
     cardBox nel manifest: sono cio' che fa coincidere il riquadro-card
     dentro il disegno con la foto vera. I valori di ripiego servono solo
     se il manifest non li porta. */
  /* Il perno della rotazione e' il centro della FOTO, non quello della
     cornice del disegno. La card ruota attorno al proprio centro; se il
     disegno ruotasse attorno al centro della sua cornice — che in due
     casi su quattro non coincide — i segni si sposterebbero rispetto alla
     card proprio perche' e' ruotata. */
  transform-origin: calc(50% + var(--sketch-dx, 0) * 100%)
    calc(50% + var(--sketch-dy, 0) * 100%);
  width: calc(100% * var(--sketch-w, 1.37) * var(--sketch-overhang));
  height: calc(100% * var(--sketch-h, 1.5) * var(--sketch-overhang));
  z-index: 0; /* dietro .card__image: visibile solo nella parte che sborda dai bordi della foto */
  pointer-events: none;
  transform: translate(
      calc(-50% - var(--sketch-dx, 0) * 100%),
      calc(-50% - var(--sketch-dy, 0) * 100%)
    )
    rotate(var(--card-rotate-base)) scale(var(--sketch-scale));
  /* Nessuna riduzione a riposo: il vecchio 0.92 (che cresceva a 1 in
     hover) era parte della calibrazione precedente. Ora la distanza dal
     bordo della foto e' calcolata sul disegno vero (vedi "stacco" nel
     manifest), e rimpicciolire a riposo riporterebbe i segni verso la
     card proprio durante la dissolvenza d'uscita — cioe' li farebbe
     toccare, che e' quello che non deve mai succedere. */
  transition: transform var(--card-duration-exit) var(--card-ease-weighted);
}

.card__sketch svg {
  display: block;
  width: 100%;
  height: 100%;
  overflow: visible;
}

/* v2: i tratti non si nascondono piu' con l'opacita' ma con il
   tratteggio (js/presence/ink.js), cosi possono essere DISEGNATI invece
   che comparire. Restano opachi: e' lo scostamento del tratteggio a
   renderli invisibili finche' Matteo non li traccia. */
.card__sketch svg path {
  opacity: 1;
}

/* Correzioni B3: uscendo dall'hover lo scarabocchio sparisce (e'
   davvero uno stato di hover, non un "una volta sola") — dissolvenza
   sull'SVG, non sui singoli path: cosi' non serve toccare la regola di
   opacita' dei path qui sopra ne' litigare per la transizione di
   transform gia' impostata su .card__sketch. Stessa
   --card-duration-exit delle altre uscite della card, che e' sempre piu'
   rapida della durata d'entrata del tracciamento (le uscite sono sempre
   piu' rapide delle entrate). Perche' una dissolvenza e non un
   ripercorrere il tratto a ritroso: vedi task-6-report.md. */
.card__sketch.is-uscita svg {
  opacity: 0;
  transition: opacity var(--card-duration-exit) var(--card-ease-out);
}

.card__content {
  width: 100%;
  max-width: 315px; /* S: matches .card__media's max-width so the text block is the same
                        width as the thumb and centers with it (text itself stays left-aligned) */
}

@media (min-width: 600px) {
  .card__content { width: auto; max-width: none; flex: 1 1 auto; }
}

.card__title {
  margin: 0 0 var(--space-2); /* S: tighter to the label — 8px */
  color: var(--color-black);
  font-size: 24px; /* S: bigger than body(16px), kept an 8px multiple */
  text-decoration-line: underline;
  text-decoration-color: transparent;
  text-decoration-thickness: 3px;
  text-underline-offset: 6px;
  transition: text-decoration-color var(--card-duration-enter) var(--card-ease);
}

/* ---------- Il nome del progetto, cerchiato/sottolineato a mano ----------
   Vedi js/card-marks.js: sul nome del progetto dentro il titolo (non su
   tutta la frase) viene disegnato, tracciato come gli altri segni del
   sito, uno dei disegni di assets/testi_card/V1..V6 — una versione a
   caso per caricamento, cosi' ogni visita sembra segnata da una mano
   diversa. Il contenitore e' lo span stesso: getBoundingClientRect() su
   di lui misura la parola vera, a qualunque dimensione di schermo. */
.card__mark {
  position: relative;
  display: inline-block;
}

.card__mark-ink {
  position: absolute;
  /* L'INCHIOSTRO STA SOTTO — stessa regola del livello presenza
     (presence.css, .presence--inchiostro): un segno che passa vicino
     alle lettere (es. il cerchio attorno a "Dot") le copriva invece di
     annotarle. z-index negativo, non 0: un discendente posizionato con
     z-index 0/auto dipinge comunque SOPRA il testo in flusso del suo
     genitore — solo il negativo lo porta sotto. */
  z-index: -1;
  /* --mark-off-x/-y (px, calcolati in JS da offX/offY misurati sui
     mockup) spostano il segno dal centro della parola: ogni disegno ha il
     proprio scostamento, non c'e' piu' un ramo "sopra" e uno "sotto" —
     vedi il commento in testa a js/card-marks.js per come sono stati
     ricavati pixel per pixel dai 24 riferimenti Figma. */
  left: calc(50% + var(--mark-off-x, 0px));
  top: calc(50% + var(--mark-off-y, 0px));
  transform: translate(-50%, -50%);
  pointer-events: none;
  /* Senza questo, lo span eredita il line-height del titolo (h1) attorno
     all'SVG che contiene: getBoundingClientRect() lo misura piu' alto di
     20-30px di quanto sia davvero, sballando la misura dell'altezza di
     riga (js/card-marks.js) su cui si basano sia l'altezza del segno che
     offY. */
  line-height: 0;
}

.card__mark-ink svg {
  /* L'SVG per default in Chrome/Safari ritaglia (overflow:hidden) tutto
     cio' che sborda dal viewBox. Il tratto e' spesso 6px e la geometria
     tocca i bordi del viewBox esatti (stiraTracciati la porta a 0..
     larghezza/altezza): senza questo, meta' dello spessore del tratto
     lungo ogni bordo veniva tagliato via, e il segno reso risultava
     sistematicamente piu' piccolo di qualche punto percentuale rispetto
     alla misura calcolata — verificato confrontando pixel per pixel il
     render effettivo con l'intenzione. */
  overflow: visible;
  /* Senza questo, l'SVG resta allineato al baseline del testo (il suo
     default da elemento inline sostituito): anche con line-height:0 sul
     contenitore, l'allineamento al baseline lascia uno scarto sotto
     l'immagine leggermente diverso da quello sopra, e il centraggio
     verticale (top:50%/translateY(-50%) su .card__mark-ink) finisce
     spostato di qualche punto percentuale verso l'alto — verificato
     confrontando il render con l'intenzione su piu' segni, sempre nella
     stessa direzione. display:block toglie l'SVG dal flusso inline della
     riga: il suo bordo, non il baseline, e' quello che conta. */
  display: block;
}

.card__label {
  margin: 0;
  color: var(--color-black-2);
  font-size: var(--font-size-caption);
}

@media (min-width: 600px) {
  .card__title { font-size: var(--font-size-h4); margin-bottom: var(--space-3); }
  .card__label { font-size: var(--font-size-body-small); }
}

@media (min-width: 900px) {
  .card__title { font-size: var(--font-size-h3); }
}

@media (min-width: 1280px) {
  .card__title { font-size: var(--font-size-h1); }
  .card__label { font-size: var(--font-size-body); }
}

/* Nessuno scatto a 1728: nella tavola XL.png (canvas 1728) il titolo
   della thumb misura ~46-48px (interlinea 55px fra le due righe), cioè
   h1 — non title1. Resta quindi h1 da 1280 in su. */

/* ---------- Hover state (Section.png: State: Hover) ---------- */

@media (hover: hover) and (pointer: fine) {
  .card:hover .card__image {
    border-color: var(--color-blue);
    box-shadow: var(--card-shadow-hover);
    /* 1.035 si leggeva chiaramente ma, live, il gesto risultava troppo
       marcato per il tono "raffinato" del sito (feedback diretto): 1.02
       resta percepibile senza sembrare un salto. */
    transform: rotate(var(--card-rotate-hover)) scale(1.02);
    /* enter timing (normal -> hover) */
    transition:
      border-color var(--card-duration-enter) var(--card-ease),
      transform var(--card-duration-enter) var(--card-ease-weighted),
      box-shadow var(--card-duration-enter) var(--card-ease-weighted);
  }

  .card:hover .card__sketch {
    transform: translate(
        calc(-50% - var(--sketch-dx, 0) * 100%),
        calc(-50% - var(--sketch-dy, 0) * 100%)
      )
      rotate(var(--card-rotate-hover)) scale(var(--sketch-scale));
    transition: transform var(--card-duration-enter) var(--card-ease-weighted);
  }

  .card:hover .card__title {
    text-decoration-color: currentColor;
  }
}

@media (prefers-reduced-motion: reduce) {
  :root {
    --card-duration-enter: 1ms;
    --card-duration-exit: 1ms;
  }
}

/* Il titolo della card e' un collegamento alla pagina del progetto. La
   sottolineatura che compare all'hover ce l'ha gia' .card__title (con la
   sua transizione): quella del browser andrebbe a sommarcisi, ferma e
   di un colore diverso. */
.card__title a {
  color: inherit;
  text-decoration: none;
}
