/* Base comune di tutte le pagine: font, reset, tipografia del kiosk + modali
   (ex style.css + ex modale.css). Aggregati perche' non hanno un solo selettore in comune
   (solo :root, con variabili di prefisso diverso) e viaggiavano sempre insieme.

   Caricato da inc/head.inc.php PRIMA del delta per-azienda, che deve restare l'ultimo
   foglio della base per poterlo sovrascrivere.

   NON aggregare qui wizard.css: lo caricano solo i tre passi della firma
   (inc/wizard-head.inc.php), e le sue regole su body cambierebbero login e home.

   ⚠️ Questo file era per due terzi il CSS del template di partenza: 69 selettori su 131 non
   comparivano piu' in nessun markup ne' in nessun JS (griglia Bootstrap smessa, UI rimossa dai
   refactor, nomi da tastiera pestata come .deswq/.qwer/.dfew). Purgati il 2026-07-29. Prima di
   aggiungere una regola qui: se serve a UNA pagina sola, va nel CSS di quella pagina — questa e'
   l'unica che viaggia su tutte e sei.
*/

/* ---- Font (ex google-fonts-local.css, incorporato qui) ----
   Erano in un file a parte tirato dentro con @import: una richiesta SERIALIZZATA, che il
   browser scopre solo dopo aver scaricato e parsato questo foglio, quindi i @font-face
   partivano al secondo round-trip. Qui partono col primo.
   I path ../fonts/ restano validi: il file incorporante sta nella stessa cartella.
   Ridotto a latin + latin-ext (app italiana): rimossi cyrillic/greek/vietnamese e il
   peso 100 (thin), mai usati. Alegreya Sans pesi 300/400/700 (500 ripiega su 400,
   600/800/900 su 700), Tangerine 400. */

