:root {
  /* Brand book PartyLab */
  --bg: #4D97D1;
  --bg-dark: #1F4E79;
  --accent: #FFD62E;
  --text: #ffffff;
  --card-bg: rgba(255, 255, 255, 0.12);
}

* { box-sizing: border-box; }

html {
  height: 100%;
}

body {
  margin: 0;
  /* Altezza vincolata (non min-height): serve perche' main e .step.active
     possano calcolare uno spazio "rimasto" reale, cosi' la contrazione del
     riquadro fotocamera scatta davvero invece di far crescere la pagina. */
  height: 100dvh;
  overflow: hidden;
  background: var(--bg);
  color: var(--text);
  /* --font-family iniettata solo in index.html (pagina evento/kiosk), mai in
     admin.html pur condividendo questo foglio di stile: il pannello resta
     sempre su Nunito (il fallback) indipendentemente da SITE_FONT - vedi
     core.site_font_css(). */
  font-family: var(--font-family, "Nunito", "Segoe UI", Arial, sans-serif);
  display: flex;
  flex-direction: column;
}

/* Avviso "ruota il telefono": nascosto di default (desktop/tablet largo,
   dove il portrait e' comunque una scelta valida), mostrato solo su un
   telefono vero nell'orientamento "sbagliato" rispetto al formato foto
   dell'evento (classe rotate-target-landscape/rotate-target-portrait sul
   body, impostata da applyAspectRatioData in app.js secondo
   state.aspectRatio - nessuna classe per "1:1"/"auto", quindi l'avviso non
   compare mai in quei casi) - orientation da solo scatterebbe anche su una
   finestra desktop stretta, pointer:coarse lo restringe al tocco (niente
   mouse/trackpad) per evitare quel falso positivo. In flusso normale (non
   position:fixed) sopra il footer nell'HTML: una riga in piu' nella colonna
   flex del body, come header/footer, invece di un overlay che avrebbe
   dovuto conoscere a mano l'altezza del footer per non coprirlo - incoraggia
   senza bloccare, chi preferisce restare nell'orientamento "sbagliato" (es.
   solo per scegliere lo stile) puo' comunque farlo. */
.rotate-hint {
  display: none;
}

/* body.rotate-target-landscape: formato 3:2 (o eredita default),
   comportamento di sempre - spinge verso l'orizzontale quando il telefono
   e' in verticale (regola sotto). */
@media (orientation: portrait) and (pointer: coarse) {
  /* Stesso bianco traslucido gia' usato altrove nell'app (es. hover di
     .fullscreen-btn) invece di un colore nuovo di zecca (era var(--accent),
     giallo, non usato altrove come sfondo di un blocco intero) - si stacca
     comunque dal blu scuro di header/footer sotto cui sta. */
  body.rotate-target-landscape .rotate-hint {
    display: flex;
    flex-shrink: 0;
    align-items: center;
    justify-content: center;
    gap: 10px;
    background: rgba(255, 255, 255, 0.25);
    color: var(--text);
    padding: 10px max(16px, env(safe-area-inset-right)) 10px max(16px, env(safe-area-inset-left));
    font-size: 14px;
    font-weight: 700;
    text-align: center;
  }

  body.rotate-target-landscape .rotate-hint-icon {
    font-size: 24px;
    animation: rotate-hint-spin 2.2s ease-in-out infinite;
  }

  body.rotate-target-landscape .rotate-hint p {
    margin: 0;
  }
}

/* Speculare: formato 2:3 (verticale), spinge verso il verticale quando il
   telefono e' in orizzontale - stesse regole/stili di sopra, solo
   orientation e classe invertite. */
@media (orientation: landscape) and (pointer: coarse) {
  /* Diverso dal caso speculare sopra: qui il body e' spesso in row-flex
     (schermo basso, vedi @media max-height:500px piu' sotto - header a
     sinistra, foto al centro, footer a destra), quindi .rotate-hint diventa
     una colonna stretta tra la foto (2:3, non usa tutta la larghezza) e il
     footer - striscia sottile con testo in mezzo a un vuoto sproporzionato.
     flex:1 + colonna centrata + icona/testo piu' grandi: riempie davvero
     quello spazio invece di limitarsi ad attraversarlo. Se il body resta a
     colonna (tablet largo ma alto abbastanza da non attivare l'overlay),
     resta comunque una banda a piena larghezza piu' vistosa - nessun danno. */
  body.rotate-target-portrait .rotate-hint {
    display: flex;
    flex: 1;
    flex-shrink: 0;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 16px;
    background: rgba(255, 255, 255, 0.25);
    color: var(--text);
    padding: 24px max(16px, env(safe-area-inset-right)) 24px max(16px, env(safe-area-inset-left));
    font-size: 18px;
    font-weight: 700;
    text-align: center;
  }

  body.rotate-target-portrait .rotate-hint-icon {
    font-size: 56px;
    animation: rotate-hint-spin 2.2s ease-in-out infinite;
  }

  body.rotate-target-portrait .rotate-hint p {
    margin: 0;
    max-width: 22ch;
  }
}

/* Avanti e indietro (0 -> -90 -> 0), non un giro continuo: suggerisce
   "ruota lo schermo di un quarto di giro", non "fai roteare il telefono".
   Torna a 0deg entro il 100% (non ci resta fermo) cosi' il loop e' fluido,
   senza scatto al riavvio dell'animazione. */
@keyframes rotate-hint-spin {
  0%, 10% { transform: rotate(0deg); }
  40%, 60% { transform: rotate(-90deg); }
  90%, 100% { transform: rotate(0deg); }
}

/* Sfondo col logo tassellato e ruotato a 45 gradi, come nella versione
   Python (li' e' sull'intera finestra, non su un singolo step): qui e'
   sul body, dietro a header/main/footer di ogni pagina, non solo lo step di
   scelta evento. position:fixed cosi' copre sempre l'intero viewport senza
   dipendere dall'altezza del contenuto (che cambia da step a step) e senza
   bisogno di un contenitore con overflow:hidden dedicato. Il logo ha uno
   sfondo blu quasi identico a --bg: il blu resta comunque invisibile
   (stesso colore), l'opacita' regola solo quanto si vede il disegno giallo. */
.guest-body::before {
  content: "";
  position: fixed;
  top: 50%;
  left: 50%;
  width: 200%;
  height: 200%;
  transform: translate(-50%, -50%) rotate(45deg);
  background-image: url("https://nyuzpgdmtkdixgqnwuvo.supabase.co/storage/v1/object/public/partylab-assets/uploads/20260729101506284110.png");
  background-repeat: repeat;
  background-size: 140px 140px;
  opacity: 0.10;
  pointer-events: none;
  z-index: -1;
}

.topbar {
  flex-shrink: 0;
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 10px max(10px, env(safe-area-inset-right)) 10px max(10px, env(safe-area-inset-left));
  padding-top: max(10px, env(safe-area-inset-top));
  background: var(--bg-dark, rgba(0, 0, 0, 0.15));
}

.brand {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
  font-size: 20px;
  font-family: var(--font-family, "Nunito", "Segoe UI", Arial, sans-serif);
  text-decoration: none;
  cursor: pointer;
}

#btn-home {
  transition: opacity 0.2s ease;
}

#btn-home:hover {
  opacity: 0.8;
}

.brand-logo {
  width: 26px;
  height: 26px;
  border-radius: 6px;
  display: block;
  flex-shrink: 0;
}

/* Logo ingrandito solo sulla pagina evento (body.guest-body), non sul
   pannello admin che condivide questo foglio di stile. Margini negativi
   simmetrici (top e bottom) riducono l'ingombro riservato nella riga
   topbar a 26px (54 - 14 - 14), cosi' l'header non si allarga: il logo
   sporge di 14px sopra e sotto la riga, centrato. */
.guest-body .brand-logo {
  width: 54px;
  height: 54px;
  border-radius: 14px;
  margin-top: -14px;
  margin-bottom: -14px;
}

.brand-text {
  color: var(--text);
  font-weight: 700;
  font-size: 23px;
  letter-spacing: 0.5px;
  white-space: nowrap;
}

/* Nome evento dopo "PartyLab" in header (vedi app.py:
   guest_client_event_page, iniettato con lo stesso meccanismo di
   brand-text) - solo da larghezza desktop in su: su mobile l'header e'
   gia' stretto, il nome evento ci va sopra al titolo invece (vedi
   .mobile-event-name piu' sotto). Nascosto di base (display:none, non solo
   :empty) cosi' non occupa spazio su mobile nemmeno mentre il testo c'e'
   gia' nel DOM. */
