/* =========================================================================
   Palestria v3.1 – sistema visivo "ambulatorio digitale"
   Tema chiaro e scuro tramite token (variabili CSS). Il tema attivo è
   scritto su <html data-theme="light|dark"> dallo script in base.html,
   prima che la pagina venga disegnata (niente lampeggio).
   ========================================================================= */

:root,
:root[data-theme="light"] {
  --bg: #F3F5F4;
  --bg-image: url("../img/bg-light.a2c01f7a2e9c.webp");
  --surface: #FFFFFF;
  --surface-2: #F3F5F4;
  --line: #DCE3E1;
  --line-soft: #E8ECEB;
  --ink: #13201D;
  --ink-2: #3D4A47;
  --muted: #55635F;
  --primary: #0A7468;
  --primary-hover: #075A51;
  --primary-ink: #FFFFFF;
  --primary-text: #0A7468;
  --tint: #E3F2EF;
  --ok-tint: #E3F2EF;  --ok-ink: #075A51;
  --warn-tint: #FFF1DC; --warn-ink: #7A4800; --warn-text: #9E5A00;
  --rec: #C2362B;      --rec-tint: #FBE7E4; --rec-ink: #9A2A21; --rec-line: #E9B7B1;
  --info-tint: #E6EEF8; --info-ink: #1F4E8C;
  --fb-ok: #0A7468; --fb-mid: #E0921F; --fb-bad: #C4502F;
  --disabled-line: #C4CFCC; --disabled-ink: #6B7975; --disabled-bg: #E8ECEB;
  --stage: #0E1413;
  --stage-2: #131B1A;
  --scrim: rgba(10, 58, 52, 0.22);
  --shadow: 0 1px 2px rgba(19, 32, 29, 0.06), 0 8px 24px rgba(19, 32, 29, 0.06);
  --shadow-lg: 0 24px 60px rgba(19, 32, 29, 0.22);
  --focus: #0A7468;
  color-scheme: light;
}

:root[data-theme="dark"] {
  --bg: #0B1110;
  --bg-image: url("../img/bg-dark.42bce4696687.webp");
  --surface: #141C1B;
  --surface-2: #1C2725;
  --line: #26322F;
  --line-soft: #1F2A28;
  --ink: #E6EEEC;
  --ink-2: #C9D5D2;
  --muted: #A3B3AF;
  --primary: #3CC7B2;
  --primary-hover: #5EE6CF;
  --primary-ink: #04211D;
  --primary-text: #5EE6CF;
  --tint: #123430;
  --ok-tint: #123430;  --ok-ink: #8DF0DF;
  --warn-tint: #3A2A10; --warn-ink: #FFD08A; --warn-text: #FFB547;
  --rec: #E0493D;      --rec-tint: #3A1714; --rec-ink: #FFB4AC; --rec-line: #6B2A24;
  --info-tint: #16263A; --info-ink: #A9C8F2;
  --fb-ok: #3CC7B2; --fb-mid: #F2A33A; --fb-bad: #E86A4A;
  --disabled-line: #33413E; --disabled-ink: #7F908C; --disabled-bg: #1C2725;
  --stage: #050807;
  --stage-2: #0B1110;
  --scrim: rgba(2, 20, 18, 0.36);
  --shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
  --shadow-lg: 0 24px 60px rgba(0, 0, 0, 0.5);
  --focus: #5EE6CF;
  color-scheme: dark;
}

/* Senza JavaScript: segue comunque il tema del sistema */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme]) {
    --bg-image: url("../img/bg-dark.42bce4696687.webp");
    --bg: #0B1110; --surface: #141C1B; --surface-2: #1C2725; --line: #26322F; --line-soft: #1F2A28;
    --ink: #E6EEEC; --ink-2: #C9D5D2; --muted: #A3B3AF; --primary: #3CC7B2; --primary-hover: #5EE6CF;
    --primary-ink: #04211D; --primary-text: #5EE6CF; --tint: #123430; --stage: #050807; --stage-2: #0B1110;
    color-scheme: dark;
  }
}

:root {
  /* Sfocatura di tutti gli elementi "di vetro" (barra in alto, popup, pannelli,
     riquadri e velature): un solo livello per tutto il sito. Non l'alone
     attorno ai popup, che sfuma con due livelli suoi. */
  --glass-blur: blur(16px) saturate(1.8);
  /* per le fasce fisse dentro un popup (vedi --glass-bar): solo sfocatura, i
     colori lì sotto sono già stati ravvivati dal vetro del popup */
  --glass-blur-bar: blur(16px);
  /* Colore del vetro: la superficie del tema con un po' del colore principale
     (verde petrolio), così il vetro prende il colore della pagina invece di
     essere bianco o nero. Tre livelli di trasparenza, tutti più trasparenti di
     prima: popup e pannelli (dove si legge), barre e riquadri, schede dentro i
     pannelli. Dove il testo conta, scheda e pannello si sommano. */
  --glass-tint: color-mix(in srgb, var(--surface) 90%, var(--primary));
  --glass: color-mix(in srgb, var(--glass-tint) 62%, transparent);
  --glass-soft: color-mix(in srgb, var(--glass-tint) 40%, transparent);
  --glass-card: color-mix(in srgb, var(--surface) 52%, transparent);
  /* Fasce fisse dentro un popup, sotto cui scorre il testo (barra delle schede
     delle impostazioni, barra dei pulsanti in fondo): più coprenti, perché lì
     sotto il testo deve sparire nella sfocatura e non restare leggibile. */
  --glass-bar: color-mix(in srgb, var(--glass-tint) 84%, transparent);
  /* Colori del disegno sul video: uguali nei due temi (il palco è sempre scuro) */
  --live-ok: #5EE6CF;
  --live-warn: #FFB547;
  --live-bad: #E86A4A;
  --radius: 18px;
  --radius-sm: 12px;
  --font: "Atkinson Hyperlegible", system-ui, -apple-system, "Segoe UI", sans-serif;
  --mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}

/* ---------- Caratteri ----------
   Serviti dal sito stesso (static/palestria/fonts, licenza OFL accanto ai
   file) e non più da Google Fonts: niente collegamenti a server esterni prima
   del disegno, cache lunga di WhiteNoise e il sito si vede uguale anche senza
   internet. Stessi file, sottoinsiemi e unicode-range di Google Fonts, quindi
   lo stesso aspetto; i due pesi del primo disegno (Atkinson 400 e 700, latin)
   sono precaricati in base.html. */