/* Alegreya Sans 300 */
@font-face {
  font-family: 'Alegreya Sans';
  font-style: normal;
  font-weight: 300;
  font-display: swap;
  src: url(../fonts/AlegreyaSans-Light-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Alegreya Sans';
  font-style: normal;
  font-weight: 300;
  font-display: swap;
  src: url(../fonts/AlegreyaSans-Light-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* Alegreya Sans 400 */
@font-face {
  font-family: 'Alegreya Sans';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(../fonts/AlegreyaSans-Regular-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Alegreya Sans';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(../fonts/AlegreyaSans-Regular-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* Alegreya Sans 700 (copre 600/800/900 per fallback; il 500 ripiega su 400) */
@font-face {
  font-family: 'Alegreya Sans';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url(../fonts/AlegreyaSans-Bold-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Alegreya Sans';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url(../fonts/AlegreyaSans-Bold-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* Tangerine 400 (titoli) */
@font-face {
  font-family: 'Tangerine';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(../fonts/Tangerine-Regular-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* Il tema per-azienda (assets/css/case_funerarie/style-<id>.css) ridefinisce queste. */
:root {
    --brand: #86754E;
    --brand-dark: #6f5f40;
    --grey: #6C6A6A;
}

html,
body {
    height: 100%;
    background-image: url(../img/backgrounds/paper30.jpg);
    touch-action: pan-x pan-y;
}

body {
    font-weight: 400;
}

* {
    box-sizing: border-box;
    font-family: "Alegreya Sans", sans-serif;
}

dl,
ol,
ul {
    padding-left: 0px;
}

ul {
    list-style: none;
}

img {
    max-width: 100%;
}

a {
    text-decoration: none;
}

a:hover {
    text-decoration: none;
}

label a {
    color: #000;
}

/* .title / .label: li usa privacy_policy.html, che e' HTML statico servito da Apache e carica
   base.css + wizard.css. */
.title {
    padding: 19px 0px 0px;
    color: var(--brand);
}

/* Campo in errore: la classe la mette/toglie indexkeyboard.js. */
.red-placeholder::placeholder {
    color: red;
}

/* ---- Le tre utility che restano di Bootstrap, copiate qui invece di tenere il foglio intero.
   Il resto del framework se n'e' andato (il reset e' in reset.css, il modale e' <dialog>). ---- */

/* Testo per i soli screen reader: le etichette dei passi del wizard, i radio di attesa.php e
   il testo dello spinner. Non display:none — sparirebbe anche per loro. */
.sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* Rotella di attesa: invio.php durante l'invio, login-page.js sul rientro offline.
   currentColor, quindi il colore lo decide chi la usa. */
.spinner-border {
    display: inline-block;
    width: 2rem;
    height: 2rem;
    vertical-align: -.125em;
    border: .25em solid currentColor;
    border-right-color: transparent;
    border-radius: 50%;
    animation: .75s linear infinite spinner-border;
}

@keyframes spinner-border {
    to { transform: rotate(360deg); }
}

/* Chi ha chiesto di ridurre le animazioni vede la rotella girare piano, non sparire: e' un
   indicatore di stato, se si ferma sembra che l'app sia bloccata. */
@media (prefers-reduced-motion: reduce) {
    .spinner-border { animation-duration: 1.5s; }
}

.text-light {
    color: #f8f9fa;
}

/* Usata dai body di main.php e invio.php, che la sovrascrivevano entrambi con lo stesso
   #fff !important dai rispettivi blocchi inline: qui la regola e' una sola. */
.bg-page {
    background-color: #fff;
    position: relative;
}

.text-brand {
    color: var(--brand);
}

/* ---- Dati del defunto (main.php) ---- */
.name {
    font-size: 35px;
    font-weight: 500;
}

.person-image {
    width: 20%;
}

@media only screen and (min-width: 1730px) {
    .person-image {
        width: 14%;
    }
}

/* Date di nascita e morte sotto la foto: 15px weight 300 su un display da sala. */
.info-defunto {
    font-weight: 400;
    display: block;
    font-size: 18px;
}

#immagine-def {
    height: auto;
}

@media only screen and (max-width: 599px) {
    .title {
        font-size: 20px;
    }
}

/* ---- Preloader: velo + spinner mostrati durante il login (login-page.js) ---- */
#preloader {
    position: fixed;
    left: 0;
    top: 0;
    z-index: 999;
    width: 100%;
    height: 100%;
    overflow: visible;
    background: #141A26;
    opacity: 0.7;
}

#preloader::after {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    width: 60px;
    height: 60px;
    margin: -30px 0 0 -30px;
    border: 6px solid rgba(255, 255, 255, 0.25);
    border-top-color: #fff;
    border-radius: 50%;
    animation: preloaderSpin 0.9s linear infinite;
}

@keyframes preloaderSpin {
    to {
        transform: rotate(360deg);
    }
}

/* ---- Override delle librerie (introJs, SweetAlert2): classi generate da loro ---- */
.introjs-relativePosition {
    position: relative !important;
}

/* L'elemento evidenziato porta da introJs position:relative e z-index 9999999, quindi emerge sopra
   l'overlay da solo — a meno che un antenato posizionato con z-index numerico non lo confini nel
   proprio stacking context, ed e' il caso in cui il tutorial finiva per illuminare il nulla.
   Qui si toglie quel confinamento invece di alzare l'antenato: era 9999999 !important, che porta
   sopra l'overlay TUTTO il ramo. Sulla home body e .allResults sono position:relative, quindi
   l'intera pagina restava illuminata e l'oscuramento del tutorial spariva. */
:has(.introjs-showElement) {
    z-index: auto !important;
}

div:has(.introjs-showElement)>*,
form:has(.introjs-showElement)>* {
    pointer-events: auto;
}

div:has(.introjs-showElement),
form:has(.introjs-showElement) {
    pointer-events: none;
}

.swal2-container {
    z-index: 100000001;
}

.introjs-tooltip .introjs-tooltip-header {
    position: static;
}

.introjs-tooltip .introjs-skipbutton {
    top: auto;
    right: auto;
    bottom: 10px;
    left: 50%;
    transform: translateX(-50%);
    width: auto;
    height: auto;
    /* 1.5 e non 'normal': la libreria dava 45px al box quadrato della "x", e 'normal' lo faceva
       tornare a 34px di altezza contro i 39px di "Precedente"/"Successivo", che ereditano 1.5 dal
       body. Cinque pixel su tre pulsanti in fila si vedono. */
    line-height: 1.5;
    padding: .5rem 1rem;
    border: 1px solid #bdbdbd;
    border-radius: .2em;
    background-color: #f4f4f4;
    color: #424242;
    font-size: 14px;
    font-weight: 400;
    text-shadow: 1px 1px 0 #fff;
}

.introjs-tooltip {
    min-width: 340px !important;
    max-width: 380px !important;
}

/* Messaggio di chiusura del tutorial (home-extra.js): un solo pulsante, "Fine". */
.lf-tutorial-fine .introjs-skipbutton {
    display: none;
}

/* Il libro firme e' pensato solo in orizzontale
   In portrait copre lo schermo e invita a ruotare */
@media (orientation: portrait) {
    body::before {
        content: "Ruota il dispositivo in orizzontale";
        position: fixed;
        inset: 0;
        z-index: 99999;
        display: flex;
        align-items: center;
        justify-content: center;
        text-align: center;
        padding: 10vw;
        background: var(--brand);
        color: #fff;
        font-size: 6vw;
        line-height: 1.3;
    }

    /* Il pulsante "Mostra tastiera" (fixed, z-index alto) non deve galleggiare
       sopra l'overlay "Ruota il dispositivo". */
    .toggle-keyboard {
        display: none !important;
    }
}

/* ==================== ex modale.css ==================== */

/* ============================================================
   MODALI — un meccanismo solo per tutta l'app.

   I modali sono <dialog> nativi aperti con apriDialog() (assets/js/dialoghi.js). Pelli diverse,
   stesso comportamento:
     .lf-modale     informativo condiviso (inc/modale.inc.php) e dettaglio firma (main.php)
     .attesa-guida  procedure di abbinamento (attesa.php, pelle in home.css)
     .login-avviso  avvisi dell'ingresso offline (index.php, pelle in login.css)

   Erano cinque meccanismi diversi: due <dialog>, un <div hidden> con position:fixed e due <div>
   costruiti in JS con innerHTML e stili in linea. Backdrop, blocco dello scroll di fondo, Esc e
   focus trap ce li aveva solo chi se li era scritti. Ora li da' il browser.

   ⛔ UNA ECCEZIONE, e non e' una dimenticanza: il dialogo dei recapiti di invio.php
   (.wz-modale, wizard.css) resta un <div hidden> con position:fixed. Un <dialog> aperto con
   showModal() entra nel TOP LAYER, che sta sopra qualunque z-index — e la tastiera virtuale
   (device senza tastiera di sistema) ci finirebbe sotto, oltre a diventare inerte: showModal
   rende inerte tutto cio' che sta fuori dal dialog. Oggi a tenerla sopra e' proprio uno
   z-index (wizard.css: .hg-theme-default a 100000, il pulsante a 100001), che nel top layer
   smetterebbe di funzionare. Convertirlo si puo', ma vuol dire spostare tastiera e pulsante
   DENTRO il dialog e rifare le regole body.kb-open: va provato sul tablet con
   forceVirtualKeyboard=1, sull'unico parco per cui quella tastiera esiste. Vedi PUNTI_APERTI §8.

   Markup canonico del solo .lf-modale:
     dialog.lf-modale > [ form>.modale-chiudi + .modale-testata + .lf-modale-corpo ]
   Niente barra del titolo: il titolo fa parte del contenuto, non di un'intestazione sopra di
   esso. Prima era un modale Bootstrap 4.6, che per questo solo componente si portava dietro
   138 KB di bundle e gli 85 di jQuery.

   ⚠️ Un <dialog> chiuso e' display:none. Qualunque regola che imposti `display` va scritta su
   [open], mai sul selettore nudo, o il modale si vede a pagina aperta.

   --brand arriva dal blocco :root qui sopra; i neutri sono quelli del restyle della home,
   ripetuti qui perche' home.css la carica solo main.php.
   ============================================================ */

:root {
  --modale-ink: #2e2924;
  --modale-muted: #8b8173;
  --modale-line: #ddd3c1;
}

/* Contenuti dei modali informativi: stanno nel markup della pagina, nascosti finche'
   showModal() non li copia dentro #modale-corpo. */
.modalBodyContent { display: none; }

/* ---- Dissolvenza: sull'elemento `dialog`, quindi vale per tutti e quattro senza che nessuna
   pelle debba ricordarsene. La meta' JS (apertura, chiusura toccando fuori) sta in
   assets/js/dialoghi.js. ---- */

dialog {
  /* Altezza minima: un modale con due righe dentro, su un totem visto a un paio di metri, e' una
     striscia in mezzo al velo che non si legge come un pannello. 40svh gli da' corpo.
     svh e non dvh: e' la viewport PIU' PICCOLA (barra comandi visibile), quindi il minimo resta
     un minimo anche quando la barra compare e non fa crescere il modale oltre lo schermo. Il
     massimo invece e' in dvh, che segue la viewport reale. */
  min-height: 35svh;

  /* Stato di riposo: e' anche quello in cui il modale ESCE. */
  opacity: 0;
  transform: translateY(10px) scale(.98);

  /* allow-discrete su display e overlay e' cio' che rende possibile l'uscita: senza, alla
     chiusura il dialog passa a display:none e lascia il top layer nello stesso istante, e la
     transizione non ha su cosa girare — si vedrebbe solo l'entrata. Con questi due, il browser
     tiene l'elemento visibile e in top layer finche' opacity e transform non sono finite.
     Dove non sono supportati non si anima niente e il modale appare/sparisce di colpo: e'
     esattamente il comportamento di prima, non un peggioramento. */
  transition:
    opacity .18s ease,
    transform .18s ease,
    overlay .18s allow-discrete,
    display .18s allow-discrete;
}

dialog[open] {
  opacity: 1;
  transform: none;
}

dialog::backdrop {
  background: rgba(30, 24, 14, 0);
  transition:
    background-color .18s ease,
    overlay .18s allow-discrete,
    display .18s allow-discrete;
}

dialog[open]::backdrop { background: rgba(30, 24, 14, .55); }

/* Da dove PARTE l'entrata. Un elemento che nasce gia' con lo stato finale non transiziona: serve
   dire al browser com'era "un istante prima di esistere". Deve stare DOPO le regole [open], o
   nel cascade perde a parita' di specificita'. */
@starting-style {
  dialog[open] {
    opacity: 0;
    transform: translateY(10px) scale(.98);
  }

  dialog[open]::backdrop { background: rgba(30, 24, 14, 0); }
}

/* Chi ha chiesto meno animazioni salta la dissolvenza, non il modale: la transizione resta
   dichiarata (serve ad allow-discrete) ma dura quanto niente. */
@media (prefers-reduced-motion: reduce) {
  dialog,
  dialog::backdrop {
    transition-duration: .01ms;
  }
}

/* ---- .lf-modale: la pelle del modale informativo e del dettaglio firma ---- */

.lf-modale {
  /* Era .modal-lg di Bootstrap (800px), col margine laterale che teneva sul tablet. */
  width: min(800px, calc(100vw - 2rem));
  max-width: none;
  /* dvh e non vh: sul tablet, con la barra comandi del browser visibile, vh darebbe un modale
     piu' alto dello spazio utile. dvh segue la viewport reale. */
  max-height: calc(100dvh - 3.5rem);
  padding: 0;
  border: 0;
  border-radius: 12px;
  background: #fff;
  color: var(--modale-ink);
  box-shadow: 0 18px 50px rgba(0, 0, 0, .28);
  overflow: hidden; /* a scorrere e' il corpo, non il dialog: la testata deve restare ferma */
}

/* display sta qui e non sopra: vedi l'avviso in testa alla sezione. Colonna, cosi' la testata
   resta fissa e .lf-modale-corpo si prende l'altezza che avanza.
   position:relative perche' .modale-chiudi e' assoluto: stesso schema di .attesa-guida[open]. */
.lf-modale[open] {
  position: relative;
  display: flex;
  flex-direction: column;
}

/* flex:1 perche' il dialog ha un min-height: senza, con poco contenuto il corpo resta alto quanto
   il testo e sotto avanza una fascia vuota che sembra un errore di rendering. Cosi' il corpo
   riempie il pannello e lo scroll continua a essere suo.
   Il contenuto sta al centro in entrambi i sensi: in verticale con questo flex, in orizzontale
   col text-align di #modale-corpo piu' i margini auto dei blocchi (paragrafi, immagini, card).

   ⚠️ `safe center` e non `center`: quando il contenuto e' PIU' ALTO del corpo, un centraggio
   normale lo fa debordare da entrambi i lati e la parte di sopra diventa irraggiungibile —
   nessuno scroll ci arriva. `safe` centra finche' c'e' spazio e per il resto si comporta da
   flex-start, che e' esattamente il caso del pensiero lungo. */
.lf-modale-corpo {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  justify-content: safe center;
  padding: 30px 26px 26px;
  overflow-y: auto;
}

/* Chiusura: e' l'unico bersaglio tattile del modale e il dito su un totem e' impreciso,
   quindi 44px pieni. In position:absolute sul dialog e non dentro il corpo, cosi'
   resta al suo posto mentre il contenuto scorre. */
.modale-chiudi {
  position: absolute;
  top: 8px;
  right: 8px;
  z-index: 1;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: transparent;
  /* Fondo chiaro anche sulla card bianca: il modale del manifesto e quello dell'informativa
     hanno immagine e iframe fin sotto la X, che senza pastiglia si perdeva sopra il contenuto. */
  background: rgba(255, 255, 255, .85);
  color: var(--modale-muted);
  font-size: 30px;
  line-height: 1;
  cursor: pointer;
}

.modale-chiudi:hover,
.modale-chiudi:focus-visible {
  background: rgba(0, 0, 0, .06);
  color: var(--modale-ink);
}

/* ---- #modale: contenuto informativo (pensiero, annuncio, cerimonia, manifesto...) ----
   Il corpo e' popolato da showModal() copiandoci dentro un .modalBodyContent, quindi le
   regole valgono sui figli diretti: icona, titolo, testo.

   Icona sopra, titolo subito sotto, contenuto in fondo: una colonna sola. */
#modale-corpo { text-align: center; }

/* L'icona in cima. Il selettore di figlio diretto esclude il QR della donazione e il logo
   dell'associazione, che sono <img> annidate: presi da qui finivano a 54px, illeggibili.

   Piccola e smorzata: dice di che si tratta, ma il peso deve stare sul titolo e sul testo,
   non su un pittogramma ripetuto identico in cima a ogni modale. */
#modale-corpo > img {
  display: block;
  width: clamp(30px, 2.9vw, 40px);
  height: auto;
  margin: 0 auto 6px;
  opacity: .55;
}

/* Titoli dei modali: stesso carattere di "Libro Firme" e del nome del defunto (Tangerine,
   .lf-firme-title in home.css). Tangerine e' un corsivo sottile disegnato per i corpi
   grandi: sotto ai ~34px perde i tratti e diventa illeggibile, quindi la scala parte molto
   piu' in alto di un titolo in Alegreya e l'interlinea scende sotto 1.

   Nessun colore qui: i titoli portano .text-brand, che la personalizzazione per
   azienda (assets/css/case_funerarie/style-<id>.css) puo' ridefinire. Una regola con l'id vincerebbe su
   quella classe e il tema dell'azienda non arriverebbe mai ai modali.

   Il minimo del clamp non e' un caso limite: il totem gira a 960px CSS fissi (manifest in
   landscape), quindi 3.4vw vale 32px e la misura effettiva sul kiosk e' SEMPRE il minimo. E'
   quello il numero da guardare; il massimo serve solo agli schermi grandi.

   Icona e titolo dicono DI COSA si tratta; quello che la persona e' venuta a leggere e' il
   testo sotto. Percio' la scala qui e' contenuta e il peso sta nel contenuto: prima il
   titolo era piu' grande del messaggio della famiglia. */
#modale-corpo h3 {
  font-family: Tangerine, cursive;
  font-weight: 400;
  font-size: clamp(28px, 2.9vw, 36px);
  line-height: .9;
  text-wrap: balance;
  margin: 0;
}

/* ---- Testata: icona + titolo su una riga, fuori dalla parte scrollabile ----
   La popola showModal spostandoci icona e titolo del contenuto. Restando fuori dal
   corpo resta ferma mentre il testo lungo scorre, e dice sempre cosa si sta leggendo.
   Il colore del titolo continua a venire da .text-brand, che il tema per-azienda
   puo' ridefinire: nessuna regola di colore qui. */
.modale-testata {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  /* simmetrico a destra e sinistra nonostante la X: cosi' il gruppo icona+titolo e' centrato
     rispetto al modale, non rispetto allo spazio che avanza accanto al pulsante */
  padding: 15px 58px;
  /* Appena piu' caldo del bianco del corpo: a separarli basta il bordo, un fondo pieno
     spezzava il modale in due blocchi. */
  background: #fdfbf6;
  border-bottom: 1px solid var(--modale-line);
  border-radius: 12px 12px 0 0;
}

/* [hidden] non basta contro display:flex */
.modale-testata[hidden] { display: none; }

.modale-testata img { flex: none; width: 26px; height: 26px; opacity: .55; }

.modale-testata h3 {
  margin: 0;
  font-family: 'Alegreya Sans', sans-serif;
  font-weight: 700;
  font-size: clamp(15px, 1.4vw, 19px);
  line-height: 1.25;
  text-align: center;
}

/* Col titolo gia' in testata il corpo non deve ricominciare con lo stacco pieno. */
.modale-testata:not([hidden]) + .lf-modale-corpo { padding-top: 20px; }

/* Il contenuto e' quello che la persona e' venuta a leggere, spesso in piedi a un paio di
   metri dal totem: piu' grande del testo di una pagina web. */
#modale-corpo p {
  margin: 14px auto 0;
  font-family: 'Alegreya Sans', sans-serif;
  font-size: clamp(12px, 2.5vw, 28px);
  line-height: 1.45;
  color: var(--modale-ink);
  /* Centrato come il resto del modale (icona, titolo, filetto): la colonna resta una sola,
     leggibile a distanza. La misura tiene comunque la riga sotto le ~65 battute. */
  max-width: 38em;
}

/* Il manifesto e il ritratto NON sono icone: sono il contenuto del loro modale, quindi
   niente clamp e riga tutta per loro. Nessun tetto in vh: il contenimento lo fa
   .lf-modale, che limita il dialog allo schermo e fa scorrere il corpo. Cosi'
   il manifesto resta leggibile invece di essere rimpicciolito per farlo entrare. */
/* opacity: 1 — manifesto e ritratto sono <img> figli diretti come le icone, ma qui l'immagine
   E' il contenuto: lo sbiadimento delle icone su di loro sarebbe un difetto.

   Il limite e' in altezza e non in larghezza: sono immagini verticali (un ritratto 3/4, un
   manifesto quasi A4) e con il solo max-width restavano piccole, con mezzo modale vuoto sotto.
   Legandole all'altezza disponibile riempiono lo spazio che c'e' davvero. Il calc toglie
   testata, margini del dialog e padding del corpo. */
#modale-corpo > #modale-manifesto-img,
#modale-corpo > #immagine-def-modal {
  display: block;
  width: auto;
  max-width: 100%;
  height: auto;
  max-height: calc(100dvh - 13rem);
  margin: 0 auto;
  opacity: 1;
  border-radius: 6px;
}

/* Il ritratto e' l'unico contenuto del suo modale: puo' prendersi tutto lo spazio.
   min-width perche' le foto dell'API sono piccole (quella di prova e' 205x273): senza, il
   modale le mostrava a grandezza naturale, cioe' poco piu' della miniatura nella colonna, e
   toccare la foto per vederla meglio non serviva a niente. Il tetto e' basso apposta: oltre
   si scala troppo una sorgente piccola e si vede la sgranatura. */
#modale-corpo > #immagine-def-modal {
  width: auto;
  max-width: 100%;
  /* Altezza imposta (non solo max-): le foto dell'API sono piccole — quella di prova e'
     205x273 — e a grandezza naturale il modale mostrava poco piu' della miniatura della
     colonna. object-fit tiene le proporzioni se la foto e' larga invece che alta. */
  height: min(calc(100dvh - 10rem), 560px);
  max-height: none;
  object-fit: contain;
}

/* Un paragrafo vuoto occupa comunque il suo margine: nel modale donazione, dove il testo
   puo' mancare ma il QR c'e', lasciava un buco sopra il codice. */
#modale-corpo p:empty { display: none; }

/* "Manifesto non disponibile" e' un messaggio di stato, non un testo da leggere: resta
   centrato invece di andare a bandiera come i contenuti. */
#modale-corpo #modale-manifesto-vuoto { text-align: center; }

#qrcode-associazione,
#qrcode-foto,
#qrcode-tomba { width: 160px; height: 160px; margin: 16px auto 0; }

/* qrcode.js emette un <img> inline: senza questo resta a sinistra invece che al centro. */
#qrcode-foto img,
#qrcode-tomba img,
#qrcode-associazione img { display: block; margin: 0 auto; }

/* Le righe che spiegano come usare il QR sono istruzioni, non il contenuto del modale:
   vanno lette una volta, da vicino, mentre si inquadra col telefono. Con la misura piena di
   #modale-corpo p spingevano il codice sotto la piega proprio mentre lo si cerca.
   Discendenti e non figli diretti: ora stanno dentro .md-qr-box insieme al codice. */
#modale-corpo #modale-salma-qr-info,
#modale-corpo #modale-foto-qr-info {
  font-size: clamp(12px, 1vw, 22px);
  line-height: 1.4;
  max-width: 34em;
  margin: 10px auto 0;
  text-align: center;
}