.brand-event-name {
  display: none;
  color: var(--text);
  opacity: 0.8;
  font-weight: 600;
  font-size: 17px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.brand-event-name:not(:empty)::before {
  content: "\00b7\0020";
}

@media (min-width: 900px) {
  .brand-event-name {
    display: inline-block;
    max-width: 280px;
  }
}

.brand-event-name:empty {
  display: none;
}

.topbar-right {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-shrink: 0;
}

/* Pallini social sotto al logo (solo result/download, vedi app.js) - stesse
   icone/colori di .thankyou-social-icon (vedi piu' sotto), 44px (-20%
   rispetto ai 54px iniziali, quanto il logo), 40px di distanza dal logo
   sopra, agganciati in cima al gruppo (vedi .topbar-brand-group) invece che
   centrati nello spazio vuoto verso topbar-right. Nascosto di default
   (anche fuori da mobile orizzontale) come gli altri elementi solo-mobile
   del topbar. */
.topbar-social {
  display: none;
}

@media (max-height: 500px) {
  .topbar-social:not(.hidden) {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 16px;
    margin-top: 30px;
  }

  .topbar-social .thankyou-social-icon {
    width: 40px;
    height: 40px;
  }

  .topbar-social .thankyou-social-icon svg {
    width: 20px;
    height: 20px;
  }
}

/* Icone social ora fino a 3 (Facebook/Instagram/WhatsApp): sotto i 368px la
   colonna e' gia' stretta di suo, WhatsApp (se configurato) e' la prima a
   saltare per fare spazio prima di arrivare al taglio netto dell'intero
   blocco (vedi @media max-height:329px sotto). */
@media (max-height: 368px) {
  .topbar-social .thankyou-social-icon-whatsapp {
    display: none;
  }
}

/* Sotto i 330px di altezza (mobile in orizzontale, tutti i passi) la colonna
   sinistra e' troppo bassa per loghetto + icone social senza schiacciarsi -
   stessa specificita' di ".topbar-social:not(.hidden)" sopra (vince per
   ordine, essendo dopo) cosi' da vincere anche quando entrambe le media
   query sono vere. */
@media (max-height: 329px) {
  .topbar-social:not(.hidden) {
    display: none;
  }
}

/* Mobile in orizzontale (stesso breakpoint del resto, vedi #step-camera e
   .page-footer/.mobile-event-name piu' sotto): il topbar orizzontale in
   cima "ruba" altezza preziosa proprio al passo che ne ha piu' bisogno (la
   fotocamera) - qui diventa una colonna stretta a sinistra, solo icone
   (niente testo "PartyLab" ne' nome evento, non c'e' spazio in una colonna
   larga quanto un'icona), cosi' main puo' usare tutta l'altezza reale dello
   schermo invece di quella meno la striscia dell'header. */
@media (max-height: 500px) {
  body {
    flex-direction: row;
  }

  /* space-between (non flex-start): logo in cima e bottoni in fondo, con
     tutto lo spazio vuoto in mezzo a separarli invece di stare ammassati
     insieme in alto - stessa idea del footer-sidebar qui sotto (Scatta in
     cima, Privacy in fondo). */
  .topbar {
    flex-direction: column;
    justify-content: space-between;
    align-items: center;
    width: auto;
    padding: max(20px, env(safe-area-inset-top)) 8px max(10px, env(safe-area-inset-bottom))
      max(8px, env(safe-area-inset-left));
  }

  /* Logo + pallini social raggruppati (vedi index.html): .topbar li' sopra
     ha justify-content:space-between fra i SUOI figli diretti - senza
     questo gruppo, topbar-social (figlio a se' stante) veniva spaziato a
     meta' colonna dallo space-between invece di restare agganciato subito
     sotto al logo. Un solo gruppo "in cima" risolve, lo spazio vuoto vero
     resta solo fra questo gruppo e topbar-right (sempre in fondo). */
  .topbar-brand-group {
    display: flex;
    flex-direction: column;
    align-items: center;
  }

  .brand-text,
  .brand-event-name {
    display: none;
  }

  .topbar-right {
    flex-direction: column;
    /* 6px (base rule) andava bene per icone affiancate in riga, troppo
       stretto in colonna - qui sembravano un blocco unico invece di
       pulsanti separati. */
    gap: 16px;
  }

  /* width:100% (base rule) sommato a flex:1 1 auto qui sotto forzerebbe un
     flex-basis di partenza pari a tutta la larghezza della riga, invece che
     lasciar decidere il flex-grow/shrink lo spazio rimasto accanto al
     topbar diventato colonna - auto lascia fare al flex normalmente. */
  main {
    width: auto;
  }

  /* Stessa forma/colore/icona del footer-camera-btn (il tasto giallo del
     footer-sidebar), ma qui sopra la foto (dove il vecchio pulsante testuale
     "Scatta" stava gia') invece che nel footer - piu' vicino alla foto
     stessa. color:transparent+font-size:0 nasconde il testo "Scatta"
     impostato da JS (BTN_SHOOT_TEXT) senza doverlo toccare in app.js -
     l'icona arriva da un'immagine di sfondo invece che da un figlio SVG
     nell'HTML, che verrebbe cancellato ad ogni cambio lingua (JS scrive su
     .textContent, che sovrascrive tutti i figli). Stesso path SVG di
     .footer-camera-btn qui sotto, solo come data-URI (stroke fisso invece
     di currentColor: un url() di sfondo non eredita i colori CSS). */
  #btn-shoot {
    width: 96px;
    height: 96px;
    padding: 0;
    border-radius: 50%;
    background-color: var(--accent, #FFD62E);
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%231F4E79' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 7h3l1.7-2.2A1 1 0 0 1 9.5 4h5a1 1 0 0 1 .8.4L17 7h3a1 1 0 0 1 1 1v11a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V8a1 1 0 0 1 1-1z'%3E%3C/path%3E%3Ccircle cx='12' cy='13' r='4'%3E%3C/circle%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: center;
    background-size: 48px;
    color: transparent;
    font-size: 0;
    box-shadow: 0 4px 14px rgba(0, 0, 0, 0.35);
  }
}

/* Selettore lingua: visibile solo quando l'evento ne ha piu' di una attiva
   (impostato via JS, vedi applyLanguage). Un solo pulsante con la bandiera
   della lingua MANCANTE (su cui si passa cliccando), non due bottoni IT/EN
   affiancati - stessa forma/dimensione degli altri pulsanti icona qui in
   topbar (.fullscreen-btn, riusata anche qui), solo con una bandiera al
   posto dell'icona SVG. */
.lang-flag {
  width: 18px;
  height: 18px;
  border-radius: 50%;
  object-fit: cover;
  display: block;
}

.fullscreen-btn {
  background: rgba(255, 255, 255, 0.15);
  color: var(--text);
  border: 2px solid transparent;
  border-radius: 8px;
  font-family: inherit;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 6px 9px;
  cursor: pointer;
  transition: all 0.2s ease;
}

.fullscreen-btn:hover {
  background: rgba(255, 255, 255, 0.25);
}

.fullscreen-wrap {
  position: relative;
}

/* Fumetto mostrato una sola volta su mobile al primo ingresso, per dare
   evidenza al pulsante schermo intero (altrimenti facile da non notare). */
.fullscreen-hint {
  position: absolute;
  top: 100%;
  right: 0;
  margin-top: 10px;
  background: var(--accent);
  color: var(--bg-dark);
  font-weight: 700;
  font-size: 13px;
  line-height: 1.3;
  padding: 8px 12px;
  border-radius: 10px;
  white-space: nowrap;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
  pointer-events: none;
  z-index: 20;
  animation: fullscreen-hint-fade 4s ease forwards;
}

.fullscreen-hint::after {
  content: "";
  position: absolute;
  bottom: 100%;
  right: 14px;
  border: 6px solid transparent;
  border-bottom-color: var(--accent);
}

.fullscreen-hint.hidden {
  display: none;
}

@keyframes fullscreen-hint-fade {
  0% { opacity: 0; transform: translateY(-4px); }
  10% { opacity: 1; transform: translateY(0); }
  80% { opacity: 1; transform: translateY(0); }
  100% { opacity: 0; transform: translateY(0); }
}

/* Il fumetto e' pensato per un topbar orizzontale in cima: right:0/top:100%
   lo piazzava sotto il pulsante allineato al suo bordo destro, che ora e'
   anche il bordo sinistro dello schermo (topbar diventato colonna a
   sinistra, vedi @media piu' in alto) - il fumetto (nowrap, nessuna
   larghezza vincolata) finiva quindi quasi tutto fuori dal viewport verso
   sinistra (body ha overflow:hidden), visibile solo per lo spicchio che
   restava dentro lo schermo: da qui probabilmente sia "sfondo minuscolo,
   testo che ne esce" (la parte visibile era solo un frammento del riquadro
   vero) sia "compare vicino al muto non a schermo intero" (quello spicchio
   finiva a ridosso dell'icona sotto). Override qui, DOPO la regola base
   sopra (non nel @media in cima al file, troppo presto nel foglio: stessa
   specificita' della regola base, quindi PRIMA nel sorgente perdeva sempre
   il cascade) e non piu' con un transform per il centraggio verticale:
   l'animazione fullscreen-hint-fade applica gia' un suo transform via
   keyframe, che avrebbe sempre sovrascritto il nostro. */
@media (max-height: 500px) {
  .fullscreen-hint {
    top: 0;
    left: 100%;
    right: auto;
    bottom: auto;
    margin-top: 0;
    margin-left: 10px;
    width: max-content;
    max-width: 200px;
    white-space: normal;
  }

  .fullscreen-hint::after {
    top: 12px;
    right: 100%;
    bottom: auto;
    left: auto;
    border-bottom-color: transparent;
    border-right-color: var(--accent);
  }
}

.fullscreen-btn.active {
  border-color: var(--accent);
  background: rgba(255, 255, 255, 0.3);
}

/* Titolo del passo corrente: non piu' nell'header (li' arrivera' un menu),
   ma spostato via JS dentro il passo attivo, sopra il suo contenuto
   principale (es. sopra il riquadro fotocamera) - stesso giallo accent e
   stile in maiuscolo del titolo pagina della versione Python. */
.step-heading {
  flex-shrink: 0;
  text-align: center;
  font-size: 24px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.3px;
  color: var(--accent, #FCDE2A);
  margin: 0 0 8px;
}

.step-heading:empty {
  display: none;
}

/* Mobile in orizzontale (schermo basso): stesso principio dello spinner
   piu' sotto (vedi @media max-height:500px li') - il titolo maiuscolo a
   24px+margine finiva tagliato fuori dal viewport quando lo step
   Elaborazione ha anche il blocco eta'/consenso sotto (vedi app.js). Vale
   per ogni step, non solo quello: uno step piu' compatto qui non fa mai
   male, il titolo resta comunque leggibile a 18px. */
@media (max-height: 500px) {
  .step-heading {
    font-size: 18px;
    margin: 0 0 4px;
  }
}

/* Nome evento sopra al titolo del passo, solo mobile in verticale: da
   larghezza desktop compare in header invece (vedi .brand-event-name
   sopra), su mobile in orizzontale (poco alto, vedi @media max-height
   sotto) non c'e' spazio libero per una riga in piu' - stesso trattamento
   di .step-heading (che si muove per passo) ma bianco/fisso in cima,
   sempre visibile qualunque sia il passo attivo. */
.mobile-event-name {
  flex-shrink: 0;
  text-align: center;
  color: var(--text);
  font-weight: 700;
  font-size: 24px;
  letter-spacing: 0.3px;
  margin: 0 0 4px;
  padding-top: 10px;
}

.mobile-event-name:empty {
  display: none;
}

@media (min-width: 900px) {
  .mobile-event-name {
    display: none;
  }
}

@media (max-height: 500px) {
  .mobile-event-name {
    display: none;
  }
}

/* Stesso motivo degli altri due @media sopra (desktop, landscape): su
   telefono stretto in verticale ogni pixel di altezza conta per il riquadro
   di inquadratura (specie con un ratio verticale tipo 2:3) - qui il nome
   evento non ha piu' un vero "spazio libero" da occupare come aveva prima,
   quando il riquadro era sempre 3:2 (piu' basso). */
@media (max-width: 480px) {
  .mobile-event-name {
    display: none;
  }
}

.page-footer {
  flex-shrink: 0;
  padding: 10px max(20px, env(safe-area-inset-right)) max(10px, env(safe-area-inset-bottom))
    max(20px, env(safe-area-inset-left));
  background: var(--bg-dark, rgba(0, 0, 0, 0.15));
  text-align: center;
}

/* Barra di istruzioni da tastiera (equivalente della status bar della
   versione Python): utile solo su web/desktop, dove si naviga con
   tastiera - su touch (mobile) non serve, l'interazione e' col dito. */
.kbd-bar {
  flex-shrink: 0;
  text-align: center;
  font-size: 15px;
  font-weight: 600;
  padding: 8px max(16px, env(safe-area-inset-right)) 8px max(16px, env(safe-area-inset-left));
  background: rgba(0, 0, 0, 0.25);
}

/* is-touch-device (capacita' reale, ignora ?kiosk=1), non is-touch: su un
   tablet kiosk touch senza tastiera fisica queste istruzioni sono inutili -
   testo lungo, andava a capo su due righe e finiva per coprire la sezione
   sotto (es. le stelline di voto sullo step risultato). */
.kbd-bar:empty,
body.is-touch-device .kbd-bar {
  display: none;
}

@media (max-height: 500px) {
  .kbd-bar {
    display: none;
  }
}

.footer-title {
  margin: 0;
  font-size: 18px;
  font-weight: 800;
  color: var(--text);
}

.footer-slogan {
  margin: 0;
  font-size: 16px;
  font-weight: 700;
  color: var(--accent, #FCDE2A);
}

.footer-powered {
  margin: 2px 0 0;
  font-size: 14px;
  opacity: 0.7;
  color: inherit;
  text-decoration: none;
  display: inline-block;
  cursor: pointer;
  transition: opacity 0.2s ease;
}

.footer-powered:hover {
  opacity: 1;
  text-decoration: underline;
}

/* Icona "primaria" (grande, gialla) del footer-diventato-colonna in mobile
   orizzontale (vedi @media sotto): Scatta in camera, Scarica in result,
   Nuova foto/Ricomincia in thankyou/error - un solo bottone riusato tra i
   passi che hanno un'azione principale, contenuto/azione aggiornati da
   app.js (updateFooterActions) ad ogni cambio passo. footer-camera-btn
   resta una classe a parte (stesso stile, id diverso) solo perche' ha uno
   stato abilitato/nascosto suo proprio, sincronizzato col vero pulsante
   Scatta durante scatto/countdown/anteprima - gli altri passi invece
   inoltrano semplicemente il click al bottone vero (.click()), niente
   stato da tenere in sync. Nascosti di default (display:none) come
   .page-footer stesso, mostrati solo dentro il @media sotto quando non
   hanno anche la classe .hidden (che qui la gestisce JS, non :has() - un
   solo bottone condiviso tra passi diversi non ha un elemento CSS stabile
   su cui scrivere un :has() per ciascun passo). */
.footer-camera-btn,
.footer-primary-btn {
  display: none;
  align-items: center;
  justify-content: center;
  width: 56px;
  height: 56px;
  border-radius: 50%;
  border: none;
  background: var(--accent, #FFD62E);
  color: var(--bg-dark, #1F4E79);
  cursor: pointer;
  padding: 0;
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.35);
}

.footer-camera-btn:active,
.footer-primary-btn:active {
  filter: brightness(0.9);
}

.footer-camera-btn:disabled {
  opacity: 0.5;
  cursor: default;
}

/* Icone "secondarie" (piccole, translucide come i pulsanti del topbar):
   Ricomincia in result, Indietro/Casuale in style e tema - stesso discorso
   di .footer-primary-btn sopra, due bottoni condivisi (mai piu' di due
   azioni secondarie in un passo alla volta) invece di uno per passo. */
.footer-privacy-icon,
.footer-secondary-btn {
  display: none;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  border: none;
  background: rgba(255, 255, 255, 0.15);
  color: var(--text);
  text-decoration: none;
  cursor: pointer;
  padding: 0;
}

.footer-privacy-icon:hover,
.footer-secondary-btn:hover {
  background: rgba(255, 255, 255, 0.25);
}

.footer-actions {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
}

/* Riempito da app.js (renderFooterSecondaryActions) con 0-3 bottoni
   .footer-secondary-btn a seconda del passo - vuoto (0 bottoni, es. camera/
   thankyou/error) non deve comunque occupare spazio/gap in .footer-actions,
   :empty lo toglie dal flusso invece di lasciare un gap fantasma. */
.footer-secondary-actions {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
}

.footer-secondary-actions:empty {
  display: none;
}

/* Coppia di frecce su/giu' (solo step result, vedi app.js): piu' compatta
   di due .footer-secondary-btn separati (stesso ingombro totale di uno
   solo), per scorrere stelle/commento/email sotto la foto senza dover
   trascinare col dito vicino al bordo della sidebar. */
.footer-scroll-pair {
  display: none;
  flex-direction: column;
  gap: 14px;
}

.footer-scroll-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 26px;
  border-radius: 8px;
  border: none;
  background: rgba(255, 255, 255, 0.15);
  color: var(--text);
  font-size: 12px;
  cursor: pointer;
  padding: 0;
}

.footer-scroll-btn:hover {
  background: rgba(255, 255, 255, 0.25);
}

/* Schermo basso (tipicamente telefono in orizzontale): il footer sparisce
   per lasciare piu' spazio verticale al contenuto - QUI diventa invece una
   colonna a destra su TUTTI i passi (non solo camera, stessa idea del
   topbar diventato colonna a sinistra su tutti i passi): azioni del passo
   (.footer-actions) in cima, Privacy sempre in fondo. */
@media (max-height: 500px) {
  /* Larghezza fissa (calcolata sul contenuto piu' largo possibile, il
     cerchio giallo da 56px di .footer-primary-btn/.footer-camera-btn +
     padding) invece di auto: senza, la colonna si restringeva sugli step
     con solo icone piccole (36px, es. style/tema senza azione principale)
     e main "saltava" di larghezza passando da un passo all'altro. */
  .page-footer {
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    align-items: center;
    width: calc(56px + 8px + max(8px, env(safe-area-inset-right)));
    padding: max(10px, env(safe-area-inset-top)) max(8px, env(safe-area-inset-right))
      max(10px, env(safe-area-inset-bottom)) 8px;
    /* Rete di sicurezza: su result puo' arrivare a 3 azioni secondarie
       (Ricomincia/Ingrandisci/Email/Commenti) piu' Scarica, frecce scroll e
       Privacy - su uno schermo molto basso potrebbero non starci tutte in
       altezza. Scorre per conto suo invece di tagliare le ultime icone. */
    overflow-y: auto;
  }

  .footer-title,
  .footer-slogan,
  .footer-powered {
    display: none;
  }

  .footer-camera-btn:not(.hidden),
  .footer-primary-btn:not(.hidden) {
    display: flex;
  }

  .footer-secondary-btn:not(.hidden) {
    display: flex;
  }

  .footer-scroll-pair:not(.hidden) {
    display: flex;
  }

  .footer-privacy-icon {
    display: flex;
  }
}

/* Icona Commenta (sidebar mobile orizzontale, solo se l'evento ha
   allow_comments - vedi updateFooterActions): sotto i 400px la colonna
   destra e' gia' stretta, e' quella che si puo' perdere con meno danno (il
   campo commento resta comunque raggiungibile scorrendo la pagina). Stesso
   principio della colonna social sinistra a 368px/329px sopra. */
@media (max-height: 400px) {
  /* .footer-secondary-btn.footer-secondary-btn-comment (due classi), non
     una sola: deve pareggiare la specificita' di ".footer-secondary-btn:
     not(.hidden){display:flex}" qui sopra (stessa (0,2,0)) per vincere per
     ordine nel file, altrimenti quella regola vince comunque a parita' di
     tutto il resto pur venendo prima. */
  .footer-secondary-btn.footer-secondary-btn-comment {
    display: none;
  }
}

/* main e' la sola area che scorre (overflow-y:auto) e resta a tutta
   larghezza: se il contenuto di uno step (es. tante card nella griglia
   stili) supera l'altezza disponibile, la scrollbar del browser compare al
   bordo reale della finestra, non al bordo di un contenitore centrato in
   mezzo allo schermo (quello che succedeva prima, con max-width+margin:auto
   qui - su schermi larghi sembrava "scrolli un riquadro", non la pagina). Il
   centraggio/padding vive invece su .step.active. */
main {
  flex: 1 1 auto;
  min-height: 0;
  width: 100%;
  overflow-y: auto;
}

.step { display: none; }

.step.active {
  position: relative;
  display: flex;
  flex-direction: column;
  max-width: 720px;
  margin: 0 auto;
  padding: 16px max(16px, env(safe-area-inset-right)) max(16px, env(safe-area-inset-bottom))
    max(16px, env(safe-area-inset-left));
}

/* Solo gli step senza griglia di card hanno bisogno di un'altezza vincolata:
   la camera la usa per calcolare lo spazio verticale rimasto (.camera-fill,
   flex: 1 1 0), lo step di attesa per centrare lo spinner in verticale
   (align-items/justify-content: center piu' sotto). Applicarla a tutti gli
   step, invece, costringe anche le griglie (eventi/stile/tema) dentro quello
   stesso spazio: se le card superano l'altezza disponibile, flexbox le
   comprime (flex-shrink di default e' 1) invece di lasciarle scorrere -
   risultato: card non piu' quadrate. Le griglie restano quindi ad altezza
   naturale (auto), scorrono dentro "main" se serve. */
#step-camera.step.active,
#step-processing.step.active {
  height: 100%;
}

/* Solo lo step camera, solo su schermi stretti (telefono in verticale) -
   il pulsante Scatta e' l'unica cosa che cambia qui: il padding laterale
   resta lo stesso minimo di 16px di .step.active (provato ad azzerarlo per
   guadagnare larghezza, ma a filo bordo sembrava sbagliato: 16px resta il
   minimo ovunque nell'app, coerenza prima del millimetro extra). 480px come
   soglia copre la stragrande maggioranza degli smartphone in verticale
   senza toccare tablet/desktop. */
@media (max-width: 480px) {
  /* Stesso principio del landscape "schermo basso" sotto (vedi
     @media max-height:500px, #step-camera .actions/#btn-shoot): il pulsante
     Scatta galleggia sopra la foto invece di occupare una riga propria sotto
     il riquadro - libera del tutto lo spazio verticale che gli era
     riservato (vedi buttonsFloat in fitCameraBox, app.js), il vincolo vero
     qui era la larghezza dello schermo, non l'altezza come in landscape. */
  #step-camera .actions {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 14px;
    z-index: 10;
    margin-top: 0;
    pointer-events: none;
  }

  #step-camera .actions .btn {
    pointer-events: auto;
    box-shadow: 0 2px 12px rgba(0, 0, 0, 0.5);
  }

  /* Stessa icona/colore del pulsante Scatta in landscape (vedi
     @media max-height:500px sopra per i dettagli del data-URI/perche' non
     un figlio SVG nell'HTML). */
  #btn-shoot {
    width: 96px;
    height: 96px;
    padding: 0;
    border-radius: 50%;
    background-color: var(--accent, #FFD62E);
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%231F4E79' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 7h3l1.7-2.2A1 1 0 0 1 9.5 4h5a1 1 0 0 1 .8.4L17 7h3a1 1 0 0 1 1 1v11a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V8a1 1 0 0 1 1-1z'%3E%3C/path%3E%3Ccircle cx='12' cy='13' r='4'%3E%3C/circle%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: center;
    background-size: 48px;
    color: transparent;
    font-size: 0;
    box-shadow: 0 4px 14px rgba(0, 0, 0, 0.35);
  }
}

