/*
Theme Name: LMCpro
Theme URI: #
Author: Luca Murani
Author URI: https://www.linkedin.com/in/luca-murani-745a2a168/
Description: Tema WordPress ibrido: template classici, design system pilotato da theme.json + Customizer, CSS-first con JavaScript ridotto al minimo indispensabile.
Version: 2.30.0
Requires at least: 6.6
Tested up to: 6.8
Requires PHP: 8.0
License: GNU General Public License v2 or later
License URI: http://www.gnu.org/licenses/gpl-2.0.html
Text Domain: lmcpro
This theme, like WordPress, is licensed under the GPL.
Use it to make something cool, have fun, and share what you've learned with others.
*/

/* ==========================================================================
   LIVELLO B — tutto il CSS del tema, dentro @layer.

   Qui NON si mettono override dei blocchi core: perderebbero comunque, perché
   il CSS di WordPress non è layerizzato e il CSS non layerizzato vince su
   qualunque @layer, a prescindere dalla specificità.
   Le override dei blocchi core stanno in assets/css/blocks.css (livello C).

   L'ordine sotto è l'ordine di priorità crescente: `utilities` è ultimo perché
   le classi utility devono poter vincere su tutto il resto senza !important.
   ========================================================================== */

@layer reset, basic, layout, main, forms, buttons, nav, consenso, animazioni, utilities;


/* ==========================================================================
   RESET
   ========================================================================== */
@layer reset {

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

	/* Nessun font-size fisso su html: sovrascriverebbe la dimensione di testo
	   scelta dall'utente nel browser, che è un'impostazione di accessibilità. */
	html {
		-webkit-text-size-adjust: 100%;
		text-size-adjust: 100%;
		/* I salti di ancora (torna in alto, indici) scorrono invece di
		   scattare. Il blocco reduced-motion nel layer animazioni lo riporta
		   a scatto secco per chi ha chiesto meno movimento. */
		scroll-behavior: smooth;
	}

	body {
		margin: 0;
		min-height: 100dvh;
		-webkit-font-smoothing: antialiased;
	}

	h1, h2, h3, h4, h5, h6,
	p, figure, blockquote, dl, dd,
	ol, ul { margin: 0; padding: 0; }

	ol, ul { list-style: none; }

	/* max-width, non width: un logo o un'icona non devono essere stirati
	   a tutta la larghezza del contenitore. */
	img, picture, svg, video, canvas {
		display: block;
		max-width: 100%;
		height: auto;
	}

	a { color: inherit; text-decoration: none; }

	input, button, textarea, select {
		font: inherit;
		color: inherit;
	}

	/* Il testo lungo non deve mai sfondare il contenitore. */
	p, li, h1, h2, h3, h4, h5, h6 { overflow-wrap: break-word; }
}


/* ==========================================================================
   BASIC — token e tipografia di base
   ========================================================================== */