/* Il codice e le sue istruzioni sono una cosa sola: inquadra QUESTO per ottenere QUELLO.
   Il riquadro li tiene insieme e li stacca dal testo del modale.

   :has(img) — il riquadro esiste solo quando il QR e' stato davvero disegnato (qrcode.js
   emette un <img>). Un defunto senza tomba pubblicata o senza plugin foto lascerebbe
   altrimenti una cornice vuota. Dove :has non e' supportato non si applica nulla e si
   ricade nell'aspetto di prima: niente cornice, nessun buco. */
.md-qr-box:has(img) {
  margin: 14px auto 0;
  padding: 18px;
  max-width: 22em;
  background: #fffdf7;
  border: 1px dashed var(--modale-line);
  border-radius: 12px;
}

/* Dentro il riquadro lo spazio attorno al codice lo fa il padding del riquadro: il margin
   del contenitore del QR si sommerebbe sopra (18+16) e il codice risulterebbe sbilanciato. */
.md-qr-box > #qrcode-associazione,
.md-qr-box > #qrcode-foto,
.md-qr-box > #qrcode-tomba { margin: 0 auto; }

/* Riga "logo + nome associazione" della donazione. */
.modale-associazione { display: flex; align-items: center; justify-content: center; gap: 14px; margin-top: 10px; }
.modale-associazione img { width: 50px; height: auto; }
#modale-donazione-nome { color: var(--brand); font-weight: 600; font-size: 20px; }