/* Su schermi da tablet/desktop c'e' molta piu' larghezza disponibile: a piena
   larghezza le griglie (eventi/stile/tema) e i form restavano pero' troppo
   sparsi/larghi, poco leggibili. 78% invece di 100% (alzato da 70%: con la
   fotocamera in overlay/orizzontale ora a priorita' altezza, vedi
   fitCameraBox in app.js, un po' di larghezza in piu' qui aiuta il box a
   raggiungere il ratio target senza sforare): centra il contenuto in una
   colonna piu' stretta e proporzionata. Non penalizza la fotocamera:
   .camera-wrap ha gia' aspect-ratio (target dinamico) + max-width/max-height
   100% (vedi sotto), che da soli scelgono gia' il lato piu' stretto tra
   spazio orizzontale e verticale disponibile, quindi si adatta comunque al
   78% senza bisogno di tutto il 100%. */
@media (min-width: 900px) {
  .step.active {
    max-width: 78%;
  }
}

.grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  align-content: start;
  gap: 14px;
  overflow-y: auto;
}

/* Mobile in orizzontale: le due sidebar (topbar a sinistra, footer a destra,
   vedi @media piu' sopra/sotto) sono subito ai lati di main, senza un vero
   margine morto - un dito che parte a scorrere la griglia molto vicino al
   bordo rischia di finire invece su un bottone della sidebar. 20px di
   respiro qui, oltre al padding gia' su .step.active. */
