/* ==========================================================================
   LIVELLO C — override dei blocchi core di WordPress.

   ⚠️ QUESTO FILE NON DEVE MAI ESSERE MESSO DENTRO UN @layer. NON È UNA DIMENTICANZA.

   Perché: nella cascata CSS, le dichiarazioni NON layerizzate hanno priorità su
   qualunque dichiarazione dentro un @layer, a prescindere dalla specificità.
   L'ordine reale è:  layer 1 → layer 2 → … → layer N → non-layerizzato (vince).

   Il CSS di WordPress non è layerizzato (né `wp-block-library`, né il CSS che
   theme.json genera). Quindi una regola come:

       :root :where(.wp-block-button__link) { background-color: … }   ← core, unlayered

   batte una nostra regola molto più specifica scritta dentro @layer buttons.
   Mettere queste override in un layer significherebbe doverle poi rincorrere
   a colpi di !important.

   Cosa ci va e cosa no:
     ✅ solo ciò che theme.json NON sa esprimere — theme.json copre :hover,
        :focus, :active e :visited, ma non :focus-visible, non :disabled,
        non le media query.
     ❌ colori, spaziature, tipografia, raggi dei bottoni: tutto questo va in
        theme.json, che è il livello A. Se stai per scriverne uno qui, il posto
        giusto è quasi sempre theme.json.

   Enqueue: dipende esplicitamente da `wp-block-library` e `global-styles`
   (vedi include/enqueue.php). Fra due regole entrambe non layerizzate e di pari
   specificità vince l'ultima nell'ordine di sorgente, quindi l'ordine conta.
   ========================================================================== */


/* --------------------------------------------------------------------------
   Bottoni core — gli stati che theme.json non conosce
   -------------------------------------------------------------------------- */

.wp-block-button__link,
.wp-element-button {
	/* cursor: pointer su tutta l'area cliccabile, in OGNI stato, :active incluso.
	   Mai un cursore che cambia o sparisce durante l'interazione. */
	cursor: pointer;
	transition:
		background-color var(--transition-fast, 0.15s) var(--easing, ease),
		border-color var(--transition-fast, 0.15s) var(--easing, ease),
		color var(--transition-fast, 0.15s) var(--easing, ease),
		transform var(--transition-fast, 0.15s) var(--easing, ease);
}

/*
 * :focus-visible — requisito di accessibilità, non estetica.
 * Deve essere chiaramente distinguibile da :hover: chi naviga da tastiera deve
 * poter capire dove si trova, e "sembra un hover" non basta.
 */
.wp-block-button__link:focus-visible,
.wp-element-button:focus-visible {
	outline: 2px solid var(--btn-border-focus, currentColor);
	outline-offset: 3px;
	background-color: var(--btn-bg-focus, var(--btn-bg-hover));
}

/* Il focus da mouse non deve disegnare l'anello: lo fa già :focus-visible. */
.wp-block-button__link:focus:not(:focus-visible),
.wp-element-button:focus:not(:focus-visible) {
	outline: none;
}

/* :active — micro-feedback tattile. theme.json sa cambiare i colori su :active
   ma non applicare una transform. */
.wp-block-button__link:active,
.wp-element-button:active {
	transform: scale(0.98);
}

/*
 * :disabled — theme.json non ha questo pseudo-selettore.
 * `[aria-disabled="true"]` copre i link che fanno da bottone: un <a> non può
 * essere :disabled, quindi senza questo selettore resterebbe attivo.
 */
.wp-block-button__link:disabled,
.wp-block-button__link[aria-disabled="true"],
.wp-element-button:disabled,
.wp-element-button[aria-disabled="true"] {
	background-color: var(--btn-bg-disabled);
	border-color: var(--btn-bg-disabled);
	color: var(--btn-text-disabled);
	cursor: not-allowed;
	transform: none;
	pointer-events: auto; /* il cursore not-allowed deve restare visibile */
}

.wp-block-button__link:disabled:hover,
.wp-block-button__link[aria-disabled="true"]:hover,
.wp-element-button:disabled:hover,
.wp-element-button[aria-disabled="true"]:hover {
	/* Nessuna transizione hover su un elemento disabilitato. */
	background-color: var(--btn-bg-disabled);
	border-color: var(--btn-bg-disabled);
	color: var(--btn-text-disabled);
}

/* Variante outline di core.
   Usa --btn-accent e non --btn-bg: la classe .btn-outline del tema porta
   --btn-bg a `transparent`, e se le due varianti venissero combinate sullo
   stesso bottone il testo diventerebbe invisibile. --btn-accent è una copia
   stabile del colore configurato nel Customizer. */
.is-style-outline > .wp-block-button__link:not(.has-background),
.wp-block-button__link.is-style-outline:not(.has-background) {
	background-color: transparent;
	color: var(--btn-accent);
	border-color: var(--btn-accent);
}

.is-style-outline > .wp-block-button__link:not(.has-background):hover,
.wp-block-button__link.is-style-outline:not(.has-background):hover {
	background-color: var(--btn-accent);
	color: var(--btn-on-accent);
}


/* --------------------------------------------------------------------------
   HEADER E MENU — colori

   Perché queste regole stanno qui e non nel layer `nav` di style.css:
   theme.json, tramite `styles.elements.link`, genera una regola come

       :root :where(a:where(:not(.wp-element-button))) { color: … }

   che è NON layerizzata e quindi batte qualunque `@layer`, per quanto specifico.
   Le voci di menu e il titolo del sito sono link, quindi finivano per prendere
   il colore della sezione "Colori → Link" del Customizer invece del proprio.

   Stando qui, non layerizzate e con specificità più alta, vincono. Sono
   l'esempio da manuale del "livello C" descritto in UseTheme.md sezione 8.
   -------------------------------------------------------------------------- */

/*
 * Colore della barra dopo lo scorrimento (solo con barra fissa attiva).
 * La classe `is-scrolled` la mette navigation.js appena si lascia la
 * posizione 0; il token è facoltativo — assente, la barra resta com'è —
 * e può valere `transparent` tramite la casella dedicata.
 */
.site-header {
	transition: background-color var(--transition-base, 0.28s) var(--easing, ease);
}