/* ==================== il biglietto (.wz-card) ====================
   Componente condiviso da due punti che devono restare speculari:
   - invio.php: anteprima di quello che si sta per firmare (passo 3 del wizard);
   - main.php #modale-firma: dettaglio di una firma gia' nel libro.
   Sta qui (base, caricata ovunque) e non in wizard.css/home.css perche' le due pagine
   caricano fogli diversi ma entrambe la base. Le --lf-* le fornisce la pagina (home.css o
   wizard.css). I .wz-card-edit ("Modifica testo/firma") esistono solo nell'anteprima. */
/* Esiste solo in invio.php (nel modale il biglietto si centra da se', vedi piu' sotto): prende
   tutta l'altezza avanzata e centra al suo interno il gruppo titolo + biglietto. In colonna e
   non in riga perche' il titolo dell'anteprima sta DENTRO il wrap: su uno schermo alto (1920x1080)
   il titolo lasciato fuori restava incollato in cima e il biglietto scendeva al centro, con un
   buco in mezzo. Cosi' i due viaggiano insieme a qualsiasi altezza, senza misure per fascia. */
.wz-card-wrap {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 14px;
}

/* Dentro il wrap il biglietto puo' restringersi (0 1 auto, non 0 0 auto): condivide la colonna
   col titolo, e senza shrink i due insieme sfonderebbero lo spazio invece di lasciare che il
   testo del pensiero scorra nel suo riquadro, che e' quello che deve cedere. */