@media (max-height: 500px) {
  .grid {
    padding: 0 20px;
  }
}

/* Da tablet in su (anche in verticale, es. 680px di larghezza: qui non
   dipende da min-width:900px usato per .step.active/fotocamera, la griglia
   ha spazio a sufficienza gia' prima) 4 colonne usano meglio lo spazio -
   niente tappa intermedia a 3 colonne (rimossa apposta): con le 16 card
   tipiche di temi/stili, 3 per riga lascia un'ultima riga spaiata (16 non
   e' multiplo di 3), 4 o le 2 di default invece dividono 16 in righe piene.
   Max 4 per riga (mai 5+). */
@media (min-width: 640px) {
  .grid { grid-template-columns: repeat(4, 1fr); }
}

/* Il vincolo vero e' l'altezza, non la larghezza: su una finestra larga ma
   NON altissima (es. 1360x768, il totem) 4 colonne piene rendono le card
   cosi' grandi che due righe superano l'altezza disponibile e la griglia
   scrolla quando non dovrebbe - qui si restringe la griglia stessa (non
   .step.active, che resta larga apposta per la fotocamera) per rimpicciolire
   le card quel poco che serve. Sulla dimensione ottimale (1920x1200) l'altezza
   c'e' a sufficienza e le card restano grandi, senza questo vincolo. */
@media (min-width: 900px) and (max-height: 900px) {
  .grid {
    max-width: 100%;
    margin: 0 auto;
  }
}

.card {
  position: relative;
  background: var(--card-bg);
  border-radius: 12px;
  overflow: hidden;
  cursor: pointer;
  border: 2px solid transparent;
  transition: transform 0.1s ease, border-color 0.1s ease;
  text-align: center;
}

.card:active { transform: scale(0.97); }
.card.selected { border-color: var(--accent); }

/* Stellina "preferito" (stile/tema piu' scelto finora in questo evento,
   vedi renderGrid) - solo il simbolo, niente sfondo/box: l'ombra la tiene
   leggibile sopra qualunque foto. */
.card-favorite-badge {
  position: absolute;
  top: 4px;
  right: 6px;
  font-size: 28px;
  line-height: 1;
  color: var(--accent, #FCDE2A);
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.7), 0 0 4px rgba(0, 0, 0, 0.5);
  z-index: 1;
  pointer-events: none;
}

/* Hover (mouse, versione web): stesso "rimpicciolimento" del click, cosi' e'
   chiaro che la card e' interattiva anche prima di premerla. Non scatta su
   touch, dove il browser terrebbe lo stato :hover "appeso" dopo un tap. */
body:not(.is-touch) .card:hover {
  transform: scale(0.97);
}

/* Evidenzia la card attiva durante la navigazione da tastiera (versione
   web/desktop) - stesso ruolo del bordo giallo nella versione Python.
   Nascosta sui dispositivi touch (vedi body.is-touch piu' sotto), dove non
   ha senso mostrare un "focus" che l'utente non ha impostato lui stesso. */
.card.focused {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(255, 214, 46, 0.45);
  transform: scale(0.97);
}

body.is-touch .card.focused {
  border-color: transparent;
  box-shadow: none;
  transform: none;
}

.card img {
  width: 100%;
  aspect-ratio: 1 / 1;
  object-fit: cover;
  display: block;
  background: rgba(0, 0, 0, 0.2);
  max-width: 48vw;
}

/* Overlay in basso sulla foto invece di una riga a parte sotto: risparmia
   spazio nella card (l'altezza totale e' solo quella dell'immagine),
   stessa tinta/trasparenza scura del footer di pagina. */
.card .label {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 54px;
  padding: 0 6px;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  font-size: 18px;
  font-weight: 600;
  background: rgba(31, 78, 121, 0.75);
  color: var(--text);
}

/* camera-fill occupa esattamente lo spazio verticale rimasto (calcolato da
   flexbox, mai una stima fissa) e centra al suo interno il gruppo
   foto+pulsanti: cosi' il tasto "Scatta" resta sempre appena sotto la foto,
   invece di restare ancorato in fondo allo schermo con un vuoto in mezzo. */
.camera-fill {
  flex: 1 1 0;
  min-height: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  /* flex-start, non center: con un ratio verticale (2:3) il gruppo
     titolo+foto+pulsanti puo' risultare piu' basso dello spazio disponibile
     (ch), e centrarlo lasciava un vuoto sia sopra che sotto - ancorato in
     alto assomiglia di piu' a un vero mirino fotocamera. In overlay/
     orizzontale (schermo basso) resta centrato, vedi override sotto - li' il
     box occupa gia' tutta l'altezza di suo (priorita' altezza in
     fitCameraBox), niente vuoto da ridistribuire. */
  justify-content: flex-start;
  overflow: hidden;
}