body.has-fixed-header .site-header.is-scrolled {
	background-color: var(--header-bg-scrolled, var(--header-bg, #3b725a));
}

/* Titolo del sito e logo: seguono il colore della barra, non quello dei link. */
.site-header .site-title a,
.site-header .site-title a:hover,
.site-header .site-title a:focus {
	color: var(--header-text, #ffffff);
	text-decoration: none;
}

/*
 * VOCE DI MENU A RIPOSO — nessuno sfondo proprio.
 * Lascia vedere la barra, così cambiando il colore della barra le voci lo
 * seguono da sole. Lo sfondo compare solo quando c'è un'interazione.
 */
.primary-menu a,
.primary-menu a:link,
.primary-menu a:visited {
	/* Vuoto nel Customizer = trasparente (si vede la barra); impostato = riempita. */
	background-color: var(--nav-bg, transparent);
	color: var(--nav-text, #ffffff);
	text-decoration: none;
	transition:
		background-color var(--transition-fast, 0.15s) var(--easing, ease),
		color var(--transition-fast, 0.15s) var(--easing, ease),
		transform var(--transition-fast, 0.15s) var(--easing, ease);
}

.primary-menu a:hover {
	background-color: var(--nav-bg-hover, #2e5a47);
	color: var(--nav-text-hover, #ffffff);
	text-decoration: none;
}

.primary-menu a:focus-visible {
	background-color: var(--nav-bg-focus, #2e5a47);
	color: var(--nav-text-hover, #ffffff);
	outline: 2px solid var(--nav-border-focus, #ffffff);
	outline-offset: 2px;
}

.primary-menu a:focus:not(:focus-visible) {
	outline: none;
}

.primary-menu a:active {
	background-color: var(--nav-bg-active, #24463a);
	transform: scale(0.98);
}

/*
 * PAGINA CORRENTE — solo una lineetta sotto il testo, nessun riempimento.
 *
 * L'indicatore è agganciato ad `aria-current`, non alla classe
 * `.current-menu-item` di WordPress: così l'informazione visiva e quella
 * annunciata dagli screen reader non possono divergere.
 */
.primary-menu a[aria-current="page"] {
	background-color: var(--nav-bg, transparent);
	color: var(--nav-text, #ffffff);
}

.primary-menu a[aria-current="page"]::after {
	content: "";
	position: absolute;
	inset-inline: var(--nav-pad-inline, 1rem);
	/* Valore fisso e non derivato dal padding: ora la voce è alta quanto tutta
	   la barra, quindi legarlo al padding porterebbe la lineetta a fondo corsa
	   dove sembrerebbe il bordo inferiore della barra, non un indicatore. */
	inset-block-end: 0.45rem;
	height: 2px;
	background-color: var(--nav-current-indicator, #ffffff);
	border-radius: 2px;
}

/* In hover la voce corrente si comporta come le altre, ma la lineetta resta:
   è uno stato persistente, non un feedback di interazione. */
.primary-menu a[aria-current="page"]:hover {
	background-color: var(--nav-bg-hover, #2e5a47);
}

/* Sotto i 768px la voce di menu occupa tutta la larghezza del pannello: una
   lineetta lunga quanto l'elemento sembrerebbe un bordo, non un indicatore.
   Si accorcia a un trattino allineato all'inizio del testo. */
@media (max-width: 767.98px) {
	.primary-menu a[aria-current="page"]::after {
		inset-inline-end: auto;
		width: 2rem;
	}
}

@media (prefers-reduced-motion: reduce) {
	.primary-menu a { transition-duration: 0.01ms; }
	.primary-menu a:active { transform: none; }
}


/* --------------------------------------------------------------------------
   Immagini core
   -------------------------------------------------------------------------- */

/* object-fit corretto ovunque: nelle celle di una griglia le immagini devono
   riempire senza deformarsi (README, sezione 8). */
.wp-block-image img,
.wp-block-post-featured-image img {
	object-fit: cover;
}

/* Un vettoriale non si ritaglia mai: `cover` ha senso su una foto dentro la
   cella di una griglia, dove il taglio e' voluto, ma su un disegno taglierebbe
   il disegno. Un SVG scala senza perdere qualita', quindi si contiene. */
.wp-block-image img[src$=".svg" i] {
	object-fit: contain;
}

.wp-block-image figcaption {
	font-size: var(--wp--preset--font-size--xs);
	color: color-mix(in srgb, var(--color-contrast, currentColor) 65%, transparent);
}


/* --------------------------------------------------------------------------
   CARD SERVIZIO E PACCHETTI (pattern di M4)

   Perché stanno qui e non in un @layer: sono blocchi Group di core, e il loro
   layout è governato da regole non layerizzate di WordPress — in particolare
   `:where(.is-layout-flow) > :not(:first-child) { margin-block-start: … }`,
   che serve a distanziare i blocchi fra loro. Per spingere il pulsante in
   fondo alla card serve un `margin-block-start: auto` che quella regola deve
   perdere: da dentro un @layer perderebbe sempre lui, per quanto specifico.

   Le classi funzionano in due forme: `is-style-card-servizio` (assegnata dal
   pannello "Stili" del blocco) e `card-servizio` (scritta a mano fra le
   "Classi CSS aggiuntive", o su markup custom nei template).
   -------------------------------------------------------------------------- */

.wp-block-group.is-style-card-servizio,
.wp-block-group.card-servizio,
.wp-block-group.is-style-card-evidenza,
.wp-block-group.card-evidenza {
	display: flex;
	flex-direction: column;
	height: 100%;
	padding: var(--space-m, 1.5rem);
	background-color: var(--color-base, #fff);
	border: 1px solid var(--color-tertiary, #c9c4b4);
	border-radius: var(--btn-radius-lg, 1rem);
}

/* Il pulsante scende in fondo alla card: così in una griglia i pulsanti di
   card con testi di lunghezza diversa restano allineati fra loro. */
.is-style-card-servizio > .wp-block-buttons,
.card-servizio > .wp-block-buttons,
.is-style-card-evidenza > .wp-block-buttons,
.card-evidenza > .wp-block-buttons {
	margin-block-start: auto;
	padding-block-start: var(--space-s, 1rem);
}

/* Variante in evidenza: bordo d'accento e un rialzo appena percettibile.
   Nessuna scala: ingrandire una card in una griglia rompe l'allineamento
   delle altre e su mobile la fa uscire dal contenitore. */
.wp-block-group.is-style-card-evidenza,
.wp-block-group.card-evidenza {
	border-color: var(--color-primary, #3b725a);
	border-width: 2px;
	box-shadow: 0 0.5rem 1.5rem rgb(0 0 0 / 0.06);
}

.card-servizio__prezzo {
	font-size: var(--wp--preset--font-size--m);
	font-weight: 600;
	color: var(--color-primary, #3b725a);
}

/* --------------------------------------------------------------------------
   ELENCO CON SPUNTA
   -------------------------------------------------------------------------- */

.wp-block-list.is-style-list-check,
.list-check {
	list-style: none;
	padding-inline-start: 0;
}

.wp-block-list.is-style-list-check li,
.list-check li {
	position: relative;
	padding-inline-start: 1.6em;
}

.wp-block-list.is-style-list-check li::before,
.list-check li::before {
	content: "";
	position: absolute;
	inset-inline-start: 0;
	inset-block-start: 0.45em;
	width: 0.75em;
	height: 0.4em;
	border-inline-start: 2px solid var(--color-primary, #3b725a);
	border-block-end: 2px solid var(--color-primary, #3b725a);
	transform: rotate(-45deg);
}

/* --------------------------------------------------------------------------
   OCCHIELLO — titolo piccolo in maiuscoletto sopra una sezione
   -------------------------------------------------------------------------- */

.wp-block-heading.is-style-occhiello,
.occhiello {
	font-size: var(--wp--preset--font-size--xs);
	font-weight: 600;
	letter-spacing: 0.12em;
	text-transform: uppercase;
	color: color-mix(in srgb, var(--color-contrast, currentColor) 60%, transparent);
}

/* --------------------------------------------------------------------------
   FASCIA CTA
   -------------------------------------------------------------------------- */

/*
 * FASCIA CTA
 *
 * Colori, spaziature e allineamenti stanno qui e non fra gli attributi del
 * blocco. Ogni attributo scritto a mano dentro un pattern è un'occasione in più
 * di far divergere il markup salvato da quello che Gutenberg genererebbe da
 * solo — ed è esattamente quella divergenza a produrre l'avviso "contenuto
 * inaspettato o non valido".
 *
 * In cambio la fascia segue da sola la palette: cambiando il colore primario
 * nel Customizer cambia anche lei, senza rimettere mano al pattern.
 *
 * Il respiro laterale serve perché la fascia arriva ai bordi della pagina ma il
 * testo dentro no; è lo stesso valore del resto del sito, così i contenuti
 * restano allineati fra una sezione e l'altra anche quando lo sfondo cambia.
 */
.cta-band {
	background-color: var(--color-primary, #3b725a);
	color: var(--color-base, #ffffff);

	/* Unità relative: si adatta senza breakpoint.
	   È un default: una classe `pad-block-*` scritta sul blocco lo sovrascrive
	   (le utility hanno specificità più alta di proposito). Il valore qui
	   corrisponde grosso modo a `pad-block-l`, quindi per vedere una differenza
	   conviene provare `pad-block-s` o `pad-block-xl`. */
	padding-block: clamp(3rem, 8vw, 6rem);
	padding-inline: var(--pad-inline, clamp(1rem, 5vw, 4rem));
	text-align: center;
}

/*
 * Il contenuto della fascia si limita alla larghezza del testo e si centra.
 * Lo fa il CSS e non l'attributo `layout` del blocco: un attributo in meno
 * scritto a mano è un'occasione in meno di far divergere il markup salvato da
 * quello che Gutenberg si aspetta.
 */
.cta-band > * {
	max-width: var(--content-width, 1160px);
	margin-inline: auto;
}

.cta-band .wp-block-buttons {
	justify-content: center;
}

/*
 * Il pulsante dentro la fascia si inverte: chiaro su fondo pieno.
 * Si ottiene ridefinendo i token, non riscrivendo le regole del bottone —
 * stessa tecnica delle varianti .btn-outline e .btn-ghost.
 */
.cta-band .wp-block-button {
	--btn-bg: var(--color-base, #ffffff);
	--btn-text: var(--color-primary, #3b725a);
	--btn-border: var(--color-base, #ffffff);
	--btn-bg-hover: transparent;
	--btn-text-hover: var(--color-base, #ffffff);
	--btn-border-hover: var(--color-base, #ffffff);
	--btn-bg-focus: transparent;
	--btn-border-focus: var(--color-base, #ffffff);
	--btn-bg-active: transparent;
}

/* Dentro una fascia colorata i link ereditano il colore del testo della fascia,
   non quello globale dei link: su fondo pieno un link nel colore d'accento
   sarebbe illeggibile. */
.cta-band a:not(.wp-element-button) {
	color: inherit;
}


/* --------------------------------------------------------------------------
   FISARMONICA — elenco servizi e FAQ

   Si usa `<details>/<summary>` nativo, non il pattern con checkbox nascosta
   (README, sezione 14). Il motivo non è la comodità: una checkbox non è un
   disclosure widget, quindi servirebbe JavaScript per tenere aggiornato
   `aria-expanded`, e il contenuto chiuso resterebbe invisibile alla ricerca
   nella pagina (Ctrl+F). Con `<details>` entrambe le cose funzionano da sole.

   Le regole stanno qui e non in un @layer perché colpiscono il blocco Dettagli
   di core, il cui CSS non è layerizzato.

   Si applica con lo stile di blocco "Fisarmonica", oppure scrivendo `faq`
   fra le classi CSS aggiuntive.
   -------------------------------------------------------------------------- */

.wp-block-details.is-style-faq,
.wp-block-details.faq {
	border-block-end: 1px solid var(--color-tertiary, #c9c4b4);
	padding: 0;

	/*
	 * Abilita l'animazione verso `auto`, che senza questa proprietà non è
	 * interpolabile. È dichiarata qui e non su :root per limitarne l'effetto
	 * a questo componente: attivarla globalmente cambierebbe il comportamento
	 * di ogni transizione futura verso una dimensione automatica.
	 */
	interpolate-size: allow-keywords;
}

/* La striscia della domanda: cliccabile su tutta la larghezza, non solo
   sull'icona (README, sezione 14). */
.wp-block-details.is-style-faq > summary,
.wp-block-details.faq > summary {
	display: flex;
	align-items: baseline;
	gap: var(--space-s, 1rem);
	padding-block: var(--space-s, 1rem);
	font-size: var(--wp--preset--font-size--m);
	font-weight: 600;
	cursor: pointer;
	list-style: none;
	transition: color var(--transition-fast, 0.15s) var(--easing, ease);
}

/* Via il triangolino di default: ne disegniamo uno nostro. Servono entrambe
   le regole, i browser non concordano su quale pseudo-elemento usare. */
.wp-block-details.is-style-faq > summary::-webkit-details-marker,
.wp-block-details.faq > summary::-webkit-details-marker {
	display: none;
}

.wp-block-details.is-style-faq > summary::marker,
.wp-block-details.faq > summary::marker {
	content: "";
}

.wp-block-details.is-style-faq > summary:hover,
.wp-block-details.faq > summary:hover {
	color: var(--color-link-hover, currentColor);
}

.wp-block-details.is-style-faq > summary:focus-visible,
.wp-block-details.faq > summary:focus-visible {
	outline: 2px solid var(--focus-ring-color, currentColor);
	outline-offset: -2px;
}

/*
 * Il prezzo va a destra.
 * È un `<strong>` e non un `<span>` con classe perché il sommario è un campo
 * di testo ricco di Gutenberg: il grassetto è un formato che l'editor conosce
 * e conserva, una classe custom verrebbe rimossa alla prima modifica.
 */
.wp-block-details.is-style-faq > summary strong,
.wp-block-details.faq > summary strong {
	margin-inline-start: auto;
	font-weight: 500;
	white-space: nowrap;
	color: var(--color-primary, #3b725a);
}

/* Chevron: ruota di 180° all'apertura, agganciato a `[open]` — nessuna classe
   da sincronizzare via JavaScript. */
.wp-block-details.is-style-faq > summary::after,
.wp-block-details.faq > summary::after {
	content: "";
	flex: 0 0 auto;
	align-self: center;
	width: 0.5em;
	height: 0.5em;
	border-inline-end: 2px solid currentColor;
	border-block-end: 2px solid currentColor;
	transform: rotate(45deg);
	transition: transform var(--transition-fast, 0.15s) var(--easing, ease);
}

.wp-block-details.is-style-faq[open] > summary::after,
.wp-block-details.faq[open] > summary::after {
	transform: rotate(-135deg);
}

.wp-block-details.is-style-faq > :last-child:not(summary),
.wp-block-details.faq > :last-child:not(summary) {
	padding-block-end: var(--space-m, 1.5rem);
}

/*
 * Variante a schede (dal 2.20.0): classe `servizi-schede` sul gruppo.
 *
 * Ogni voce e' una scheda di cartella: fondo pieno, bordo, angoli alti
 * arrotondati, e ciascuna sale sopra la precedente di quanto e' alto
 * l'arrotondamento, cosi' della scheda sotto resta visibile la linguetta.
 * La sovrapposizione e' un margine negativo e non un posizionamento assoluto:
 * l'altezza resta quella del contenuto e una scheda aperta spinge giu' le
 * altre come in una fisarmonica normale. Per questo ogni scheda ha in fondo
 * un padding pari al margine che la successiva le mangia.
 *
 * `position: relative` non sposta nulla ma e' indispensabile: fra blocchi non
 * posizionati il browser dipinge PRIMA tutti gli sfondi e POI tutti i testi,
 * quindi il testo di una scheda aperta finirebbe sopra lo sfondo di quella che
 * la copre. Da posizionate, ogni scheda si dipinge intera e nel suo ordine.
 *
 * Il gruppo va a tutta larghezza (`alignfull`) e le schede escono dalla
 * colonna del contenuto con `max-width: none`, che batte il limite del layout
 * vincolato di WordPress (selettore a specificita' 0,1,0).
 *
 * I due font del titolo si agganciano al CORSIVO: nel sommario si scrive
 * `<em>Origine</em> - Packaging Design`, con Ctrl+I sulla prima parola.
 * Il corsivo e' un formato che Gutenberg conosce e conserva, mentre una classe
 * scritta a mano dentro il sommario verrebbe tolta alla prima modifica (vedi
 * il prezzo in grassetto, qui sopra). E siccome blocks.css e' caricato anche
 * nell'iframe dell'editor, i due font si vedono gia' mentre si scrive.
 */
.servizi-schede {
	--scheda-radius: clamp(1.5rem, 4vw, 3rem);
}

/*
 * Un gruppo `alignfull` riceve da WordPress la classe `has-global-padding`,
 * cioe' il padding laterale della pagina: le schede restavano a 64px dai
 * bordi. Lo si toglie al gruppo e lo si restituisce a tutto cio' che non e'
 * una scheda (titolo, paragrafo introduttivo), che altrimenti su mobile
 * toccherebbe il bordo dello schermo.
 */
.servizi-schede.has-global-padding {
	padding-inline: 0;
}

.servizi-schede > :not(details) {
	padding-inline: var(--pad-inline, clamp(1rem, 5vw, 4rem));
}

.servizi-schede > .wp-block-details:is(.is-style-faq, .faq) {
	position: relative;
	max-width: none;
	padding: 0 var(--pad-inline, clamp(1rem, 5vw, 4rem)) var(--scheda-radius);
	color: var(--color-tertiary, #ffffff);
	background-color: var(--color-secondary, #d2837a);
	border: 1px solid var(--color-primary, #574a92);
	border-radius: var(--scheda-radius) var(--scheda-radius) 0 0;
}

.servizi-schede > .wp-block-details:is(.is-style-faq, .faq) + .wp-block-details:is(.is-style-faq, .faq) {
	margin-block-start: calc(var(--scheda-radius) * -1);
}

/*
 * `gap: 0` perche' il sommario e' un contenitore flex: il corsivo e il testo
 * che lo segue sono due elementi flex distinti, e il gap di serie li
 * separerebbe di 1rem. Lo spazio verso prezzo e chevron torna come margine.
 */
.servizi-schede > .wp-block-details:is(.is-style-faq, .faq) > summary {
	gap: 0;
	padding-block: var(--space-m, 1.5rem);
	font-family: var(--font-2);
}

.servizi-schede > .wp-block-details:is(.is-style-faq, .faq) > summary em {
	margin-inline-end: 0.3em;
	font-family: var(--font-3);
	font-style: normal;
	/* Il sommario base e' a 600 e il corsivo lo ereditava: su un font display
	   senza quel peso il browser lo ingrossa da se'. */
	font-weight: 400;
}

.servizi-schede > .wp-block-details:is(.is-style-faq, .faq) > summary strong {
	padding-inline-start: var(--space-s, 1rem);
}

.servizi-schede > .wp-block-details:is(.is-style-faq, .faq) > summary::after {
	margin-inline-start: var(--space-s, 1rem);
}

/*
 * Schermo stretto: il prezzo non va a capo (`nowrap` della regola base) e
 * accanto a un titolo lungo sbordava dalla scheda, allargando la pagina a
 * 517px su 390. Qui scende su una riga sua sotto il titolo e lo chevron resta
 * in alto a destra. `text-align: start` perche' il sommario, andando a capo,
 * ereditava l'allineamento centrato della pagina.
 */
/* La riga del titolo rientra dai bordi della scheda; il contenuto aperto no. */
.servizi-schede > .wp-block-details:is(.is-style-faq, .faq) > summary {
	padding-inline: clamp(0.75rem, 4vw, 3rem);
	text-align: start;
}

.servizi-schede > .wp-block-details:is(.is-style-faq, .faq) > :not(summary) {
	text-align: start;
}

/*
 * Su schermo stretto tutto torna centrato, con `text-wrap: balance`: righe
 * centrate di lunghezza molto diversa si leggono male. La freccia esce dal
 * flusso e va nell'angolo in alto a destra — dentro una riga centrata
 * sposterebbe il titolo di lato — e il padding del sommario le fa posto su
 * entrambi i lati, perche' il titolo resti al centro vero della scheda.
 */
@media (max-width: 40rem) {

	.servizi-schede > .wp-block-details:is(.is-style-faq, .faq) > summary {
		position: relative;
		flex-wrap: wrap;
		justify-content: center;
		padding-inline: 2rem;
		text-align: center;
		text-wrap: balance;
	}

	.servizi-schede > .wp-block-details:is(.is-style-faq, .faq) > summary strong {
		flex-basis: 100%;
		padding-inline-start: 0;
		padding-block-start: var(--space-2xs, 0.5rem);
		white-space: normal;
	}

	.servizi-schede > .wp-block-details:is(.is-style-faq, .faq) > summary::after {
		position: absolute;
		inset-block-start: calc(var(--space-m, 1.5rem) + 0.35em);
		inset-inline-end: 0.25rem;
		margin: 0;
	}

	.servizi-schede > .wp-block-details:is(.is-style-faq, .faq) > :not(summary) {
		text-align: center;
		text-wrap: balance;
	}
}

/* Sul fondo pieno il cambio di colore al passaggio sparirebbe o stonerebbe:
   il testo resta del colore della scheda. */
.servizi-schede > .wp-block-details:is(.is-style-faq, .faq) > summary:hover {
	color: inherit;
}

/* Il prezzo: colore primario (la scheda cambia il colore del testo intorno,
   quindi lo si ribadisce), font3 sottolineato a peso normale — e' un
   `<strong>` solo come gancio per l'editor, non per il grassetto. */
.servizi-schede > .wp-block-details:is(.is-style-faq, .faq) > summary strong {
	color: var(--color-primary, #574a92);
	font-family: var(--font-3);
	font-weight: 400;
	text-decoration: underline;
	text-decoration-thickness: 1px;
	text-underline-offset: 0.2em;
}

/*
 * Apertura animata.
 * `::details-content` è il contenitore che il browser genera per la parte
 * apribile: senza di esso `<details>` non era animabile, ed è il motivo per
 * cui la prima stesura della specifica prevedeva il trucco della checkbox.
 *
 * Dove non è supportato non succede nulla di male: il pannello apre e chiude
 * di scatto, che è il fallback previsto.
 */
@supports selector(::details-content) {

	.wp-block-details.is-style-faq::details-content,
	.wp-block-details.faq::details-content {
		block-size: 0;
		overflow: hidden;
		transition:
			block-size var(--transition-base, 0.28s) var(--easing, ease),
			content-visibility var(--transition-base, 0.28s) var(--easing, ease) allow-discrete;
	}

	.wp-block-details.is-style-faq[open]::details-content,
	.wp-block-details.faq[open]::details-content {
		block-size: auto;
	}
}

@media (prefers-reduced-motion: reduce) {
	.wp-block-details.is-style-faq::details-content,
	.wp-block-details.faq::details-content,
	.wp-block-details.is-style-faq > summary::after,
	.wp-block-details.faq > summary::after {
		transition-duration: 0.01ms;
	}
}


/* --------------------------------------------------------------------------
   HERO — le tre varianti di apertura (M6)
   -------------------------------------------------------------------------- */

.hero {
	padding-block: clamp(2.5rem, 7vw, 5.5rem);
}

/* Titolo di apertura: più grande della scala normale, ma non troppo.
   Il rapporto min/max è volutamente contenuto (1.9×): su schermo grande un
   titolo che cresce senza freno diventa "urlato", e per un sito di grafica il
   protagonista deve restare il lavoro mostrato sotto (README, sezione 8). */
.title-hero {
	font-size: clamp(2.25rem, 6vw, 4.25rem);
	line-height: 1.05;
	text-wrap: balance;
}

/* --- Variante con immagine affiancata ---------------------------------- */

/* Il gruppo usa il layout a griglia di WordPress, che si occupa già di
   affiancare e di impilare da solo. Qui serve solo allineare verticalmente
   il testo con l'immagine. */
.hero-immagine {
	align-items: center;
}

.hero-immagine__testo {
	display: flex;
	flex-direction: column;
	gap: var(--space-s, 1rem);
}

.hero-immagine__media {
	margin: 0;
	border-radius: var(--btn-radius-lg, 1rem);
	overflow: hidden;
}

.hero-immagine__media img {
	width: 100%;
	/* Proporzione fissa: l'apertura non cambia altezza a seconda di quale
	   immagine viene caricata, quindi il layout non balla fra una pagina e
	   l'altra. */
	aspect-ratio: 4 / 3;
	object-fit: cover;
}

/* --- Variante a tutta pagina con copertina ------------------------------ */

/*
 * Immagine e testo si sovrappongono usando la stessa cella di griglia, invece
 * di posizionare l'immagine in assoluto: così è l'immagine a determinare
 * l'altezza della sezione e non serve fissarla a mano.
 */
.hero-copertina {
	position: relative;
	display: grid;
	padding: 0;
	isolation: isolate;
	min-height: min(70svh, 40rem);
}

.hero-copertina > .hero-copertina__media,
.hero-copertina > .hero-copertina__testo {
	grid-area: 1 / 1;
}

.hero-copertina__media {
	margin: 0;
	z-index: 0;

	/*
	 * Il parallax ingrandisce l'immagine del 14% e la fa scorrere: senza un
	 * taglio qui deborda dalla sezione, copre quelle vicine e — su una fascia a
	 * tutta larghezza — allarga la pagina di lato, facendo comparire la barra di
	 * scorrimento orizzontale. Costava caro perche' il sintomo ("si rompe tutto")
	 * non somiglia affatto alla causa.
	 *
	 * `clip` e non `hidden`: non crea un contenitore di scorrimento, quindi
	 * niente barre a sorpresa e le posizioni sticky degli antenati continuano a
	 * funzionare.
	 *
	 * Il taglio sta sul media e NON su `.hero-copertina`: il testo puo' sporgere
	 * di proposito dalla fascia con margini negativi, e non va tagliato.
	 */
	overflow: clip;
}

.hero-copertina__media img {
	width: 100%;
	height: 100%;
	object-fit: cover;
}

/*
 * Velo scuro fra immagine e testo.
 * È una sfumatura e non una tinta piatta: il testo resta leggibile su
 * qualunque fotografia senza coprire il lavoro più del necessario.
 */
.hero-copertina::after {
	content: "";
	grid-area: 1 / 1;
	z-index: 1;
	background: linear-gradient(to top, rgb(0 0 0 / 0.72), rgb(0 0 0 / 0.15));
}

.hero-copertina__testo {
	position: relative;
	z-index: 2;
	align-self: end;
	display: flex;
	flex-direction: column;
	gap: var(--space-s, 1rem);
	padding: var(--pad-inline, clamp(1rem, 5vw, 4rem));
	padding-block-end: clamp(2rem, 6vw, 4rem);
	color: #ffffff;
	max-width: var(--content-width, 1160px);
	margin-inline: auto;
	width: 100%;
}

/* Su fondo fotografico il pulsante si inverte, come nella fascia CTA. */
.hero-copertina__testo .wp-block-button {
	--btn-bg: #ffffff;
	--btn-text: var(--color-contrast, #16181d);
	--btn-border: #ffffff;
	--btn-bg-hover: transparent;
	--btn-text-hover: #ffffff;
	--btn-border-hover: #ffffff;
	--btn-bg-focus: transparent;
	--btn-border-focus: #ffffff;
	--btn-bg-active: transparent;
}

/* L'occhiello dentro una copertina non può usare il grigio del testo normale. */
.hero-copertina__testo .is-style-occhiello,
.hero-copertina__testo .occhiello {
	color: color-mix(in srgb, #ffffff 80%, transparent);
}


/* --------------------------------------------------------------------------
   PARALLAX (M8)

   Si applica scrivendo `has-parallax` fra le classi aggiuntive di un blocco.
   Funziona in due modi diversi a seconda di cosa c'è dentro.
   -------------------------------------------------------------------------- */

/*
 * 1. Blocchi con IMMAGINE DI SFONDO impostata dall'editor.
 *    Approccio classico: lo sfondo resta fermo mentre la pagina scorre.
 */
.has-parallax {
	background-attachment: fixed;
	background-size: cover;
	background-position: center;
}

/*
 * Su iOS Safari `background-attachment: fixed` è rotto da anni: l'immagine
 * viene ingrandita a dismisura e non si muove affatto. Si disattiva dove il
 * puntatore non è preciso, che è il modo di riconoscere i dispositivi touch
 * senza fare sniffing del browser.
 */
@media (hover: none) {
	.has-parallax { background-attachment: scroll; }
}

@media (prefers-reduced-motion: reduce) {
	.has-parallax { background-attachment: scroll; }
}

/*
 * 2. Blocchi con un'IMMAGINE VERA dentro (l'hero copertina).
 *
 *    Qui il moto lo scrive assets/js/parallax.js, che aggiorna una sola
 *    variabile: `--parallax-progress`, da 0 quando la fascia entra dal basso a
 *    1 quando esce dalla cima.
 *
 *    STORIA, perche' non venga riproposta: fino alla v2.16.2 questo pezzo era
 *    CSS puro con `animation-timeline: view()` — zero JavaScript, animazione sul
 *    compositore. Sulla carta la soluzione migliore, sul campo l'immagine non si
 *    e' mai mossa nemmeno esasperando la corsa. Prima di tornarci, riprodurre il
 *    caso su una pagina vuota: e' una strada da riaprire solo con una prova in
 *    mano, non per eleganza.
 *
 *    Quanto si muove e quanto si ingrandisce restano decisioni del CSS: lo
 *    script non conosce una sola misura.
 */
.hero-copertina.has-parallax .hero-copertina__media img {
	/*
	 * Corsa e ingrandimento vanno SEMPRE insieme: l'immagine puo' traslare solo
	 * dentro il margine che lo zoom le ha dato, altrimenti scopre i bordi.
	 * Regola: zoom = 1 + corsa. Con corsa 40% (cioe' +-20%) serve `scale(1.4)`.
	 *
	 * Perche' 30% e non il 14% della prima stesura: misurato sulla landing, una
	 * corsa del 14% su una fascia alta 950px muove l'immagine di 133px mentre se
	 * ne scorrono 1850 — uno scarto del 7%, che tecnicamente c'e' ma non si
	 * percepisce. Un parallax si sente dal 15% in su; al 40% e' dichiarato.
	 *
	 * Il tetto e' di nitidezza, non estetico: oltre lo zoom a cui il file
	 * originale finisce i pixel, l'immagine si sgrana. Sulla copertina della
	 * landing l'originale e' largo 1920 e viene mostrato a 1425, quindi
	 * `scale(1.35)` e' gratuito e 1.4 lo supera di un 4% — impercettibile su una
	 * fotografia. Con immagini piu' piccole, abbassare.
	 *
	 * Per un parallax molto marcato senza gonfiare lo zoom la strada e' opposta:
	 * accorciare la fascia. Una finestra piu' bassa dell'immagine regala margine
	 * di scorrimento senza ingrandire niente.
	 *
	 * Si sovrascrivono da CSS aggiuntivo per calibrare caso per caso.
	 */
	--parallax-shift: 40%;
	--parallax-zoom: 1.4;

	/* 0.5 di riserva = fascia a meta' corsa, cioe' immagine centrata: e' lo stato
	   in cui resta se lo script non gira. */
	transform:
		translateY(calc(var(--parallax-shift) * (var(--parallax-progress, 0.5) - 0.5)))
		scale(var(--parallax-zoom));
}

@media (prefers-reduced-motion: reduce) {
	.hero-copertina.has-parallax .hero-copertina__media img {
		transform: none;
	}
}


/* --------------------------------------------------------------------------
   CAROSELLO A LOOP CONTINUO (M8)

   Scorrimento infinito senza librerie: una striscia larga il doppio del
   necessario che trasla del 50%. Arrivata a metà, la seconda copia si trova
   esattamente dove stava la prima, quindi la ripartenza è invisibile.

   La seconda copia la genera PHP al render (include/carousel.php), non il
   browser: il server sa già cosa c'è dentro la striscia, non c'è motivo di
   farlo scoprire al browser a pagina caricata.
   -------------------------------------------------------------------------- */

.carousel-loop {
	overflow: hidden;
	/* Le estremità sfumano invece di tagliare di netto: un elemento troncato a
	   metà sul bordo fa sembrare la striscia un errore di impaginazione. */
	mask-image: linear-gradient(to right, transparent, #000 6%, #000 94%, transparent);
}

.carousel-loop__track {
	display: flex;
	align-items: center;
	gap: var(--carousel-gap, var(--space-xl, 3rem));
	width: max-content;
}

/*
 * `display: contents` fa sparire il contenitore della copia dal layout: i suoi
 * figli diventano elementi flex della striscia esattamente come gli originali,
 * senza un livello in più da gestire.
 */
.carousel-loop__clone {
	display: contents;
}

/*
 * L'animazione parte solo se la copia esiste davvero.
 * Serve dentro l'editor: lì il markup non passa dai filtri di render, quindi
 * la copia non c'è e la striscia scorrerebbe a vuoto con un salto visibile.
 * Con `:has()` la condizione si esprime in CSS, senza classi di stato da
 * aggiungere via JavaScript.
 */
.carousel-loop:has(.carousel-loop__clone) .carousel-loop__track {
	animation: lmcpro-marquee var(--carousel-speed, 40s) linear infinite;
}

/* Senza copia gli elementi vanno a capo, così si vedono comunque tutti. */
.carousel-loop:not(:has(.carousel-loop__clone)) .carousel-loop__track {
	flex-wrap: wrap;
	width: auto;
	justify-content: center;
}

@keyframes lmcpro-marquee {
	to { transform: translateX(-50%); }
}

/*
 * Loghi tutti alla stessa altezza, larghezza libera: è l'unico modo perché una
 * fila di marchi di proporzioni diverse non sembri sbilanciata. `contain` e non
 * `cover`, perché un logo tagliato non è più quel logo.
 */
.carousel-loop__track .wp-block-image {
	margin: 0;
}

.carousel-loop__track .wp-block-image img {
	height: var(--carousel-logo-height, clamp(2rem, 4vw, 3.25rem));
	width: auto;
	object-fit: contain;
}

/* Direzione e velocità, da scrivere fra le classi aggiuntive. */
.carousel-loop.direction-reverse .carousel-loop__track { animation-direction: reverse; }
.carousel-loop.carousel-slow { --carousel-speed: 70s; }
.carousel-loop.carousel-fast { --carousel-speed: 22s; }

/*
 * PAUSA — requisito di conformità, non un vezzo.
 * WCAG 2.2.2 chiede che un contenuto in movimento automatico che dura più di
 * cinque secondi possa essere fermato. `:focus-within` non è ridondante
 * rispetto a `:hover`: copre chi arriva con il Tab e non ha un puntatore.
 *
 * È il motivo per cui l'hover mette in pausa invece di invertire il senso di
 * marcia come prevedeva la prima stesura della specifica: le due cose sono
 * alternative, e la conformità viene prima dell'effetto.
 */
.carousel-loop:hover .carousel-loop__track,
.carousel-loop:focus-within .carousel-loop__track {
	animation-play-state: paused;
}

/* Verticale. */
.carousel-loop.is-vertical {
	max-height: var(--carousel-height, 24rem);
	mask-image: linear-gradient(to bottom, transparent, #000 6%, #000 94%, transparent);
}

.carousel-loop.is-vertical .carousel-loop__track {
	flex-direction: column;
	width: auto;
	height: max-content;
}

.carousel-loop.is-vertical:has(.carousel-loop__clone) .carousel-loop__track {
	animation-name: lmcpro-marquee-vertical;
}

@keyframes lmcpro-marquee-vertical {
	to { transform: translateY(-50%); }
}

/*
 * FOTO INVECE DI LOGHI (v2.25.0) — classe `carousel-foto`.
 * Le regole qui sopra sono tarate sui loghi: altezza fissa di una riga di
 * testo, larghezza libera. Una foto trattata così diventa una striscia di
 * 50px. Qui la misura si ribalta: larghezza decisa dal carosello, altezza
 * dalla proporzione, ritaglio `cover` e angoli delle card del carosello
 * navigabile.
 */
.carousel-loop.carousel-foto .carousel-loop__track .wp-block-image {
	flex: none;
	width: var(--carousel-item, clamp(12rem, 22vw, 18rem));
	border-radius: var(--btn-radius-lg, 1rem);
	overflow: hidden;
}

.carousel-loop.carousel-foto .carousel-loop__track .wp-block-image img {
	width: 100%;
	height: auto;
	aspect-ratio: var(--carousel-ratio, 4 / 5);
	object-fit: cover;
}

/* In verticale la larghezza è quella della colonna che ospita il carosello. */
.carousel-loop.carousel-foto.is-vertical .carousel-loop__track {
	align-items: stretch;
}

.carousel-loop.carousel-foto.is-vertical .carousel-loop__track .wp-block-image {
	width: 100%;
}

@media (prefers-reduced-motion: reduce) {
	.carousel-loop .carousel-loop__track {
		animation: none;
		flex-wrap: wrap;
		width: auto;
		justify-content: center;
	}
	.carousel-loop { mask-image: none; max-height: none; }
	/* Una colonna di foto senza tetto sarebbe alta metri: resta una finestra
	   ferma sulle prime immagini. */
	.carousel-loop.carousel-foto.is-vertical { max-height: var(--carousel-height, 24rem); }
	/* Senza animazione la copia è solo contenuto ripetuto: si toglie. */
	.carousel-loop__clone { display: none; }
}


/* --------------------------------------------------------------------------
   CAROSELLO NAVIGABILE (M8)

   Scorrimento con aggancio, nativo. Dito, trackpad e frecce della tastiera
   funzionano già senza JavaScript: quello serve solo al clic sui pulsanti.
   -------------------------------------------------------------------------- */

.carousel-nav {
	position: relative;
}

.carousel-nav__track {
	display: flex;
	gap: var(--carousel-gap, var(--space-m, 1.5rem));
	overflow-x: auto;
	scroll-snap-type: x mandatory;
	/* Da qui viene lo scorrimento morbido dei pulsanti: è CSS, quindi rispetta
	   da solo "riduci animazioni" senza doverlo controllare in JavaScript. */
	scroll-behavior: smooth;
	/* Arrivati in fondo lo scorrimento si ferma invece di trascinarsi dietro
	   la pagina. */
	overscroll-behavior-x: contain;

	/*
	 * Niente barra di scorrimento: scelta estetica esplicita (2/9). L'avviso
	 * "quanto contenuto resta" che la barra dava lo coprono i pulsanti che si
	 * attenuano ai capi e l'elemento che spunta tagliato sul bordo; la
	 * manovrabilità che dava al mouse la copre il trascinamento (carousel.js).
	 */
	scrollbar-width: none;
	cursor: grab;
}

.carousel-nav__track::-webkit-scrollbar {
	display: none;
}

/* Durante il trascinamento: aggancio e scorrimento morbido spenti — entrambi
   combatterebbero contro la mano — e niente selezione accidentale di testo. */
.carousel-nav__track.is-dragging {
	cursor: grabbing;
	scroll-snap-type: none;
	scroll-behavior: auto;
	user-select: none;
}

.carousel-nav__track > * {
	flex: 0 0 auto;
	scroll-snap-align: start;
	width: var(--carousel-item, min(20rem, 80%));
	margin-block: 0;
}

/* Le immagini diventano card: angoli arrotondati e proporzione fissa, così la
   striscia ha un'altezza stabile qualunque cosa ci venga messo dentro. */
.carousel-nav__track > .wp-block-image {
	margin: 0;
	border-radius: var(--btn-radius-lg, 1rem);
	overflow: hidden;
}

.carousel-nav__track > .wp-block-image img {
	width: 100%;
	aspect-ratio: var(--carousel-ratio, 4 / 3);
	object-fit: cover;
}

/* Dentro una card trascinabile l'immagine non va trascinata come file. */
.carousel-nav__track img {
	-webkit-user-drag: none;
	user-select: none;
}

/*
 * CARTE CHE SI GIRANO (v2.27.0) — classe `carousel-flip` sul gruppo del
 * carosello. Al passaggio del mouse l'immagine ruota e sul retro compare il
 * suo testo alternativo, in tertiary su fondo secondary.
 *
 * `data-retro` (il testo) e `--retro-radius` (gli angoli della foto) li mette
 * il tema al render sul link che avvolge l'immagine: vedi
 * lmcpro_render_carousel_flip() in include/carousel.php. Senza link o senza
 * testo alternativo la carta resta ferma.
 *
 * Ruota il link e non il figure: il figure resta fermo e tiene l'hover. Se
 * ruotasse lui, a metà giro sarebbe largo zero, perderebbe il puntatore e
 * tremerebbe avanti e indietro. Il retro sta dentro il link: da girata la
 * carta resta cliccabile.
 */
.carousel-flip [data-retro] {
	position: relative;
	display: block;
	transform-style: preserve-3d;
	transform: perspective(75rem) rotateY(0deg);
	transition: transform 0.6s cubic-bezier(0.4, 0.2, 0.2, 1);
}

.carousel-flip [data-retro] > img {
	-webkit-backface-visibility: hidden;
	backface-visibility: hidden;
}

.carousel-flip [data-retro]::after {
	content: attr(data-retro);
	position: absolute;
	inset: 0;
	display: grid;
	place-items: center;
	padding: var(--space-m, 1.5rem);
	background: var(--color-secondary);
	color: var(--color-tertiary);
	font-size: var(--wp--preset--font-size--m);
	line-height: 1.25;
	text-align: center;
	text-wrap: balance;
	border-radius: var(--retro-radius, 0);
	transform: rotateY(180deg);
	-webkit-backface-visibility: hidden;
	backface-visibility: hidden;
}

/* Solo dove l'hover esiste davvero: su touch il tocco apre il link. */
@media (hover: hover) {
	.carousel-flip .carousel-nav__track > .wp-block-image:hover > [data-retro] {
		transform: perspective(75rem) rotateY(180deg);
	}
}

/* Da tastiera il link a fuoco mostra il retro, come l'hover. */
.carousel-flip [data-retro]:focus-visible {
	transform: perspective(75rem) rotateY(180deg);
}

@media (prefers-reduced-motion: reduce) {
	.carousel-flip [data-retro] {
		transition: none;
	}
}

.carousel-nav__track:focus-visible {
	outline: 2px solid var(--focus-ring-color, currentColor);
	outline-offset: 4px;
}

.carousel-nav__controls {
	display: flex;
	gap: var(--space-2xs, 0.5rem);
	justify-content: flex-end;
	margin-block-start: var(--space-s, 1rem);
}

/* In un carosello a tutta larghezza i controlli non toccano il bordo dello
   schermo: rientrano del respiro laterale della pagina. I caroselli nella
   colonna del contenuto non sono toccati — lì il bordo giusto è quello. */
.carousel-nav:is(.full-bleed, .alignfull) .carousel-nav__controls {
	padding-inline-end: var(--pad-inline, clamp(1rem, 5vw, 4rem));
}

.carousel-nav__btn {
	display: grid;
	place-items: center;
	/* 44px: area di tocco minima raccomandata. */
	width: 2.75rem;
	height: 2.75rem;
	padding: 0;
	background-color: transparent;
	color: inherit;
	/* Colore del bordo regolabile dal CSS aggiuntivo del carosello (v2.30.0):
	   --carousel-btn-border sul gruppo, senza gare di specificità. */
	border: 1px solid var(--carousel-btn-border, var(--color-tertiary, #c9c4b4));
	border-radius: var(--btn-radius-full, 999rem);
	cursor: pointer;
	transition:
		background-color var(--transition-fast, 0.15s) var(--easing, ease),
		border-color var(--transition-fast, 0.15s) var(--easing, ease);
}

.carousel-nav__btn:hover {
	background-color: var(--btn-accent, currentColor);
	border-color: var(--btn-accent, currentColor);
	color: var(--btn-on-accent, #fff);
}

.carousel-nav__btn:focus-visible {
	outline: 2px solid var(--focus-ring-color, currentColor);
	outline-offset: 3px;
}

/* Il chevron è un bordo ruotato: nessuna icona da caricare. */
.carousel-nav__btn span {
	width: 0.5em;
	height: 0.5em;
	border-inline-end: 2px solid currentColor;
	border-block-end: 2px solid currentColor;
}

.carousel-nav__btn--prev span { transform: rotate(135deg); margin-inline-start: 0.15em; }
.carousel-nav__btn--next span { transform: rotate(-45deg); margin-inline-end: 0.15em; }

/*
 * I pulsanti si attenuano quando non c'è più niente in quella direzione.
 * Anche questo senza JavaScript: la posizione dello scorrimento diventa la
 * linea temporale di un'animazione. Dove non è supportato i pulsanti restano
 * pieni e continuano a funzionare — si perde solo l'indizio visivo.
 */
@supports (animation-timeline: scroll()) {
	.carousel-nav { timeline-scope: --lmcpro-carousel; }
	.carousel-nav__track { scroll-timeline: --lmcpro-carousel inline; }
	.carousel-nav.is-vertical .carousel-nav__track { scroll-timeline: --lmcpro-carousel block; }

	.carousel-nav__btn--prev {
		animation: lmcpro-btn-wake linear both;
		animation-timeline: --lmcpro-carousel;
		animation-range: 0% 6%;
	}

	.carousel-nav__btn--next {
		animation: lmcpro-btn-rest linear both;
		animation-timeline: --lmcpro-carousel;
		animation-range: 94% 100%;
	}
}

@keyframes lmcpro-btn-wake { from { opacity: 0.35; } to { opacity: 1; } }
@keyframes lmcpro-btn-rest { from { opacity: 1; } to { opacity: 0.35; } }

/* Verticale. */
.carousel-nav.is-vertical .carousel-nav__track {
	flex-direction: column;
	overflow-x: hidden;
	overflow-y: auto;
	scroll-snap-type: y mandatory;
	overscroll-behavior-y: contain;
	max-height: var(--carousel-height, 28rem);
}

.carousel-nav.is-vertical .carousel-nav__track > * { width: auto; }
.carousel-nav.is-vertical .carousel-nav__btn--prev span { transform: rotate(-135deg); margin: 0.15em 0 0; }
.carousel-nav.is-vertical .carousel-nav__btn--next span { transform: rotate(45deg); margin: 0 0 0.15em; }

@media (prefers-reduced-motion: reduce) {
	.carousel-nav__track { scroll-behavior: auto; }
	.carousel-nav__btn { transition-duration: 0.01ms; }
}


/* --------------------------------------------------------------------------
   COMPARSE — due sistemi, due personalità

   1. `reveal-*` — AL PRIMO INGRESSO: la prima volta che il blocco entra nel
      viewport si rivela (opacità + discesa + leggera scala) e poi resta lì.
      Serve un osservatore che annoti l'avvenuto ingresso: il CSS non può
      "ricordare", quindi c'è assets/js/reveal.js (una manciata di righe).

   2. `reveal-scroll-*` — LEGATO ALLO SCROLL: CSS puro, zero JavaScript.
      La posizione nella pagina È la linea temporale: scorrendo avanti
      l'elemento si compone, scorrendo indietro si scompone. È una moviola,
      non un interruttore — va scelto quando quel comportamento è voluto.
   -------------------------------------------------------------------------- */

/* ==========================================================================
   1. REVEAL AL PRIMO INGRESSO (con assets/js/reveal.js)

   ⚠️ SICUREZZA — lo stato nascosto esiste SOLO sotto `[data-reveal-ready]`,
   attributo che mette lo script dopo aver verificato di poter girare.
   Senza JavaScript, o con "riduci animazioni" attivo, l'attributo non c'è e
   nessun contenuto viene mai nascosto. Non spostare queste regole fuori da
   quel selettore: un elemento nascosto dal CSS in attesa di un JavaScript che
   non arriverà è una pagina con dei buchi.
   ========================================================================== */

/*
 * Stato di partenza: trasparente, leggermente rimpicciolito, fuori posto nella
 * direzione scelta. Si usano le proprietà singole `translate` e `scale` invece
 * di `transform`: si combinano senza sovrascriversi, e la direzione cambia
 * toccando una proprietà sola.
 */
[data-reveal-ready] :is(.reveal, .reveal-bottom, .reveal-left, .reveal-right, .reveal-fade),
[data-reveal-ready] .reveal-stagger > * {
	opacity: 0;
	scale: 0.97;
	translate: 0 calc(var(--reveal-distance, 2.25rem) * -1);
	transition:
		opacity var(--reveal-duration, 0.7s) var(--reveal-easing, cubic-bezier(0.16, 1, 0.3, 1)),
		translate var(--reveal-duration, 0.7s) var(--reveal-easing, cubic-bezier(0.16, 1, 0.3, 1)),
		scale var(--reveal-duration, 0.7s) var(--reveal-easing, cubic-bezier(0.16, 1, 0.3, 1));
}

/* Le direzioni cambiano solo il punto di partenza. */
[data-reveal-ready] .reveal-bottom { translate: 0 var(--reveal-distance, 2.25rem); }
[data-reveal-ready] .reveal-left   { translate: calc(var(--reveal-distance, 2.25rem) * -1) 0; }
[data-reveal-ready] .reveal-right  { translate: var(--reveal-distance, 2.25rem) 0; }
[data-reveal-ready] .reveal-fade   { translate: none; scale: none; }

/*
 * Stato finale: al proprio posto. La transizione dichiarata sopra fa il resto.
 * L'easing di default parte deciso e frena dolcemente: il movimento si sente
 * all'inizio e si posa senza rimbalzo.
 */
[data-reveal-ready] .is-inview:is(.reveal, .reveal-bottom, .reveal-left, .reveal-right, .reveal-fade),
[data-reveal-ready] .reveal-stagger.is-inview > * {
	opacity: 1;
	translate: none;
	scale: none;
}

/*
 * Cascata: `reveal-stagger` sul CONTENITORE. Lo script osserva il contenitore,
 * e i figli partono in fila grazie a un ritardo crescente — che qui si può
 * usare davvero, perché la transizione è a tempo e non legata allo scroll.
 */
[data-reveal-ready] .reveal-stagger > :nth-child(2) { transition-delay: 90ms; }
[data-reveal-ready] .reveal-stagger > :nth-child(3) { transition-delay: 180ms; }
[data-reveal-ready] .reveal-stagger > :nth-child(4) { transition-delay: 270ms; }
[data-reveal-ready] .reveal-stagger > :nth-child(5) { transition-delay: 360ms; }
[data-reveal-ready] .reveal-stagger > :nth-child(n + 6) { transition-delay: 450ms; }

/* Ampiezza dello spostamento e durata, come classi aggiuntive.
   Le distanze valgono per entrambi i sistemi; la durata solo per questo
   (nell'altro la velocità è lo scroll stesso). */
.reveal-near  { --reveal-distance: 1rem; }
.reveal-far   { --reveal-distance: 4rem; }
.reveal-quick { --reveal-duration: 0.35s; }
.reveal-slow  { --reveal-duration: 1.1s; }

/*
 * Cintura oltre alle bretelle: anche se l'attributo fosse presente, con
 * "riduci animazioni" attivo tutto resta fermo e visibile. Lo script esce da
 * solo in quel caso, ma una preferenza può cambiare a pagina aperta.
 */
@media (prefers-reduced-motion: reduce) {
	[data-reveal-ready] :is(.reveal, .reveal-bottom, .reveal-left, .reveal-right, .reveal-fade),
	[data-reveal-ready] .reveal-stagger > * {
		opacity: 1;
		translate: none;
		scale: none;
		transition: none;
	}
}

/* ==========================================================================
   2. REVEAL LEGATO ALLO SCROLL — CSS puro, nessun JavaScript

   ⚠️ PERCHÉ LA DURATA È `1ms`: nei browser con animazioni da scroll la linea
   temporale sostituisce il tempo e il millisecondo non conta nulla; Firefox
   però RICHIEDE una durata diversa da zero (documentato su MDN), e nei browser
   senza supporto resta una normale animazione da un millisecondo che si
   completa al caricamento lasciando il contenuto visibile. È questo fallback
   incorporato a rendere superfluo qualunque @supports.

   ⚠️ PERCHÉ `cover` E NON `entry`: le percentuali di `entry` sono relative
   all'altezza dell'elemento — per un paragrafo basso l'intera animazione si
   consuma in pochi pixel di scroll: eseguita sempre, visibile mai. Quelle di
   `cover` sono relative all'intero attraversamento, quindi "cover 50%" vuol
   dire circa mezzo viewport per qualunque elemento.
   ========================================================================== */

.reveal-scroll,
.reveal-scroll-bottom,
.reveal-scroll-fade {
	animation-name: lmcpro-reveal;
	animation-duration: 1ms; /* vedi sopra: non è un refuso */
	animation-timing-function: linear;
	animation-fill-mode: both;
	animation-timeline: view();
	animation-range: entry 0% cover 50%;
}

.reveal-scroll-bottom { animation-name: lmcpro-reveal-bottom; }
.reveal-scroll-fade   { animation-name: lmcpro-reveal-fade; }

/* Dall'alto verso il basso: l'elemento parte sopra al proprio posto e ci scende. */
@keyframes lmcpro-reveal {
	from { opacity: 0; transform: translateY(calc(var(--reveal-distance, 2.25rem) * -1)); }
	to   { opacity: 1; transform: none; }
}

@keyframes lmcpro-reveal-bottom {
	from { opacity: 0; transform: translateY(var(--reveal-distance, 2.25rem)); }
	to   { opacity: 1; transform: none; }
}

@keyframes lmcpro-reveal-fade {
	from { opacity: 0; }
	to   { opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
	.reveal-scroll,
	.reveal-scroll-bottom,
	.reveal-scroll-fade {
		animation: none;
		opacity: 1;
		transform: none;
	}
}


/* --------------------------------------------------------------------------
   FLUTTUA (v2.25.2) — keyframes da richiamare dal CSS aggiuntivo di un blocco

   Il CSS aggiuntivo di un blocco (Avanzate) non può contenere `@keyframes`:
   WordPress lo spezza alle graffe e scarta le regole annidate, e con loro
   tutto ciò che sta nello stesso pezzo. I keyframes stanno quindi qui, e nel
   blocco basta una riga:

       animation: lmcpro-fluttua 2s ease-in-out infinite;

   Su e giù di `--fluttua-ampiezza` (di serie 2px) attorno alla posizione di
   riposo; la durata è il periodo intero. Anima `translate` e non `transform`,
   così uno `scale` o un `transform` sullo stesso elemento restano liberi.

   Dichiarati solo con `no-preference`: con "riduci animazioni" il nome non
   corrisponde a nessun keyframe e l'elemento resta fermo, senza bisogno di
   annullare l'`animation` scritta nel blocco.
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: no-preference) {
	@keyframes lmcpro-fluttua {
		0%, 100% { translate: 0 calc(var(--fluttua-ampiezza, 2px) * -1); }
		50% { translate: 0 var(--fluttua-ampiezza, 2px); }
	}
}


/* --------------------------------------------------------------------------
   INTRECCIO MOBILE (v2.25.1) — classe `intreccio-mobile` sul blocco Colonne

   Impilate, le colonne restano due blocchi interi: tutta la prima, poi tutta
   la seconda. Con questa classe, sotto la soglia a cui WordPress impila le
   colonne (782px), la seconda colonna entra subito dopo il PRIMO blocco
   della prima: tipicamente titolo → immagine o caroselli → testo e bottone.

   Le due colonne spariscono dal layout (`display: contents`) e i loro blocchi
   diventano figli diretti del flex delle Colonne, dove `order` li può
   rimescolare senza toccare il markup. Costo: sotto i 782px si perdono
   sfondo, bordo e padding impostati sulle singole colonne, perché il loro
   riquadro non esiste più.

   Lo spazio fra i blocchi resta quello del flusso della colonna
   (`* + *` di WordPress): per questo il `gap` delle Colonne va a zero,
   altrimenti si sommerebbe. Al primo blocco della seconda colonna quel
   margine manca, perché nella sua colonna è il primo: si aggiunge qui.
   -------------------------------------------------------------------------- */

@media (max-width: 781px) {
	.wp-block-columns.intreccio-mobile {
		flex-direction: column;
		gap: 0;
	}

	.wp-block-columns.intreccio-mobile > .wp-block-column {
		display: contents;
	}

	.wp-block-columns.intreccio-mobile > .wp-block-column > * {
		order: 3;
	}

	.wp-block-columns.intreccio-mobile > .wp-block-column:first-child > :first-child {
		order: 1;
	}

	.wp-block-columns.intreccio-mobile > .wp-block-column:not(:first-child) > * {
		order: 2;
	}

	.wp-block-columns.intreccio-mobile > .wp-block-column:not(:first-child) > :first-child {
		margin-block-start: var(--wp--style--block-gap, 1.5rem);
	}
}


/* --------------------------------------------------------------------------
   MOBILE INVERTI (v2.25.4) — classe `mobile-inverti` sul blocco Colonne

   Sotto la soglia a cui WordPress impila le colonne (782px) l'ordine si
   ribalta: l'ultima colonna sale in cima. Serve quando il titolo sta sopra
   le colonne e su mobile l'immagine, messa a destra da desktop, deve venire
   subito dopo il titolo e prima del testo. Le colonne restano intere (sfondi
   e padding compresi): se l'immagine deve infilarsi DENTRO la prima colonna,
   dopo il suo primo blocco, la classe giusta è `intreccio-mobile`.

   Cambia solo l'ordine a schermo: nel markup, e quindi per tastiera e screen
   reader, il testo resta prima dell'immagine.
   -------------------------------------------------------------------------- */

@media (max-width: 781px) {
	.wp-block-columns.mobile-inverti {
		flex-direction: column-reverse;
	}
}


/* --------------------------------------------------------------------------
   TORNA IN ALTO (pattern lmcpro/torna-su)
   -------------------------------------------------------------------------- */

.torna-su-riga {
	text-align: end;
}

.torna-su {
	display: inline-flex;
	align-items: center;
	gap: 0.4em;
	padding: 0.5rem 1.1rem;
	background-color: transparent;
	color: var(--color-contrast, currentColor);
	border: 1px solid var(--color-tertiary, #c9c4b4);
	border-radius: var(--btn-radius-full, 999rem);
	font-size: var(--wp--preset--font-size--xs);
	text-decoration: none;
	transition:
		background-color var(--transition-fast, 0.15s) var(--easing, ease),
		border-color var(--transition-fast, 0.15s) var(--easing, ease),
		color var(--transition-fast, 0.15s) var(--easing, ease);
}

.torna-su:hover {
	background-color: var(--btn-accent, currentColor);
	border-color: var(--btn-accent, currentColor);
	color: var(--btn-on-accent, #ffffff);
	text-decoration: none;
}

.torna-su:focus-visible {
	outline: 2px solid var(--focus-ring-color, currentColor);
	outline-offset: 3px;
}


/* --------------------------------------------------------------------------
   ZOOM INTERNO (v2.28.0) — classe `zoom-in-inside` sul blocco Immagine

   Al passaggio del mouse la foto si ingrandisce DENTRO la sua cornice, senza
   sbordare. Il taglio lo fa il figure con `overflow: hidden`, e segue la forma
   del figure, non quella della foto: per questo arrotondamento e larghezza
   stanno sul figure. Con gli angoli sulla sola foto, ingrandendola i suoi
   angoli uscirebbero dalla curva; con un figure più largo della foto, la foto
   crescerebbe nello spazio vuoto prima di essere tagliata.

   Regolabili dal CSS aggiuntivo del blocco:
     --zoom-radius  angoli della cornice (di serie 50px, 0 = dritti)
     --zoom-scale   ingrandimento (di serie 1.1)

   `scale` e non `transform`: la proprietà singola si compone con un eventuale
   transform sull'immagine invece di sostituirlo.
   -------------------------------------------------------------------------- */

.zoom-in-inside {
	overflow: hidden;
	position: relative;
	isolation: isolate; /* senza, Safari non ritaglia gli angoli durante lo zoom */
	border-radius: var(--zoom-radius, 50px);
}

/* Specificità zero: una larghezza data all'immagine nel suo CSS vince sempre. */
:where(.zoom-in-inside) {
	width: fit-content;
}

.zoom-in-inside img {
	display: block;
	width: 100%;
	height: auto;
	transition: scale 0.4s ease;
}

/* Gli angoli li taglia la cornice. Un arrotondamento impostato nell'editor
   sull'immagine resta (stile in linea): va tenuto uguale a --zoom-radius. */
:where(.zoom-in-inside) img {
	border-radius: 0;
}

@media (hover: hover) {
	.zoom-in-inside:hover img {
		scale: var(--zoom-scale, 1.1);
	}
}

.zoom-in-inside:focus-within img {
	scale: var(--zoom-scale, 1.1);
}

/*
 * Nella Griglia portfolio la cornice è `.portfolio-item__media`, messa dal
 * template della card (template-parts/portfolio-item.php). Queste regole
 * stanno qui e non in style.css perché devono battere quelle della utility,
 * che non sono in un layer: la cornice riempie la cella (non fit-content) e
 * la foto riempie la cornice (non height: auto). Lo zoom parte passando sopra
 * tutta la card, testi compresi, e con il focus da tastiera sul link.
 */
.portfolio-item__media {
	width: 100%;
}

.portfolio-item__media img {
	height: 100%;
}

@media (hover: hover) {
	.portfolio-item:hover .portfolio-item__media img {
		scale: var(--zoom-scale, 1.1);
	}
}

.portfolio-item__link:focus-visible .portfolio-item__media img {
	scale: var(--zoom-scale, 1.1);
}

@media (prefers-reduced-motion: reduce) {
	.zoom-in-inside img {
		transition: none;
	}

	.zoom-in-inside:is(:hover, :focus-within) img,
	.portfolio-item:is(:hover, :focus-within) .portfolio-item__media img {
		scale: none;
	}
}


/* --------------------------------------------------------------------------
   UTILITY DI SPAZIATURA — da scrivere fra le "Classi CSS aggiuntive"

   Stanno qui, non layerizzate, perché vanno applicate ai blocchi di core: da
   dentro un @layer perderebbero contro le regole di layout di WordPress.

   Tutti i valori sono in `clamp()`: si adattano da soli fra schermo piccolo e
   grande, senza breakpoint. Nessun valore fisso in pixel.
   -------------------------------------------------------------------------- */

/*
 * NOTA SUL SELETTORE RIPETUTO — `.pad-block-m.pad-block-m` non è un errore.
 *
 * Una classe utility deve vincere su qualunque componente, sempre. Scritta una
 * volta sola avrebbe la stessa specificità di `.cta-band`, e a parità di
 * specificità decide l'ordine nel file: funzionerebbe oggi e smetterebbe di
 * funzionare il giorno in cui qualcuno sposta una regola.
 *
 * Ripetere la classe porta la specificità a (0,2,0) senza cambiare cosa il
 * selettore seleziona: è il modo di rendere una utility prevedibile senza
 * ricorrere a `!important`, che invece toglierebbe la possibilità di
 * sovrascriverla ancora più avanti.
 */

/* Padding interno verticale — lo spazio sta DENTRO il blocco, quindi uno
   sfondo colorato lo comprende. È quello che serve a una fascia. */
.pad-block-none.pad-block-none { padding-block: 0; }
.pad-block-xs.pad-block-xs { padding-block: clamp(0.75rem, 2vw, 1.25rem); }
.pad-block-s.pad-block-s   { padding-block: clamp(1.25rem, 3vw, 2rem); }
.pad-block-m.pad-block-m   { padding-block: clamp(2rem, 5vw, 3.5rem); }
.pad-block-l.pad-block-l   { padding-block: clamp(3rem, 7vw, 5.5rem); }
.pad-block-xl.pad-block-xl { padding-block: clamp(4.5rem, 10vw, 8rem); }

/* Padding laterale allineato al resto della pagina: serve ai blocchi a tutta
   larghezza, il cui contenuto altrimenti tocca i bordi dello schermo. */
.pad-inline-page.pad-inline-page { padding-inline: var(--pad-inline, clamp(1rem, 5vw, 4rem)); }
.pad-inline-none.pad-inline-none { padding-inline: 0; }

/* Margine esterno verticale — lo spazio sta FUORI dal blocco, quindi uno
   sfondo colorato non lo comprende. È quello che serve a distanziare due
   sezioni fra loro. */
.space-block-none.space-block-none { margin-block: 0; }
.space-block-xs.space-block-xs { margin-block: clamp(0.75rem, 2vw, 1.25rem); }
.space-block-s.space-block-s   { margin-block: clamp(1.25rem, 3vw, 2rem); }
.space-block-m.space-block-m   { margin-block: clamp(2rem, 5vw, 3.5rem); }
.space-block-l.space-block-l   { margin-block: clamp(3rem, 7vw, 5.5rem); }
.space-block-xl.space-block-xl { margin-block: clamp(4.5rem, 10vw, 8rem); }


/* --------------------------------------------------------------------------
   Segnaposto del form nel pattern Contatti
   -------------------------------------------------------------------------- */

.cf7-placeholder {
	padding: var(--space-m, 1.5rem);
	border: 1px dashed var(--color-tertiary, #c9c4b4);
	border-radius: var(--btn-radius-md, 0.5rem);
	font-size: var(--wp--preset--font-size--xs);
	color: color-mix(in srgb, var(--color-contrast, currentColor) 65%, transparent);
}


/* --------------------------------------------------------------------------
   DICONO DI ME — testimonianze a dissolvenza

   Si scrive `dicono-di-me` fra le Classi CSS aggiuntive di un Gruppo che
   contiene un blocco Colonne: ogni colonna e' una testimonianza, e il tema
   aggiunge sotto un pallino per ciascuna (include/carousel.php).

   ZERO JAVASCRIPT, e non per sport: ogni pallino e' l'etichetta di un radio
   button. Commutare fra alternative che si escludono e' il mestiere di un
   gruppo di radio, la tastiera arriva in regalo (dentro un gruppo di radio le
   frecce direzionali passano da una voce all'altra da sole) e lo stato vive
   nel DOM, dove `:has()` lo legge senza che nessuno debba annotarlo.

   Il tetto di otto testimonianze e' scritto anche in PHP
   (LMCPRO_TESTIMONIANZE_MAX): l'abbinamento pallino -> colonna e' una coppia di
   selettori per indice e il CSS non ha cicli. Oltre il tetto PHP non genera i
   pallini e la fascia resta un elenco normale.
   -------------------------------------------------------------------------- */

.dicono-di-me__dots {
	/*
	 * Cintura oltre alle bretelle, come per il reveal: senza `:has()` i pallini
	 * non potrebbero commutare niente, quindi restano nascosti e le
	 * testimonianze si vedono tutte in fila. Nessuno resta davanti al vuoto.
	 */
	display: none;
	justify-content: center;
	gap: 0.25rem;
	margin-block-start: var(--space-m, 1.5rem);
}

/* La citazione e' l'unico contenuto: niente stanghetta laterale, niente
   rientro, si presenta centrata e larga quanto una riga leggibile. */
.dicono-di-me .wp-block-quote {
	max-inline-size: 42rem;
	margin-inline: auto;
	padding: 0;
	border: 0;
	text-align: center;
}

.dicono-di-me .wp-block-quote p {
	font-size: var(--wp--preset--font-size--l);
	line-height: 1.35;
	text-wrap: balance;
}

.dicono-di-me .wp-block-quote cite {
	display: block;
	margin-block-start: var(--space-s, 1rem);
	font-size: var(--wp--preset--font-size--xs);
	font-style: normal;
	color: color-mix(in srgb, var(--color-contrast, currentColor) 65%, transparent);
}

@supports selector(:has(*)) {

	.dicono-di-me__dots {
		display: flex;
	}

	/*
	 * ⚠️ TUTTO SUBORDINATO A `:has(.dicono-di-me__dots)`, e non e' pignoleria.
	 *
	 * I pallini li aggiunge `render_block`, che gira SOLO sul front-end: dentro
	 * l'editor non esistono. Senza questa condizione le regole qui sotto
	 * spegnerebbero le colonne anche in Gutenberg — dove blocks.css arriva
	 * davvero, via `enqueue_block_assets` (vedi include/enqueue.php) — e la
	 * fascia diventerebbe invisibile e non scrivibile. E' successo: prima
	 * versione del 2.19.0, corretta in 2.19.2.
	 *
	 * In regalo, la condizione allinea CSS e PHP da sola: quando PHP non genera
	 * i pallini (una sola testimonianza, o piu' del tetto) non c'e' niente da
	 * commutare e le testimonianze restano un elenco normale, senza che le due
	 * soglie debbano essere ricordate in due posti.
	 *
	 * Le testimonianze si impilano nella STESSA cella di griglia. Non e' un
	 * dettaglio: cosi' la fascia e' alta quanto la testimonianza piu' lunga e
	 * resta ferma al cambio, invece di far saltare la pagina a ogni pallino.
	 */
	.dicono-di-me:has(.dicono-di-me__dots) .wp-block-columns {
		display: grid;
		grid-template-columns: 1fr;
		gap: 0;
	}

	.dicono-di-me:has(.dicono-di-me__dots) .wp-block-columns > .wp-block-column {
		grid-area: 1 / 1;
		opacity: 0;
		/*
		 * `visibility` e non la sola opacita': una testimonianza spenta deve
		 * sparire anche dalla tabulazione e dagli screen reader, non solo dalla
		 * vista — altrimenti la tastiera attraversa quattro citazioni invisibili.
		 */
		visibility: hidden;
		transition:
			opacity var(--dicono-durata, 0.55s) var(--easing, ease),
			visibility var(--dicono-durata, 0.55s) var(--easing, ease);
	}

	.dicono-di-me:has(.dicono-di-me__dot:nth-child(1) input:checked) .wp-block-columns > .wp-block-column:nth-child(1),
	.dicono-di-me:has(.dicono-di-me__dot:nth-child(2) input:checked) .wp-block-columns > .wp-block-column:nth-child(2),
	.dicono-di-me:has(.dicono-di-me__dot:nth-child(3) input:checked) .wp-block-columns > .wp-block-column:nth-child(3),
	.dicono-di-me:has(.dicono-di-me__dot:nth-child(4) input:checked) .wp-block-columns > .wp-block-column:nth-child(4),
	.dicono-di-me:has(.dicono-di-me__dot:nth-child(5) input:checked) .wp-block-columns > .wp-block-column:nth-child(5),
	.dicono-di-me:has(.dicono-di-me__dot:nth-child(6) input:checked) .wp-block-columns > .wp-block-column:nth-child(6),
	.dicono-di-me:has(.dicono-di-me__dot:nth-child(7) input:checked) .wp-block-columns > .wp-block-column:nth-child(7),
	.dicono-di-me:has(.dicono-di-me__dot:nth-child(8) input:checked) .wp-block-columns > .wp-block-column:nth-child(8) {
		opacity: 1;
		visibility: visible;
	}

	.dicono-di-me__dot {
		position: relative;
		display: grid;
		place-items: center;
		/* 36px di area sensibile attorno a un pallino da 9: il bersaglio e' la
		   mano, non il disegno (WCAG 2.5.8). */
		inline-size: 2.25rem;
		block-size: 2.25rem;
		cursor: pointer;
	}

	.dicono-di-me__dot input {
		/* Il radio resta dov'e' e raggiungibile: sparisce solo alla vista.
		   `display: none` lo toglierebbe anche alle frecce della tastiera. */
		position: absolute;
		inset: 0;
		margin: 0;
		opacity: 0;
		cursor: pointer;
	}

	.dicono-di-me__dot::before {
		content: "";
		inline-size: 0.5625rem;
		block-size: 0.5625rem;
		border: 1px solid currentColor;
		border-radius: 50%;
		transition:
			background-color var(--transition-base, 0.28s) var(--easing, ease),
			scale var(--transition-base, 0.28s) var(--easing, ease);
	}

	.dicono-di-me__dot:has(input:checked)::before {
		background-color: currentColor;
		scale: 1.2;
	}

	.dicono-di-me__dot:hover::before {
		background-color: color-mix(in srgb, currentColor 35%, transparent);
	}

	/* Il focus si disegna sull'etichetta, non sul radio invisibile. */
	.dicono-di-me__dot:has(input:focus-visible) {
		border-radius: 50%;
		outline: 2px solid currentColor;
		outline-offset: -4px;
	}
}

@media (prefers-reduced-motion: reduce) {
	.dicono-di-me .wp-block-columns > .wp-block-column,
	.dicono-di-me__dot::before {
		transition-duration: 0.01ms;
	}
}


/* --------------------------------------------------------------------------
   FILTRI PORTFOLIO — categorie senza JavaScript (dal 2.21.0)

   I pulsanti sono un gruppo di radio button generato da render.php del blocco
   Griglia portfolio (lmcpro_portfolio_filters_markup() in include/blocks.php):
   il valore di ogni radio e' l'indice della categoria, e ogni riquadro porta
   le classi `filtro-N` delle sue categorie. Il CSS legge con `:has()` quale
   radio e' acceso e nasconde i riquadri che non hanno la classe
   corrispondente. `display: none` toglie il riquadro anche dal flusso della
   griglia, che si ricompone da sola senza buchi.

   Il radio resta nel DOM e sopra l'etichetta, trasparente: e' lui a ricevere
   clic e focus, quindi tastiera e screen reader funzionano senza aiuti.
   -------------------------------------------------------------------------- */

.portfolio-filtri {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	gap: var(--space-2xs, 0.5rem);
	min-inline-size: 0;
	margin: 0 0 var(--space-l, 2rem);
	padding: 0;
	border: 0;
}

.portfolio-filtri__opzione {
	position: relative;
	display: inline-flex;
}

.portfolio-filtri__radio {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	margin: 0;
	opacity: 0;
	cursor: pointer;
}

.portfolio-filtri__etichetta {
	display: inline-flex;
	align-items: center;
	min-height: 2.75rem;
	padding: 0.5em 1.25em;
	border: 1px solid var(--btn-accent, currentColor);
	border-radius: var(--btn-radius-full, 999rem);
	color: var(--btn-accent, currentColor);
	background-color: transparent;
	transition:
		background-color var(--transition-fast, 0.15s) var(--easing, ease),
		color var(--transition-fast, 0.15s) var(--easing, ease);
}

.portfolio-filtri__opzione:hover .portfolio-filtri__etichetta {
	background-color: color-mix(in srgb, var(--btn-accent, currentColor) 12%, transparent);
}

.portfolio-filtri__radio:checked + .portfolio-filtri__etichetta {
	color: var(--btn-on-accent, #ffffff);
	background-color: var(--btn-accent, currentColor);
}

.portfolio-filtri__radio:focus-visible + .portfolio-filtri__etichetta {
	outline: 2px solid var(--btn-accent, currentColor);
	outline-offset: 3px;
}

/* Senza :has() i pulsanti non potrebbero filtrare nulla: meglio non mostrarli. */
@supports not selector(:has(*)) {
	.portfolio-filtri {
		display: none;
	}
}

/* Una riga per categoria, fino a LMCPRO_PORTFOLIO_FILTRI_MAX (12).
   Il valore 0 e' "Tutte le categorie" e non nasconde niente. */
@supports selector(:has(*)) {
	.portfolio-filtrabile:has(.portfolio-filtri__radio[value="1"]:checked) .portfolio-item:not(.filtro-1),
	.portfolio-filtrabile:has(.portfolio-filtri__radio[value="2"]:checked) .portfolio-item:not(.filtro-2),
	.portfolio-filtrabile:has(.portfolio-filtri__radio[value="3"]:checked) .portfolio-item:not(.filtro-3),
	.portfolio-filtrabile:has(.portfolio-filtri__radio[value="4"]:checked) .portfolio-item:not(.filtro-4),
	.portfolio-filtrabile:has(.portfolio-filtri__radio[value="5"]:checked) .portfolio-item:not(.filtro-5),
	.portfolio-filtrabile:has(.portfolio-filtri__radio[value="6"]:checked) .portfolio-item:not(.filtro-6),
	.portfolio-filtrabile:has(.portfolio-filtri__radio[value="7"]:checked) .portfolio-item:not(.filtro-7),
	.portfolio-filtrabile:has(.portfolio-filtri__radio[value="8"]:checked) .portfolio-item:not(.filtro-8),
	.portfolio-filtrabile:has(.portfolio-filtri__radio[value="9"]:checked) .portfolio-item:not(.filtro-9),
	.portfolio-filtrabile:has(.portfolio-filtri__radio[value="10"]:checked) .portfolio-item:not(.filtro-10),
	.portfolio-filtrabile:has(.portfolio-filtri__radio[value="11"]:checked) .portfolio-item:not(.filtro-11),
	.portfolio-filtrabile:has(.portfolio-filtri__radio[value="12"]:checked) .portfolio-item:not(.filtro-12) {
		display: none;
	}
}

@media (prefers-reduced-motion: reduce) {
	.portfolio-filtri__etichetta {
		transition-duration: 0.01ms;
	}
}


/* --------------------------------------------------------------------------
   Movimento ridotto — anche per i blocchi core
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
	.wp-block-button__link,
	.wp-element-button {
		transition-duration: 0.01ms;
	}
	.wp-block-button__link:active,
	.wp-element-button:active {
		transform: none;
	}
}


/* --------------------------------------------------------------------------
   Banner di consenso — le due cose che il layer non può vincere

   Il grosso del banner sta in style.css, dentro @layer consenso, e da lì
   funziona: sfondo, impaginazione, bottoni. Due dichiarazioni però perdono
   comunque, e non per una questione di specificità:

     h2                              { font-size: … }   ← qui sopra, non layerizzata
     a:where(:not(.wp-element-button)) { color: … }     ← global-styles di theme.json

   Sono entrambe FUORI da ogni layer, quindi battono qualunque regola dentro
   @layer per quanto specifica. Verificato a runtime con CSS.getMatchedStylesForNode:
   senza queste due righe il titolo esce grande come un titolo di sezione e il
   link della policy esce turchese su fondo viola — 1,9:1, illeggibile.

   Stanno qui e non in theme.json perché theme.json descrive i blocchi, e questo
   markup non è un blocco: è il banner stampato da include/consent.php.
   -------------------------------------------------------------------------- */

.consenso .consenso__titolo {
	font-size: var(--wp--preset--font-size--s, 1rem);
	line-height: var(--line-height-tight);
	color: var(--wp--preset--color--tertiary);
}

/* Il colore dei link del tema è pensato su fondo chiaro. Dentro il banner
   eredita il bianco, e la sottolineatura resta perché tolto il colore è
   l'unica cosa che distingue un link dal testo intorno (WCAG 1.4.1). */
.consenso .consenso__link a {
	color: var(--wp--preset--color--tertiary);
	text-decoration: underline;
	text-underline-offset: 0.2em;
}

/* L'hover NON cambia colore: il secondario su fondo viola darebbe 2,86:1,
   cioè un link che diventa illeggibile proprio mentre lo si punta. Si ispessisce
   la sottolineatura, che è un segnale altrettanto chiaro e non costa contrasto. */
.consenso .consenso__link a:hover,
.consenso .consenso__link a:focus-visible {
	color: var(--wp--preset--color--tertiary);
	text-decoration-thickness: 2px;
}

.consenso .consenso__link a:focus-visible {
	outline: var(--focus-ring-width, 2px) solid var(--wp--preset--color--tertiary);
	outline-offset: var(--focus-ring-offset, 3px);
}