.wz-card-wrap .wz-card {
  flex: 0 1 auto;
}

.wz-card {
  flex: 0 0 auto;
  width: min(660px, 100%);
  max-height: 100%;
  display: flex;
  flex-direction: column;
  background: linear-gradient(180deg, var(--lf-panel), var(--lf-panel2));
  border: 1px solid var(--lf-line);
  border-radius: 12px;
  padding: 18px 22px 14px;
  box-shadow: 0 6px 16px rgba(60, 45, 20, .10);
}

/* Nome e messaggio nel font di lettura: il calligrafico resta ai titoli delle schermate.
   Qui contano leggibilita' e gerarchia - il nome in grassetto, il pensiero in corsivo. */
.wz-card-mitt {
  font-size: 24px;
  font-weight: 700;
  line-height: 1.2;
  color: var(--lf-ink);
  margin: 0;
  overflow-wrap: anywhere;
}

.wz-card-msg {
  margin: 14px 0 6px;
  padding: 0 4px;
  font-size: 18px;
  font-style: italic;
  line-height: 1.55;
  color: #4a443c;
  overflow-y: auto;
  overflow-wrap: anywhere;
  white-space: pre-wrap;
}

.wz-card-msg[hidden] {
  display: none;
}

/* Riga di chiusura: data a sinistra, firma a destra sopra la sua linea. Il filetto separa il
   pensiero dalla sottoscrizione, come su un registro di carta. */