.camera-group {
  display: flex;
  flex-direction: column;
  align-items: center;
  min-height: 0;
  max-width: 100%;
  max-height: 100%;
}

/* Nessuna larghezza/altezza esplicita: aspect-ratio + max-width/max-height al
   100% del contenitore fanno si' che il riquadro resti sempre un vero
   rettangolo nel ratio target, scegliendo da solo se il lato stretto e' la
   larghezza o l'altezza - in verticale sara' la larghezza (schermo stretto)
   a decidere, in orizzontale sara' l'altezza (poco spazio verticale
   rimasto) - mai stiramento, mai sforamento dello spazio disponibile.
   --camera-ratio e' impostata da fitCameraBox in app.js (default 3/2 se lo
   script non ha ancora girato, es. JS disabilitato) - qui e' solo un
   fallback: width/height espliciti in px, impostati dalla stessa funzione,
   sono la vera sorgente di verita' (vedi commento li' sul perche'). */
.camera-wrap {
  position: relative;
  aspect-ratio: var(--camera-ratio, 3 / 2);
  max-width: 100%;
  max-height: 100%;
  /* Senza questo, il minimo automatico dei flex item si basa sulla dimensione
     intrinseca del <video> figlio: prima che lo stream carichi, il video ha
     una dimensione di default piccola (300x150), quindi il riquadro nero
     risulta piu' piccolo finche' il video reale non lo "sblocca". */
  min-width: 0;
  min-height: 0;
  background: #000;
  border-radius: 12px;
  overflow: hidden;
  border: 2px solid #fff;
}

.camera-wrap video,
.camera-wrap img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* Solo mobile verticale (is-touch-device, vedi app.js): in orizzontale il
   pulsante equivalente vive nella sidebar footer (vedi @media piu' sotto e
   updateCameraFooterState), su desktop/webcam singola resta sempre nascosto
   (.hidden, aggiunto/tolto da updateCameraSwitchAvailability in base al
   numero di fotocamere rilevate). */
.camera-switch-btn {
  display: none;
}

body.is-touch-device .camera-switch-btn:not(.hidden) {
  display: flex;
  position: absolute;
  top: 10px;
  right: 10px;
  z-index: 8;
  background: rgba(0, 0, 0, 0.45);
  color: #fff;
}

.countdown-overlay {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: clamp(75px, min(37.5vw, 50dvh), 275px);
  font-weight: 700;
  color: var(--accent, #FCDE2A);
  text-shadow:
    -2px -2px 0 rgba(0, 0, 0, 0.6),
    0 -2px 0 rgba(0, 0, 0, 0.6),
    2px -2px 0 rgba(0, 0, 0, 0.6),
    -2px 0 0 rgba(0, 0, 0, 0.6),
    2px 0 0 rgba(0, 0, 0, 0.6),
    -2px 2px 0 rgba(0, 0, 0, 0.6),
    0 2px 0 rgba(0, 0, 0, 0.6),
    2px 2px 0 rgba(0, 0, 0, 0.6);
  pointer-events: none;
  z-index: 5;
  user-select: none;
}

.countdown-overlay.hidden {
  display: none;
}

/* A schermo intero (non solo sul riquadro foto): un vero flash da fotocamera
   deve coprire tutta la vista, non solo il piccolo riquadro dell'anteprima. */
.flash-overlay {
  position: fixed;
  inset: 0;
  background: #fff;
  opacity: 0;
  pointer-events: none;
  z-index: 200;
}

.hidden { display: none !important; }

/* Contatore foto rimaste: solo web/kiosk (postazione condivisa, staff che
   deve tenere d'occhio la scorta), mai su mobile - vedi
   updatePhotosRemainingBadge in app.js. Sempre visibile, sopra qualunque step. */
.photos-remaining-badge {
  position: fixed;
  right: max(14px, env(safe-area-inset-right));
  bottom: max(14px, env(safe-area-inset-bottom));
  background: rgba(0, 0, 0, 0.55);
  color: var(--text);
  font-size: 13px;
  font-weight: 700;
  padding: 6px 12px;
  border-radius: 20px;
  z-index: 30;
  pointer-events: none;
}

.actions {
  flex-shrink: 0;
  display: flex;
  gap: 12px;
  justify-content: center;
  margin-top: 20px;
  flex-wrap: wrap;
  padding: 10px 0 10px;
}

/* Ricomincia "di riserva" in fondo allo step risultato: esiste solo per il
   caso mobile in orizzontale (vedi @media max-height:500px piu' sotto, dove
   torna visibile), altrove ridondante col #btn-restart gia' accanto a
   Scarica qui sopra. */
.landscape-restart-actions {
  display: none;
}

/* Schermo basso (telefono in orizzontale): la fotocamera usa tutta l'altezza
   disponibile, il pulsante "Scatta" (e Rifai/Continua) galleggia sopra la
   foto invece di occupare una riga propria - stesso 3:2 di sempre, solo piu'
   grande perche' non deve piu' condividere lo spazio con i pulsanti. */
@media (max-height: 500px) {
  /* .step.active ha 16px di padding fisso su tutti i lati (vedi sopra): in
     landscape va tolto, altrimenti .camera-fill qui sotto (position:absolute;
     inset:0) resta comunque staccato dai bordi reali dello schermo di quei
     16px invece di sfruttare tutto lo spazio verticale rimasto (main e'
     gia' sotto il topbar di suo, vedi body flex sopra) - restano solo i
     safe-area-inset (notch/home indicator), mai un padding fisso. */
  #step-camera.step.active {
    padding: env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left);
  }

  #step-camera .camera-fill {
    position: absolute;
    inset: 0;
    /* Qui il box riempie gia' tutta l'altezza (fitCameraBox, priorita'
       altezza in overlay mode), quindi non c'e' un vuoto verticale da
       ridistribuire come nel caso verticale sopra - resta centrato invece
       di ereditare flex-start. */
    justify-content: center;
  }

  /* Tutti e tre i bottoni (Scatta/Rifai/Continua) restano visibili anche
     qui, oltre che nella sidebar (vedi app.js:updateCameraFooterState):
     doppia via d'accesso invece di spostarli del tutto come per gli altri
     passi, piu' facile da notare per chi ha meno familiarita' col
     linguaggio "icona nella colonna laterale". */
  #step-camera .actions {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 14px;
    z-index: 10;
    margin-top: 0;
    pointer-events: none;
  }

  #step-camera .actions .btn {
    pointer-events: auto;
    box-shadow: 0 2px 12px rgba(0, 0, 0, 0.5);
  }

  /* Resta visibile anche qui (oltre che nella sidebar, vedi
     updateCameraFooterState in app.js - stessa "doppia via d'accesso" gia'
     usata per Scatta/Rifai/Continua), ma spostato in basso a destra: in alto
     ci finiva sotto lo step-heading (mosso dentro camera-wrap in orizzontale,
     vedi placeStepHeading in app.js), che lo copriva parzialmente.
     :not(.hidden) ripetuto per pareggiare la specificita' della regola base
     sopra (stessa altrimenti vincente a parita' di specificita' solo per
     ordine nel file, qui invece servirebbe vincere per specificita' vera dato
     il contesto @media). */
  body.is-touch-device .camera-switch-btn:not(.hidden) {
    top: auto;
    bottom: 14px;
  }
}

/* Il titolo dello step camera vive dentro .camera-wrap (mosso li' via JS),
   sempre in overlay sopra la foto - stessa tecnica gia' usata e funzionante
   per countdown/flash, non solo in orizzontale come per il pulsante. */
.camera-wrap .step-heading {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  z-index: 7;
  margin: 0;
  padding: 10px 10px 18px;
  background: linear-gradient(to bottom, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0));
  pointer-events: none;
  text-shadow: 0 1px 6px rgba(0, 0, 0, 0.85);
}

/* Errore fotocamera (permesso negato/nessuna fotocamera/gia' in uso): stesso
   overlay in stile di .step-heading sopra, allineato in alto (sotto il
   titolo, non sovrapposto) invece che centrato - centrato finiva troppo in
   basso su schermi bassi, arrivando a coprire il pulsante Scatta sotto al
   riquadro. Niente schermata/bottoni a parte, il pulsante Scatta resta
   l'unico punto d'azione (vedi handleShootClick in app.js). Vuoto (nessun
   errore in corso) = invisibile, .error:empty gia' lo nasconde di suo. */
.camera-wrap .error {
  position: absolute;
  top: 40px;
  left: 12px;
  right: 12px;
  z-index: 6;
  margin: 0;
  padding: 14px 16px;
  background: rgba(0, 0, 0, 0.55);
  border-radius: 10px;
  text-shadow: 0 1px 6px rgba(0, 0, 0, 0.85);
}

.btn {
  border: none;
  border-radius: 10px;
  padding: 14px 26px;
  font-size: 20px;
  font-weight: 700;
  cursor: pointer;
  text-decoration: none;
  display: inline-block;
  text-align: center;
  text-transform: uppercase;
}