@layer basic {

	:root {
		/* --- Colori -------------------------------------------------------
		   Alias leggibili dei preset generati da theme.json. La sorgente vera
		   dei valori è il Customizer, che li inietta in theme.json a runtime
		   (include/tokens.php). Il fallback dopo la virgola serve solo se
		   theme.json non è ancora stato caricato. */
		--color-base:        var(--wp--preset--color--base, #ffffff);
		--color-contrast:    var(--wp--preset--color--contrast, #16181d);
		--color-primary:     var(--wp--preset--color--primary, #3b725a);
		--color-secondary:   var(--wp--preset--color--secondary, #544790);
		--color-tertiary:    var(--wp--preset--color--tertiary, #c9c4b4);
		/* Le sorgenti sono i preset `anchor*` (dal 2.15: lo slug `link` in
		   palette collideva con la classe riservata `.has-link-color` di
		   Gutenberg); gli alias interni restano `--color-link*`, perché il
		   loro nome descrive il ruolo, non lo slug. */
		--color-link:        var(--wp--preset--color--anchor, #048ea0);
		--color-link-hover:  var(--wp--preset--color--anchor-hover, #105862);
		--color-link-active: var(--wp--preset--color--anchor-active, #0a3a41);

		/* --- Spaziature ---------------------------------------------------
		   Scala fluida definita in theme.json (settings.spacing.spacingSizes).
		   Nessun breakpoint: la dimensione interpola da sola fra 320px e 1440px. */
		--space-3xs: var(--wp--preset--spacing--xxxs, clamp(0.25rem, 0.241rem + 0.045vw, 0.281rem));
		--space-2xs: var(--wp--preset--spacing--xxs, clamp(0.5rem, 0.482rem + 0.089vw, 0.563rem));
		--space-xs:  var(--wp--preset--spacing--xs,  clamp(0.75rem, 0.723rem + 0.134vw, 0.844rem));
		--space-s:   var(--wp--preset--spacing--s,   clamp(1rem, 0.964rem + 0.179vw, 1.125rem));
		--space-m:   var(--wp--preset--spacing--m,   clamp(1.5rem, 1.446rem + 0.268vw, 1.688rem));
		--space-l:   var(--wp--preset--spacing--l,   clamp(2rem, 1.929rem + 0.357vw, 2.25rem));
		--space-xl:  var(--wp--preset--spacing--xl,  clamp(3rem, 2.893rem + 0.536vw, 3.375rem));
		--space-2xl: var(--wp--preset--spacing--xxl, clamp(4rem, 3.857rem + 0.714vw, 4.5rem));
		--space-3xl: var(--wp--preset--spacing--xxxl, clamp(6rem, 5.786rem + 1.071vw, 6.75rem));

		/* Respiro orizzontale della pagina. Usato anche da theme.json come
		   root padding, così i blocchi alignfull escono correttamente a filo. */
		--pad-inline: clamp(1rem, 5vw, 4rem);
		--pad-section: clamp(2rem, 8vw, 6rem);

		/* --- Layout -------------------------------------------------------- */
		--content-width: var(--wp--style--global--content-size, 1160px);
		--wide-width:    var(--wp--style--global--wide-size, 1400px);
		--header-height: clamp(3.5rem, 4rem + 2vw, 5.5rem);

		/* --- Tipografia -----------------------------------------------------
		   M7 sostituirà questi stack con i font scelti dal cliente. Fino ad
		   allora il tema gira su font di sistema: nessuna chiamata esterna,
		   nessun layout shift, nessun problema GDPR. */
		--font-primary: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
		--font-2: Georgia, "Times New Roman", serif;
		--font-3: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;

		--line-height-tight: 1.15;
		--line-height-base: 1.6;
		--measure: 68ch; /* larghezza di riga leggibile */

		/* --- Bottoni: forma e dimensione -------------------------------------
		   I COLORI dei bottoni (--btn-bg, --btn-text…) NON stanno qui: arrivano
		   dal Customizer come blocco :root non layerizzato (include/tokens.php).

		   Queste variabili sono il meccanismo con cui funzionano TUTTE le
		   varianti di bottone: theme.json non scrive più valori letterali ma
		   `var(--btn-radius)`, `var(--btn-pad-block)` ecc. Una classe come
		   .btn-pill si limita quindi a ridefinire la variabile, e il valore
		   scende per ereditarietà fino al bottone — anche quando la classe è
		   sul contenitore del blocco Gutenberg e non sul link vero e proprio.
		   Nessuna guerra di specificità con il CSS di core. */
		--btn-radius-sm: 0.25rem;
		--btn-radius-md: 0.5rem;
		--btn-radius-lg: 1rem;
		--btn-radius-full: 999rem;

		--btn-radius: var(--btn-radius-md);

		/* Rapporto di partenza 1:2 verticale/orizzontale (README, sezione 11).
		   Le dimensioni .btn-sm e .btn-lg scalano da qui, non lo sostituiscono. */
		--btn-pad-block: 1rem;
		--btn-pad-inline: 2rem;
		--btn-font-size: var(--wp--preset--font-size--s, 1rem);

		/* Voci di menu: stessa logica, scala più compatta. */
		--nav-pad-block: 0.5rem;
		--nav-pad-inline: 1rem;

		/* --- Interazione ---------------------------------------------------- */
		--transition-fast: 0.15s;
		--transition-base: 0.28s;
		--easing: cubic-bezier(0.2, 0, 0, 1);

		--focus-ring-width: 2px;
		--focus-ring-offset: 3px;
		--focus-ring-color: var(--color-contrast);
	}

	body {
		background-color: var(--color-base);
		color: var(--color-contrast);
		font-family: var(--font-primary);
		line-height: var(--line-height-base);
	}

	h1, h2, h3, h4, h5, h6 {
		line-height: var(--line-height-tight);
		font-weight: 600;
		text-wrap: balance;
	}

	/* Le dimensioni tipografiche arrivano dai preset di theme.json: una sola
	   scala, usata sia dai blocchi core sia dal markup dei template. */
	h1 { font-size: var(--wp--preset--font-size--xxl, clamp(2.07rem, 1.661rem + 2.043vw, 3.5rem)); }
	h2 { font-size: var(--wp--preset--font-size--xl,  clamp(1.728rem, 1.462rem + 1.331vw, 2.66rem)); }
	h3 { font-size: var(--wp--preset--font-size--l,   clamp(1.44rem, 1.28rem + 0.8vw, 2rem)); }
	h4 { font-size: var(--wp--preset--font-size--m,   clamp(1.2rem, 1.114rem + 0.429vw, 1.5rem)); }
	h5 { font-size: var(--wp--preset--font-size--s,   clamp(1rem, 0.964rem + 0.179vw, 1.125rem)); }
	h6 { font-size: var(--wp--preset--font-size--xs,  clamp(0.833rem, 0.803rem + 0.149vw, 0.938rem)); }

	p, li, dd { text-wrap: pretty; }

	/*
	 * Link senza sottolineatura a riposo, sottolineati su hover e focus.
	 *
	 * Nota di accessibilità: WCAG 1.4.1 chiede che un link dentro un blocco di
	 * testo non sia distinguibile SOLO dal colore. Senza sottolineatura la
	 * condizione si rispetta se il contrasto fra --color-link e --color-contrast
	 * è almeno 3:1 — cosa che dipende dai colori scelti nel Customizer, quindi va
	 * verificata lì. Se un giorno non tornasse, la classe `.link-underline`
	 * (layer utilities) rimette la sottolineatura dove serve.
	 */
	a:where(:not([class])) {
		color: var(--color-link);
		text-decoration: none;
		text-underline-offset: 0.15em;
		transition: color var(--transition-fast) var(--easing);
	}
	a:where(:not([class])):hover {
		color: var(--color-link-hover);
		text-decoration: underline;
	}
	a:where(:not([class])):focus-visible { text-decoration: underline; }
	a:where(:not([class])):active { color: var(--color-link-active); }

	/* Focus visibile ovunque, una volta sola. Mai `outline: none` senza
	   alternativa: è il modo più rapido di rendere un sito inutilizzabile
	   da tastiera. */
	:focus-visible {
		outline: var(--focus-ring-width) solid var(--focus-ring-color);
		outline-offset: var(--focus-ring-offset);
		border-radius: 2px;
	}

	::selection {
		background-color: var(--color-primary);
		color: var(--color-base);
	}
}


/* ==========================================================================
   LAYOUT — struttura di pagina e contenitori
   ========================================================================== */
@layer layout {

	.site {
		display: flex;
		flex-direction: column;
		min-height: 100dvh;
	}

	/* `overflow-x: clip` (v2.25.3): un elemento decorativo che sborda di lato
	   di proposito — un fiore tagliato a metà dal bordo dello schermo — viene
	   tagliato qui invece di allargare la pagina con una barra orizzontale.
	   `clip` e non `hidden`: non crea un contenitore di scorrimento, quindi
	   `position: sticky` dentro il main continua a funzionare, e l'asse
	   verticale resta libero di sbordare. */
	.site-main {
		flex: 1 0 auto;
		overflow-x: clip;
	}

	/* Contenitore standard. `min()` invece di una media query: la larghezza
	   massima e il respiro laterale sono la stessa regola. */
	.content {
		width: min(100% - (var(--pad-inline) * 2), var(--content-width));
		margin-inline: auto;
	}

	.content--wide { max-width: var(--wide-width); }

	.section {
		padding-block: var(--pad-section);
	}

	/* Quando la pagina APRE con un hero o una fascia a tutta larghezza, il
	   respiro sopra il contenuto lo gestisce la fascia: il padding della
	   sezione sparisce e la pagina attacca alla barra. Simmetrico in chiusura:
	   una fascia finale (es. CTA) atterra direttamente sul footer. */
	.section:has(.entry-content > :is(.hero, .full-bleed):first-child) {
		padding-block-start: 0;
	}

	.section:has(.entry-content > :is(.hero, .full-bleed):last-child) {
		padding-block-end: 0;
	}

	/* Ritmo verticale del contenuto: ogni elemento riceve spazio dal precedente,
	   il primo no. Un solo selettore invece di margini sparsi sui componenti. */
	.flow > * + * { margin-block-start: var(--flow-space, var(--space-m)); }

	/* Il ritmo automatico vale per il testo nudo; i mattoni di composizione
	   (gruppi, colonne, cover, spaziatori) si posizionano da soli: lo spazio
	   fra le sezioni lo decide chi compone, con gli spaziatori. Le pagine
	   documento (testo al primo livello) non sono toccate. */
	.entry-content > :is(.wp-block-group, .wp-block-columns, .wp-block-cover, .wp-block-spacer) {
		margin-block-start: 0;
	}

	/*
	 * Il reset azzera `list-style` su tutti gli elenchi, perché quasi tutti
	 * quelli del tema sono menu e griglie. Gli elenchi scritti nei contenuti
	 * però i punti li devono avere: qui si rimettono, senza toccare il reset
	 * che serve a tutto il resto.
	 */
	ul.wp-block-list,
	.entry-content ul:not([class]) { list-style: disc; }

	ol.wp-block-list,
	.entry-content ol:not([class]) { list-style: decimal; }

	.wp-block-list,
	.entry-content :is(ul, ol):not([class]) { padding-inline-start: 1.4em; }

	/* ------------------------------------------------------------------
	   CONTENITORE DEL CONTENUTO — alignwide e alignfull

	   Perché serve: un blocco marcato "a tutta larghezza" in Gutenberg riceve
	   la classe `.alignfull`, ma da solo non può uscire da un contenitore che
	   lo limita. Prima `.entry-content` era dentro `.content` (max 1160px),
	   quindi una fascia a tutta pagina restava larga 1160px.

	   La soluzione è quella dei temi a blocchi: il contenitore è largo quanto
	   la pagina e mette il respiro laterale come PADDING; i figli si limitano
	   da soli alla larghezza del contenuto, e `.alignfull` annulla il padding
	   con un margine negativo.

	   Si usa il padding e non `width: 100vw`: `vw` include la barra di scorrimento
	   e su Windows produce qualche pixel di scroll orizzontale su ogni fascia.
	   ------------------------------------------------------------------ */
	.content-canvas {
		padding-inline: var(--pad-inline);
	}

	.content-canvas > * {
		max-width: var(--content-width);
		margin-inline: auto;
	}

	.content-canvas > .alignwide {
		max-width: var(--wide-width);
	}

	.content-canvas > .alignfull,
	.content-canvas > .full-bleed {
		max-width: none;
		/* Annulla il padding del contenitore: la fascia arriva ai bordi della
		   pagina restando dentro il flusso, senza margini negativi da viewport. */
		margin-inline: calc(var(--pad-inline) * -1);
	}

	/* Colonna di testo leggibile. Non è più applicata d'ufficio a tutto il
	   contenuto: una pagina Servizi con griglie e fasce ha bisogno di tutta la
	   larghezza, un articolo no. Si mette dove serve. */
	.prose { max-width: var(--measure); }
	.prose > * { max-width: var(--measure); }

	.entry-thumbnail img { width: 100%; }
	.entry-thumbnail figcaption {
		margin-block-start: var(--space-2xs);
		font-size: var(--wp--preset--font-size--xs);
		color: color-mix(in srgb, var(--color-contrast) 65%, transparent);
	}

	/* ------------------------------------------------------------------
	   GRIGLIA PORTFOLIO A MOSAICO

	   Nessuna libreria: `auto-fill` + `minmax()` decidono da soli quante
	   colonne stanno nello spazio disponibile, `grid-auto-rows` dà alle righe
	   un'altezza fissa — che è la condizione perché uno span verticale
	   significhi davvero "alto il doppio".

	   Il `min()` dentro `minmax()` non è un vezzo: senza, su schermi più
	   stretti della larghezza minima di colonna la griglia sfonderebbe il
	   viewport producendo scroll orizzontale.
	   ------------------------------------------------------------------ */
	.portfolio-grid {
		display: grid;
		grid-template-columns: repeat(auto-fill, minmax(min(var(--grid-col-min, 20rem), 100%), 1fr));
		grid-auto-rows: var(--grid-row-height, 14rem);
		gap: var(--space-m);
	}

	/*
	 * Ritmo automatico: sfalsa alcuni riquadri così che una griglia mai curata
	 * a mano non risulti monotona.
	 *
	 * `:not([class*="span-"])` è la parte importante: un progetto a cui il
	 * grafico ha assegnato una dimensione esplicita deve restare esattamente
	 * come l'ha voluto, non ricevere anche lo span automatico e diventare 2×2
	 * per sbaglio.
	 */
	.portfolio-grid.has-auto-rhythm > :nth-child(6n + 1):not([class*="span-"]) { grid-row: span 2; }
	.portfolio-grid.has-auto-rhythm > :nth-child(6n + 4):not([class*="span-"]) { grid-column: span 2; }

	/* Sotto i 640px la griglia sfalsata diventa illeggibile: si normalizza.
	   Le classi .span-* esplicite si normalizzano da sole nel layer utilities. */
	@media (max-width: 639.98px) {
		.portfolio-grid.has-auto-rhythm > * {
			grid-column: auto;
			grid-row: auto;
		}
	}

	.pagination ul {
		display: flex;
		flex-wrap: wrap;
		gap: var(--space-2xs);
		justify-content: center;
	}
	.pagination a,
	.pagination span {
		display: inline-flex;
		align-items: center;
		justify-content: center;
		min-width: 2.75rem;
		min-height: 2.75rem;
		padding-inline: var(--space-2xs);
		border: 1px solid var(--color-tertiary);
		border-radius: var(--btn-radius-sm);
	}
	.pagination .current {
		background-color: var(--color-primary);
		border-color: var(--color-primary);
		color: var(--color-base);
	}
}


/* ==========================================================================
   MAIN — componenti di contenuto
   ========================================================================== */
@layer main {

	.entry-header { margin-block-end: var(--space-l); }

	.entry-meta {
		margin-block-start: var(--space-2xs);
		font-size: var(--wp--preset--font-size--xs);
		color: color-mix(in srgb, var(--color-contrast) 65%, transparent);
	}

	.entry-list {
		display: grid;
		gap: var(--space-xl);
		grid-template-columns: repeat(auto-fill, minmax(min(20rem, 100%), 1fr));
	}

	.entry-card__title { font-size: var(--wp--preset--font-size--l); }

	/* ------------------------------------------------------------------
	   RIQUADRO DELLA GRIGLIA PORTFOLIO
	   ------------------------------------------------------------------ */
	.portfolio-item {
		position: relative;
		overflow: hidden;
		border-radius: var(--btn-radius-md);
		background-color: color-mix(in srgb, var(--color-tertiary) 45%, transparent);

		/*
		 * Il browser salta il lavoro di rendering dei riquadri fuori schermo e
		 * lo fa solo quando stanno per entrare nel viewport. Su un portfolio
		 * lungo è la differenza fra disegnare dodici riquadri e disegnarne
		 * cinquanta.
		 *
		 * È sicuro qui perché l'altezza del riquadro la decide la griglia
		 * (`grid-auto-rows`), non il suo contenuto: saltare il contenuto non
		 * può quindi provocare sobbalzi di layout. `auto` in
		 * contain-intrinsic-size fa comunque ricordare al browser l'ultima
		 * dimensione reale.
		 */
		content-visibility: auto;
		contain-intrinsic-size: auto var(--grid-row-height, 14rem);
	}

	.portfolio-item__link {
		display: block;
		height: 100%;
		color: inherit;
		text-decoration: none;
	}

	/* height: 100% è ciò che fa riempire la cella; object-fit: cover evita che
	   un'immagine con proporzioni diverse dallo span venga deformata. */
	.portfolio-item img,
	.portfolio-item__placeholder {
		display: block;
		width: 100%;
		height: 100%;
		object-fit: cover;
	}

	/* Cornice della foto: lo zoom al passaggio avviene dentro di lei
	   (utility `zoom-in-inside` in blocks.css, dal 2.29.0). Gli angoli si
	   regolano con --zoom-radius, anche dal CSS aggiuntivo del blocco. */
	.portfolio-item__media {
		display: block;
		height: 100%;
		--zoom-radius: var(--btn-radius-md);
	}

	.portfolio-item__body {
		position: absolute;
		inset-inline: 0;
		inset-block-end: 0;
		display: flex;
		flex-direction: column;
		gap: var(--space-3xs);
		padding: var(--space-s);
		color: #fff;
		/* Sfumatura e non tinta piatta: il titolo resta leggibile su qualunque
		   immagine senza coprire il lavoro del grafico più del necessario. */
		background: linear-gradient(to top, rgb(0 0 0 / 0.75), rgb(0 0 0 / 0));
	}

	.portfolio-item__title {
		font-size: var(--wp--preset--font-size--m);
		font-weight: 600;
		line-height: var(--line-height-tight);
		text-wrap: balance;
	}

	.portfolio-item__meta,
	.portfolio-item__categoria {
		font-size: var(--wp--preset--font-size--xs);
		opacity: 0.85;
	}

	/*
	 * Descrizione breve: al massimo due righe. Le righe della griglia hanno
	 * altezza fissa, quindi un testo libero di allungarsi toglierebbe spazio
	 * all'immagine di un solo riquadro e sfalserebbe i bordi fra vicini.
	 * `-webkit-line-clamp` e' la forma supportata da tutti i browser attuali.
	 */
	.portfolio-item__descrizione {
		display: -webkit-box;
		-webkit-box-orient: vertical;
		-webkit-line-clamp: 2;
		overflow: hidden;
		font-size: var(--wp--preset--font-size--xs);
		line-height: var(--line-height-tight, 1.3);
	}

	/*
	 * TESTI SOTTO L'IMMAGINE — opzione "Testi sotto l'immagine" del blocco
	 * (classe `has-caption-below` sulla griglia, dal 2.23.0).
	 *
	 * Ogni riga si allunga da sola dello spazio dei testi (`--caption-space`):
	 * l'altezza riga scelta nel blocco resta cosi' l'altezza dell'IMMAGINE.
	 * Dentro la cella il link e' una colonna flex, i testi hanno altezza fissa
	 * e l'immagine prende il resto (`flex: 1 1 0` + `min-height: 0`, senza il
	 * quale un'immagine alta sfonderebbe la cella). Misurato nel 2.23.0 senza
	 * questa riserva: un titolo su due righe accorciava l'immagine del suo solo
	 * riquadro (92px contro i 137 del vicino) e i bordi non combaciavano piu'.
	 * Le dimensioni verticale, orizzontale e grande continuano a valere.
	 *
	 * Lo zoom al passaggio resta dentro la cornice della foto
	 * (`.portfolio-item__media`), quindi non esce dall'arrotondamento e non
	 * finisce sopra i testi. Fino al 2.28 qui era una schiarita.
	 */
	/*
	 * Lo spazio dei testi e' calcolato dai token tipografici, non scritto a
	 * mano: stacco dall'immagine + 2 righe di titolo + 1 di categoria + 2 di
	 * descrizione + i due spazi interni. Nel 2.23.1 era un 7.5rem fisso e non
	 * bastava: a 1512px (titolo 24px) il riquadro dei testi schiacciava il
	 * titolo a 48px invece dei 55 delle sue due righe, tagliandolo. Con i
	 * font-size fluidi del tema la formula resta giusta a ogni larghezza.
	 * I 2px finali assorbono gli arrotondamenti dei sub-pixel.
	 */
	.portfolio-grid.has-caption-below {
		--caption-lh: 1.25;
		--caption-space: calc(
			var(--space-2xs) + 2 * var(--space-3xs) + 2px
			+ (2 * var(--wp--preset--font-size--m) + 3 * var(--wp--preset--font-size--xs)) * var(--caption-lh)
		);
		grid-auto-rows: calc(var(--grid-row-height, 14rem) + var(--caption-space));
	}

	/* Senza categoria e descrizione ("Mostra categoria e descrizione" spento)
	   resta da riservare solo il titolo. */
	.portfolio-grid.has-caption-below:not(:has(.portfolio-item__categoria, .portfolio-item__descrizione)) {
		--caption-space: calc(var(--space-2xs) + 2px + 2 * var(--wp--preset--font-size--m) * var(--caption-lh));
	}

	/*
	 * Righe fisse: titolo e descrizione occupano sempre due righe anche quando
	 * il testo ne usa una, cosi' tutti i riquadri hanno testi alti uguali e le
	 * immagini della stessa riga finiscono allo stesso pixel. Nessun elemento
	 * puo' restringersi. Interlinea 1.25 e non 1.15: con il titolo tagliato a
	 * due righe, le lettere che scendono sotto la riga (g, p) verrebbero
	 * mozzate in basso.
	 */
	.portfolio-grid.has-caption-below .portfolio-item__body > * {
		flex-shrink: 0;
		line-height: var(--caption-lh);
	}

	.portfolio-grid.has-caption-below .portfolio-item__title,
	.portfolio-grid.has-caption-below .portfolio-item__descrizione {
		min-height: calc(2em * var(--caption-lh));
	}

	.portfolio-grid.has-caption-below .portfolio-item {
		overflow: visible;
		border-radius: 0;
		background-color: transparent;
	}

	.portfolio-grid.has-caption-below .portfolio-item__link {
		display: flex;
		flex-direction: column;
		gap: var(--space-2xs);
	}

	.portfolio-grid.has-caption-below .portfolio-item__media {
		flex: 1 1 0;
		min-height: 0;
		background-color: color-mix(in srgb, var(--color-tertiary) 45%, transparent);
	}

	/*
	 * Colore esplicito e non `inherit`: il riquadro dei testi sta dentro un
	 * <a>, e il colore dei link arriva da theme.json (styles.elements.link)
	 * in una regola NON layerizzata che batte qualunque @layer — ereditando,
	 * titolo e descrizione uscivano del colore dei link. Questo span non e'
	 * un link, quindi la regola di theme.json non lo tocca.
	 *
	 * Altezza fissa pari allo spazio riservato alla riga, meno lo stacco fra
	 * immagine e testi: e' cio' che tiene l'immagine alta uguale in tutti i
	 * riquadri della stessa riga.
	 */
	.portfolio-grid.has-caption-below .portfolio-item__body {
		position: static;
		flex: 0 0 auto;
		height: calc(var(--caption-space) - var(--space-2xs));
		overflow: hidden;
		padding: 0;
		color: var(--color-contrast, #16181d);
		background: none;
	}

	.portfolio-grid.has-caption-below .portfolio-item__title {
		display: -webkit-box;
		-webkit-box-orient: vertical;
		-webkit-line-clamp: 2;
		overflow: hidden;
	}

	/* L'anello di focus torna fuori dal riquadro: i testi sono sulla pagina. */
	.portfolio-grid.has-caption-below .portfolio-item__link:focus-visible {
		outline-color: currentColor;
		outline-offset: var(--focus-ring-offset);
	}

	/* Offset negativo: l'anello di focus deve restare dentro il riquadro, che ha
	   overflow: hidden e altrimenti lo taglierebbe. */
	.portfolio-item__link:focus-visible {
		outline: var(--focus-ring-width) solid #fff;
		outline-offset: calc(var(--focus-ring-offset) * -1);
	}

	.portfolio-grid-empty {
		padding: var(--space-xl);
		text-align: center;
		border: 1px dashed var(--color-tertiary);
		border-radius: var(--btn-radius-md);
	}

	/* La scheda del progetto (riassunto, cliente, anno, ruolo) e il suo
	   layout a due colonne sono stati tolti nel 2.26.0: la pagina del
	   progetto si compone tutta in Gutenberg. */

	/* Link al contenuto precedente e successivo degli articoli (single.php). */
	.entry-nav {
		display: flex;
		flex-wrap: wrap;
		gap: var(--space-m);
		justify-content: space-between;
		margin-block-start: var(--space-2xl);
		padding-block-start: var(--space-m);
		border-block-start: 1px solid var(--color-tertiary);
	}

	.entry-nav__next { margin-inline-start: auto; text-align: end; }

	/* 404 e stati vuoti */
	.page-placeholder {
		padding-block: var(--space-3xl);
		text-align: center;
	}

	/* Footer */
	.site-footer {
		margin-block-start: var(--space-3xl);
		padding-block: var(--space-xl);
		border-block-start: 1px solid var(--color-tertiary);
		font-size: var(--wp--preset--font-size--xs);
	}

	.site-footer__inner {
		display: flex;
		flex-wrap: wrap;
		gap: var(--space-m);
		justify-content: space-between;
		align-items: start;
	}

	.site-legal__name { font-weight: 600; }

	.site-legal__details {
		display: flex;
		flex-wrap: wrap;
		gap: var(--space-2xs) var(--space-s);
	}

	.footer-menu {
		display: flex;
		flex-wrap: wrap;
		gap: var(--space-2xs) var(--space-m);
	}
}


/* ==========================================================================
   FORMS — struttura pronta, riempita in M5 (Contact Form 7)
   ========================================================================== */
@layer forms {

	label { display: block; }

	input:not([type="checkbox"]):not([type="radio"]):not([type="submit"]),
	textarea,
	select {
		width: 100%;
		padding: var(--space-2xs) var(--space-xs);
		background-color: var(--color-base);
		border: 1px solid var(--color-tertiary);
		border-radius: var(--btn-radius-sm);
		transition: border-color var(--transition-fast) var(--easing);
	}

	input:focus-visible,
	textarea:focus-visible,
	select:focus-visible { border-color: var(--color-primary); }

	textarea { min-height: 8rem; resize: vertical; }

	/* Modulo di ricerca (404 e pagina risultati): il campo occupa tutta la
	   riga e il pulsante Cerca va a capo — senza questo margine i due si
	   toccherebbero. */
	.search-form .search-submit { margin-block-start: var(--space-2xs); }
}


/* ==========================================================================
   BUTTONS — forma base. Il sistema completo (varianti, outline, ghost) è M2.
   Gli stati :focus-visible e :disabled dei bottoni CORE stanno in blocks.css,
   perché theme.json non conosce quei due pseudo-selettori.
   ========================================================================== */
@layer buttons {

	/*
	 * Forma base del bottone per il markup NOSTRO (template PHP, form).
	 * I bottoni di Gutenberg non passano da qui: li veste theme.json, che legge
	 * esattamente le stesse variabili. Un solo design system, due canali.
	 */
	.btn,
	button:not(.nav-toggle):not([class*="wp-"]),
	input[type="submit"] {
		display: inline-flex;
		align-items: center;
		justify-content: center;
		gap: var(--space-2xs);
		padding: var(--btn-pad-block) var(--btn-pad-inline);
		background-color: var(--btn-bg);
		color: var(--btn-text);
		border: 1px solid var(--btn-border);
		border-radius: var(--btn-radius);
		font-size: var(--btn-font-size);
		line-height: 1.2;
		text-align: center;
		text-decoration: none;
		/* cursor: pointer su TUTTA l'area cliccabile, in ogni stato, :active incluso. */
		cursor: pointer;
		transition:
			background-color var(--transition-fast) var(--easing),
			border-color var(--transition-fast) var(--easing),
			color var(--transition-fast) var(--easing),
			transform var(--transition-fast) var(--easing);
	}

	.btn:hover,
	button:not(.nav-toggle):not([class*="wp-"]):hover,
	input[type="submit"]:hover {
		background-color: var(--btn-bg-hover);
		border-color: var(--btn-border-hover);
		color: var(--btn-text-hover);
	}

	/* Focus visibile e distinto dall'hover: chi naviga da tastiera deve capire
	   dove si trova, e "sembra un hover" non è un'informazione sufficiente. */
	.btn:focus-visible,
	button:not(.nav-toggle):not([class*="wp-"]):focus-visible,
	input[type="submit"]:focus-visible {
		background-color: var(--btn-bg-focus);
		outline: var(--focus-ring-width) solid var(--btn-border-focus);
		outline-offset: var(--focus-ring-offset);
	}

	.btn:active,
	button:not(.nav-toggle):not([class*="wp-"]):active,
	input[type="submit"]:active {
		background-color: var(--btn-bg-active);
		transform: scale(0.98);
	}

	.btn:disabled,
	.btn[aria-disabled="true"],
	button:disabled,
	input[type="submit"]:disabled {
		background-color: var(--btn-bg-disabled);
		border-color: var(--btn-bg-disabled);
		color: var(--btn-text-disabled);
		cursor: not-allowed;
		transform: none;
	}

	.btn:disabled:hover,
	.btn[aria-disabled="true"]:hover,
	button:disabled:hover,
	input[type="submit"]:disabled:hover {
		background-color: var(--btn-bg-disabled);
		border-color: var(--btn-bg-disabled);
		color: var(--btn-text-disabled);
	}
}


/* ==========================================================================
   NAV — header e menu principale
   ========================================================================== */
@layer nav {

	.skip-link {
		position: absolute;
		inset-inline-start: var(--space-s);
		inset-block-start: var(--space-s);
		z-index: 999;
		padding: var(--space-2xs) var(--space-s);
		background-color: var(--color-contrast);
		color: var(--color-base);
		border-radius: var(--btn-radius-sm);
		/* Fuori schermo finché non riceve il focus da tastiera. */
		transform: translateY(-200%);
		transition: transform var(--transition-fast) var(--easing);
	}
	.skip-link:focus-visible { transform: translateY(0); }

	/* Barra fissa (Customizer, Header e menu). `sticky` e non `fixed`: non
	   toglie la barra dal flusso, quindi niente salto di layout né padding di
	   compensazione da calcolare. Il `top` tiene conto della barra admin di
	   WordPress, che espone la propria altezza come variabile. */
	body.has-fixed-header .site-header {
		position: sticky;
		top: var(--wp-admin--admin-bar--height, 0px);
	}

	.site-header {
		position: relative;
		z-index: 100;
		display: flex;
		flex-wrap: wrap;
		/* stretch e non center: è ciò che permette alle voci di menu di
		   occupare tutta l'altezza della barra. Gli elementi che non devono
		   allungarsi si ricentrano da soli con align-self. */
		align-items: stretch;
		justify-content: space-between;
		gap: var(--space-m);
		min-height: var(--header-height);
		padding-inline: var(--pad-inline);
		/* Nessun padding verticale sulla barra: lo spazio lo mettono i singoli
		   elementi, altrimenti l'hover a tutta altezza lascerebbe due strisce
		   scoperte sopra e sotto. */
		padding-block: 0;
		/* Il fallback non è ridondante: se per qualsiasi motivo i token runtime
		   non venissero stampati, senza di esso la barra resterebbe trasparente. */
		background-color: var(--header-bg, #3b725a);
		color: var(--header-text, #ffffff);
	}

	.site-nav {
		display: flex;
		align-items: stretch;
		/* gap zero: le voci si toccano, così l'evidenziazione dell'hover è
		   continua e non lascia striscioline di barra fra un elemento e l'altro. */
		gap: 0;
	}

	.site-branding {
		display: flex;
		flex-direction: column;
		justify-content: center;
		padding-block: var(--space-2xs);
	}
	.site-title { font-size: var(--wp--preset--font-size--m); font-weight: 600; }
	.site-description {
		font-size: var(--wp--preset--font-size--xs);
		color: color-mix(in srgb, var(--header-text, #ffffff) 75%, transparent);
	}
	.custom-logo { max-height: calc(var(--header-height) - var(--space-s)); width: auto; }

	/*
	 * LOGO SVG — altezza ESPLICITA, non `max-height`.
	 *
	 * Un SVG esportato col solo `viewBox` (il caso normale di Illustrator) ha una
	 * proporzione ma NESSUNA dimensione intrinseca. Con `height: auto` del reset
	 * il browser non ha una misura da cui partire, e qui dentro — contenitore
	 * flex, altezza governata dall'header — non ripiega sul default 300x150: il
	 * logo collassa a 0x0. Caricato, visibile, opaco, e largo zero: il tipo di
	 * guasto che non somiglia affatto alla sua causa.
	 *
	 * Dando l'altezza, la larghezza esce dalla proporzione. La regola vale solo
	 * per gli SVG: un logo raster ha dimensioni sue e continua a essere limitato
	 * dal `max-height` qui sopra, senza venire stirato se e' piu' basso.
	 *
	 * Parente stretto del fix della v2.16.0 sui contenuti (UseTheme 18.1): la'
	 * mancavano le dimensioni nei metadati, qui manca la misura intrinseca al
	 * file — stessa origine, due sintomi diversi.
	 */
	.custom-logo[src$=".svg" i] {
		height: calc(var(--header-height) - var(--space-s));
		width: auto;
		max-width: 100%;
		object-fit: contain;
	}

	/*
	 * VOCI DI MENU COME PULSANTI.
	 *
	 * Restano <a>, quindi mantengono la semantica corretta di link — un menu
	 * fatto di <button> sarebbe sbagliato per gli screen reader e romperebbe
	 * l'apertura in nuova scheda. Ereditano però forma e comportamento del
	 * pulsante, con la stessa scala di stati.
	 *
	 * I colori vengono dai token --nav-*, separati da quelli dei bottoni:
	 * un menu su barra colorata ha bisogno di una scala diversa da un bottone
	 * su fondo chiaro. Si configurano in Personalizza → Header e menu.
	 */
	/*
	 * ⚠️ Qui c'è solo FORMA e LAYOUT. I colori delle voci di menu stanno in
	 * assets/css/blocks.css, non per capriccio ma per necessità: theme.json
	 * genera per i link una regola NON layerizzata, che batte qualunque cosa
	 * scritta dentro un @layer. Vedi la sezione "Header e menu" di blocks.css.
	 */
	/* Ogni voce è una cella flessibile a tutta altezza: è l'<li> a distribuire
	   lo spazio, il link si limita a riempirlo. */
	.primary-menu li { display: flex; }

	.primary-menu a {
		position: relative; /* aggancio per la lineetta della pagina corrente */
		display: inline-flex;
		align-items: center;
		justify-content: center;
		padding: var(--nav-pad-block) var(--nav-pad-inline);
		border: 0;
		/* Spigoli vivi: l'evidenziazione va da bordo a bordo della barra, e un
		   raggio di curvatura la staccherebbe dal bordo superiore e inferiore. */
		border-radius: 0;
		white-space: nowrap;
		cursor: pointer;
	}

	/* --- Bottone hamburger: 3 lineette ---------------------------------- */
	.nav-toggle {
		position: relative;
		z-index: 2;
		/* La barra allunga i suoi figli: il bottone si ricentra da solo. */
		align-self: center;
		display: grid;
		place-items: center;
		width: 2.75rem;   /* 44px: area di tocco minima raccomandata */
		height: 2.75rem;
		padding: 0;
		background: none;
		border: 0;
		color: inherit;
		border-radius: var(--btn-radius-sm);
		cursor: pointer;
	}

	.nav-toggle:focus-visible {
		outline: var(--focus-ring-width) solid var(--nav-border-focus);
		outline-offset: var(--focus-ring-offset);
	}

	.hamburger-icon {
		position: relative;
	}

	.hamburger-icon,
	.hamburger-icon::before,
	.hamburger-icon::after {
		display: block;
		width: 1.5rem;
		height: 2px;
		background-color: currentColor;
		transition:
			transform var(--transition-fast) var(--easing),
			background-color var(--transition-fast) var(--easing);
	}

	/* Le due lineette esterne sono posizionate rispetto alla lineetta centrale,
	   non rispetto al bottone: così restano centrate qualunque sia la
	   dimensione dell'area di tocco. */
	.hamburger-icon::before,
	.hamburger-icon::after {
		content: "";
		position: absolute;
		inset-inline-start: 0;
		inset-block-start: 0;
	}
	.hamburger-icon::before { transform: translateY(-0.5rem); }
	.hamburger-icon::after  { transform: translateY(0.5rem); }

	/* Aperto: le tre lineette diventano una X. Lo stato lo detta aria-expanded,
	   che è l'unica fonte di verità — nessuna classe parallela da tenere in sync. */
	.nav-toggle[aria-expanded="true"] .hamburger-icon { background-color: transparent; }
	.nav-toggle[aria-expanded="true"] .hamburger-icon::before { transform: rotate(45deg); }
	.nav-toggle[aria-expanded="true"] .hamburger-icon::after  { transform: rotate(-45deg); }

	/* --- Sotto 768px: pannello a tutto schermo che entra da destra --------
	   Media query usata come rinforzo strutturale (cambio di paradigma di
	   layout), non per aggiustare dimensioni: quelle le gestisce clamp(). */
	@media (max-width: 767.98px) {

		.primary-menu {
			position: fixed;
			inset: 0;
			z-index: 1;
			display: flex;
			flex-direction: column;
			/* Niente spaziatura fra le righe e nessun padding laterale sul
			   pannello: il respiro orizzontale lo mette il link con il proprio
			   --nav-pad-inline. Se stesse qui, ogni riga resterebbe rientrata
			   dai bordi dello schermo e l'evidenziazione dell'hover
			   sembrerebbe un riquadro invece di una riga piena. */
			gap: 0;
			padding: calc(var(--header-height) + var(--space-l)) 0 var(--space-xl);
			/* Stesso fondo della barra: il pannello è la barra che si espande. */
			background-color: var(--header-bg, #3b725a);
			color: var(--header-text, #ffffff);
			overflow-y: auto;
			overscroll-behavior: contain;

			/* Entra da destra e copre TUTTA la pagina: nessuna sosta a metà
			   schermo, nessun velo semi-trasparente sul resto (README §10). */
			transform: translateX(100%);
			/* `visibility` non è decorativa: impedisce che le voci di menu
			   restino raggiungibili con Tab mentre il pannello è chiuso. */
			visibility: hidden;
			transition:
				transform var(--transition-base) var(--easing),
				visibility 0s linear var(--transition-base);
		}

		/* A schermo intero le voci diventano pulsanti a tutta larghezza.
		   Si ridefiniscono le variabili di padding, non la proprietà: la
		   lineetta della pagina corrente si posiziona a partire da quelle, e
		   scrivere `padding` a mano la manderebbe fuori registro. */
		.primary-menu a {
			--nav-pad-block: var(--space-xs);
			/* Stesso respiro laterale del resto della pagina: il testo delle
			   voci resta allineato ai contenuti, ma lo sfondo dell'hover
			   arriva comunque fino ai bordi dello schermo. */
			--nav-pad-inline: var(--pad-inline);
			/* L’<li> è un contenitore flex a tutta larghezza: senza flex: 1 il
			   link resterebbe largo quanto il testo e l’evidenziazione
			   dell’hover coprirebbe solo quello, non tutta la riga. */
			flex: 1;
			justify-content: flex-start;
			font-size: var(--wp--preset--font-size--m);
		}

		body.menu-open .primary-menu {
			transform: translateX(0);
			visibility: visible;
			transition:
				transform var(--transition-base) var(--easing),
				visibility 0s;
		}

		/* Niente scroll dietro al pannello aperto. */
		body.menu-open { overflow: hidden; }
	}

	/* --- Da 768px in su: menu orizzontale sempre visibile ----------------- */
	@media (min-width: 768px) {

		/* Il toggle non esiste proprio: non serve nasconderlo via JS. */
		.nav-toggle { display: none; }

		.primary-menu {
			display: flex;
			flex-wrap: wrap;
			align-items: stretch;
			gap: 0;
		}
	}
}


/* ==========================================================================
   CONSENSO — la barra che chiede se caricare i font Adobe.

   Il markup è sempre in pagina (include/consent.php lo stampa su wp_body_open,
   quindi sta in cima al DOM e in fondo allo schermo: chi naviga da tastiera
   incontra la scelta per prima) e sta nascosto qui: è lo snippet in <head> a
   rivelarlo mettendo
   `consenso-aperto` su <html>. Costruirlo in JavaScript a pagina caricata
   darebbe il lampo di una barra che compare in ritardo, e un salto del layout.

   Conseguenza voluta: senza JavaScript la classe non arriva mai, il banner non
   si vede e i font Adobe non si caricano. Il sito resta sul carattere di
   riserva, che è esattamente il comportamento prudente.

   Il layer sta DOPO `buttons` di proposito: i bottoni del banner devono poter
   ignorare i token globali dei bottoni senza rincorrerne la specificità, perché
   vivono su fondo viola e non sulla pagina bianca.
   ========================================================================== */
@layer consenso {

	.consenso { display: none; }

	.consenso-aperto .consenso { display: block; }

	.consenso {
		position: fixed;
		inset-inline: 0;
		inset-block-end: 0;
		/* Sopra la barra fissa (999): una scelta ancora da prendere non deve
		   finire sotto a nient'altro. */
		z-index: 1000;
		background-color: var(--color-primary);
		color: var(--color-tertiary);
		border-block-start: 1px solid var(--color-tertiary);
		font-size: var(--wp--preset--font-size--xs, 0.9rem);
		line-height: var(--line-height-base);
		animation: consenso-entra var(--transition-base) var(--easing);
	}

	@keyframes consenso-entra {
		from { transform: translateY(100%); }
		to   { transform: translateY(0); }
	}

	.consenso__inner {
		width: min(100% - (var(--pad-inline) * 2), var(--wide-width));
		margin-inline: auto;
		padding-block: var(--space-s);
		display: flex;
		flex-wrap: wrap;
		align-items: center;
		justify-content: space-between;
		gap: var(--space-s);
	}

	/* `flex: 1 1 32ch` e non una percentuale: il testo si allarga finché può e
	   va a capo quando scenderebbe sotto una riga leggibile, senza media query. */
	.consenso__testo {
		flex: 1 1 32ch;
		max-width: var(--measure);
	}

	/* ATTENZIONE — la dimensione del titolo e il colore dei link NON si
	   scrivono qui: perderebbero comunque. Li governano due regole fuori da
	   ogni layer (`h2` in blocks.css e `a:where(…)` degli stili globali di
	   theme.json), e il non-layerizzato batte qualunque @layer a prescindere
	   dalla specificità. Stanno in fondo a assets/css/blocks.css. */
	.consenso__titolo {
		margin: 0 0 var(--space-3xs);
	}

	.consenso__testo p { margin: 0; }

	.consenso__link {
		margin-block-start: var(--space-2xs);
		display: flex;
		flex-wrap: wrap;
		gap: var(--space-s);
	}

	.consenso__azioni {
		display: flex;
		flex-wrap: wrap;
		gap: var(--space-xs);
	}

	/*
	 * Bottoni bianchi con testo viola: 7,64:1 sul testo e 7,64:1 fra bottone e
	 * fondo, quindi conformi sia al 1.4.3 sia al 1.4.11. L'alternativa più
	 * ovvia — arancione con scritta bianca — sta a 2,67:1 e 2,86:1: si legge
	 * male e il bottone non stacca dal fondo. Non è un dettaglio da poco in un
	 * componente che esiste per dimostrare conformità.
	 *
	 * I due bottoni sono identici, e non per pigrizia: rifiutare deve costare
	 * quanto accettare. Differenziarli è il dark pattern contestato per primo.
	 */
	.consenso__btn {
		flex: 1 1 auto;
		min-width: 9rem;
		padding: var(--space-2xs) var(--space-m);
		background-color: var(--color-tertiary);
		color: var(--color-primary);
		border: 1px solid var(--color-tertiary);
		border-radius: var(--btn-radius);
		font-family: inherit;
		font-size: inherit;
		line-height: 1.2;
		text-align: center;
		cursor: pointer;
		transition:
			background-color var(--transition-fast) var(--easing),
			border-color var(--transition-fast) var(--easing),
			color var(--transition-fast) var(--easing);
	}

	/* Hover arancione col testo scuro: 6,21:1. Col bianco sarebbe 2,67:1 —
	   un bottone che diventa illeggibile proprio mentre lo si punta. */
	.consenso__btn:hover {
		background-color: var(--color-secondary);
		border-color: var(--color-secondary);
		color: var(--color-contrast);
	}

	/* L'anello di focus è bianco e staccato: sul viola fa 7,64:1, mentre lo
	   scuro del resto del sito si perderebbe (2,17:1). */
	.consenso__btn:focus-visible {
		outline: var(--focus-ring-width) solid var(--color-tertiary);
		outline-offset: var(--focus-ring-offset);
	}

	/* Il titolo riceve il focus quando si riaprono le preferenze: l'anello
	   serve a far capire dove si è finiti, non a decorare. */
	.consenso__titolo:focus-visible {
		outline: var(--focus-ring-width) solid var(--color-tertiary);
		outline-offset: var(--focus-ring-offset);
	}

	/* Una barra di consenso su un foglio di carta non ha senso. */
	@media print {
		.consenso { display: none !important; }
	}
}


/* ==========================================================================
   ANIMAZIONI — parallax e caroselli arrivano in M8.
   Qui c'è già la regola che li governerà tutti.
   ========================================================================== */
@layer animazioni {

	/*
	 * Rispetto della preferenza di sistema "riduci animazioni".
	 * Regola globale e non caso per caso: ogni animazione aggiunta in futuro
	 * è coperta da qui senza doversene ricordare.
	 *
	 * Non si azzera del tutto la durata (0s può rompere gli eventi
	 * transitionend/animationend): si porta a 0.01ms, che è impercettibile
	 * ma resta un'animazione valida per il browser.
	 */
	@media (prefers-reduced-motion: reduce) {
		*,
		*::before,
		*::after {
			animation-duration: 0.01ms !important;
			animation-iteration-count: 1 !important;
			transition-duration: 0.01ms !important;
			scroll-behavior: auto !important;
		}
	}
}


/* ==========================================================================
   UTILITIES — ultimo layer: deve poter vincere sul resto del CSS del tema.
   ========================================================================== */
@layer utilities {

	/* Visibile agli screen reader, invisibile a schermo. */
	.visually-hidden:not(:focus):not(:active) {
		position: absolute;
		width: 1px;
		height: 1px;
		margin: -1px;
		padding: 0;
		overflow: hidden;
		clip-path: inset(50%);
		white-space: nowrap;
		border: 0;
	}

	/* Font secondario e terzo: applicabili a qualunque blocco dal campo
	   "Classi CSS aggiuntive" di Gutenberg. */
	.font2 { font-family: var(--font-2); }
	.font3 { font-family: var(--font-3); }

	/* ------------------------------------------------------------------
	   VARIANTI DI BOTTONE

	   Nota architetturale: queste classi non dichiarano NESSUNA proprietà CSS
	   visibile — ridefiniscono soltanto delle custom property. È quello che le
	   rende immuni al problema della cascata descritto nella sezione 8 di
	   UseTheme.md: non competono con il CSS di core, cambiano solo il valore che
	   le regole di core (generate da theme.json) leggeranno con var().

	   Conseguenza pratica: funzionano identiche sia scritte sul link, sia
	   scritte sul contenitore — che è esattamente dove Gutenberg mette le
	   "Classi CSS aggiuntive" del blocco Bottone. Le custom property si
	   ereditano, quindi il valore scende dal contenitore al pulsante da solo.
	   ------------------------------------------------------------------ */

	/* Dimensioni — scalano dal rapporto 1:2 di partenza, non lo sostituiscono. */
	.btn-sm {
		--btn-pad-block: 0.625rem;
		--btn-pad-inline: 1.25rem;
		--btn-font-size: var(--wp--preset--font-size--xs);
		--nav-pad-block: 0.35rem;
		--nav-pad-inline: 0.7rem;
	}
	.btn-lg {
		--btn-pad-block: 1.25rem;
		--btn-pad-inline: 2.5rem;
		--btn-font-size: var(--wp--preset--font-size--m);
	}

	/* Forme */
	.btn-radius-sm { --btn-radius: var(--btn-radius-sm); }
	.btn-radius-md { --btn-radius: var(--btn-radius-md); }
	.btn-radius-lg { --btn-radius: var(--btn-radius-lg); }
	.btn-pill      { --btn-radius: var(--btn-radius-full); }
	.btn-square    { --btn-radius: 0; }

	/* Variante contorno: solo bordo, sfondo trasparente, si riempie in hover. */
	.btn-outline {
		--btn-bg: transparent;
		--btn-text: var(--btn-accent);
		--btn-border: var(--btn-accent);
		--btn-bg-hover: var(--btn-accent);
		--btn-text-hover: var(--btn-on-accent);
		--btn-border-hover: var(--btn-accent);
		--btn-bg-focus: var(--btn-accent);
		--btn-bg-active: var(--btn-accent-hover);
	}

	/* Variante fantasma: nessun bordo né sfondo, l'hover rivela un fondo tenue. */
	.btn-ghost {
		--btn-bg: transparent;
		--btn-text: var(--btn-accent);
		--btn-border: transparent;
		--btn-bg-hover: color-mix(in srgb, var(--btn-accent) 12%, transparent);
		--btn-text-hover: var(--btn-accent);
		--btn-border-hover: transparent;
		--btn-bg-focus: color-mix(in srgb, var(--btn-accent) 12%, transparent);
		--btn-bg-active: color-mix(in srgb, var(--btn-accent) 22%, transparent);
	}

	/* Sottolineatura dei link, da rimettere caso per caso su un contenitore
	   (es. un blocco di testo lungo dove i link devono spiccare). */
	.link-underline a { text-decoration: underline; text-underline-offset: 0.15em; }
	.no-underline a,
	a.no-underline { text-decoration: none; }

	.text-center { text-align: center; }
	.text-balance { text-wrap: balance; }
	.measure { max-width: var(--measure); margin-inline: auto; }

	/* Compatibilità con la v1 del tema: `.main` centrava e bilanciava il testo. */
	.main { text-align: center; text-wrap: balance; }

	/* Spaziature. `.pad` esisteva già nella v1, ora senza bordo di debug. */
	.pad { padding: var(--space-m); }
	.pad-section { padding-block: var(--pad-section); }
	.flow-tight { --flow-space: var(--space-2xs); }
	.flow-loose { --flow-space: var(--space-xl); }

	/*
	 * Span della griglia mosaico (M3).
	 * Le classi esistono già qui perché sono pubbliche e riusabili a mano su
	 * markup custom, non solo generate dal blocco portfolio-grid. Stando in
	 * `utilities` vincono sul pattern nth-child() automatico del layer `layout`.
	 */
	.span-2-cols { grid-column: span 2; }
	.span-2-rows { grid-row: span 2; }
	.span-2x2 { grid-column: span 2; grid-row: span 2; }

	/* Sotto i 640px la griglia sfalsata diventa illeggibile: si normalizza. */
	@media (max-width: 639.98px) {
		.span-2-cols,
		.span-2-rows,
		.span-2x2 { grid-column: auto; grid-row: auto; }
	}
}