.wz-card-riga {
  display: flex;
  align-items: flex-end;
  gap: 18px;
  margin-top: 18px;
  padding-top: 12px;
  border-top: 1px solid var(--lf-line);
}

.wz-card-data {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  font-size: 15px;
  color: var(--lf-muted);
}

.wz-card-firma-box {
  flex: 0 0 auto;
  text-align: center;
}

.wz-card-firma-box[hidden] {
  display: none;
}

.wz-card-firma {
  display: block;
  height: 64px;
  margin: 0 auto;
}

.wz-card-firma-cap {
  border-top: 1px solid var(--lf-muted);
  min-width: 240px;
  margin: 0;
  padding-top: 2px;
  font-size: 13px;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--lf-muted);
}

.wz-card-edit {
  background: none;
  border: none;
  font-family: inherit;
  font-size: 15px;
  color: var(--brand);
  text-decoration: underline;
  cursor: pointer;
  padding: 4px 6px;
  min-height: 44px;
}

.wz-card-data .wz-card-edit {
  padding-left: 0;
}

/* Nel modale il biglietto non ha il .wz-card-wrap che in invio.php lo centra: lo centriamo
   orizzontalmente qui (width e' min(660px, 100%), quindi i margini auto hanno spazio). */
#modale-firma .wz-card {
  margin-left: auto;
  margin-right: auto;
}