@font-face {
  font-family: "Atkinson Hyperlegible"; font-style: normal; font-weight: 400; font-display: swap;
  src: url("../fonts/atkinson-hyperlegible-400-latin-ext.fe905e20f857.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-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Atkinson Hyperlegible"; font-style: normal; font-weight: 400; font-display: swap;
  src: url("../fonts/atkinson-hyperlegible-400-latin.f1f8a8210104.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;
}
@font-face {
  font-family: "Atkinson Hyperlegible"; font-style: normal; font-weight: 700; font-display: swap;
  src: url("../fonts/atkinson-hyperlegible-700-latin-ext.764b69c9ccc8.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-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Atkinson Hyperlegible"; font-style: normal; font-weight: 700; font-display: swap;
  src: url("../fonts/atkinson-hyperlegible-700-latin.13a58e05dfd2.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;
}
@font-face {
  font-family: "IBM Plex Mono"; font-style: normal; font-weight: 500; font-display: swap;
  src: url("../fonts/ibm-plex-mono-500-latin-ext.fa8d8838b94a.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-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "IBM Plex Mono"; font-style: normal; font-weight: 500; font-display: swap;
  src: url("../fonts/ibm-plex-mono-500-latin.b1c8a895f5fd.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;
}
@font-face {
  font-family: "IBM Plex Mono"; font-style: normal; font-weight: 600; font-display: swap;
  src: url("../fonts/ibm-plex-mono-600-latin-ext.f2fe87d55f72.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-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "IBM Plex Mono"; font-style: normal; font-weight: 600; font-display: swap;
  src: url("../fonts/ibm-plex-mono-600-latin.5a2ce7798732.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;
}

* { box-sizing: border-box; }
/* Barre di scorrimento di tutto il sito: sottili, a pillola su fondo
   trasparente (come nei popup delle pose). Quella normale è una striscia piena
   che sui pannelli arrotondati fa sembrare squadrato il bordo. Chrome, Edge e
   Safari usano ::-webkit-scrollbar (ignorato se c'è scrollbar-width), Firefox
   scrollbar-width / scrollbar-color. */
::-webkit-scrollbar { width: 12px; height: 12px; background: transparent; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
  background: color-mix(in srgb, var(--ink) 28%, transparent); background-clip: padding-box;
  border: 3px solid transparent; border-radius: 999px;
}
/* margine trasparente solo ai lati: in cima alla pagina il cursore tocca il
   bordo superiore (con il margine anche in alto sembrava già sceso) */
::-webkit-scrollbar-thumb:vertical { border-width: 0 3px; }
::-webkit-scrollbar-thumb:horizontal { border-width: 3px 0; }
::-webkit-scrollbar-thumb:hover { background-color: color-mix(in srgb, var(--ink) 42%, transparent); }
::-webkit-scrollbar-corner { background: transparent; }
@supports not selector(::-webkit-scrollbar) {
  * { scrollbar-width: thin; scrollbar-color: color-mix(in srgb, var(--ink) 28%, transparent) transparent; }
}
/* Pagina, popup e pannelli: la barra del browser è nascosta e al suo posto
   c'è un cursore a scomparsa, disegnato sopra il contenuto da
   core/scrollbar.js (stesso elenco in SCROLLERS). Non occupando spazio, quando
   compare o sparisce non sposta più né i contenuti né lo sfondo. Le regole
   qui sopra restano per tutto il resto (es. le aree di testo). */
html, .panel, .side, .table-wrap { scrollbar-width: none; }
:is(html, body, .panel, .side, .table-wrap)::-webkit-scrollbar { display: none; }
/* Con un popup aperto la pagina sotto non scorre (classe messa da
   lockPageScroll in core/scrollbar.js): né arrivando in fondo al popup, né con
   il mouse fuori. Non essendoci la barra del browser, bloccarla non sposta nulla. */
html.scroll-lock { overflow: hidden; }
.panel { overscroll-behavior: contain; }
/* .sbar è la fascia (posizione e lunghezza da core/scrollbar.js), .sbar__thumb
   il cursore: una pillola un po' trasparente, senza sfocatura. Acceso, il
   cursore eredita la visibilità ("inherit" e non "visible"): dentro un popup
   chiuso, che è nascosto con visibility, resta nascosto anche lui. La fascia
   dentro un popup entra ed esce insieme al pannello (motion.css, sezione 6). */
.sbar { position: absolute; z-index: 3; pointer-events: none; }
.sbar--y { width: 10px; }
.sbar--x { height: 10px; }
.sbar--page { position: fixed; z-index: 60; }
.sbar--page.sbar--y { top: 4px; bottom: 4px; right: 2px; }
.sbar--page.sbar--x { left: 4px; right: 4px; bottom: 2px; }
.sbar.is-off { display: none; }
.sbar__thumb {
  position: absolute; border-radius: 999px; cursor: default;
  background: rgba(128, 128, 128, .55);
  background: color-mix(in srgb, var(--ink) 40%, transparent);
  border: 1px solid color-mix(in srgb, var(--surface) 35%, transparent);
  opacity: 0; visibility: hidden; pointer-events: auto; touch-action: none;
  -webkit-user-select: none; user-select: none;
}
.sbar--y .sbar__thumb { top: 0; right: 0; width: 6px; transform-origin: 100% 50%; }
.sbar--x .sbar__thumb { left: 0; bottom: 0; height: 6px; transform-origin: 50% 100%; }
/* area di presa più larga del cursore */
.sbar__thumb::before { content: ""; position: absolute; inset: -2px -3px -2px -8px; }
.sbar--x .sbar__thumb::before { inset: -8px -2px -3px; }
.sbar.is-on .sbar__thumb { opacity: 1; visibility: inherit; }
.sbar__thumb:hover, .sbar.is-drag .sbar__thumb { background: color-mix(in srgb, var(--ink) 58%, transparent); }
.sbar--y .sbar__thumb:hover, .sbar--y.is-drag .sbar__thumb { scale: 1.5 1; }
.sbar--x .sbar__thumb:hover, .sbar--x.is-drag .sbar__thumb { scale: 1 1.5; }
html, body { min-height: 100%; }
body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font);
  font-size: 17px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}
/* Sfondo della pagina, uno per tema (static/palestria/img). Fermo dietro a
   tutto mentre la pagina scorre e ritagliato per coprire lo schermo: le
   decorazioni restano negli angoli. Strato fisso e non "background-attachment:
   fixed" (che a ogni scorrimento ridisegna tutta la pagina e sui telefoni non
   funziona). Al cambio di tema sfuma con il resto della pagina: la dissolvenza
   di core/theme.js (View Transitions) riguarda tutto ciò che si vede.
   Il colore --bg resta sotto finché l'immagine non è caricata. */
body::before {
  content: ""; position: fixed; inset: 0; z-index: -1; pointer-events: none;
  background: var(--bg-image) center / cover no-repeat;
}
/* nelle sezioni un poco ingrandito (animazione in motion.css, sezione 15b) */
html.bg-section body::before { scale: 1.06; }
/* Sfondo sfocato: uno strato sopra quello nitido, con la stessa immagine
   sfocata e un velo del colore del tema. C'è solo quando serve: nella pagina
   di accesso (bg-blurred), mentre svanisce appena entrati (bg-unblur) e mentre
   compare uscendo (is-leaving); classi messe da base.html e core/common.js,
   animazioni in motion.css 15c. Si anima la trasparenza dello strato, non il
   raggio della sfocatura (molto più leggero). Sporge dai bordi: una sfocatura
   lascerebbe i margini trasparenti. */
html:is(.bg-blurred, .bg-unblur, .is-leaving) body::after {
  content: ""; position: fixed; inset: -48px; z-index: -1; pointer-events: none;
  background:
    linear-gradient(color-mix(in srgb, var(--bg) 28%, transparent), color-mix(in srgb, var(--bg) 28%, transparent)),
    var(--bg-image) center / cover no-repeat;
  filter: blur(22px) saturate(1.25);
}
html.bg-unblur body::after { opacity: 0; }
/* animazioni ridotte: niente sfocatura, solo il velo; spente: niente */
html.perf-noblur:is(.bg-blurred, .bg-unblur, .is-leaving) body::after { filter: none; background: color-mix(in srgb, var(--bg) 55%, transparent); }
html.perf-off body::after { content: none !important; }
a { color: var(--primary-text); }
a:hover { color: var(--primary-hover); }
h1, h2, h3 { line-height: 1.15; margin: 0; }
p { margin: 0; }
svg { flex: none; }
.muted { color: var(--muted); }
.mono { font-family: var(--mono); }
.num { font-variant-numeric: tabular-nums; }
.hidden { display: none !important; }
.visually-hidden { position: absolute !important; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
:focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; }

/* ---------- Intestazione dell'app ---------- */
/* Barra semitrasparente su vetro sfocato, sempre (anche con la pagina in cima):
   lascia intravedere lo sfondo della pagina e il contenuto che le scorre sotto.
   Quando la pagina scorre (core/common.js) compare anche un'ombra leggera. */
.app-header {
  position: sticky; top: 0; z-index: 30;
  background: var(--glass-soft);
  border-bottom: 1px solid color-mix(in srgb, var(--line) 60%, transparent);
  -webkit-backdrop-filter: var(--glass-blur);
          backdrop-filter: var(--glass-blur);
  transition: background-color calc(.2s * var(--fx-k, 1)) ease, box-shadow calc(.2s * var(--fx-k, 1)) ease, border-color calc(.2s * var(--fx-k, 1)) ease;
}
.app-header.is-scrolled { box-shadow: 0 6px 24px rgba(0, 0, 0, .08); }
:root[data-theme="dark"] .app-header.is-scrolled { box-shadow: 0 6px 24px rgba(0, 0, 0, .35); }
@supports not (((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) and (background-color: color-mix(in srgb, red 50%, transparent))) {
  .app-header { background: var(--surface); border-bottom-color: var(--line); }
}
.app-header__inner {
  display: flex; align-items: center; gap: 16px; flex-wrap: wrap;
  padding: 12px 24px;
}
.app-header--doc .app-header__inner { max-width: 1280px; margin: 0 auto; padding: 16px 32px; }
.app-header__title { min-width: 0; }
.app-header__title h1 { font-size: 24px; font-weight: 700; }
.app-header__title p { font-size: 14px; color: var(--muted); }
.app-header__status { margin-left: auto; display: flex; gap: 10px; flex-wrap: wrap; align-items: center; }

/* Benvenuto appena entrati (core/common.js, playWelcome): la barra è più alta
   (html.welcome-tall, messa da base.html prima del primo disegno) e la
   scritta, grande, sta al suo centro con una riga sotto, sopra gli elementi
   ancora nascosti (html.welcoming). Poi il nome vola sul pulsante dell'utente
   mentre la barra si abbassa fino alla sua altezza di sempre (lo anima
   playWelcome, tra le due altezze). Il saluto e ogni
   lettera del nome sono riquadri a sé (inline-block), altrimenti non si
   potrebbero spostare. Per chi ha un ruolo la riga è in due metà che si
   allargano dal centro, con in mezzo il suo distintivo (.role-badge, più
   sotto) in grande, e dorate anche loro per l'amministratore. Per gli esterni
   è una riga sola, intera. Stesso elenco di HEADER_STAGGER. */
html.welcome-tall .app-header__inner { min-height: 152px; }
.welcome { position: absolute; inset: 0; z-index: 1; display: flex; align-items: center; justify-content: center; pointer-events: none; }
.welcome__stack { display: inline-flex; flex-direction: column; align-items: stretch; gap: 10px; }
.welcome__text { font-size: clamp(26px, 4.6vw, 42px); font-weight: 700; white-space: nowrap; text-align: center; }
.welcome__hi, .welcome__ch { display: inline-block; }
.welcome__rule { --welcome-accent: var(--primary); display: flex; align-items: center; }
.welcome__rule--admin { --welcome-accent: var(--warn-text); }
.welcome__line { flex: 1; min-width: 24px; height: 3px; border-radius: 3px; }
.welcome__line--l { background: linear-gradient(90deg, transparent, var(--welcome-accent)); transform-origin: 100% 50%; }
.welcome__line--r { background: linear-gradient(90deg, var(--welcome-accent), transparent); transform-origin: 0 50%; }
/* senza distintivo (gli esterni): una riga sola, intera, che si allarga dal suo centro */
.welcome__line--full { background: linear-gradient(90deg, transparent, var(--welcome-accent), transparent); }
.welcome .role-badge { margin: 0 12px; font-size: 13px; }
/* Distintivo del ruolo (_user_button.html): nella barra in alto della home,
   accanto al pulsante dell'utente, e in grande nel benvenuto. Dorato per
   l'amministratore, verde per il dipendente NAPS Lab. Tutte le misure seguono
   la grandezza della scritta (em): quello del benvenuto è lo stesso, solo più
   grande, e può rimpicciolirsi fino a coincidere con questo. */
.role-badge {
  position: relative; overflow: hidden; flex: none;
  display: inline-flex; align-items: center; gap: .55em; height: 2.15em; padding: 0 1em 0 .77em; border-radius: 999px;
  font-size: 11px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase; white-space: nowrap;
  background: var(--ok-tint); color: var(--ok-ink); border: 1px solid color-mix(in srgb, var(--ok-ink) 35%, transparent);
}
.role-badge svg { width: 1.25em; height: 1.25em; flex: none; }
.role-badge--referent { background: var(--info-tint); color: var(--info-ink); border-color: color-mix(in srgb, var(--info-ink) 35%, transparent); }
.role-badge--admin { background: var(--warn-tint); color: var(--warn-ink); border-color: color-mix(in srgb, var(--warn-text) 55%, transparent); }
/* il riflesso che attraversa il distintivo dell'amministratore nel benvenuto: fuori dal bordo finché non parte (motion.css) */
.role-badge--admin::after {
  content: ""; position: absolute; inset: 0; translate: -130% 0;
  background: linear-gradient(105deg, transparent 30%, color-mix(in srgb, #FFFFFF 60%, transparent) 50%, transparent 70%);
}
@media (max-width: 640px) { html.welcome-tall .app-header__inner { min-height: 116px; } }
.welcome__name { color: var(--primary-text); }
html.welcoming :is(.app-header__inner > :not(.brand-group, .app-header__status), .app-header .brand-group > *, .app-header__status > *) { opacity: 0; }

.brand { display: flex; align-items: center; gap: 12px; color: var(--ink); text-decoration: none; }
.brand:hover { color: var(--ink); }
.brand__mark {
  width: 44px; height: 44px; border-radius: 12px; background: var(--primary); color: var(--primary-ink);
  display: flex; align-items: center; justify-content: center;
}
.brand__name { font-weight: 700; font-size: 22px; line-height: 1.1; }
.brand__sub { font-size: 14px; color: var(--muted); }
.brand-group { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; }
/* Logo NAPS Lab senza riquadro, in due livelli (static/palestria/img):
   "·lab" petrolio è l'immagine; "naps" è una maschera colorata con --ink,
   quindi scuro nel tema chiaro e chiaro nel tema scuro (nell'originale è
   bianco e su fondo chiaro non si leggerebbe). Le due immagini hanno la
   stessa tela, quindi la maschera copre esattamente l'immagine. */
.naps-logo { position: relative; display: inline-flex; flex: none; }
.naps-logo img { height: 28px; width: auto; display: block; }
.naps-logo::before {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: var(--ink);
  -webkit-mask: url("../img/naps-logo-naps.d8de3560b9ad.webp") center / 100% 100% no-repeat;
          mask: url("../img/naps-logo-naps.d8de3560b9ad.webp") center / 100% 100% no-repeat;
}
@media (forced-colors: active) {
  .naps-logo::before { background: CanvasText; forced-color-adjust: none; }
}

/* ---------- Pulsanti ---------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  min-height: 48px; padding: 0 20px;
  border-radius: var(--radius-sm); border: 1px solid var(--line);
  background: var(--surface); color: var(--ink);
  font: 700 17px var(--font); text-decoration: none; cursor: pointer;
  transition: background-color .15s ease, border-color .15s ease, transform .06s ease;
}
.btn:hover { border-color: var(--muted); color: var(--ink); }
/* pressione dei pulsanti: vedi motion.css (usa 'scale', che non tocca il 'transform' degli elementi centrati) */
.btn[disabled] { opacity: .5; cursor: not-allowed; transform: none; }
.btn-primary { background: var(--primary); border-color: var(--primary); color: var(--primary-ink); }
.btn-primary:hover { background: var(--primary-hover); border-color: var(--primary-hover); color: var(--primary-ink); }
.btn-outline { background: transparent; border: 2px solid var(--primary); color: var(--primary-text); }
.btn-outline:hover { background: var(--tint); color: var(--primary-text); border-color: var(--primary); }
.btn-danger { background: var(--rec); border-color: var(--rec); color: #FFFFFF; }
.btn-danger:hover { filter: brightness(1.08); color: #FFFFFF; border-color: var(--rec); }
.btn-sm { min-height: 44px; padding: 0 16px; font-size: 15px; border-radius: 10px; }
.btn-lg { min-height: 56px; font-size: 18px; }
.btn-block { width: 100%; }
.btn-back { min-height: 44px; padding: 0 14px; border-radius: 10px; font-size: 16px; }
.btn-icon { width: 44px; padding: 0; }
/* Pallino nel pulsante di registrazione: cerchio = avvia, quadrato = ferma */
#recBtn::before { content: ""; width: 13px; height: 13px; border-radius: 50%; background: currentColor; }
#recBtn.btn-danger::before { border-radius: 3px; }

/* ---------- Chip di stato ---------- */
.chip {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 6px 12px; border-radius: 999px;
  background: var(--surface-2); color: var(--ink-2);
  font-weight: 700; font-size: 15px; white-space: nowrap;
}
.chip-ok { background: var(--ok-tint); color: var(--ok-ink); }
.chip-warn { background: var(--warn-tint); color: var(--warn-ink); }
.chip-rec { background: var(--rec-tint); color: var(--rec-ink); }
.chip-info { background: var(--info-tint); color: var(--info-ink); }
/* tipo di account "Referente" (pagina Utenti): viola, per distinguerlo da amministratore (azzurro) e dipendente (verde) */
.chip-referent { background: #ECE6F8; color: #4A2D91; }
:root[data-theme="dark"] .chip-referent { background: #2A2145; color: #D9CCF7; }
.chip-sm { font-size: 13px; padding: 4px 10px; }
.chip .dot { width: 10px; height: 10px; border-radius: 50%; background: currentColor; }
.rec-chip { display: none; }
body.is-recording .rec-chip { display: inline-flex; }
body.is-recording .rec-chip .dot { animation: blink 1s steps(2) infinite; }
.badge { display: inline-block; padding: 2px 10px; border-radius: 999px; font-size: 13px; font-weight: 700; background: var(--surface-2); color: var(--ink-2); vertical-align: middle; }
.badge.beta { background: var(--warn-tint); color: var(--warn-ink); }

/* ---------- Selettore del tema ---------- */
.seg {
  display: inline-grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); gap: 4px;
  padding: 4px; background: var(--surface-2); border: 1px solid var(--line); border-radius: var(--radius-sm);
}
.seg button {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  min-height: 40px; padding: 0 12px; border: none; border-radius: 9px;
  background: transparent; color: var(--muted);
  font: 700 14px var(--font); cursor: pointer; white-space: nowrap;
}
.seg button:hover { color: var(--ink); }
.seg button[aria-pressed="true"], .seg button[aria-checked="true"], .seg button[aria-selected="true"] {
  background: var(--surface); color: var(--primary-text); box-shadow: 0 1px 3px rgba(0,0,0,.18);
}
.seg-block { display: grid; width: 100%; }
/* I pulsanti e la pillola hanno uno z-index (motion.css): restano dentro il
   loro controllo, senza finire sopra ciò che gli passa davanti (es. la barra
   delle schede delle impostazioni, agganciata in cima al popup). */
.seg { isolation: isolate; }

/* Controllo a segmenti ripiegato (core/segmented.js, .seg--fold): un pulsante
   solo, con il nome della scelta e il valore attuale (.seg__face), che al clic
   apre un popup con le opzioni (.optpop, qui sotto). Le opzioni vere restano
   nel gruppo, nascoste: il pulsante copre esattamente il loro posto. */
.seg--fold { position: relative; }
.seg > .seg__face {
  position: absolute; inset: 4px; z-index: 2; min-height: 0;
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 0 12px 0 14px; border-radius: 9px;
  background: var(--surface); color: var(--ink); box-shadow: 0 1px 3px rgba(0, 0, 0, .18);
  font-size: 15px; text-align: left;
}
.seg__face-title { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.seg__face-value { flex: none; display: inline-flex; align-items: center; gap: 6px; font-size: 14px; color: var(--primary-text); }
/* due frecce, su e giù: apre un elenco */
.seg__face-value::after {
  content: ""; width: 14px; height: 14px; flex: none; background: var(--muted);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M7 9.5l5-5 5 5M7 14.5l5 5 5-5'/%3E%3C/svg%3E") center / contain no-repeat;
          mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M7 9.5l5-5 5 5M7 14.5l5 5 5-5'/%3E%3C/svg%3E") center / contain no-repeat;
}
/* le opzioni non si vedono, non si premono e non si raggiungono con Tab: si scelgono dal popup */
.seg--fold > button:not(.seg__face) { visibility: hidden; opacity: 0; pointer-events: none; }
.seg--fold > .seg__pill { opacity: 0 !important; }  /* vince sullo stile messo da segmented.js */
/* con il popup aperto il pulsante resta evidenziato */
.seg--fold.is-open > .seg__face { box-shadow: 0 0 0 2px var(--primary); }

/* Popup delle opzioni di un controllo ripiegato: un piccolo menu di vetro, con
   l'alone, come gli altri popup (.glass-host). Uno solo per pagina, creato e
   messo in posizione da core/segmented.js: fissa rispetto alla finestra, sotto
   o sopra (optpop--up) il controllo. Dentro un altro popup (Impostazioni,
   Controlli) basta stare sopra il suo pannello; altrimenti sopra tutta la
   pagina. Animazioni in motion.css, sezione 3b. */
.optpop { --glass-radius: 16px; position: fixed; z-index: 55; }
:is(.popover, .modal) > .optpop { z-index: 10; }
.optpop:not(.show) { visibility: hidden; pointer-events: none; }
.optpop > .panel {
  width: 100%; max-height: none; overflow: hidden;
  padding: 8px; gap: 2px; border-radius: 16px;
}
.optpop__title { padding: 6px 12px 4px; font-size: 12px; font-weight: 700; letter-spacing: 1px; text-transform: uppercase; color: var(--muted); }
.optpop__item {
  display: flex; align-items: center; gap: 10px; width: 100%; min-height: 44px; padding: 0 12px;
  border: none; border-radius: 10px; background: transparent; color: var(--ink);
  font: 700 15px var(--font); text-align: left; cursor: pointer;
}
.optpop__item svg { color: var(--muted); }
.optpop__label { flex: 1; min-width: 0; }
/* segno di spunta sulla voce scelta */
.optpop__item::after {
  content: ""; width: 18px; height: 18px; flex: none; background: currentColor; opacity: 0;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12.5l4.5 4.5L19 7.5'/%3E%3C/svg%3E") center / contain no-repeat;
          mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12.5l4.5 4.5L19 7.5'/%3E%3C/svg%3E") center / contain no-repeat;
}
.optpop__item[aria-selected="true"] { background: var(--tint); color: var(--primary-text); }
.optpop__item[aria-selected="true"]::after { opacity: 1; }
.optpop__item[aria-selected="true"] svg { color: inherit; }
@media (hover: hover) and (pointer: fine) {
  .optpop__item:not([aria-selected="true"]):hover { background: color-mix(in srgb, var(--ink) 9%, transparent); }
}
.optpop__item:focus-visible { outline-offset: -3px; }

/* ---------- Pagine "documento" ---------- */
.container { max-width: 1280px; margin: 0 auto; padding: 40px 32px 64px; display: flex; flex-direction: column; gap: 40px; }
.container-narrow { max-width: 760px; }
.hero { display: flex; flex-wrap: wrap; gap: 24px; align-items: flex-end; justify-content: space-between; }
.hero h1 { font-size: clamp(32px, 4.5vw, 48px); letter-spacing: -0.5px; margin-bottom: 10px; }
.hero p { font-size: 20px; color: var(--muted); max-width: 720px; }
.section { display: flex; flex-direction: column; gap: 16px; }
.section-title { font-size: 15px; letter-spacing: 1.5px; text-transform: uppercase; color: var(--muted); font-weight: 700; }

.tiles { display: grid; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); gap: 16px; }
.tiles-wide { grid-template-columns: repeat(auto-fill, minmax(min(100%, 500px), 1fr)); }
.tile {
  position: relative;
  display: flex; flex-direction: column; gap: 14px; min-height: 196px; padding: 24px;
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius);
  color: var(--ink); text-decoration: none; text-align: left; font: inherit;
  transition: translate calc(.22s * var(--fx-k, 1)) cubic-bezier(.2, .7, .2, 1);
}
/* Bordo colorato e ombra del passaggio del mouse disegnati su uno strato a
   parte (::after) di cui si anima solo la trasparenza: prima la transizione di
   border-color e box-shadow ridisegnava tutta la scheda, testo compreso, a
   ogni fotogramma. */
.tile::after {
  content: ""; position: absolute; inset: -1px; border-radius: inherit; pointer-events: none;
  border: 1px solid var(--primary); box-shadow: var(--shadow);
  opacity: 0; transition: opacity calc(.2s * var(--fx-k, 1)) ease;
}
.tile.disabled::after { content: none; }
/* Il sollevamento al passaggio del mouse solo con un mouse vero: sugli schermi
   touch l'hover "resta attaccato" dopo il tocco. */
@media (hover: hover) and (pointer: fine) {
  a.tile:hover, button.tile:hover { color: var(--ink); translate: 0 -2px; }
  a.tile:hover::after, button.tile:hover::after { opacity: 1; }
  /* scheda di DigitalMenti: l'arcobaleno al posto del bordo verde */
  a.tile--rainbow:is(:hover, :focus-visible)::before { opacity: 1; scale: 1; will-change: opacity, scale; }
  a.tile--rainbow:hover::after { border-color: transparent; }
}
.tile__top { display: flex; align-items: center; justify-content: space-between; }
.tile__icon {
  width: 56px; height: 56px; border-radius: 14px; background: var(--tint); color: var(--primary-text);
  display: flex; align-items: center; justify-content: center;
}
.tile__go { font-size: 14px; font-weight: 700; color: var(--primary-text); }
.tile__title { font-size: 22px; font-weight: 700; }
.tile__text { color: var(--muted); }
.tile__tags { display: flex; gap: 8px; flex-wrap: wrap; margin-top: auto; }
.tag { font-size: 13px; padding: 4px 10px; border-radius: 999px; background: var(--surface-2); color: var(--ink-2); }
.tile.disabled { background: transparent; border-color: color-mix(in srgb, var(--line) 60%, transparent); color: var(--disabled-ink); }
/* scheda "in arrivo" e piè di pagina: vetro sfocato sopra lo sfondo della pagina */
@supports ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) and (background-color: color-mix(in srgb, red 50%, transparent)) {
  .tile.disabled, .footer {
    background: color-mix(in srgb, var(--glass-tint) 30%, transparent);
    -webkit-backdrop-filter: var(--glass-blur);
            backdrop-filter: var(--glass-blur);
  }
}
html.perf-noblur :is(.tile.disabled, .footer) { -webkit-backdrop-filter: none; backdrop-filter: none; background: color-mix(in srgb, var(--surface) 70%, transparent); }
.tile.disabled .tile__icon { background: var(--disabled-bg); color: var(--disabled-ink); }
.tile.disabled .tile__text { color: var(--disabled-ink); }
/* Scheda di DigitalMenti (3.6): passandoci sopra, dietro si accende un
   arcobaleno sfocato con i colori dei personaggi dello Specchio delle
   espressioni (digitalmenti/mascots.js). È uno strato a parte (::before) che
   sporge un poco dalla scheda: dentro, sotto un velo del colore della scheda,
   fa da vetro colorato; fuori fa da alone. Come per il bordo (::after) si
   animano solo trasparenza e scala. Con le sfocature spente diventa una
   cornice arcobaleno dentro la scheda. */
.tile--rainbow { isolation: isolate; }
.tile--rainbow::before {
  --veil: color-mix(in srgb, var(--surface) 58%, transparent);
  content: ""; position: absolute; inset: -14px; z-index: -1; pointer-events: none;
  border-radius: calc(var(--radius) + 14px);
  background:
    linear-gradient(var(--veil), var(--veil)) center / calc(100% - 28px) calc(100% - 28px) no-repeat,
    radial-gradient(circle at 8% 22%, #FFC83D, transparent 40%),
    radial-gradient(circle at 34% 92%, #F0533F, transparent 42%),
    radial-gradient(circle at 62% 10%, #9B6BE0, transparent 42%),
    radial-gradient(circle at 92% 72%, #4D8FE8, transparent 42%),
    linear-gradient(105deg, #FF8D3F, #F0533F 25%, #9B6BE0 50%, #4D8FE8 75%, #57C26A);
  filter: blur(18px) saturate(1.15);
  opacity: 0; scale: .94;
  transition: opacity calc(.3s * var(--fx-k, 1)) ease, scale calc(.45s * var(--fx-k, 1)) cubic-bezier(.2, .7, .2, 1);
}
html.perf-noblur .tile--rainbow::before {
  --veil: color-mix(in srgb, var(--surface) 80%, transparent);
  inset: 0; border-radius: inherit; filter: none;
  background-size: calc(100% - 8px) calc(100% - 8px), auto, auto, auto, auto, auto;
}

/* Schede della home che si aprono al passaggio del mouse (o con il focus da tastiera):
   a riposo icona + titolo; poi l'icona esce verso l'alto, il titolo sale e sotto
   compaiono descrizione ed etichette. Sui dispositivi touch restano sempre aperte.

   Come è fatto: icona, titolo e descrizione sono impaginati UNA volta nella
   posizione finale (scheda aperta); a riposo il titolo è spostato in basso e la
   descrizione è trasparente, solo con transform. Durante l'animazione cambiano
   quindi solo transform e opacity: niente ricalcolo dell'impaginazione e niente
   ridisegno del testo (prima si animava grid-template-rows: impaginazione e
   testo ricalcolati a ogni fotogramma, da qui gli scatti). */
.tile--reveal .tile__go { position: absolute; top: 24px; right: 24px; }
.tile__more-inner { display: flex; flex-direction: column; gap: 12px; }
.tile--reveal .tile__tags { margin-top: 0; }
@media (hover: hover) and (pointer: fine) {
  .tiles--reveal { grid-auto-rows: 208px; }
  .tiles--reveal .tile.disabled { justify-content: space-between; }
  .tile--reveal {
    --reveal-ease: cubic-bezier(.2, .7, .2, 1);
    /* contenuto alto 158px (208 - bordi - padding); titolo alto 33px, 14px sotto
       il margine superiore: a riposo scende di 158 - 33 - 14 = 111px, fino al fondo */
    --title-drop: 111px;
    height: 208px; gap: 0; contain: layout;
  }
  .tile--reveal .tile__lead { position: absolute; top: 24px; left: 24px; }
  .tile--reveal .tile__title {
    margin-top: 14px; line-height: 33px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
    transform: translate3d(0, var(--title-drop), 0);
  }
  /* la descrizione occupa lo spazio rimasto e non esce mai dalla scheda */
  .tile--reveal .tile__more { flex: 1 1 0; min-height: 0; overflow: hidden; }
  .tile--reveal .tile__more-inner { padding-top: 10px; opacity: 0; transform: translate3d(0, 14px, 0); }
  .tile--reveal .tile__go { opacity: 0; transform: translate3d(-6px, 0, 0); }
  .tile--reveal .tile__lead, .tile--reveal .tile__title, .tile--reveal .tile__more-inner {
    transition: opacity calc(var(--reveal-fade, .25s) * var(--fx-k, 1)) ease, transform calc(var(--reveal-dur, .38s) * var(--fx-k, 1)) var(--reveal-ease);
  }
  .tile--reveal .tile__go { transition: opacity calc(.2s * var(--fx-k, 1)) ease, transform calc(.25s * var(--fx-k, 1)) ease; }

  .tile--reveal:is(:hover, :focus-visible) .tile__lead { opacity: 0; transform: translate3d(0, -16px, 0); }
  .tile--reveal:is(:hover, :focus-visible) .tile__title { transform: none; }
  .tile--reveal:is(:hover, :focus-visible) .tile__more-inner { opacity: 1; transform: none; transition-delay: calc(.06s * var(--fx-k, 1)); }
  .tile--reveal:is(:hover, :focus-visible) .tile__go { opacity: 1; transform: none; }
  /* strati del compositore solo per la scheda aperta, non per tutte sempre */
  .tile--reveal:is(:hover, :focus-visible) :is(.tile__lead, .tile__title, .tile__more-inner) { will-change: transform, opacity; }
}

.game-card { display: flex; gap: 20px; padding: 24px; background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius); flex-wrap: wrap; }
.game-card__art { width: 120px; height: 120px; border-radius: 16px; background: var(--stage); display: flex; align-items: center; justify-content: center; flex: none; }
.game-card__body { flex: 1 1 220px; display: flex; flex-direction: column; gap: 10px; }
.game-card__body .btn { align-self: flex-start; margin-top: auto; }

/* piè di pagina: riquadro con contorno, su vetro sfocato come la scheda "in arrivo" (più sopra) */
.footer {
  display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 12px;
  padding: 14px 20px; border: 1px solid color-mix(in srgb, var(--line) 60%, transparent); border-radius: var(--radius);
  font-size: 14px; color: var(--muted);
}

/* ---------- Card e pannelli ---------- */
.card {
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 20px; display: flex; flex-direction: column; gap: 14px;
}
.card-title { font-weight: 700; font-size: 17px; display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.card-rec { border: 2px solid var(--line); }
body.is-recording .card-rec { border-color: var(--rec-line); }
.label-caps { font-size: 13px; font-weight: 700; letter-spacing: 1px; text-transform: uppercase; color: var(--muted); }
.big-number { font-size: clamp(72px, 8vw, 112px); font-weight: 700; line-height: .95; font-variant-numeric: tabular-nums; }
.mid-number { font-size: clamp(40px, 4vw, 56px); font-weight: 700; line-height: 1; font-variant-numeric: tabular-nums; }

.table-wrap { overflow-x: auto; background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius); }
table.data { width: 100%; border-collapse: collapse; font-size: 16px; }
table.data th, table.data td { padding: 14px 14px; border-bottom: 1px solid var(--line-soft); text-align: left; vertical-align: middle; }
table.data tr:last-child td { border-bottom: none; }
table.data th { color: var(--muted); font-weight: 700; font-size: 13px; text-transform: uppercase; letter-spacing: 1px; border-bottom-color: var(--line); }
table.data td.r, table.data th.r { text-align: right; }
table.data tr[data-href] { cursor: pointer; }  /* riga cliccabile (Sessioni registrate) */
table.kv th { width: 180px; text-transform: none; letter-spacing: 0; font-size: 15px; }
pre.json { white-space: pre-wrap; margin: 0; font: 13px/1.5 var(--mono); color: var(--ink-2); }
/* Elenco di voci "nome: valore" (dati di una sessione): come la tabella .kv,
   ma senza essere una tabella, così può stare anche dentro una riga di un'altra. */
.kv-list { margin: 0; background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius); }
.kv-list > div { display: grid; grid-template-columns: 180px minmax(0, 1fr); gap: 4px 14px; padding: 14px; border-bottom: 1px solid var(--line-soft); }
.kv-list > div:last-child { border-bottom: none; }
.kv-list dt { color: var(--muted); font-weight: 700; font-size: 15px; }
.kv-list dd { margin: 0; min-width: 0; overflow-wrap: anywhere; }
@media (max-width: 640px) { .kv-list > div { grid-template-columns: minmax(0, 1fr); } }

/* ---------- Form ---------- */
.field { display: flex; flex-direction: column; gap: 6px; }
.field > label, .field > .label { font-size: 14px; color: var(--muted); }
input[type=text], input[type=number], input[type=password], select, textarea {
  width: 100%; min-height: 48px; padding: 10px 12px; border-radius: 10px;
  background: var(--surface); color: var(--ink);
  border: 1px solid var(--line); font: 16px var(--font); outline: none;
}
textarea { min-height: 72px; resize: vertical; }
input:focus, select:focus, textarea:focus { border-color: var(--primary); box-shadow: 0 0 0 3px var(--tint); }
input[type=checkbox] { width: 22px; height: 22px; accent-color: var(--primary); margin: 0; }
.check { display: inline-flex; align-items: center; gap: 10px; font-weight: 700; cursor: pointer; }
.row { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.row > .field { flex: 1 1 140px; }
/* campi uno sotto l'altro, a tutta larghezza (es. pannello laterale di registrazione) */
.field-stack { display: flex; flex-direction: column; gap: 12px; }
.error-text { color: var(--rec-ink); font-weight: 700; }
.panel p.error-text { color: var(--rec-ink); }  /* nei popup i paragrafi sono grigi: gli errori no */

/* ---------- Moduli "vivi": accesso, nuovo utente ---------- */
/* Moduli inviati senza cambiare pagina, con l'esito animato (pages/login.js,
   pages/users.js; animazioni in motion.css 15c): live-form sul modulo,
   live-submit sul pulsante (con dentro live-spinner), live-error sul messaggio
   sotto. --live-gap: lo spazio tra gli elementi del modulo. */
.live-form { --live-gap: 18px; }
/* il pulsante con la sua rotellina (compare dopo l'invio) */
.live-submit { gap: 12px; }
.live-spinner {
  display: none; width: 18px; height: 18px; flex: none; border-radius: 50%;
  border: 2.5px solid color-mix(in srgb, currentColor 30%, transparent); border-top-color: currentColor;
  animation: spin .8s linear infinite;
}
.live-submit.is-loading { pointer-events: none; }
.live-submit.is-loading .live-spinner { display: block; }
/* dati non validi: rosso per 4 secondi, con la scossa di motion.css */
.live-submit.is-error, .live-submit.is-error:hover { background: var(--rec); border-color: var(--rec); color: #FFFFFF; box-shadow: none; translate: none; }
/* Messaggio sotto il pulsante: chiuso è alto zero e non lascia nemmeno lo
   spazio tra gli elementi del modulo (margine negativo = --live-gap); aperto,
   la riga della griglia passa da 0 a tutta la sua altezza e il modulo si
   allarga con lei. */
.live-error { display: grid; grid-template-rows: 0fr; margin-top: calc(-1 * var(--live-gap)); opacity: 0; text-align: center; }
.live-error > p { min-height: 0; overflow: hidden; }
.live-error.show { grid-template-rows: 1fr; margin-top: 0; opacity: 1; }
/* Finché i campi obbligatori (quelli con un segnaposto) non sono scritti tutti il pulsante è
   spento: grigio e sfocato (resta premibile: se manca qualcosa il browser lo
   dice). :placeholder-shown = campo vuoto. Nei browser senza :has resta acceso. */
.live-form:has(input:placeholder-shown) .live-submit:not(.is-error) {
  background: var(--disabled-bg); border-color: var(--disabled-line); color: var(--disabled-ink);
  filter: blur(1.6px); scale: .97; box-shadow: none; translate: none;
}
html.perf-noblur .live-form:has(input:placeholder-shown) .live-submit:not(.is-error) { filter: none; }

/* ---------- Popup aperto: il resto si rimpicciolisce ---------- */
/* Con un popup aperto sotto il suo pulsante (Impostazioni, Controlli, utente,
   "Nuovo utente", eliminazione: core/popover.js, shrinkPage) il resto
   dell'interfaccia si rimpicciolisce un poco: il contenuto della pagina tutto
   insieme, attorno al centro del suo bordo superiore, e gli elementi della
   barra in alto uno per uno (la barra, con il suo vetro, resta ferma). Non
   cambia il pulsante che ha aperto il popup (.pop-anchor): se sta dentro la
   pagina (il cestino di una riga) la pagina si rimpicciolisce attorno a lui
   (lo decide shrinkPage) e lui si ingrandisce di quanto lei si rimpicciolisce.
   Solo la scala, che non ricalcola l'impaginazione; il movimento è in
   motion.css. Gli elenchi sono quelli di PAGE (core/popover.js) e di
   HEADER_STAGGER (core/common.js). */
:root { --pop-shrink: .97; --pop-shrink-bar: .94; }
:is(body > main, body > .split, body > .stage-only) { transform-origin: 50% 0; }
html.pop-open :is(body > main, body > .split, body > .stage-only) { scale: var(--pop-shrink); }
html.pop-open :is(body > main, body > .split, body > .stage-only) .pop-anchor { scale: calc(1 / var(--pop-shrink)); }
html.pop-open :is(.app-header__inner > :not(.brand-group, .app-header__status), .app-header .brand-group > *, .app-header__status > *):not(.pop-anchor) { scale: var(--pop-shrink-bar); }
/* il cestino con il suo popup aperto resta acceso, come i pulsanti della barra */
.btn-trash.pop-anchor { background: var(--rec-tint); border-color: var(--rec-line); }

/* ---------- Pagine con un popup che mette a fuoco (focus-page) ---------- */
/* Utenti, Sessioni e scheda di una sessione: con il popup "Nuovo utente"
   (pages/users.js, html.is-creating) o un popup di eliminazione
   (core/delpop.js, html.is-deleting) aperto, il resto della pagina resta
   nitido (si rimpicciolisce soltanto, come con ogni popup: qui sopra) ma non
   si può premere: un clic fuori chiude solo il popup. Attorno al popup c'è
   l'alone sfocato di tutti i menu (.halo, più sotto). Resta premibile il
   pulsante "Nuovo utente", che richiude il suo popup. */
html.is-creating .focus-page :is(main, .app-header__inner > :not(.app-header__status), .app-header__status > *),
html.is-deleting .focus-page :is(main, .app-header) { pointer-events: none; }
.user-new { --live-gap: 14px; }
.user-new ul.rules { margin: 0; padding-left: 20px; display: flex; flex-direction: column; gap: 2px; }
/* Esito: un vetro verde sopra tutto il pannello, con la spunta e "Utente creato".
   Fratello del pannello: sfoca il modulo che ha sotto. */
.create-done {
  position: absolute; inset: 0; z-index: 4; border-radius: 20px; pointer-events: none;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 10px; text-align: center;
  background: color-mix(in srgb, var(--primary) 46%, transparent);
  border: 1px solid color-mix(in srgb, var(--primary) 70%, transparent);
  -webkit-backdrop-filter: blur(18px) saturate(1.7);
          backdrop-filter: blur(18px) saturate(1.7);
  color: var(--ink); opacity: 0; visibility: hidden;
}
html.perf-noblur .create-done { -webkit-backdrop-filter: none; backdrop-filter: none; background: color-mix(in srgb, var(--primary) 30%, var(--surface)); }
.create-pop.is-done .create-done { opacity: 1; visibility: visible; }
/* partito il volo verso l'elenco, al suo posto c'è la copia (.create-ghost): questo sparisce di colpo */
.create-pop.is-flying .create-done { opacity: 0; visibility: hidden; transition: none; }
.create-done__check {
  width: 72px; height: 72px; border-radius: 50%; display: flex; align-items: center; justify-content: center;
  background: var(--primary); color: var(--primary-ink); box-shadow: 0 8px 24px color-mix(in srgb, var(--primary) 55%, transparent);
}
.create-done__check path { stroke-dasharray: 1 1.1; }
.create-done__title { font-size: 24px; font-weight: 700; }
.create-done__name { font-size: 16px; }
/* Il vetro verde in volo verso la sua riga nell'elenco (pages/users.js): una
   copia identica a .create-done, fuori dal popup, che si sposta e cambia
   misura fino a coincidere con la riga. Sta sopra il popup che si chiude. */
.create-ghost {
  position: fixed; z-index: 46; pointer-events: none; overflow: hidden; border-radius: 20px;
  display: flex; align-items: center; justify-content: center;
  background: color-mix(in srgb, var(--primary) 46%, transparent);
  border: 1px solid color-mix(in srgb, var(--primary) 70%, transparent);
  -webkit-backdrop-filter: blur(18px) saturate(1.7);
          backdrop-filter: blur(18px) saturate(1.7);
  color: var(--ink);
}
html.perf-noblur .create-ghost { -webkit-backdrop-filter: none; backdrop-filter: none; background: color-mix(in srgb, var(--primary) 30%, var(--surface)); }
.create-ghost__inner { flex: none; display: flex; flex-direction: column; align-items: center; gap: 10px; text-align: center; }
/* Scheda che si apre sotto una riga di un elenco (core/rowdetail.js): quella
   di un utente (_user_detail.html) e i dati di una sessione
   (_session_detail.html). È una riga in più, che si allarga verso il basso.
   Chiusa è alta zero: la riga della griglia passa da 0 a tutta l'altezza del
   contenuto (motion.css). La freccia della riga gira quando è aperta. */
.row-chevron { margin-right: 8px; vertical-align: -2px; color: var(--muted); }
tr.is-open .row-chevron { rotate: 90deg; color: var(--primary-text); }
table.data tbody tr.is-open { background: var(--tint); }
table.data tbody tr.is-open td { border-bottom-color: transparent; }
table.data tbody tr.row-detail, table.data tbody tr.row-detail:hover { background: var(--surface-2); cursor: default; }
table.data tbody tr.row-detail > td { padding: 0; box-shadow: none !important; }
.row-detail__clip { display: grid; grid-template-rows: 0fr; }
.row-detail.show .row-detail__clip { grid-template-rows: 1fr; }
.row-detail__inner { min-height: 0; overflow: hidden; }
.user-detail__grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 340px), 1fr)); gap: 16px; align-items: start;
  padding: 18px 16px 0;
}
.user-detail__grid .card { --live-gap: 14px; }
.user-detail__grid ul.rules { margin: 0; padding-left: 20px; display: flex; flex-direction: column; gap: 2px; }
.user-detail__meta { padding: 12px 16px 16px; }
/* colonna di destra: il cambio della password e, sotto, il pulsante che attiva o disattiva l'account */
.user-detail__side { display: flex; flex-direction: column; gap: 16px; min-width: 0; }
.user-active { --live-gap: 10px; display: flex; flex-direction: column; gap: 10px; }
.user-active > p { text-align: center; }
.user-active .live-submit { scale: 1; }  /* largo quanto la scheda che ha sopra, non un poco di più */
/* dati di una sessione sotto la sua riga: i riquadri e, sotto, l'elenco delle voci */
.session-detail { display: flex; flex-direction: column; gap: 16px; padding: 18px 16px 16px; }
/* conferma verde sotto il pulsante ("Modifiche salvate"), nello stesso posto degli errori */
.live-error.is-ok .error-text { color: var(--ok-ink); }

/* Moduli da accendere (_module_tiles.html): i moduli che un utente può usare,
   come le schede della home ma in piccolo, tre per riga. Ogni riquadro è
   l'etichetta di una casella nascosta: spento è grigio, acceso è verde e un
   poco più grande (il movimento è in motion.css). */
.mod-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); grid-auto-rows: 1fr; gap: 10px; }
.mod-tile { position: relative; display: flex; cursor: pointer; -webkit-user-select: none; user-select: none; }
.mod-tile__face {
  flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 8px; padding: 10px;
  border-radius: 12px; border: 1px solid var(--disabled-line); background: var(--disabled-bg); color: var(--disabled-ink);
  font-size: 13px; font-weight: 700; line-height: 1.2;
}
.mod-tile__icon {
  width: 32px; height: 32px; flex: none; border-radius: 9px; display: flex; align-items: center; justify-content: center;
  background: color-mix(in srgb, currentColor 14%, transparent);
}
.mod-tile__name { overflow-wrap: anywhere; }
.mod-tile input:checked + .mod-tile__face { background: var(--primary); border-color: var(--primary); color: var(--primary-ink); scale: 1.05; }
.mod-tile input:focus-visible + .mod-tile__face { outline: 3px solid var(--focus); outline-offset: 2px; }
@media (hover: hover) and (pointer: fine) {
  .mod-tile:hover input:not(:checked) + .mod-tile__face { border-color: var(--muted); color: var(--ink-2); }
}

/* Pagina Utenti: tre elenchi separati (users.html). La tabella dei gruppi
   (_group_row.html) ha una riga per gruppo, con la colonna "Gruppo"; cliccata,
   sotto si apre l'elenco dei suoi membri (_group_detail.html), con la stessa
   riga che si allarga delle schede degli utenti (core/rowdetail.js), e lì ogni
   membro si apre sulla sua scheda. "Senza gruppo" è in fondo, in corsivo. */
table.data tr[hidden] { display: none !important; }
.groups-table .group-row__name { font-weight: 700; font-size: 17px; }
.group-detail { display: flex; flex-direction: column; gap: 12px; padding: 14px 16px 18px; }
.group-detail .table-wrap { box-shadow: var(--shadow); }
.group-detail__head { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
/* intestazione di una sezione della pagina Utenti: titolo e, a destra, il pulsante per aggiungere */
.section__head { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
/* il pulsante che ha aperto un popup resta premibile (lo richiude) anche con la pagina bloccata */
html.is-creating .focus-page .pop-anchor { pointer-events: auto; }
.new-user__group { font-size: 15px; }
/* Schede della pagina Utenti (users.html; pages/users.js, initTabs): un controllo a
   segmenti con la pillola che scivola, sopra la sezione aperta. La sezione che
   cambia si rimpicciolisce e torna grande attorno al centro del suo bordo alto.
   Scorrendo la pagina le schede restano in vista, appena sotto la barra in alto
   (--users-tabs-top: la sua altezza, misurata da pages/users.js). Come quelle
   delle impostazioni, quando si agganciano (is-compact) si rimpiccioliscono e
   diventano di vetro sfocato, staccate dal contenuto da un'ombra; tornando in
   cima riprendono il loro aspetto. */
.users-tabs { position: sticky; top: var(--users-tabs-top, 84px); z-index: 20; margin: 4px 0 22px; }
.users-tabs > .seg {
  transition: scale var(--dur-bounce, .4s) var(--ease-bounce, ease), background-color var(--dur-1, .15s) ease, box-shadow var(--dur-1, .15s) ease;
}
.users-tabs.is-compact > .seg {
  scale: .9;
  background: var(--glass-bar);
  border-color: color-mix(in srgb, var(--line) 80%, transparent);
  box-shadow: 0 10px 28px rgba(0, 0, 0, .14);
  -webkit-backdrop-filter: var(--glass-blur-bar);
          backdrop-filter: var(--glass-blur-bar);
}
:root[data-theme="dark"] .users-tabs.is-compact > .seg { box-shadow: 0 10px 28px rgba(0, 0, 0, .4); }
@supports not (((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) and (background-color: color-mix(in srgb, red 50%, transparent))) {
  .users-tabs.is-compact > .seg { background: var(--surface-2); }
}
html.perf-noblur .users-tabs.is-compact > .seg { -webkit-backdrop-filter: none; backdrop-filter: none; background: var(--surface-2); }
.users-tabs .seg button { min-height: 46px; font-size: 15px; }
.users-tabs .seg button svg { flex: none; }
.users-panel { transform-origin: 50% 0; }
.users-panel[hidden] { display: none; }
@media (max-width: 420px) {
  .users-tabs .seg button { padding: 0 6px; font-size: 14px; }
  .users-tabs .seg button svg { display: none; }
}
/* Elenco a parte dentro una sezione (membri senza gruppo, collaboratori senza accesso) */
.sublist { display: flex; flex-direction: column; gap: 10px; margin-top: 8px; }
.sublist[hidden] { display: none; }
.sublist__title { font-size: 15px; font-weight: 700; color: var(--ink-2); }

/* Menu a riquadri (_module_picker.html, _group_picker.html; core/picker.js): un
   pulsante con il nome della scelta e ciò che è acceso, come i controlli a
   segmenti ripiegati; cliccato, sotto si apre (la riga della griglia passa da 0
   a tutta l'altezza, come le schede che si aprono sotto una riga) con i
   riquadri da accendere. Chiuso, i riquadri non si raggiungono con Tab. */
.picker { padding: 4px; background: var(--surface-2); border: 1px solid var(--line); border-radius: var(--radius-sm); }
.picker__face {
  display: flex; align-items: center; gap: 12px; width: 100%; min-height: 44px; padding: 0 12px 0 14px;
  border: 0; border-radius: 9px; background: var(--surface); color: var(--ink); box-shadow: 0 1px 3px rgba(0, 0, 0, .18);
  font: 700 15px var(--font); text-align: left; cursor: pointer;
}
.picker__title { flex: none; }
.picker__value { flex: 1; min-width: 0; text-align: right; font-size: 14px; color: var(--primary-text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.picker__value.muted { color: var(--muted); }
.picker__chev { flex: none; color: var(--muted); transition: rotate calc(.3s * var(--fx-k, 1)) cubic-bezier(.2, .7, .2, 1); }
.picker.is-open .picker__chev { rotate: 180deg; color: var(--primary-text); }
.picker.is-open .picker__face { box-shadow: 0 0 0 2px var(--primary); }
.picker__drawer { display: grid; grid-template-rows: 0fr; transition: grid-template-rows calc(.32s * var(--fx-k, 1)) cubic-bezier(.2, .7, .2, 1); }
.picker.is-open .picker__drawer { grid-template-rows: 1fr; }
.picker__inner { min-height: 0; overflow: hidden; }
.picker:not(.is-open) .picker__inner { visibility: hidden; transition: visibility 0s linear calc(.32s * var(--fx-k, 1)); }
/* spazio attorno ai riquadri: acceso, un riquadro si ingrandisce un poco e non va tagliato */
.picker__inner > .mod-grid { padding: 12px 8px 8px; }
/* telefono: ciò che è acceso va sotto il nome della scelta, intero invece che tagliato */
@media (max-width: 480px) {
  .picker__face { flex-wrap: wrap; row-gap: 2px; padding-block: 9px; }
  .picker__title { flex: 1; }
  .picker__chev { order: 2; }
  .picker__value { order: 3; flex-basis: 100%; text-align: left; white-space: normal; }
}
/* parti dei moduli degli utenti che valgono solo per alcuni tipi di account (data-kinds, pages/users.js):
   nascoste anche quando sono un .field, che altrimenti con il suo display le terrebbe visibili */
[data-kinds][hidden], [data-kind-help][hidden] { display: none !important; }
/* collaboratori del gruppo: verdi quelli che ne vedono le sessioni */
.group-detail__collab { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
table.data .list-empty > td { font-size: 14px; }
table.data tbody tr.list-empty { cursor: default; }

/* Gruppi di un utente (_group_chips.html): pillole da accendere, come i
   riquadri dei moduli qui sopra. Ognuna è l'etichetta di una casella nascosta:
   spenta è grigia, accesa è verde. */
.group-chips { display: flex; flex-wrap: wrap; gap: 8px; }
.group-chip { display: inline-flex; cursor: pointer; -webkit-user-select: none; user-select: none; }
.group-chip__face {
  display: inline-flex; align-items: center; min-height: 40px; padding: 0 14px; border-radius: 999px;
  border: 1px solid var(--disabled-line); background: var(--disabled-bg); color: var(--disabled-ink);
  font-size: 14px; font-weight: 700; overflow-wrap: anywhere;
}
.group-chip input:checked + .group-chip__face { background: var(--primary); border-color: var(--primary); color: var(--primary-ink); }
.group-chip input:focus-visible + .group-chip__face { outline: 3px solid var(--focus); outline-offset: 2px; }
@media (hover: hover) and (pointer: fine) {
  .group-chip:hover input:not(:checked) + .group-chip__face { border-color: var(--muted); color: var(--ink-2); }
}

/* Popup per eliminare un utente o una sessione (_user_delete_pop.html,
   _session_delete_pop.html): sotto il cestino premuto, come gli altri menu.
   La posizione la mette core/delpop.js; come entra ed esce è in motion.css. */
.delpop { position: fixed; z-index: 47; width: min(440px, calc(100vw - 32px)); }
.delpop:not(.show) { visibility: hidden; pointer-events: none; }
.delpop > .panel {
  width: 100%; max-height: calc(100vh - 32px); max-height: calc(100dvh - 32px);
  padding: 22px; gap: 14px; border-radius: 20px; --live-gap: 14px;
}
.delpop > .panel h2 { font-size: 22px; }
/* Riga dell'elemento eliminato: un vetro rosso sopra la riga (e sopra la sua
   scheda, se è aperta sotto), che sfoca ciò che ha sotto, con la scritta. Sta dentro il riquadro della tabella (posizione e
   misure della riga: pages/users.js), quindi si muove con la pagina. */
.focus-page .table-wrap { position: relative; }
.row-gone {
  position: absolute; z-index: 1; display: flex; align-items: center; justify-content: center;
  background: color-mix(in srgb, var(--rec) 48%, transparent); color: #FFFFFF; font-weight: 700;
  -webkit-backdrop-filter: blur(5px); backdrop-filter: blur(5px);
}
html.perf-noblur .row-gone { -webkit-backdrop-filter: none; backdrop-filter: none; background: color-mix(in srgb, var(--rec) 78%, var(--surface)); }
table.data tbody tr.is-gone { pointer-events: none; }
/* la riga appena aggiunta resta evidenziata per un momento */
table.data tbody tr.is-new { background: var(--tint); }
table.data tbody tr.is-new td:first-child { box-shadow: inset 3px 0 0 var(--primary); }
/* Esito di un'azione in cima alla pagina (utente creato, sessione eliminata...) o motivo per cui non si può fare */
.notice { padding: 12px 16px; border-radius: var(--radius-sm); background: var(--ok-tint); color: var(--ok-ink); font-weight: 700; }
.notice--error { background: var(--rec-tint); color: var(--rec-ink); }
/* Pulsante "elimina" (cestino): quadrato, rosso solo nell'icona finché non ci si passa sopra */
.btn-trash { width: 44px; padding: 0; color: var(--rec-ink); }
.btn-trash:hover { background: var(--rec-tint); border-color: var(--rec-line); color: var(--rec-ink); }
select.seg-source { display: none; }

/* ---------- Pagine con la webcam ---------- */
body.stage-page { height: 100vh; height: 100dvh; display: flex; flex-direction: column; overflow: hidden; }
.split { flex: 1; min-height: 0; display: flex; gap: 20px; padding: 20px 24px 24px; }
.stage {
  position: relative; flex: 1 1 auto; min-width: 0; min-height: 0;
  background: var(--stage); border-radius: 20px; overflow: hidden;
  display: flex; align-items: center; justify-content: center;
}
.stage canvas.view { max-width: 100%; max-height: 100%; width: auto; height: auto; display: block; }
video.source { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; }
/* 16px in più a destra, dentro il margine della pagina: lì passa il cursore
   della barra di scorrimento (core/scrollbar.js), senza coprire le schede */
.side { flex: 0 0 436px; overflow-y: auto; display: flex; flex-direction: column; gap: 16px; min-height: 0; margin-right: -16px; padding-right: 16px; }
.side > * { flex-shrink: 0; }
.stage-only { flex: 1; min-height: 0; display: flex; padding: 20px 24px 24px; }
.stage-only .stage { flex: 1; }
/* Tablet e telefoni: il video sopra, il pannello sotto, e la pagina scorre.
   Il riquadro del video è alto quanto il video (prima era sempre il 62% dello
   schermo: con un video orizzontale su uno schermo verticale restava quasi
   tutto vuoto) e non supera il 62% dello schermo, così sotto si vede
   l'inizio del pannello. Un minimo di altezza per ciò che gli sta sopra
   (avvisi, conto alla rovescia) quando il video è basso o non c'è ancora. */
@media (max-width: 1000px) {
  body.stage-page { height: auto; overflow: auto; }
  .split { flex-direction: column; }
  .split .stage, .stage-only .stage { height: auto; min-height: 200px; }
  .split .stage { flex: none; }
  .stage canvas.view { max-height: 62vh; max-height: max(62svh, 280px); }  /* 280px: telefono in orizzontale */
  .side { flex: none; overflow: visible; margin-right: 0; padding-right: 0; }
  /* popup sopra il video (calibrazione del viso): il riquadro gli fa posto finché è aperto */
  .stage:has(.stage-pop.show) { min-height: min(440px, 80svh); }
}

.stage-chip {
  position: absolute; z-index: 5; padding: 6px 12px; border-radius: 999px;
  background: rgba(255,255,255,.12); color: #E6EEEC; font-size: 14px;
}
.stage-chip.tl { top: 16px; left: 16px; }
.stage-chip.tr { top: 16px; right: 16px; }
.stage-chip.bl { bottom: 16px; left: 16px; }

/* Riquadro sopra il video: vetro scuro sfocato in entrambi i temi (il video è sempre scuro) */
.hud {
  position: absolute; left: 16px; bottom: 16px; z-index: 20;
  width: 248px; padding: 12px 14px;
  border-radius: 14px; color: #F2F7F6;
  background: rgba(6, 30, 27, .34);
  border: 1px solid rgba(255, 255, 255, .14);
  -webkit-backdrop-filter: var(--glass-blur);
          backdrop-filter: var(--glass-blur);
  box-shadow: 0 8px 24px rgba(0, 0, 0, .22);
}
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .hud { background: rgba(8, 14, 13, .8); }
}
.hud .hud-title { display: flex; align-items: center; justify-content: space-between; gap: 8px; font-weight: 700; font-size: 15px; margin-bottom: 8px; }
.hud .chip { background: rgba(94, 230, 207, .16); color: var(--live-ok); }
.hud .bar { height: 8px; margin-bottom: 10px; background: rgba(255, 255, 255, .16); }
.hud .grid2 { display: grid; grid-template-columns: auto auto; column-gap: 14px; row-gap: 4px; font-size: 14px; }
.hud .label { color: rgba(230, 240, 238, .75); }
.hud .value { text-align: right; font-weight: 700; font-variant-numeric: tabular-nums; }
.hud .value.ok { color: var(--live-ok) !important; }
.hud .value.warn { color: var(--live-warn) !important; }
.hud .value.bad { color: #FF8A70 !important; }
.value.ok { color: var(--ok-ink) !important; }
.value.warn { color: var(--warn-text) !important; }
.value.bad { color: var(--rec-ink) !important; }

.warning {
  position: fixed; left: 50%; bottom: 24px; transform: translateX(-50%); z-index: 25;
  display: none; align-items: center; gap: 10px; max-width: min(92vw, 720px);
  padding: 12px 18px; border-radius: 12px;
  background: #FFF1DC; color: #5E3800; font-weight: 700; font-size: 17px; text-align: center;
  box-shadow: 0 8px 24px rgba(0,0,0,.25);
}
.warning::before {
  content: ""; width: 20px; height: 20px; flex: none;
  background: currentColor;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.5' stroke-linecap='round'%3E%3Cpath d='M12 4l9 16H3zM12 10v4M12 17v.5'/%3E%3C/svg%3E") center / contain no-repeat;
          mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.5' stroke-linecap='round'%3E%3Cpath d='M12 4l9 16H3zM12 10v4M12 17v.5'/%3E%3C/svg%3E") center / contain no-repeat;
}
.warning.show { display: inline-flex; }
.stage .warning { position: absolute; bottom: 20px; max-width: calc(100% - 40px); }
/* in alto dove in basso c'è già il riquadro informazioni (specchio virtuale) */
.stage .warning.warning-top { top: 20px; bottom: auto; }

.banner {
  position: absolute; top: 18px; left: 50%; transform: translateX(-50%); z-index: 22;
  display: none; align-items: center; gap: 10px;
  padding: 10px 20px; border-radius: 999px;
  background: rgba(14, 20, 19, .85); color: #FFFFFF; font-weight: 700; font-size: 20px; white-space: nowrap;
}
.banner.show { display: inline-flex; }
.banner.ok { background: #0A7468; color: #FFFFFF; }
.banner.bad { background: rgba(14, 20, 19, .85); color: #FFD08A; }

/* ---------- Overlay, popup, caricamento ---------- */
.overlay {
  position: fixed; inset: 0; z-index: 40;
  display: none; align-items: center; justify-content: center; flex-direction: column; gap: 18px;
  padding: 20px; text-align: center; color: #FFFFFF;
  background: rgba(4, 18, 16, .6);
  -webkit-backdrop-filter: var(--glass-blur); backdrop-filter: var(--glass-blur);
}
.overlay.show { display: flex; }
.overlay .count {
  width: 190px; height: 190px; border-radius: 50%; border: 8px solid var(--live-ok);
  display: flex; align-items: center; justify-content: center;
  font-size: 112px; font-weight: 700; line-height: 1; font-variant-numeric: tabular-nums;
}
.overlay .hint { font-size: 22px; font-weight: 700; max-width: 560px; }
.spinner {
  width: 72px; height: 72px; border-radius: 50%;
  border: 6px solid rgba(255,255,255,.14); border-top-color: var(--live-ok);
  animation: spin .9s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* Popup con lo sfondo sfocato */
.modal {
  position: fixed; inset: 0; z-index: 50;
  display: none; align-items: center; justify-content: center; padding: 16px;
  background: var(--scrim);
  -webkit-backdrop-filter: var(--glass-blur); backdrop-filter: var(--glass-blur);
}
.modal.show { display: flex; }
.panel {
  width: min(520px, 100%); max-height: 92vh; overflow: auto;
  background: var(--surface); color: var(--ink); text-align: left;
  border: 1px solid var(--line); border-radius: 22px; padding: 28px;
  box-shadow: var(--shadow-lg); display: flex; flex-direction: column; gap: 18px;
}
.panel h2 { font-size: 26px; }
.panel p { color: var(--muted); }
.panel .actions { display: flex; gap: 10px; justify-content: flex-end; flex-wrap: wrap; }
/* Barra dei pulsanti che resta in fondo al popup mentre il contenuto scorre,
   su vetro sfocato (stesso vetro della fascia delle schede delle impostazioni,
   .settings-nav). I margini negativi la allargano fino ai bordi del pannello
   (padding 28px) e bottom negativo la porta sul bordo inferiore. */
.panel .actions-sticky {
  position: sticky; bottom: -28px; z-index: 1;
  margin: 0 -28px -28px; padding: 16px 28px 24px;
  background: var(--glass-bar);
  border-top: 1px solid color-mix(in srgb, var(--line) 80%, transparent);
  -webkit-backdrop-filter: var(--glass-blur-bar);
          backdrop-filter: var(--glass-blur-bar);
}
@supports not (((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) and (background-color: color-mix(in srgb, red 50%, transparent))) {
  .panel .actions-sticky { background: var(--surface); }
}
html.perf-noblur .panel .actions-sticky { -webkit-backdrop-filter: none; backdrop-filter: none; background: var(--surface); }
.panel-wide { width: min(720px, 100%); }
/* intestazione con titolo e pulsante di chiusura (Impostazioni della home) */
.panel__head { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.panel--settings .card { gap: 12px; padding: 16px 18px; }
/* Schede "Generali" e "MediaPipe" (v3.3): la barra è un controllo a segmenti,
   con la pillola che scivola (core/segmented.js) */
/* La barra delle schede resta in cima al popup mentre il contenuto scorre.
   È una fascia larga quanto il popup, bordo a bordo e fin dal bordo superiore
   (i margini negativi annullano il padding di 20px del pannello e il suo
   stesso padding verticale, così a riposo le distanze non cambiano). Quando si
   aggancia (core/settings.js, is-compact) compare il suo vetro sfocato
   (::before, in dissolvenza) e le schede si rimpiccioliscono; risalendo in
   cima tornano grandi e il vetro sparisce. Prima era sfocato solo il riquadro
   delle schede, più stretto del popup e staccato dal bordo: ai lati e sopra
   il testo che scorreva si leggeva nitido. Si animano solo "scale" e la
   trasparenza del vetro (motion.css).
   "top" negativo: un elemento sticky si ferma al bordo del CONTENUTO di ciò
   che scorre, cioè dopo il padding (20px) del pannello; -20px lo porta sul
   bordo vero del popup (come "bottom" negativo di .actions-sticky). La
   sfocatura della fascia vede anche il vetro del popup perché quello sta su
   uno strato a parte (.glass-host, più sotto), non sul pannello. */
.settings-nav { position: sticky; top: -20px; z-index: 5; margin: -10px -20px; padding: 10px 20px; }
.settings-nav::before {
  content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background: var(--glass-bar);
  border-bottom: 1px solid color-mix(in srgb, var(--line) 80%, transparent);
  -webkit-backdrop-filter: var(--glass-blur-bar);
          backdrop-filter: var(--glass-blur-bar);
  opacity: 0;
}
.settings-nav.is-compact::before { opacity: 1; }
.settings-nav.is-compact > .seg { scale: .86; }
@supports not (((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) and (background-color: color-mix(in srgb, red 50%, transparent))) {
  .settings-nav::before { background: var(--surface); }
}
html.perf-noblur .settings-nav::before { -webkit-backdrop-filter: none; backdrop-filter: none; background: var(--surface); }
.settings-section { display: flex; flex-direction: column; gap: 14px; }
.settings-section[hidden] { display: none; }
/* Cursori delle soglie: nome e valore sulla stessa riga, sotto il cursore e la spiegazione */
.range-field { display: flex; flex-direction: column; gap: 6px; }
.range-field + .range-field { padding-top: 12px; border-top: 1px solid var(--line-soft); }
.range-field__head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; font-weight: 700; }
.range-field__head output { font: 600 15px var(--mono); color: var(--primary-text); font-variant-numeric: tabular-nums; }
input[type=range] { width: 100%; height: 28px; margin: 0; accent-color: var(--primary); background: transparent; cursor: pointer; }
/* niente riquadro attorno al cursore quando lo si usa: è l'alone che i campi
   di testo hanno con il focus (input:focus, più sopra), qui fuori posto. Da
   tastiera il focus si vede lo stesso (:focus-visible, o il pomello qui sotto). */
input[type=range]:focus { box-shadow: none; }
/* Cursore disegnato da core/range.js: l'<input> vero è trasparente e sopra a
   tutto (riceve mouse, tocco e tastiera), sotto ci sono binario, riempimento e
   pomello. --p (da 0 a 1) è la posizione: muove il pomello con translate e
   allunga il riempimento con scale, senza impaginazione. Il pomello
   dell'<input>, invisibile, è largo come quello disegnato: così i due
   coincidono. Animazioni in motion.css, sezione 3e. */
.range { --p: 0; --range-thumb: 22px; position: relative; display: block; height: 28px; }
.range > input[type=range] {
  -webkit-appearance: none; appearance: none;
  position: absolute; inset: 0; z-index: 1; width: 100%; height: 100%; opacity: 0;
  outline: none; touch-action: pan-y;
}
.range > input[type=range]::-webkit-slider-thumb { -webkit-appearance: none; width: var(--range-thumb); height: 28px; }
.range > input[type=range]::-moz-range-thumb { width: var(--range-thumb); height: 28px; border: 0; }
.range__track {
  position: absolute; top: 50%; left: calc(var(--range-thumb) / 2); right: calc(var(--range-thumb) / 2);
  height: 6px; margin-top: -3px; border-radius: 999px; overflow: hidden;
  background: var(--disabled-line); pointer-events: none;
}
.range__fill { display: block; height: 100%; background: var(--primary); transform-origin: 0 50%; scale: var(--p) 1; }
/* La corsa del pomello: larga quanto il binario, con il pomello attaccato alla
   sua estremità destra; a fine corsa (--p = 1) è al suo posto, altrimenti è
   spostata verso sinistra della parte che manca. Verso sinistra e non verso
   destra: ciò che sporge a destra allargherebbe l'area che scorre del popup
   (compariva la barra di scorrimento orizzontale), a sinistra no. */
.range__rail {
  position: absolute; top: 0; bottom: 0; left: 0; width: calc(100% - var(--range-thumb));
  translate: calc((var(--p) - 1) * 100%) 0; pointer-events: none;
}
.range__thumb {
  position: absolute; top: 50%; left: 100%; width: var(--range-thumb); height: var(--range-thumb);
  margin-top: calc(var(--range-thumb) / -2); border-radius: 50%;
  background: #FFFFFF; box-shadow: 0 1px 4px rgba(0, 0, 0, .35), 0 0 0 1px rgba(0, 0, 0, .06);
}
/* focus da tastiera: un anello attorno al pomello */
.range.is-focus .range__thumb { box-shadow: 0 1px 4px rgba(0, 0, 0, .35), 0 0 0 3px var(--focus); }
/* Riga di stato in fondo al popup, nelle pagine con la webcam (core/settings.js:
   modello in caricamento, registrazione in corso): la barra di vetro dei
   popup, portata ai bordi del pannello (padding 20px) */
.popover > .panel .actions-sticky { bottom: -20px; margin: 0 -20px -20px; padding: 12px 20px 16px; }
.panel .settings-status { justify-content: flex-start; }
.panel .settings-status p { color: var(--ink); }
.panel .settings-status[hidden] { display: none; }
/* scelte bloccate durante una registrazione (attributo inert, core/settings.js) */
.settings-section [data-mp-lock][inert] { opacity: .45; }

/* Alone sfocato attorno a un popup (Impostazioni, Controlli dello Specchio,
   pose, calibrazione del viso): lo stesso per tutti. Sfoca la pagina per circa
   1 cm oltre i bordi del popup, forte vicino al bordo e sempre meno
   allontanandosi. Due strati sovrapposti, ognuno con la sua sfocatura e una
   maschera a sfumatura sui quattro lati (le due sfumature, orizzontale e
   verticale, si intersecano e arrotondano gli angoli): quello leggero arriva a
   1 cm, quello forte a metà. L'alone sta DIETRO al popup,
   fratello e non figlio: dentro il popup (che ha già la sua sfocatura e
   overflow) vedrebbe solo il popup. Non va messa opacity sull'elemento .halo:
   farebbe da "radice" alle sfocature degli strati, che non vedrebbero più la
   pagina; si animano i due strati (motion.css). Il bordo superiore può avere
   un alone più corto (--halo-top, es. sotto la barra in alto della home). */
:root { --halo: 1cm; }
.halo {
  --halo-top: var(--halo);
  position: absolute; inset: calc(-1 * var(--halo)); top: calc(-1 * var(--halo-top));
  pointer-events: none;
}
.halo::before, .halo::after {
  content: ""; position: absolute; inset: 0;
  -webkit-mask-image: var(--halo-x), var(--halo-y); -webkit-mask-composite: source-in;
          mask-image: var(--halo-x), var(--halo-y);         mask-composite: intersect;
}
.halo::before {
  --halo-x: linear-gradient(to right, transparent, #000 var(--halo), #000 calc(100% - var(--halo)), transparent);
  --halo-y: linear-gradient(to bottom, transparent, #000 var(--halo-top), #000 calc(100% - var(--halo)), transparent);
  -webkit-backdrop-filter: blur(4px); backdrop-filter: blur(4px);
}
.halo::after {
  --halo-x: linear-gradient(to right, transparent calc(var(--halo) * .5), #000 var(--halo), #000 calc(100% - var(--halo)), transparent calc(100% - var(--halo) * .5));
  --halo-y: linear-gradient(to bottom, transparent calc(var(--halo-top) * .5), #000 var(--halo-top), #000 calc(100% - var(--halo)), transparent calc(100% - var(--halo) * .5));
  -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px);
}

/* Popup sotto un pulsante della barra in alto (Impostazioni di tutte le
   pagine, Controlli dello Specchio): vetro sfocato che non copre la pagina. La
   posizione (--pop-top, --pop-right) la calcola core/popover.js dal pulsante.
   Sta sopra la barra in alto, che sfiora. */
.popover {
  position: fixed; z-index: 45;
  top: var(--pop-top, 84px); right: var(--pop-right, 16px);
  width: min(440px, calc(100vw - 32px));
}
.popover:not(.show) { visibility: hidden; pointer-events: none; }
/* Popup dell'utente nella home (_user_menu.html): un menu, più stretto */
.popover--menu { width: min(300px, calc(100vw - 32px)); }
.popover > .panel {
  position: relative; width: 100%;
  max-height: calc(100vh - var(--pop-top, 84px) - 16px);
  max-height: calc(100dvh - var(--pop-top, 84px) - 16px);
  padding: 20px; gap: 14px; border-radius: 20px;
}
.popover > .panel h2 { font-size: 22px; }
.user-menu__who { display: flex; align-items: center; gap: 12px; min-width: 0; }
.user-menu__avatar {
  width: 44px; height: 44px; flex: none; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: var(--tint); color: var(--primary-text);
}
.popover > .panel.user-menu h2 { font-size: 18px; overflow-wrap: anywhere; }
/* voci del menu: pulsanti a tutta larghezza, icona e testo a sinistra */
.user-menu__item { width: 100%; justify-content: flex-start; gap: 12px; }
/* nome utente nella barra in alto: se è lungo si tronca */
#userBtn .btn-label { max-width: 180px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Popup sopra il video (calibrazione del viso): vetro sfocato con alone, come
   i popup dei menu, al centro del riquadro della camera. Copre solo il video:
   il pannello laterale resta usabile. Il riquadro (.stage) ritaglia l'alone. */
.stage-pop {
  position: absolute; inset: 0; z-index: 24;
  display: flex; align-items: center; justify-content: center; padding: 16px;
  pointer-events: none;
}
.stage-pop:not(.show) { visibility: hidden; }
.stage-pop__box { position: relative; z-index: 0; width: min(460px, 100%); max-height: 100%; display: flex; pointer-events: auto; }
.stage-pop:not(.show) .stage-pop__box { pointer-events: none; }
.stage-pop .panel { position: relative; width: 100%; max-height: 100%; padding: 24px; gap: 14px; border-radius: 20px; }
.stage-pop .panel h2 { font-size: 22px; }
.stage-pop .panel-icon { background: var(--tint); color: var(--primary-text); }
.stage-pop ul { margin: 0; padding-left: 20px; color: var(--muted); display: flex; flex-direction: column; gap: 4px; }
.stage-pop .error { color: var(--rec-ink); font-weight: 700; }
.stage-pop .error:empty { display: none; }

/* Pannello di vetro sfocato: Impostazioni, Controlli dello Specchio, popup
   delle pose, calibrazione del viso. Tutti fatti allo stesso modo. */
.panel--glass {
  background: var(--glass);
  border-color: color-mix(in srgb, var(--line) 70%, transparent);
  -webkit-backdrop-filter: var(--glass-blur);
          backdrop-filter: var(--glass-blur);
}
/* le schede dentro il pannello lasciano intravedere il vetro */
.panel--glass .card { background: var(--glass-card); }
@supports not (((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) and (background-color: color-mix(in srgb, red 50%, transparent))) {
  .panel--glass, .panel--glass .card { background: var(--surface); }
}
/* .glass-host: il contenitore di un pannello di vetro (grande quanto il
   pannello, posizionato, con dentro l'alone). Il vetro, cioè colore e
   sfocatura della pagina, non sta sul pannello ma su uno strato a parte
   (::before), grande uguale e subito dietro. Con la sfocatura sul pannello,
   ciò che è sfocato DENTRO il pannello (la fascia delle schede delle
   impostazioni, le barre dei pulsanti in fondo) vedrebbe solo il contenuto del
   pannello su fondo trasparente, e in alcuni browser il testo che scorre lì
   sotto restava leggibile, solo sbiadito. Così invece quelle fasce sfocano
   tutto ciò che hanno dietro, pagina compresa, come la barra in alto.
   L'alone va sotto lo strato (z-index). Lo strato deve entrare e uscire
   insieme al pannello: motion.css per .popover e .stage-pop, pages/poses.js
   per il popup delle pose. Solo dove sfocatura e color-mix esistono: altrove
   il pannello resta a fondo pieno (regola qui sopra). Con le animazioni
   ridotte o spente lo strato non c'è e il pannello è a fondo pieno
   (motion.css, 18a). */
@supports ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) and (background-color: color-mix(in srgb, red 50%, transparent)) {
  .glass-host > .halo { z-index: -1; }
  .glass-host::before {
    content: ""; position: absolute; inset: 0; border-radius: var(--glass-radius, 20px); pointer-events: none;
    background: var(--glass);
    -webkit-backdrop-filter: var(--glass-blur);
            backdrop-filter: var(--glass-blur);
  }
  /* "relative": il pannello deve essere posizionato come lo strato di vetro,
     altrimenti lo strato (posizionato) verrebbe disegnato sopra il suo contenuto */
  .glass-host > .panel--glass { position: relative; background: transparent; -webkit-backdrop-filter: none; backdrop-filter: none; }
}
html.perf-noblur .glass-host::before { content: none; }
.panel-icon { width: 48px; height: 48px; border-radius: 12px; display: flex; align-items: center; justify-content: center; background: var(--rec-tint); color: var(--rec); }

.choices { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
.choice {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 10px;
  min-height: 132px; border-radius: 16px; border: 1px solid var(--line);
  background: var(--surface); color: var(--ink); font: 700 18px var(--font); cursor: pointer;
}
.choice svg { color: var(--muted); }
.choice[aria-checked="true"] { border: 3px solid var(--primary); background: var(--tint); }
.choice[aria-checked="true"] svg { color: var(--primary-text); }

/* ---------- Dati in tempo reale ---------- */
.stat-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
.stat { background: var(--surface); border: 1px solid var(--line); border-radius: 14px; padding: 12px 14px; }
.stat .label { font-size: 13px; color: var(--muted); }
.stat .value { font-size: 22px; font-weight: 700; margin-top: 2px; font-variant-numeric: tabular-nums; }
.stat.accent { grid-column: 1 / -1; }
/* quanti riquadri stanno in una riga, larghi almeno 200px (dati di una sessione); due per riga sui telefoni */
.stat-grid--auto { grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); }

.bar { height: 14px; border-radius: 7px; background: var(--line-soft); overflow: hidden; }
/* Riempimento con transform: scaleX (core/ui.js, setBar): cambia solo il
   transform, senza impaginazione né ridisegno della barra */
.bar > span { display: block; height: 100%; width: 100%; transform-origin: 0 50%; transform: scaleX(0); background: var(--fb-ok); transition: transform 120ms linear; }
.bar-labels { display: flex; justify-content: space-between; font-size: 13px; color: var(--muted); font-weight: 700; margin-top: 6px; }

.rec-status { font: 13px/1.6 var(--mono); color: var(--muted); }
.rec-status a { font-weight: 600; }
.rec-dot { display: inline-block; width: 9px; height: 9px; border-radius: 50%; background: var(--rec); margin-right: 6px; animation: blink 1s steps(2) infinite; }
@keyframes blink { 50% { opacity: .25; } }

.loading { font-size: 15px; color: var(--muted); }

/* ---------- Telefoni ---------- */
/* Bordi dello schermo (tacca, angoli arrotondati, barra in basso dell'iPhone):
   la pagina arriva fino al bordo (viewport-fit=cover in base.html), quindi i
   margini laterali e quello in fondo non scendono mai sotto la zona sicura.
   Vale a ogni larghezza: un telefono in orizzontale è largo più di 640px. */
.app-header__inner, .app-header--doc .app-header__inner {
  padding-left: max(24px, env(safe-area-inset-left)); padding-right: max(24px, env(safe-area-inset-right));
}
.app-header--doc .app-header__inner { padding-left: max(32px, env(safe-area-inset-left)); padding-right: max(32px, env(safe-area-inset-right)); }
.container { padding-left: max(32px, env(safe-area-inset-left)); padding-right: max(32px, env(safe-area-inset-right)); padding-bottom: calc(64px + env(safe-area-inset-bottom)); }
.split, .stage-only { padding-left: max(24px, env(safe-area-inset-left)); padding-right: max(24px, env(safe-area-inset-right)); padding-bottom: calc(24px + env(safe-area-inset-bottom)); }

/* Tablet e telefoni in orizzontale: se nella barra in alto non c'è posto, si
   accorcia il titolo (il sottotitolo si tronca) invece di mandare a capo stato
   e pulsanti: con uno schermo basso la barra su due righe ne occupava un terzo. */
@media (max-width: 1000px) {
  .app-header__title { flex: 1 1 0; min-width: 140px; }
  .app-header__title p { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
}

@media (max-width: 640px) {
  /* Barra in alto su una riga sola: freccia per tornare indietro, titolo (che
     si tronca) e, a destra, stato e pulsanti con la sola icona. Prima erano tre
     righe, un quinto dello schermo sempre occupato. Va a capo solo se a destra
     c'è troppo (punteggio e tempo di Raggiungi il target). */
  .app-header__inner, .app-header--doc .app-header__inner {
    padding: 8px max(12px, env(safe-area-inset-right)) 8px max(12px, env(safe-area-inset-left)); gap: 8px;
  }
  .app-header__title { flex: 1 1 0; min-width: 96px; }
  /* titolo su due righe al massimo; il sottotitolo su una, troncato */
  .app-header__title h1 { font-size: 18px; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; }
  .app-header__title p { font-size: 12.5px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  /* nelle pagine con la webcam a destra ci sono anche fotogrammi e pulsanti: il posto va al titolo */
  .stage-page .app-header__title p { display: none; }
  .app-header__status { gap: 6px; justify-content: flex-end; }
  .app-header .chip { font-size: 13px; padding: 5px 9px; }
  .brand-group { flex-wrap: nowrap; gap: 8px; }
  .brand { gap: 8px; }
  .brand__mark { width: 38px; height: 38px; border-radius: 10px; }
  .brand__name { font-size: 18px; }
  .brand__sub { display: none; }
  .naps-logo img { height: 18px; }
  /* sui telefoni i pulsanti della barra mostrano solo l'icona */
  .app-header .btn-label {
    position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap;
  }
  .app-header .seg button { padding: 0 12px; }
  .app-header :is(.btn-collapse, .btn-back) { padding: 0; width: 44px; flex: none; }
  /* anche il distintivo del ruolo: solo il disegno, in un cerchio */
  .app-header__status > .role-badge { width: 2.15em; padding: 0; justify-content: center; font-size: 13px; }
  .app-header__status > .role-badge .role-badge__text { display: none; }

  /* Pagine "documento" */
  .container {
    padding: 20px max(16px, env(safe-area-inset-right)) calc(40px + env(safe-area-inset-bottom)) max(16px, env(safe-area-inset-left));
    gap: 26px;
  }
  .hero p { font-size: 17px; }
  .section { gap: 12px; }
  .section-title { font-size: 13.5px; letter-spacing: 1.2px; }
  .tiles { grid-template-columns: 1fr; gap: 12px; }
  .tile { min-height: 0; padding: 16px 18px; gap: 10px; }
  .tile__icon { width: 48px; height: 48px; border-radius: 12px; }
  .tile__title { font-size: 20px; }
  .game-card { flex-wrap: nowrap; gap: 14px; padding: 16px; }
  .game-card__art { width: 84px; height: 84px; border-radius: 14px; }
  .game-card__art svg { width: 62%; height: 62%; }
  .game-card__body { flex: 1 1 0; min-width: 0; }
  .card { padding: 16px; }
  .footer { padding: 12px 16px; }
  .notice { font-size: 15px; }

  /* Pagine con la webcam */
  .split, .stage-only {
    padding: 10px max(10px, env(safe-area-inset-right)) calc(16px + env(safe-area-inset-bottom)) max(10px, env(safe-area-inset-left));
    gap: 12px;
  }
  /* in colonna: sotto il video può stare il riquadro informazioni (più sotto) */
  .stage { border-radius: 16px; flex-direction: column; }
  .stage-chip { font-size: 13px; padding: 5px 10px; }
  .stage-chip.tl { top: 10px; left: 10px; }
  .stage-chip.tr { top: 10px; right: 10px; }
  .stage-chip.bl { bottom: 10px; left: 10px; }
  /* messaggi sopra il video: su più righe, più piccoli, dentro il riquadro */
  .banner {
    top: 10px; width: max-content; max-width: calc(100% - 20px); padding: 8px 14px; border-radius: 14px;
    font-size: 15px; white-space: normal; text-align: center;
  }
  .warning { bottom: calc(16px + env(safe-area-inset-bottom)); padding: 10px 14px; font-size: 15px; }
  .stage .warning { bottom: 10px; max-width: calc(100% - 20px); width: max-content; }
  .stage .warning.warning-top { top: 10px; }
  /* Riquadro informazioni (Specchio): sotto il video invece che sopra, dove su
     uno schermo stretto copriva mezza persona. Largo quanto il video, con i
     valori su due colonne. */
  .hud {
    position: static; align-self: stretch; width: auto; padding: 10px 12px;
    border-radius: 0; border-width: 1px 0 0; box-shadow: none;
    background: transparent; -webkit-backdrop-filter: none; backdrop-filter: none;
  }
  .hud.is-off { display: none; }
  .hud .grid2 { grid-template-columns: auto 1fr auto 1fr; column-gap: 8px; font-size: 13px; }
  .hud .grid2 .value { white-space: nowrap; }
  .hud .grid2 .value:nth-child(4n+2) { padding-right: 10px; margin-right: 2px; border-right: 1px solid rgba(255, 255, 255, .14); }
  /* popup sopra il video (calibrazione del viso): in basso, più compatto, così
     l'avviso in cima al video ("Nessun viso inquadrato") resta leggibile */
  .stage:has(.stage-pop.show) { min-height: min(470px, 82svh); justify-content: flex-start; }
  .stage:has(.stage-pop.show) > .warning { top: 10px; bottom: auto; }
  .stage-pop { padding: 10px; align-items: flex-end; }
  .stage-pop .panel { padding: 16px; gap: 10px; }
  .stage-pop .panel h2 { font-size: 20px; }
  .stage-pop .panel p { font-size: 15px; }
  .stage-pop .panel-icon { display: none; }
  .overlay { padding: 16px; }
  .overlay .count { width: 150px; height: 150px; font-size: 88px; }
  .overlay .hint { font-size: 18px; }

  /* Popup: meno margine attorno, quasi tutto lo schermo */
  .modal { padding: 10px; }
  .panel { padding: 20px; gap: 14px; border-radius: 18px; max-height: 92dvh; }
  .panel h2 { font-size: 22px; }
  .panel .actions-sticky { bottom: -20px; margin: 0 -20px -20px; padding: 12px 20px 16px; }
  .panel .actions .btn { flex: 1 1 auto; }
  /* i popup sotto la barra (Impostazioni, Controlli, Nuovo utente) larghi quanto
     lo schermo; il menu dell'utente resta sotto il suo pulsante, senza uscire a sinistra */
  .popover:not(.popover--menu) { left: max(10px, env(safe-area-inset-left)); right: max(10px, env(safe-area-inset-right)); width: auto; }
  .popover--menu { max-width: calc(100vw - var(--pop-right, 16px) - 10px); }
  .delpop { width: min(440px, calc(100vw - 20px)); }
  .choices { grid-template-columns: 1fr 1fr; }
  .choice { min-height: 108px; }
  .mod-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .user-detail__grid { padding: 14px 12px 0; }
  .user-detail__meta { padding: 10px 12px 14px; }
  .session-detail { padding: 14px 12px; }

  /* Elenchi (Sessioni, Utenti): ogni riga della tabella diventa una scheda, con
     il nome della colonna accanto a ogni valore (data-label sulle celle). Prima
     la tabella scorreva di lato e su un telefono se ne vedevano due colonne.
     La scheda che si apre sotto una riga (core/rowdetail.js) resta attaccata a lei. */
  .table-wrap--cards { overflow: visible; background: none; border: none; border-radius: 0; }
  table.data--cards { display: block; min-width: 0 !important; }
  table.data--cards thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }
  table.data--cards tbody { display: block; }
  table.data--cards tbody tr {
    display: flex; flex-direction: column; margin-top: 12px; padding: 12px 14px;
    background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius);
  }
  table.data--cards tbody tr:first-child { margin-top: 0; }
  table.data--cards tbody td {
    display: flex; align-items: baseline; justify-content: space-between; gap: 14px;
    padding: 5px 0; border: 0; text-align: right; min-width: 0; overflow-wrap: anywhere;
  }
  table.data--cards tbody td:empty { display: none; }
  table.data--cards tbody td[data-label]::before {
    content: attr(data-label); flex: none; text-align: left;
    font-size: 12.5px; font-weight: 700; letter-spacing: .6px; text-transform: uppercase; color: var(--muted);
  }
  /* prima cella: il titolo della scheda; ultima: i pulsanti */
  table.data--cards tbody td:first-child { justify-content: flex-start; align-items: center; padding: 2px 0 8px; font-size: 17px; font-weight: 700; text-align: left; }
  table.data--cards tbody td:last-child:not([data-label]) { justify-content: flex-end; align-items: center; gap: 8px; padding-top: 10px; }
  table.data--cards tbody tr.is-open { border-bottom-left-radius: 0; border-bottom-right-radius: 0; }
  table.data--cards tbody tr.row-detail { margin-top: 0; padding: 0; border-top: 0; border-top-left-radius: 0; border-top-right-radius: 0; overflow: hidden; }
  table.data--cards .cards-only { display: inline; }
  /* elenchi vuoti e membri dentro la riga di un gruppo aperta */
  table.data--cards tbody tr.list-empty > td { display: block; padding: 0; text-align: left; font-size: 14px; font-weight: 400; }
  .group-detail { padding: 12px 0 4px; }
  .group-detail .table-wrap { box-shadow: none; }
  .stat-grid--auto { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  table.data--cards tbody tr.row-detail > td { display: block; padding: 0; text-align: left; font-size: inherit; font-weight: inherit; }
  table.kv th { width: 120px; }
}
/* schermi molto stretti: nella barra della home resta il nome, senza il logo */
@media (max-width: 350px) { .app-header .naps-logo { display: none; } }

/* Schede della home sui telefoni (schermo stretto e niente mouse): icona e
   titolo sulla stessa riga, descrizione sotto. Una scheda occupa metà dello
   spazio di prima. Con il mouse le schede si aprono al passaggio (più sopra) e
   hanno le loro misure: lì queste regole non valgono. */
@media (max-width: 640px) and (hover: none), (max-width: 640px) and (pointer: coarse) {
  .tile--reveal { display: grid; grid-template-columns: auto minmax(0, 1fr); align-items: center; column-gap: 14px; row-gap: 10px; }
  .tile--reveal .tile__more { grid-column: 1 / -1; }
  .tile--reveal .tile__more-inner { gap: 10px; }
  /* tutta la scheda è il collegamento: "Apri →" toglierebbe posto al titolo */
  .tile--reveal .tile__go { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation: none !important; transition: none !important; }
}

/* Colori delle serie nei grafici (sinistra/destra) */
:root, :root[data-theme="light"] { --series-left: #00796B; --series-right: #B35A00; }
:root[data-theme="dark"] { --series-left: #5EE6CF; --series-right: #FF9F43; }
#calcStatus:empty { display: none; }

/* ---------- Interruttori (Controlli dello Specchio virtuale) ---------- */
/* pulsante della barra in alto con il suo popup aperto */
:is(#panelBtn, #settingsBtn, #userBtn, #groupNewBtn)[aria-expanded="true"] { background: var(--tint); border-color: var(--primary); color: var(--primary-text); }

.switch-list { display: flex; flex-direction: column; }
.switch-row {
  display: flex; align-items: center; gap: 12px; min-height: 52px; padding: 8px 0;
  border-top: 1px solid var(--line-soft); cursor: pointer;
}
.switch-row:first-child { border-top: none; padding-top: 0; }
.switch-row[hidden] { display: none; }
.switch-row__text { flex: 1; font-weight: 700; display: flex; flex-direction: column; }
.switch-row__text small { font-weight: 400; font-size: 13px; color: var(--muted); }
input.switch {
  -webkit-appearance: none; appearance: none; flex: none;
  width: 48px; height: 28px; border-radius: 999px; margin: 0; position: relative; cursor: pointer;
  background: var(--disabled-line); border: 1px solid var(--disabled-line);
  transition: background .15s ease, border-color .15s ease;
}
input.switch::before {
  content: ""; position: absolute; top: 3px; left: 3px; width: 20px; height: 20px; border-radius: 50%;
  background: #FFFFFF; box-shadow: 0 1px 3px rgba(0, 0, 0, .3); transition: transform .15s ease;
}
input.switch:checked { background: var(--primary); border-color: var(--primary); }
input.switch:checked::before { transform: translateX(20px); }
input.switch:focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; box-shadow: none; }

kbd {
  font: 600 13px var(--mono); padding: 2px 8px; border-radius: 6px; white-space: nowrap;
  border: 1px solid var(--line); border-bottom-width: 2px; background: var(--surface-2); color: var(--ink);
}
.small-text { font-size: 13px; }
.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;
}
/* testo che serve solo quando una tabella è mostrata a schede (telefoni: data--cards) */
.cards-only { display: none; }