.btn.primary { background: var(--bg-dark, #1F4E79); color: white; }
.btn.primary:active { background: #163a5c; }
.btn.secondary { background: rgba(255, 255, 255, 1); color: var(--bg-dark, #1F4E79); }
.btn.secondary:active { background: rgba(255, 255, 255, 0.85); }

/* Rotellina inline su #btn-send-email durante l'invio (04/09/2026,
   segnalato in test manuale: il solo disabled non dava la sensazione che
   stesse lavorando) - riusa @keyframes spin gia' definito sotto per
   .spinner, solo piu' piccola per stare dentro al bottone. */
#btn-send-email {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
}
.btn-spinner-sm {
  display: none;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  border: 2px solid rgba(255, 255, 255, 0.35);
  border-top-color: currentColor;
  animation: spin 0.7s linear infinite;
  flex-shrink: 0;
}
#btn-send-email.is-loading .btn-spinner-sm { display: inline-block; }

/* Icona via CSS (non nel testo del pulsante): cosi' il testo vero e proprio,
   impostato da JS in base alla lingua, non deve preoccuparsi di ricostruirla
   ogni volta insieme all'emoji. */
.btn-icon-back::before { content: "\2190\00a0"; }
.btn-icon-random::before { content: "\1F3B2\00a0"; }

/* Indicatore di focus da tastiera (versione web) sui pulsanti azione - stesso
   ruolo del bordo giallo delle card durante la navigazione a frecce. Nessun
   anello su touch: li' il focus e' solo un dettaglio implementativo del tap,
   non una scelta dell'utente. */
.btn:focus {
  outline: 3px solid var(--accent);
  outline-offset: 2px;
}

body.is-touch .btn:focus {
  outline: none;
}

.error {
  flex-shrink: 0;
  color: #ffdada;
  text-align: center;
  font-weight: 600;
  margin-top: 14px;
}

/* Senza display:none esplicito, un <p class="error"> vuoto (nessun errore
   in corso) riserva comunque il suo margin-top - es. in .email-form,
   spazio vuoto "fantasma" sotto l'ultimo testo scritto davvero (l'hint
   privacy) anche senza nessun errore da mostrare. */
.error:empty {
  display: none;
}

.hint {
  flex-shrink: 0;
  text-align: center;
  opacity: 0.8;
  font-size: 18px;
}

/* Stesso principio di .step-heading/.spinner - vedi i rispettivi commenti
   @media max-height:500px. */
@media (max-height: 500px) {
  .hint {
    font-size: 14px;
  }
}

/* Su mobile la foto occupa tutta la larghezza disponibile (il contenuto e'
   comunque in colonna, non c'e' altro accanto). Su schermi larghi (desktop,
   main allargato per la fotocamera) resta invece limitata: a piena
   larghezza diventerebbe enorme e spingerebbe pulsanti/email fuori dalla
   vista - si puo' comunque ingrandire a schermo intero toccandola (vedi
   .lightbox). */
.result-img {
  display: block;
  width: auto;
  margin: 0 auto;
  border-radius: 12px;
  cursor: zoom-in;
  max-width: 100%;
}

/* Contenitore di posizionamento per .result-demo-badge-clip sotto - un div
   qualunque, nessuno stile visivo proprio: .result-img dentro si centra
   esattamente come prima (margin:0 auto), invariato. */
.result-img-wrap {
  position: relative;
}

/* Ancora del nastro "immagine demo" (solo /demo, /demo/en) - un div
   separato dalla foto invece che overflow:hidden su .result-img-wrap
   stesso: .result-img ha vincoli di dimensione (max-width/max-height)
   percentuali sul PROPRIO genitore .result-img-wrap in alcuni breakpoint
   (es. max-width:40% su schermi >=900px) - un contenitore dimensionato
   per combaciare con la foto creerebbe quindi un riferimento circolare
   (prima versione: la foto si rimpiccioliva inseguendo un contenitore che
   si rimpiccioliva inseguendo lei, quasi a sparire). Questo div invece e'
   POSIZIONATO IN ASSOLUTO (fuori dal flusso, non influenza ne' e'
   influenzato dal dimensionamento della foto) e ridimensionato via JS
   (vedi ResizeObserver su .result-img in app.js) per combaciare col
   riquadro della foto GIA' risolto dal browser, niente circolarita'.
   overflow:hidden + stesso border-radius della foto: senza, il nastro
   ruotato sporgerebbe oltre gli angoli arrotondati invece di restare
   tagliato al bordo, come invece succede correttamente a
   .package-on-request-badge in home.css grazie a overflow:hidden su
   .package-card. */
.result-demo-badge-clip {
  position: absolute;
  overflow: hidden;
  border-radius: 12px;
  pointer-events: none;
}

/* Nastro diagonale nell'angolo in BASSO a sinistra della foto - non in alto:
   li' a sinistra c'e' l'etichetta "AI GENERATED" impressa sulle foto demo
   (core.apply_ai_generated_label) e a destra il logo PartyLab (core.
   apply_logo, vedi generate_demo_example_photos.py) - un nastro d'angolo
   copre sempre l'angolo esatto per costruzione, in alto avrebbe sempre
   tagliato l'uno o l'altro. In basso a sinistra invece non c'e' nulla (le
   foto demo non hanno testo evento, vedi generate_demo_example_photos.py).
   Stessi valori di .package-on-request-badge in home.css (nastro "A
   richiesta" sulle card pacchetti) - stessi token colore (--bg-dark/
   --text-on-dark) invece di nero/bianco fissi, cosi' segue anche qui i
   colori personalizzati dell'evento. */
.result-demo-badge {
  position: absolute;
  bottom: 37px;
  left: -37px;
  width: 170px;
  padding: 5px 0;
  background: var(--bg-dark);
  color: var(--text-on-dark);
  font-weight: 800;
  font-size: 13px;
  letter-spacing: 0.02em;
  text-align: center;
  transform: rotate(45deg);
  box-shadow: 0 2px 8px rgba(31, 78, 121, 0.35);
  pointer-events: none;
}

.result-mobile-quicknav {
  display: none;
}

@media (max-width: 480px) {
  /* Solo mobile verticale (vedi index.html): riga orizzontale fissa su
     tutta la larghezza, bottoni centrati, appena sotto l'header - sempre
     visibile mentre si scorre lo step risultato, segnala che sotto la foto
     c'e' altro (voto/eta'-consenso/commento/email) invece di lasciarlo
     scoprire solo per caso scorrendo. Scoped a questo solo step (non e' il
     sistema condiviso della sidebar mobile orizzontale, vedi
     updateFooterActions): nessun rischio di toccare style/tema/thankyou/
     camera. 66px = altezza reale della topbar in verticale (56px, vedi
     .topbar) + margine. */
  .result-mobile-quicknav {
    display: flex;
    flex-direction: row;
    justify-content: center;
    align-items: center;
    gap: 22px;
    position: fixed;
    left: 0;
    right: 0;
    /* Attaccata all'header, non staccata: cosi' si legge come un vero
       sottomenu (prosecuzione della topbar) invece che come un widget
       fluttuante a se' - --topbar-height e' l'altezza REALE del topbar,
       misurata via ResizeObserver in app.js (gia' include il suo padding-top
       con env(safe-area-inset-top), niente da sommare qui). 56px resta solo
       come fallback per il brevissimo istante prima che il JS giri. -4px:
       correzione a mano (richiesta esplicita) per un piccolo scarto residuo
       fra l'altezza misurata e la posizione visivamente corretta. */
    top: calc(var(--topbar-height, 56px) - 4px);
    padding: 8px max(12px, env(safe-area-inset-right)) 8px max(12px, env(safe-area-inset-left));
    /* rgba invece di var(--bg) piena: lascia intravedere quel che c'e'
       sotto (titolo/foto durante lo scroll) invece di un blocco opaco. */
    background: rgba(77, 151, 209, 0.95);
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.25);
    z-index: 15;
  }

  .result-quicknav-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 30px;
    height: 30px;
    border-radius: 50%;
    border: none;
    background: transparent;
    color: #fff;
    cursor: pointer;
    padding: 0;
  }

  /* Stesso giallo del bottone primario (Scarica) della sidebar mobile
     orizzontale, vedi .footer-primary-btn - qui un cerchio pieno invece di
     trasparente, per farlo risaltare come azione principale nella riga. */
  .result-quicknav-btn--primary {
    background: var(--accent, #FFD62E);
    color: var(--bg-dark, #1F4E79);
  }

  /* La barra e' fixed (non occupa spazio nel flusso): senza questo la foto,
     che parte subito in cima allo step, ci finirebbe sotto per meta'.
     --quicknav-height e' l'altezza REALE della barra, misurata via
     ResizeObserver in app.js - 54px resta solo come fallback iniziale.
     +10px di margine oltre l'altezza esatta: il titolo (.step-heading,
     primo contenuto dello step) restava altrimenti troppo a ridosso della
     barra. */
  #step-result,
  #step-thankyou {
    padding-top: calc(var(--quicknav-height, 54px) + 10px);
  }

  .result-quicknav-btn:active {
    background: rgba(255, 255, 255, 0.15);
  }

  /* Solo la barra dello step Grazie (non result, che invece ha piu' bottoni
     centrati come gruppo): Indietro a sinistra, social a destra - stesso
     schema sinistra/destra gia' usato in orizzontale (vedi .topbar-social),
     qui semplicemente su una riga invece che in colonna. */
  #thankyou-mobile-quicknav {
    justify-content: space-between;
  }

  .quicknav-social {
    display: flex;
    align-items: center;
    gap: 8px;
  }

  /* Piu' piccole del cerchio da 52px usato nel corpo (.thankyou-social-icon
     base): qui devono stare dentro una barra sottile, stessa taglia dei
     bottoni tondi accanto (.result-quicknav-btn, 30px). */
  .quicknav-social .thankyou-social-icon {
    width: 26px;
    height: 26px;
  }

  .quicknav-social .thankyou-social-icon svg {
    width: 14px;
    height: 14px;
  }
}

@media (min-width: 900px) {
  .result-img {
    max-width: 40%;
    /* Il max-width da solo basta per una foto 3:2 (landscape), ma per una
       verticale 2:3 l'altezza cresce proporzionalmente (height = width *
       1.5) senza alcun freno su uno schermo alto - bottoni/stelline/email
       finivano sotto al fold esattamente come nei casi @media max-height
       piu' sotto, ma li' scattano solo su schermi BASSI: qui serve lo
       stesso freno anche su un desktop normale con foto verticale. */
    max-height: 40vh;
  }

  /* Foto verticale 2:3 (vedi body.rotate-target-portrait, applyAspectRatioData
     in app.js): il 40% di sopra pensato per una 3:2 orizzontale qui la
     rimpiccioliva doppiamente (gia' stretta di suo per l'aspect ratio, E
     limitata in larghezza) - max-height:40vh da solo basta gia' a tenerla
     dentro la prima schermata, il max-width puo' restare libero. */
  body.rotate-target-portrait .result-img {
    max-width: 100%;
  }
}

/* Era 92% ("il kiosk ha piu' spazio, sfruttiamolo"): su un tablet kiosk in
   orizzontale una foto quasi a piena larghezza (quindi altissima, aspect
   3:2) spingeva bottoni/stelline/email sotto al fold senza che restasse
   ovvio scorrere per trovarli - stessa 40% (min-width:900px sopra) di un
   ospite qualunque su schermo largo, il kiosk non ha piu' bisogno di
   un'eccezione. */

/* Schermo basso: qualunque sia la larghezza, se l'altezza e' risicata (telefono
   in orizzontale, ma anche un telefono/tablet piccolo in verticale) la foto a
   dimensione "naturale" spinge bottoni/stelline/email sotto al fold - qui si
   rimpicciolisce in base all'altezza (si puo' comunque ingrandire a schermo
   intero toccandola, vedi .lightbox) cosi' il resto resta visibile senza
   scorrere. Il blocco piu' sotto (max-height:500px, telefono in orizzontale,
   dove la larghezza abbonda) resta piu' generoso: viene dopo nel file, vince
   lui sulle altezza ancora piu' basse. */
@media (max-height: 700px) {
  .result-img {
    width: auto;
    max-width: 100%;
    max-height: 22vh;
    margin: 0 auto;
  }
}

/* Schermo basso (telefono in orizzontale): la foto a piena larghezza non
   lascerebbe spazio a titolo/pulsanti/email nella stessa schermata - qui si
   rimpicciolisce (si puo' comunque ingrandire a schermo intero toccandola,
   vedi .lightbox) e i margini sotto si stringono un po'. */
@media (max-height: 500px) {
  .result-img {
    width: auto;
    max-width: 100%;
    max-height: 62vh;
    margin: 0 auto;
  }

  #step-result .email-form,
  #step-result .rating-block {
    margin-top: 10px;
    padding-top: 10px;
  }

  /* Le azioni di result/style/tema/thankyou/error si spostano nel footer-
     diventato-colonna a destra (footer-primary-btn/footer-secondary-*,
     vedi piu' sopra, app.js:updateFooterActions) invece di stare sotto la
     foto/griglia - le barre originali qui vanno quindi nascoste, altrimenti
     i bottoni comparirebbero due volte. #step-camera apposta ESCLUSO: li' i
     bottoni restano visibili anche nella barra originale (vedi
     #step-camera .actions poco piu' sopra) oltre che nella sidebar.
     #step-result NON ha lo stesso trattamento (tornata nascosta dopo un
     ripensamento): Scarica/Ricomincia visibili subito sotto la foto davano
     l'impressione che la schermata finisse li', nascondendo che sotto ci
     sono ancora le stelle di valutazione (e commento/email) da scoprire
     solo scorrendo. */
  #step-result .actions,
  #step-style .actions,
  #step-theme .actions,
  #step-thankyou .actions,
  #step-error .actions {
    display: none;
  }

  /* Eccezione al display:none qui sopra (specificita' maggiore: due classi
     invece di una): l'unico bottone che qui in orizzontale resta visibile
     nel flusso normale, apposta in fondo a tutto - vedi il commento su
     #landscape-restart-actions in index.html sul perche'. */
  #step-result .actions.landscape-restart-actions {
    display: flex;
  }

  /* Altra eccezione allo stesso display:none: i bottoni Si/No eta'/
     consenso gallery pubblica (inline su touch, vedi app.js
     setupPublicGalleryConsentBlock) sono nascosti da #step-result .actions
     sopra come tutti gli altri - qui in orizzontale sparivano del tutto,
     rendendo la domanda impossibile da usare invece che solo posticipata
     con lo scroll. */
  #step-result #public-gallery-consent-block .actions {
    display: flex;
  }
}