/* Informativa privacy: iframe a tutta larghezza dentro il modale. */
#privacy-iframe { display: block; width: 100%; height: 65dvh; border: 0; }

/* ---- Toast di offline-manager.js ----
   Erano un <style> iniettato a runtime da _injectToastStyles(): con style-src senza
   'unsafe-inline' la CSP lo scarta e i toast escono nudi. Qui li vede anche il precache del SW. */
.lf-toast {
  position: fixed; top: 16px; right: 16px; z-index: 10000;
  min-width: 190px; max-width: 290px;
  display: flex; align-items: center; gap: 9px;
  padding: 9px 11px;
  background: #fff; color: #2a2a2a;
  border-radius: 9px; border-left: 3px solid #8a8a8a;
  box-shadow: 0 6px 18px rgba(0,0,0,.15);
  font-family: 'Alegreya Sans', system-ui, -apple-system, Arial, sans-serif;
  transform: translateX(120%); opacity: 0;
  transition: transform .3s cubic-bezier(.2,.8,.2,1), opacity .3s ease;
}
.lf-toast.show { transform: translateX(0); opacity: 1; }
.lf-toast .lf-toast-ico {
  flex: 0 0 24px; width: 24px; height: 24px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center; color: #666;
}
.lf-toast .lf-toast-ico svg { display: block; }
.lf-toast .lf-toast-body { flex: 1; min-width: 0; }
.lf-toast .lf-toast-title { font-weight: 700; font-size: 13px; line-height: 1.25; }
.lf-toast .lf-toast-sub { font-size: 11.5px; color: #666; margin-top: 2px; line-height: 1.3; }
.lf-toast .lf-toast-x {
  background: none; border: none; color: #b0b0b0; cursor: pointer;
  font-size: 17px; line-height: 1; padding: 0 1px; align-self: center;
}
.lf-toast .lf-toast-x:hover { color: #555; }
.lf-toast--success { border-left-color: #28a745; } .lf-toast--success .lf-toast-ico { color: #28a745; background: #e9f7ee; }
.lf-toast--info    { border-left-color: #86754E; } .lf-toast--info .lf-toast-ico    { color: #86754E; background: #f6f1e6; }
.lf-toast--warning { border-left-color: #e0932a; } .lf-toast--warning .lf-toast-ico { color: #e0932a; background: #fbf1e0; }
.lf-toast--offline { border-left-color: #dc3545; } .lf-toast--offline .lf-toast-ico { color: #dc3545; background: #fbe9eb; }
.lf-toast--offline .lf-toast-title { color: #dc3545; }
.lf-toast--error   { border-left-color: #dc3545; } .lf-toast--error .lf-toast-ico   { color: #dc3545; background: #fbe9eb; }
@media (max-width: 600px) {
  .lf-toast { left: 12px; right: 12px; max-width: none; }
}