/* Tocco/click sulla foto risultato per vederla a schermo intero (comodo
   soprattutto quando e' stata rimpicciolita, vedi sopra). */
.lightbox {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.92);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
  cursor: zoom-out;
  z-index: 50;
}

.lightbox img {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
  border-radius: 8px;
}

.alert-modal {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.6);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
  z-index: 55;
}

.alert-modal-box {
  position: relative;
  max-width: 360px;
  background: var(--bg-dark, #1F4E79);
  color: var(--text);
  border-radius: 12px;
  padding: 28px 24px;
  text-align: center;
  font-weight: 600;
  box-shadow: 0 8px 30px rgba(0, 0, 0, 0.4);
}

.alert-modal-close {
  position: absolute;
  top: 6px;
  right: 6px;
  width: 32px;
  height: 32px;
  border: none;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.15);
  color: var(--text);
  font-size: 20px;
  line-height: 1;
  cursor: pointer;
}

.alert-modal-close:hover,
.alert-modal-close:focus-visible {
  background: rgba(255, 255, 255, 0.3);
}

.alert-modal-actions {
  display: flex;
  justify-content: center;
  gap: 12px;
  margin-top: 20px;
}

.alert-modal-actions .btn {
  font-size: 16px;
  padding: 10px 18px;
}

/* .btn.primary e' sfondo blu scuro (var(--bg-dark)) di suo - identico allo
   sfondo di .alert-modal-box, ci si confondeva quasi del tutto. Un bordo
   chiaro basta a distinguerlo senza reinventare un colore nuovo. */
.alert-modal-actions .btn.primary {
  border: 2px solid rgba(255, 255, 255, 0.6);
}

/* Consenso privacy prima dello scatto (#consent-modal in index.html) -
   stesso overlay semi-trasparente di .alert-modal (la preview webcam resta
   visibile, solo attenuata) ma box piu' largo (piu' testo: titolo + corpo +
   link + due bottoni) e SENZA .alert-modal-close: qui non esiste una X,
   deve essere una scelta esplicita tra i due bottoni sotto (vedi app.js). */
.consent-modal {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.6);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
  z-index: 56;
}

.consent-modal-box {
  max-width: 440px;
  background: var(--bg-dark, #1F4E79);
  color: var(--text);
  border-radius: 12px;
  padding: 28px 24px;
  text-align: center;
  box-shadow: 0 8px 30px rgba(0, 0, 0, 0.4);
}

.consent-modal-box h2 {
  margin: 0 0 12px;
  font-size: 22px;
}

.consent-modal-box p {
  margin: 0;
  font-size: 15px;
  line-height: 1.5;
  font-weight: 500;
}

.consent-modal-box a {
  color: var(--accent, #FFD62E);
}

.consent-modal-actions {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-top: 22px;
}

/* Stesso .btn.primary/.btn.secondary del resto del sito (identica
   dimensione/padding: il bottone secondario deve restare leggibile e
   cliccabile quanto il primario, solo meno enfatizzato nel colore - non un
   dark pattern). Bordo sul primario per lo stesso motivo di
   .alert-modal-actions .btn.primary sopra (altrimenti si confonde con lo
   sfondo scuro del box). Colonna invece che riga (a differenza di
   .alert-modal-actions): due bottoni a piena larghezza sono piu' facili da
   centrare nel focus/toccare su schermi stretti con questo testo piu' lungo. */
.consent-modal-actions .btn.primary {
  border: 2px solid rgba(255, 255, 255, 0.6);
}

/* Blocco eta'/consenso pubblicazione gallery pubblica (#public-gallery-
   consent-block in index.html) - sempre inline, mai overlay/popup: su touch
   e' un altro .rating-block dello step risultato (dopo le stelle), su
   tastiera vive invece nello step Grazie (spostato li' via JS all'avvio,
   vedi app.js isTouchDevice) per non rompere l'effetto della foto appena
   mostrata - in entrambi i casi e' contenuto normale della pagina, nessuno
   stile posizionale a parte. */

/* No/Si' altrimenti hanno larghezza diversa (auto sul testo, "No" piu'
   largo di "Si'") - una coppia visivamente sbilanciata invece di due
   bottoni pari, anche se il gruppo nel suo insieme resta centrato. */
#public-gallery-consent-block .actions .btn {
  min-width: 96px;
}

.email-form {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  margin-top: 14px;
  padding-top: 20px;
  border-top: 1px solid rgba(255, 255, 255, 0.25);
  text-align: center;
}

.email-form label {
  font-weight: 700;
}

.email-form input[type="email"] {
  width: 100%;
  max-width: 320px;
  padding: 12px 16px;
  border-radius: 10px;
  border: none;
  font-size: 18px;
  font-family: inherit;
  text-align: center;
}

.email-form input[type="email"]:focus {
  outline: 3px solid var(--accent);
  outline-offset: 2px;
}

.email-newsletter-optin {
  display: flex;
  align-items: center;
  gap: 8px;
  font-weight: 400;
  font-size: 14px;
  text-align: left;
  max-width: 320px;
  cursor: pointer;
}

.email-newsletter-optin input[type="checkbox"] {
  flex-shrink: 0;
  width: 18px;
  height: 18px;
}

.pin-form {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
  text-align: center;
  max-width: 360px;
  margin: 0 auto;
}

.pin-form label {
  font-weight: 700;
}

.pin-form input {
  width: 100%;
  max-width: 220px;
  padding: 14px 16px;
  border-radius: 10px;
  border: none;
  font-size: 24px;
  letter-spacing: 4px;
  font-family: inherit;
  text-align: center;
}

.pin-form input:focus {
  outline: 3px solid var(--accent);
  outline-offset: 2px;
}

.pin-form .error {
  margin-top: 0;
}

.download-info {
  margin: 4px 0;
  padding: 16px 20px;  
  background: #fff;
  border-radius: 12px;
  text-align: center;
  font-size: 15px;
  line-height: 1.5;
  color:#555;
}

.download-info-content :first-child {
  margin-top: 0;
}

.download-info-content :last-child {
  margin-bottom: 0;
}

/* Centrato anche in verticale (non solo orizzontale, gia' garantito da
   margin:auto/text-align:center sui figli) nello spazio disponibile. */
#step-processing {
  align-items: center;
  justify-content: center;
}

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

/* Unico indicatore di attesa nello step Elaborazione (04/09/2026: prima
   affiancava una rotellina indeterminata, tolta su richiesta - ridondante
   una volta che la barra comunica un progresso vero, anche se
   approssimato, vedi app.js updateProcessingProgress). Tarata sulla
   mediana storica reale di jobs.generation_seconds - piu' presente di
   prima (era un dettaglio secondario sotto la rotellina), ma resta
   comunque una striscia sottile, non un elemento pesante: non deve
   competere per spazio col blocco eta'/consenso che segue. Riga
   barra+percentuale (04/09/2026, su richiesta) invece della sola barra. */
.processing-progress-row {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  margin: 30px auto 16px;
  flex-shrink: 0;
}

.processing-progress {
  width: 220px;
  max-width: 60%;
  height: 8px;
  background: rgba(255, 255, 255, 0.2);
  border-radius: 999px;
  overflow: hidden;
  flex-shrink: 0;
}

.processing-progress-bar {
  height: 100%;
  width: 0%;
  background: var(--accent);
  border-radius: inherit;
  transition: width 0.4s linear;
}

.processing-progress-pct {
  font-size: 13px;
  font-variant-numeric: tabular-nums;
  opacity: 0.75;
  min-width: 2.4em;
}

/* Mobile in orizzontale (schermo basso): barra+hint+blocco eta'/consenso
   (vedi app.js, spostato qui sotto durante l'attesa) insieme non ci
   stavano - una versione piu' compatta libera lo spazio verticale che
   serve al blocco sotto, invece di lasciarlo tagliato fuori dal viewport
   (stesso principio/numeri di quando qui c'era la rotellina). */
@media (max-height: 500px) {
  .processing-progress-row {
    margin: 8px auto 6px;
    gap: 6px;
  }
  .processing-progress {
    width: 100px;
    height: 4px;
  }
  .processing-progress-pct {
    font-size: 11px;
  }
}

.thankyou {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  gap: 12px;
}

#thankyou-social-block {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
}

/* Valutazione 1-5 stelle (solo mobile, vedi maybeShowRatingBlock in app.js).
   Il bordo superiore fa da separatore visivo tra le sezioni dello step
   risultato (azioni/stelle/commento/email) - vive sul blocco stesso (non su
   un <hr> a parte) cosi' scompare da solo insieme al blocco quando e'
   nascosto (kiosk, commenti disattivati, ecc.), senza lasciare separatori
   "orfani" da gestire via JS. */
.rating-block {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  margin-top: 14px;
  padding-top: 20px;
  border-top: 1px solid rgba(255, 255, 255, 0.25);
}

/* Stesso principio di .step-heading/.hint/.spinner - vedi i rispettivi
   commenti @media max-height:500px. Il blocco eta'/consenso (spostato
   qui sotto lo step Elaborazione, vedi app.js) e' quello che soffriva di
   piu': divisore+padding+gap costavano 44px da soli su un totale gia'
   troppo stretto. */
@media (max-height: 500px) {
  .rating-block {
    gap: 6px;
    margin-top: 8px;
    padding-top: 8px;
  }
}

.rating-prompt {
  margin: 0;
  font-weight: 700;
  text-align: center;
}

/* Intro sopra le domande eta'/consenso, SOLO mentre il blocco e' parcheggiato
   nello step Elaborazione (04/09/2026, su richiesta - girato di 180°
   rispetto al tentativo precedente: "dobbiamo dare risalto non togliere",
   il blocco resta quindi alla sua prominenza normale come nello step
   Risultato). Vive DENTRO #public-gallery-consent-block (si muove col resto
   del blocco tra i 2 step, vedi app.js) ma la si nasconde quando il blocco
   e' promosso in #step-result (li' "mentre aspetti" non avrebbe piu' senso,
   il risultato e' gia' arrivato) - scoping sull'ANTENATO, niente classe da
   alternare a mano quando cambia posizione. */
#step-result #processing-consent-heading {
  display: none;
}

#processing-consent-heading {
  font-size: 20px;
}

.public-gallery-consent-inner {
  font-weight: 400;
}

#public-gallery-consent-text {
  font-weight: 500;
  font-size: 16px;
}

.stars {
  display: flex;
  gap: 6px;
}

.star-btn {
  background: none;
  border: none;
  font-size: 34px;
  line-height: 1;
  padding: 4px;
  color: rgba(255, 255, 255, 0.35);
  cursor: pointer;
}

.star-btn.active {
  color: var(--accent);
}

.rating-comment {
  width: 100%;
  max-width: 320px;
  padding: 10px 14px;
  border-radius: 10px;
  border: none;
  font-size: 15px;
  font-family: inherit;
  resize: vertical;
  min-height: 80px;
}

.rating-thanks {
  margin: 0;
  font-weight: 700;
  color: var(--accent);
}

.thankyou-title {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 22px;
  font-weight: 700;
}

.thankyou-title .emoji {
  font-size: 30px;
}

.qr-img {
  width: 160px;
  height: 160px;
  background: #fff;
  padding: 8px;
  border-radius: 8px;
}

/* Solo touch reale, non kiosk (vedi document.body.classList "is-touch" in
   app.js, gia' esclude ?kiosk=1): un ospite col PROPRIO telefono in mano ha
   gia' le icone social subito sotto (.thankyou-social), toccabili col dito -
   inquadrare un QR per aprire lo stesso link che ha gia' davanti non ha
   senso. Su kiosk (postazione condivisa, l'ospite non tiene il telefono che
   mostra questo schermo) resta invece l'unico modo pratico per raggiungere
   i social dal proprio telefono personale. Il testo sotto (.thankyou-invite)
   resta invece visibile in entrambi i casi: cambia solo il CONTENUTO,
   niente "scannerizza il QR" su touch - vedi THANKYOU_INVITE_TOUCH in
   app.js/core.py. */
body.is-touch #thankyou-qr {
  display: none;
}

/* Mobile in orizzontale: #step-thankyou.step.active non aveva height:100%
   (solo camera/processing, vedi sopra - li' serve a lasciare le griglie ad
   altezza naturale, qui invece non c'e' nessuna griglia) quindi .thankyou
   (justify-content:center, vedi sopra) non aveva davvero spazio extra da
   centrare: il contenuto era alto quanto il suo stesso contenuto, niente
   di piu'. Con l'altezza vincolata qui sotto il centraggio verticale
   funziona per davvero, senza dover scorrere - QR a una via di mezzo (130px,
   ne' i 160px originali ne' i 90px ridotti troppo) cosi' ci sta comodo
   insieme al resto. Le frecce scroll (vedi app.js:updateFooterActions)
   restano comunque disponibili come rete di sicurezza su schermi molto bassi. */
@media (max-height: 500px) {
  #step-thankyou.step.active {
    height: 100%;
  }

  .qr-img {
    width: 130px;
    height: 130px;
  }
}

.thankyou-invite,
.thankyou-thanks {
  margin: 0;
  font-size: 18px;
  opacity: 0.9;
}

/* Cerchietto con icona (stessa SVG di templates/_footer.html, vedi
   core.SOCIAL_ICON_SVG) invece di un link di testo semplice: su questo
   sfondo scuro un link senza bottone/bordo si notava a stento - stesso
   linguaggio grafico degli altri pulsanti icona dello step (schermo
   intero/muto/lingua nel topbar, vedi .fullscreen-btn). */
.thankyou-social {
  margin: 0;
  display: flex;
  gap: 10px;
}

.thankyou-social-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 52px;
  height: 52px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.15);
  color: var(--text);
  transition: filter 0.15s ease;
}

.thankyou-social-icon svg {
  width: 26px;
  height: 26px;
}

/* Stesso blu/rosa-rosso dei pulsanti social nel template email (vedi Admin
   -> Tipo eventi -> corpo email risultato), invece del cerchietto neutro
   generico - colore invece che sfondo su hover/focus (filter, non
   background) perche' qui background E' il colore del brand. */
.thankyou-social-icon-facebook {
  background: #1877f2;
  color: #fff;
}

.thankyou-social-icon-instagram {
  background: #e4405f;
  color: #fff;
}

.thankyou-social-icon-whatsapp {
  background: #25d366;
  color: #fff;
}

.thankyou-social-icon:hover,
.thankyou-social-icon:focus-visible {
  filter: brightness(1.15);
}

.thankyou-thanks {
  font-weight: 700;
  color: var(--accent);
  opacity: 1;
}

.thankyou-countdown {
  margin: 4px 0 0;
  font-size: 15px;
  opacity: 0.75;
  text-align: center;
}

.thankyou-countdown:empty {
  display: none;
}
