/* ==========================================================================
   Temi
   --------------------------------------------------------------------------
   Tre stati: chiaro, scuro, oppure "auto" che segue l'impostazione del
   sistema. La scelta esplicita vive in data-tema sull'elemento radice e
   deve vincere su prefers-color-scheme, per questo la regola automatica e'
   protetta da :not([data-tema="chiaro"]).

   I colori del marchio non cambiano fra i temi: un logo che cambia colore
   non e' piu' un logo. Cambiano fondo, superfici, testo e bordi.
   ========================================================================== */

/* --------------------------------------------------------------------------
   I valori veri: i token di shadcn/ui, tavolozza violet.
   https://ui.shadcn.com/docs/theming

   Sono gli unici colori dichiarati del progetto. Tutto il resto - comprese
   le pagine Jinja, che di React non sanno niente - li legge da qui, e il
   frontend li rimappa sui nomi di Tailwind in frontend/src/stile.css.

   Tre blocchi e non dodici: prima ogni gruppo di token (colori, vetro,
   barre di scorrimento) aveva i suoi tre temi, e cambiarne uno senza
   cambiare gli altri due era gia' successo. Qui tutto cio' che dipende dal
   tema sta in questi tre blocchi, e basta leggerli affiancati.
   -------------------------------------------------------------------------- */

:root {
  --background: oklch(1 0 0);
  --foreground: oklch(0.145 0 0);
  --card: oklch(1 0 0);
  --card-foreground: oklch(0.145 0 0);
  --popover: oklch(1 0 0);
  --popover-foreground: oklch(0.145 0 0);
  --primary: oklch(0.606 0.25 292.717);
  --primary-foreground: oklch(0.969 0.016 293.756);
  --secondary: oklch(0.97 0 0);
  --secondary-foreground: oklch(0.205 0 0);
  --muted: oklch(0.97 0 0);
  --muted-foreground: oklch(0.556 0 0);
  --accent: oklch(0.97 0 0);
  --accent-foreground: oklch(0.205 0 0);
  --destructive: oklch(0.577 0.245 27.325);
  --border: oklch(0.922 0 0);
  --input: oklch(0.922 0 0);
  --ring: oklch(0.606 0.25 292.717);
  --radius: 0.625rem;
  --chart-1: oklch(0.646 0.222 41.116);
  --chart-2: oklch(0.6 0.118 184.704);
  --chart-3: oklch(0.398 0.07 227.392);
  --chart-4: oklch(0.828 0.189 84.429);
  --chart-5: oklch(0.769 0.188 70.08);

  /* Stati. shadcn ha un solo colore semantico, --destructive: non ha un
     "tutto bene" ne' un "da tenere d'occhio", perche' e' una libreria di
     componenti, non un cruscotto. Qui verde e ambra dicono se un apparato
     risponde, ed e' l'informazione principale della pagina: restano, e
     restano questi due, scelti per passare il contrasto su fondo chiaro. */
  --ok: oklch(0.48 0.13 162);
  --warn: oklch(0.5 0.13 70);
  /* shadcn ha un rosso solo, --destructive, pensato come superficie con
     --destructive-foreground sopra: come testo piccolo sulla propria tinta
     misura 3.70, sotto la soglia AA. --destructive resta intatto per i
     componenti shadcn, --danger e' lo stesso rosso abbassato finche' non
     passa. Nel tema scuro non serve: li' --destructive misura gia' 5.14. */
  --danger: oklch(0.52 0.2 27.325);

  /* Materiale: superfici di vetro. Il contorno e il riflesso sono bianchi
     in entrambi i temi ma con opacita' lontanissime, quindi stanno qui e
     non fra gli alias. */
  --vetro-bordo: rgba(255, 255, 255, 0.8);
  --vetro-luce: rgba(255, 255, 255, 0.95);
  --vetro-contorno: rgba(18, 20, 31, 0.07);
  --vetro-tenue: rgba(255, 255, 255, 0.5);
  --vetro-tenue-bordo: rgba(255, 255, 255, 0.7);
  --vetro-tenue-hover: rgba(255, 255, 255, 0.78);
  --binario: rgba(18, 20, 31, 0.04);

  /* Le ombre restano nere nei due temi: un'ombra che schiarisce non e'
     un'ombra. Cambia solo quanto pesa. */
  --ombra: 0 1px 2px rgba(16, 24, 40, 0.05);
  --ombra-vetro:
    0 1px 2px rgba(16, 24, 40, 0.05),
    0 8px 24px rgba(16, 24, 40, 0.07);
  --ombra-vetro-alta:
    0 2px 4px rgba(16, 24, 40, 0.06),
    0 16px 40px rgba(16, 24, 40, 0.11);

  --opacita-macchie: 0.16;
  color-scheme: light;
}

/* tema scuro: sia scelto a mano, sia ereditato dal sistema quando l'utente
   non ha espresso una preferenza. I due blocchi vanno tenuti identici. */
:root[data-tema="scuro"] {
  --background: oklch(0.145 0 0);
  --foreground: oklch(0.985 0 0);
  --card: oklch(0.205 0 0);
  --card-foreground: oklch(0.985 0 0);
  --popover: oklch(0.205 0 0);
  --popover-foreground: oklch(0.985 0 0);
  --primary: oklch(0.541 0.281 293.009);
  --primary-foreground: oklch(0.969 0.016 293.756);
  --secondary: oklch(0.269 0 0);
  --secondary-foreground: oklch(0.985 0 0);
  --muted: oklch(0.269 0 0);
  --muted-foreground: oklch(0.708 0 0);
  --accent: oklch(0.269 0 0);
  --accent-foreground: oklch(0.985 0 0);
  --destructive: oklch(0.704 0.191 22.216);
  --border: oklch(1 0 0 / 10%);
  --input: oklch(1 0 0 / 15%);
  --ring: oklch(0.541 0.281 293.009);
  --chart-1: oklch(0.646 0.222 41.116);
  --chart-2: oklch(0.6 0.118 184.704);
  --chart-3: oklch(0.398 0.07 227.392);
  --chart-4: oklch(0.828 0.189 84.429);
  --chart-5: oklch(0.769 0.188 70.08);

  --ok: oklch(0.78 0.16 162);
  --warn: oklch(0.78 0.14 75);
  --danger: var(--destructive);

  --vetro-bordo: rgba(255, 255, 255, 0.09);
  --vetro-luce: rgba(255, 255, 255, 0.14);
  --vetro-contorno: rgba(0, 0, 0, 0.5);
  --vetro-tenue: rgba(255, 255, 255, 0.055);
  --vetro-tenue-bordo: rgba(255, 255, 255, 0.1);
  --vetro-tenue-hover: rgba(255, 255, 255, 0.12);
  --binario: rgba(255, 255, 255, 0.04);

  --ombra: 0 1px 2px rgba(0, 0, 0, 0.4);
  --ombra-vetro:
    0 1px 2px rgba(0, 0, 0, 0.3),
    0 8px 24px rgba(0, 0, 0, 0.38);
  --ombra-vetro-alta:
    0 2px 4px rgba(0, 0, 0, 0.34),
    0 16px 40px rgba(0, 0, 0, 0.5);

  --opacita-macchie: 0.5;
  color-scheme: dark;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-tema="chiaro"]) {
    --background: oklch(0.145 0 0);
    --foreground: oklch(0.985 0 0);
    --card: oklch(0.205 0 0);
    --card-foreground: oklch(0.985 0 0);
    --popover: oklch(0.205 0 0);
    --popover-foreground: oklch(0.985 0 0);
    --primary: oklch(0.541 0.281 293.009);
    --primary-foreground: oklch(0.969 0.016 293.756);
    --secondary: oklch(0.269 0 0);
    --secondary-foreground: oklch(0.985 0 0);
    --muted: oklch(0.269 0 0);
    --muted-foreground: oklch(0.708 0 0);
    --accent: oklch(0.269 0 0);
    --accent-foreground: oklch(0.985 0 0);
    --destructive: oklch(0.704 0.191 22.216);
    --border: oklch(1 0 0 / 10%);
    --input: oklch(1 0 0 / 15%);
    --ring: oklch(0.541 0.281 293.009);
    --chart-1: oklch(0.646 0.222 41.116);
    --chart-2: oklch(0.6 0.118 184.704);
    --chart-3: oklch(0.398 0.07 227.392);
    --chart-4: oklch(0.828 0.189 84.429);
    --chart-5: oklch(0.769 0.188 70.08);

    --ok: oklch(0.78 0.16 162);
    --warn: oklch(0.78 0.14 75);
    --danger: var(--destructive);

    --vetro-bordo: rgba(255, 255, 255, 0.09);
    --vetro-luce: rgba(255, 255, 255, 0.14);
    --vetro-contorno: rgba(0, 0, 0, 0.5);
    --vetro-tenue: rgba(255, 255, 255, 0.055);
    --vetro-tenue-bordo: rgba(255, 255, 255, 0.1);
    --vetro-tenue-hover: rgba(255, 255, 255, 0.12);
    --binario: rgba(255, 255, 255, 0.04);

    --ombra: 0 1px 2px rgba(0, 0, 0, 0.4);
    --ombra-vetro:
      0 1px 2px rgba(0, 0, 0, 0.3),
      0 8px 24px rgba(0, 0, 0, 0.38);
    --ombra-vetro-alta:
      0 2px 4px rgba(0, 0, 0, 0.34),
      0 16px 40px rgba(0, 0, 0, 0.5);

    --opacita-macchie: 0.5;
    color-scheme: dark;
  }
}

/* --------------------------------------------------------------------------
   I nomi di prima, ora alias.

   Tremila righe di foglio di stile li chiamano cosi'. Riscriverle tutte
   sarebbe stato un diff illeggibile e un'occasione di sbagliare in tremila
   punti; qui invece ogni nome storico punta al token di shadcn che gli
   corrisponde, e il foglio cambia colore senza che nessuna regola si tocchi.

   Un blocco solo, non tre: var() si risolve quando il valore serve, non
   quando viene dichiarato. Nel tema scuro --background cambia e --bg lo
   segue da se'.

   Chi scrive codice nuovo usa i nomi di shadcn, non questi: vedi CLAUDE.md.
   -------------------------------------------------------------------------- */

:root {
  --bg: var(--background);
  --text: var(--foreground);
  /* shadcn ha un solo grigio di testo spento, --muted-foreground. Resta
     quello il terziario; il secondario gli somma un 15% di --foreground,
     perche' sopra --traccia il grigio puro misura 4.35 a 10 px e la soglia
     AA e' 4.5. Si guadagna anche il livello intermedio che il design
     system non prevede. */
  --text-secondary: color-mix(in oklab, var(--muted-foreground) 85%, var(--foreground));
  --text-terziario: var(--muted-foreground);
  --campo: var(--background);
  --traccia: var(--muted);
  --hover: var(--accent);

  --accento: var(--primary);
  --accento-chiaro: color-mix(in oklab, var(--primary) 75%, white);
  --accento-premuto: color-mix(in oklab, var(--primary) 85%, black);
  --accento-tenue: color-mix(in oklab, var(--primary) 12%, transparent);
  /* --primary come testo sulla propria tinta misura 3.76: e' un colore da
     superficie, non da testo. Questo e' lo stesso viola tirato verso il
     testo quel tanto che basta a leggerlo. */
  --accento-testo: color-mix(in oklab, var(--primary) 70%, var(--foreground));
  --accento-alone: color-mix(in oklab, var(--primary) 35%, transparent);

  --ok-bg: color-mix(in oklab, var(--ok) 14%, transparent);
  --warn-bg: color-mix(in oklab, var(--warn) 14%, transparent);
  --danger-bg: color-mix(in oklab, var(--destructive) 14%, transparent);

  --card-vetro: color-mix(in oklab, var(--card) 92%, transparent);
  --vetro: color-mix(in oklab, var(--card) 58%, transparent);
  --vetro-alto: color-mix(in oklab, var(--card) 72%, transparent);
  --sfuma: blur(30px) saturate(150%);

  --cursore: color-mix(in oklab, var(--primary) 34%, transparent);
  --cursore-attivo: color-mix(in oklab, var(--primary) 60%, transparent);

  /* shadcn ha un raggio solo e ne deriva gli altri: --radius-sm e' 0.6 del
     raggio base, come in frontend/src/stile.css */
  --raggio: var(--radius);
  --raggio-piccolo: calc(var(--radius) * 0.6);

  /* I colori del marchio non sono token dell'interfaccia e non cambiano mai:
     un logo che cambia colore non e' piu' un logo. */
  --evolve-ciano: #009EE2;
  --evolve-verde: #009640;
  --evolve-rosso: #E30613;
  --evolve-grigio: #565656;
}

/* --------------------------------------------------------------------------
   Geist, il carattere di shadcn/ui.

   Sta in static/font/ e non fra le dipendenze del frontend: lo deve avere
   anche chi apre una pagina Jinja, che il bundle di Vite non lo carica
   nemmeno. Due sottoinsiemi, latino e latino esteso, circa 46 kB in tutto.
   Licenza SIL Open Font accanto ai file.
   -------------------------------------------------------------------------- */

@font-face {
  font-family: "Geist Variable";
  font-style: normal;
  font-display: swap;
  font-weight: 100 900;
  src: url("font/geist-latin-wght-normal.woff2") format("woff2-variations");
  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: "Geist Variable";
  font-style: normal;
  font-display: swap;
  font-weight: 100 900;
  src: url("font/geist-latin-ext-wght-normal.woff2") format("woff2-variations");
  unicode-range: U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;
}


* { box-sizing: border-box; }

/* ===================== sfondi animati ===================== */

/* Due livelli fissi dietro a tutto e non cliccabili. L'opacita' e' bassa di
   proposito: sopra ci sono numeri da leggere, e uno sfondo che compete con
   i dati e' uno sfondo sbagliato. */
.sfondo {
  position: fixed;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  pointer-events: none;
}

.macchia {
  position: absolute;
  width: 58vmax;
  height: 58vmax;
  border-radius: 50%;
  opacity: var(--opacita-macchie);
  filter: blur(78px);
  will-change: transform;
}

.costellazione {
  position: fixed;
  inset: 0;
  z-index: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}

/* il contenuto sta sopra gli sfondi */
.layout, .login-card { position: relative; z-index: 1; }

/* le superfici diventano appena traslucide, cosi' il movimento si intuisce
   sotto le schede senza disturbare la lettura */
.sidebar, .card, .kpi, .device-card, .alert-row, .empty, .login-card, .pill {
  background: var(--card-vetro);
  backdrop-filter: blur(6px);
}

@media (prefers-reduced-motion: reduce) {
  .macchia { opacity: 0.07; }
}

body {
  margin: 0;
  font-family: "Geist Variable", -apple-system, "Segoe UI", Roboto, Arial, sans-serif;
  background: var(--bg);
  color: var(--text);
  font-size: 14px;
}

h1 { font-size: 20px; font-weight: 600; margin: 0; }
h2 { font-size: 14px; font-weight: 600; margin: 0 0 12px; color: var(--text-secondary); }

/* ===================== struttura ===================== */

.layout { display: flex; flex-direction: column; min-height: 100vh; }



.sidebar-brand { padding: 0 0.35rem 1.5rem; }

.brand-logo {
  width: 100%;
  max-width: 175px;
  height: auto;
  display: block;
}

.brand-sub {
  font-size: 11px;
  color: var(--text-terziario);
  margin-top: 10px;
  line-height: 1.4;
}

/* Tutte le pagine raccolte sotto il nome dell'azienda: un solo gruppo oggi,
   ma la struttura regge l'aggiunta di altre sedi senza rifare la sidebar. */
.gruppo-nav { margin-bottom: 4px; }

.gruppo-nav-titolo {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 7px 10px;
  border-radius: 8px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.06em;
  color: var(--text-terziario);
  cursor: pointer;
  list-style: none;
  user-select: none;
  transition: background 0.15s ease, color 0.15s ease;
}
.gruppo-nav-titolo::-webkit-details-marker { display: none; }
.gruppo-nav-titolo:hover { background: var(--bg); color: var(--text-secondary); }

.freccia-gruppo {
  width: 0;
  height: 0;
  border-left: 4px solid currentColor;
  border-top: 3.5px solid transparent;
  border-bottom: 3.5px solid transparent;
  transition: transform 0.18s ease;
}
.gruppo-nav[open] .freccia-gruppo { transform: rotate(90deg); }

.sidebar-nav { display: flex; flex-direction: column; gap: 2px; padding-left: 6px; }

.nav-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
  border-radius: 8px;
  font-size: 13px;
  color: var(--text-secondary);
  text-decoration: none;
  transition: background 0.15s ease, color 0.15s ease;
}
.nav-item:hover { background: var(--bg); color: var(--text); }
.nav-item.attivo { background: var(--bg); color: var(--text); font-weight: 600; }

.nav-icon {
  width: 6px;
  height: 6px;
  border-radius: 2px;
  background: var(--text-terziario);
  flex-shrink: 0;
  transition: background 0.15s ease;
}
.nav-item.attivo .nav-icon { background: var(--accento); }

.sidebar-footer {
  margin-top: auto;
  padding-top: 1rem;
  border-top: 1px solid var(--border);
  font-size: 12px;
  color: var(--text-terziario);
}

.selettore-tema {
  display: flex;
  gap: 2px;
  padding: 2px;
  margin-bottom: 10px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 8px;
}
.selettore-tema button {
  flex: 1;
  padding: 4px 0;
  font-size: 11px;
  font-family: inherit;
  font-weight: 600;
  color: var(--text-terziario);
  background: transparent;
  border: none;
  border-radius: 6px;
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease;
}
.selettore-tema button:hover { color: var(--text-secondary); }
/* Pieno di --primary con --primary-foreground sopra misura 4.01, e il
   bianco puro 4.40: sotto la soglia AA per un'etichetta da 11 px. La scelta
   si segna con un anello nel colore d'accento e il testo resta quello
   normale, che e' poi come shadcn evidenzia una voce selezionata quando il
   pieno non si puo' usare. */
.selettore-tema button.attivo {
  background: var(--card);
  color: var(--text);
  box-shadow: inset 0 0 0 1px var(--primary), var(--ombra);
}

.link-status { display: flex; align-items: center; gap: 8px; }

/* LED di attivita': lampeggia come la spia di uno switch */
.link-led {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--ok);
  box-shadow: 0 0 0 0 rgba(0, 150, 64, 0.5);
  animation: battito 2.4s ease-out infinite;
}
.link-led.attivo { animation: battito 0.7s ease-out infinite; }
.link-led.spento { background: var(--danger); animation: none; }

@keyframes battito {
  0%   { box-shadow: 0 0 0 0 rgba(0, 150, 64, 0.45); }
  70%  { box-shadow: 0 0 0 6px rgba(0, 150, 64, 0); }
  100% { box-shadow: 0 0 0 0 rgba(0, 150, 64, 0); }
}

.sidebar-user {
  display: flex;
  justify-content: space-between;
  margin-top: 10px;
}
.sidebar-user a { color: var(--accento); text-decoration: none; }
.sidebar-user a:hover { text-decoration: underline; }

.main {
  width: 100%;
  min-width: 0;
  max-width: 1400px;
  margin: 0 auto;
  padding: 1.5rem 2rem 3rem;
}

.main-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: 1.25rem;
}

.sottotitolo { font-size: 12px; color: var(--text-terziario); margin-top: 3px; }

.pill {
  display: inline-block;
  padding: 5px 12px;
  border-radius: 20px;
  background: var(--card);
  border: 1px solid var(--border);
  font-size: 12px;
  color: var(--text-secondary);
  font-variant-numeric: tabular-nums;
}

/* ===================== schede ===================== */

.card {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 12px;
  box-shadow: var(--ombra);
}

.card-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 14px 18px;
  border-bottom: 1px solid var(--border);
  position: relative;
  overflow: hidden;
}
.card-titolo { font-weight: 600; font-size: 14px; }
.card-conteggio { font-size: 12px; color: var(--text-terziario); }

/* passata di scansione quando arrivano dati nuovi */
.card-header.scansione::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg, transparent, var(--accento-tenue), transparent);
  animation: scansione 0.9s ease-out;
}
@keyframes scansione {
  from { transform: translateX(-100%); }
  to   { transform: translateX(100%); }
}

/* ===================== riga KPI ===================== */

.kpi-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 14px;
  margin-bottom: 1.75rem;
}

.kpi {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 12px;
  box-shadow: var(--ombra);
  padding: 16px 18px;
}

@keyframes comparsa {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: none; }
}

.kpi-label {
  font-size: 12px;
  color: var(--text-secondary);
  display: flex;
  align-items: center;
  gap: 7px;
  margin-bottom: 8px;
}

.kpi-valore {
  font-size: 28px;
  font-weight: 600;
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
}
.kpi-valore.ok { color: var(--ok); }
.kpi-valore.warn { color: var(--warn); }
.kpi-valore.danger { color: var(--danger); }

.kpi-nota { font-size: 12px; color: var(--text-terziario); margin-top: 6px; }

.kpi-barra {
  height: 4px;
  border-radius: 2px;
  background: var(--border);
  margin-top: 12px;
  overflow: hidden;
}
.kpi-barra span {
  display: block;
  height: 100%;
  border-radius: 2px;
  background: var(--accento);
  width: 0;
}
.kpi-barra span.ok { background: var(--ok); }
.kpi-barra span.warn { background: var(--warn); }
.kpi-barra span.danger { background: var(--danger); }

/* ===================== griglia principale ===================== */

.griglia-principale {
  display: grid;
  grid-template-columns: minmax(0, 2.1fr) minmax(0, 1fr);
  gap: 20px;
  align-items: start;
  margin-bottom: 1.75rem;
}

.colonna-stretta { position: sticky; top: 1.75rem; }

/* le schede dispositivo stanno affiancate quando c'e' spazio */
#devices {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
  gap: 14px;
}

.device-card {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 12px;
  box-shadow: var(--ombra);
  padding: 1rem 1.15rem 1.1rem;
}

.device-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding-bottom: 10px;
  border-bottom: 1px solid var(--border);
}

.device-name { font-weight: 600; font-size: 14px; }

.badge {
  font-size: 11px;
  font-weight: 600;
  padding: 3px 10px;
  border-radius: 20px;
  white-space: nowrap;
}
.badge.online { background: var(--ok-bg); color: var(--ok); }
.badge.offline { background: var(--danger-bg); color: var(--danger); }

/* ===================== grafici circolari ===================== */

.tile-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(104px, 1fr));
  gap: 4px;
  padding: 14px 0 2px;
}

.tile { text-align: center; padding: 4px 2px; }

.donut { width: 70px; height: 70px; transform: rotate(-90deg); }
.donut-track { fill: none; stroke: var(--traccia); stroke-width: 7; }
.donut-value {
  fill: none;
  stroke-width: 7;
  stroke-linecap: round;
}
.donut-text {
  transform: rotate(90deg);
  transform-origin: 32px 32px;
  text-anchor: middle;
  dominant-baseline: middle;
  font-size: 17px;
  font-weight: 600;
  fill: var(--text);
  font-variant-numeric: tabular-nums;
}
.donut-pct { font-size: 10px; fill: var(--text-terziario); }

.tile-label {
  font-size: 12px;
  margin-top: 4px;
  line-height: 1.3;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 5px;
}
.tile-detail { font-size: 11px; color: var(--text-terziario); margin-top: 1px; }

.tile-dot { width: 7px; height: 7px; border-radius: 50%; flex-shrink: 0; }
.tile-dot.warn { background: var(--warn); animation: battito-punto 2s ease-out infinite; }
.tile-dot.danger { background: var(--danger); animation: battito-punto 1.2s ease-out infinite; }

@keyframes battito-punto {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.35; }
}

/* ===================== metriche testuali ===================== */

.metric-list { margin-top: 10px; }

.metric-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  font-size: 13px;
  padding: 7px 0;
  border-top: 1px solid var(--border);
}
.metric-row:first-child { border-top: none; }

.metric-label { color: var(--text-secondary); min-width: 0; }
.metric-sub { display: block; font-size: 11px; color: var(--text-terziario); }
.metric-value { font-variant-numeric: tabular-nums; text-align: right; white-space: nowrap; }
.metric-value.ok { color: var(--ok); }
.metric-value.danger { color: var(--danger); font-weight: 600; }
.metric-value.warn { color: var(--warn); font-weight: 600; }

/* ===================== alert ===================== */

.alert-row {
  display: flex;
  gap: 10px;
  padding: 12px 14px;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 10px;
  margin-bottom: 8px;
  font-size: 13px;
  box-shadow: var(--ombra);
}
.alert-row.danger { border-left: 3px solid var(--danger); }
.alert-row.warning { border-left: 3px solid var(--warn); }

.alert-dot { width: 8px; height: 8px; border-radius: 50%; margin-top: 5px; flex-shrink: 0; }
.alert-dot.danger { background: var(--danger); animation: battito-punto 1.2s ease-out infinite; }
.alert-dot.warning { background: var(--warn); }

.alert-time { color: var(--text-terziario); font-size: 11px; margin-top: 3px; }

.empty {
  color: var(--text-terziario);
  font-size: 13px;
  padding: 1rem 1.1rem;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 10px;
}

/* ===================== tabella inventario ===================== */

.tabella-scroll { overflow-x: auto; }

.tabella { width: 100%; border-collapse: collapse; font-size: 13px; }

.tabella th {
  text-align: left;
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-terziario);
  padding: 10px 18px;
  border-bottom: 1px solid var(--border);
  white-space: nowrap;
}

.tabella td {
  padding: 11px 18px;
  border-bottom: 1px solid var(--border);
  vertical-align: middle;
}
.tabella tbody tr:last-child td { border-bottom: none; }
.tabella tbody tr { transition: background 0.15s ease; }
.tabella tbody tr:hover { background: var(--bg); }

.destra { text-align: right; }
.td-valore { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.td-dispositivo { font-weight: 600; white-space: nowrap; }

.chip {
  display: inline-block;
  padding: 2px 9px;
  border-radius: 20px;
  font-size: 11px;
  font-weight: 600;
  white-space: nowrap;
}
.chip.ok { background: var(--ok-bg); color: var(--ok); }
.chip.warn { background: var(--warn-bg); color: var(--warn); }
.chip.danger { background: var(--danger-bg); color: var(--danger); }
.chip.neutro { background: var(--bg); color: var(--text-secondary); }

.tipo-tag { font-size: 12px; color: var(--text-secondary); }

/* scheletro di caricamento: barre che scorrono come dati in transito */
.skeleton {
  height: 12px;
  border-radius: 4px;
  background: linear-gradient(90deg, var(--traccia) 25%, var(--hover) 37%, var(--traccia) 63%);
  background-size: 400% 100%;
  animation: scorrimento 1.3s ease infinite;
}
@keyframes scorrimento {
  from { background-position: 100% 50%; }
  to   { background-position: 0 50%; }
}

/* ===================== elementi comuni alle pagine ===================== */

.nav-conteggio {
  margin-left: auto;
  min-width: 19px;
  height: 19px;
  padding: 0 6px;
  border-radius: 10px;
  color: #fff;
  font-size: 11px;
  font-weight: 600;
  display: none;
  align-items: center;
  justify-content: center;
  transition: background 0.3s ease;
}
.nav-conteggio.visibile { display: flex; }

/* il colore segue la gravita' peggiore fra gli alert non letti */
.nav-conteggio.critico {
  background: var(--danger);
  animation: pulsa-badge 1.8s ease-out infinite;
}
.nav-conteggio.avviso {
  /* l'ambra della palette e' troppo chiara per reggere il testo bianco:
     qui serve il tono scuro, altrimenti il numero diventa illeggibile */
  background: var(--warn);
}

@keyframes pulsa-badge {
  0%   { box-shadow: 0 0 0 0 rgba(227, 6, 19, 0.5); }
  70%  { box-shadow: 0 0 0 7px rgba(227, 6, 19, 0); }
  100% { box-shadow: 0 0 0 0 rgba(227, 6, 19, 0); }
}

@media (prefers-reduced-motion: reduce) {
  .nav-conteggio.critico { animation: none; }
}

.card-sotto { font-size: 12px; color: var(--text-terziario); margin-top: 3px; }

.vuoto-inline { color: var(--text-terziario); font-size: 13px; padding: 1rem 1.15rem; }
.vuoto-cella { color: var(--text-terziario); padding: 1rem 18px; }

.vedi-tutti {
  display: block;
  text-align: center;
  padding: 9px;
  font-size: 12px;
  color: var(--accento);
  text-decoration: none;
}
.vedi-tutti:hover { text-decoration: underline; }

.conta-grigio { font-size: 12px; color: var(--text-terziario); }

.riepilogo-filtro {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 0.75rem;
}
.riepilogo-filtro.seconda-riga { margin-bottom: 1.25rem; }

/* ===================== pagina dispositivi ===================== */

.scheda-estesa { margin-bottom: 14px; }

.tile-grid.con-bordo { padding: 16px 18px; border-bottom: 1px solid var(--border); }

.tabella-interna { font-size: 13px; }
.tabella-interna td { padding: 10px 18px; }
.tabella-interna td:first-child { color: var(--text-secondary); }
.td-stato { width: 1%; white-space: nowrap; }
.td-valore.ok { color: var(--ok); }
.td-valore.warn { color: var(--warn); font-weight: 600; }
.td-valore.danger { color: var(--danger); font-weight: 600; }

/* ===================== panoramica a plancia ===================== */

.plancia-panoramica {
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr) minmax(0, 1fr);
  gap: 16px;
  height: calc(100vh - 364px);
  min-height: 360px;
}

.colonna-plancia {
  display: flex;
  flex-direction: column;
  min-height: 0;
  overflow: hidden;
}
.corpo-plancia { padding: 10px 14px 14px; overflow-y: auto; flex: 1; }
.corpo-risorse { display: flex; flex-direction: column; gap: 10px; }

.riga-dispositivo {
  display: grid;
  grid-template-columns: 10px minmax(0, auto) minmax(0, 1fr);
  align-items: center;
  gap: 9px;
  padding: 9px 2px;
  border-top: 1px solid var(--border);
}
.riga-dispositivo:first-child { border-top: none; }

.pallino-stato {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  flex-shrink: 0;
}
.pallino-stato.online { background: var(--ok); }
.pallino-stato.offline { background: var(--danger); animation: battito-punto 1.2s ease-out infinite; }

.disp-nome {
  font-size: 13px;
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.disp-chip { display: flex; flex-wrap: wrap; gap: 4px; justify-content: flex-end; }

.mini-chip {
  font-size: 10px;
  padding: 2px 7px;
  border-radius: 10px;
  background: var(--bg);
  color: var(--text-secondary);
  white-space: nowrap;
}
.mini-chip.ok { background: var(--ok-bg); color: var(--ok); }
.mini-chip.warn { background: var(--warn-bg); color: var(--warn); font-weight: 600; }
.mini-chip.danger { background: var(--danger-bg); color: var(--danger); font-weight: 600; }

.elenco-barre { display: flex; flex-direction: column; gap: 8px; }

.riga-barra {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 70px 38px;
  align-items: center;
  gap: 8px;
  font-size: 11px;
}
.barra-etichetta {
  color: var(--text-secondary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.barra-etichetta .metric-sub { display: block; font-size: 10px; }
.barra-piccola {
  height: 6px;
  border-radius: 3px;
  background: var(--traccia);
  overflow: hidden;
}
.barra-piccola span { display: block; height: 100%; width: 0; background: var(--accento); }
.barra-piccola span.ok { background: var(--ok); }
.barra-piccola span.warn { background: var(--warn); }
.barra-piccola span.danger { background: var(--danger); }
.barra-valore {
  text-align: right;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.barra-valore.ok { color: var(--ok); }
.barra-valore.warn { color: var(--warn); }
.barra-valore.danger { color: var(--danger); }

.corpo-plancia .alert-row { box-shadow: none; margin-bottom: 6px; }

@media (max-width: 1100px) {
  .plancia-panoramica { grid-template-columns: 1fr; height: auto; }
  .corpo-plancia { overflow: visible; }
}

/* ===================== pagina telecamere ===================== */

/* ---- sottomenu per sede ---- */

.sottomenu {
  display: flex;
  gap: 6px;
  margin-bottom: 14px;
  border-bottom: 1px solid var(--border);
}

.scheda-telecamere {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 14px;
  font-size: 13px;
  font-family: inherit;
  font-weight: 600;
  color: var(--text-secondary);
  background: transparent;
  border: none;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  cursor: pointer;
  transition: color 0.15s ease, border-color 0.15s ease;
}
.scheda-telecamere:hover { color: var(--text); }
.scheda-telecamere.attiva {
  color: var(--text);
  border-bottom-color: var(--accento);
}

.scheda-conta {
  font-size: 11px;
  font-weight: 600;
  padding: 1px 7px;
  border-radius: 10px;
  background: var(--bg);
  color: var(--text-terziario);
}
.scheda-conta.giu { background: var(--danger-bg); color: var(--danger); }

/* Plancia a due colonne alta quanto la finestra: i grafici a sinistra non si
   muovono, l'elenco a destra scorre dentro il proprio riquadro. Cosi' lo
   stato complessivo resta sempre sotto gli occhi anche con molti siti. */
.telecamere-plancia {
  display: grid;
  grid-template-columns: 260px minmax(0, 1fr);
  gap: 16px;
  height: calc(100vh - 322px);
  min-height: 400px;
}

.colonna-grafici {
  display: grid;
  grid-template-rows: auto minmax(0, 1fr);
  gap: 16px;
  min-height: 0;
}

.riquadro-anello, .riquadro-siti, .colonna-griglia {
  display: flex;
  flex-direction: column;
  min-height: 0;
  overflow: hidden;
}

/* ---- anello riepilogativo ---- */

.corpo-anello {
  padding: 14px 16px 16px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
}

.anello-grande { width: 130px; height: 130px; transform: rotate(-90deg); }
.anello-fondo { fill: none; stroke: var(--danger); stroke-width: 11; opacity: 0.35; }
.anello-quota {
  fill: none;
  stroke: var(--ok);
  stroke-width: 11;
  stroke-linecap: round;
}
.anello-numero, .anello-sotto {
  transform: rotate(90deg);
  transform-origin: 65px 65px;
  text-anchor: middle;
  fill: var(--text);
  font-variant-numeric: tabular-nums;
}
.anello-numero { font-size: 30px; font-weight: 700; }
.anello-sotto { font-size: 12px; fill: var(--text-terziario); }

.anello-didascalia {
  display: flex;
  flex-direction: column;
  gap: 5px;
  font-size: 12px;
  color: var(--text-secondary);
}
.anello-didascalia span { display: flex; align-items: center; gap: 7px; }

.quadretto { width: 9px; height: 9px; border-radius: 3px; display: inline-block; }
.quadretto.online { background: var(--ok); }
.quadretto.offline { background: var(--danger); }

/* ---- barre per sito ---- */

.corpo-siti {
  padding: 10px 14px 12px;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 7px;
}

.riga-sito {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 54px 34px;
  align-items: center;
  gap: 8px;
  font-size: 11px;
}
.sito-nome {
  color: var(--text-secondary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.sito-barra {
  height: 6px;
  border-radius: 3px;
  background: var(--danger);
  overflow: hidden;
}
.parte-online { display: block; height: 100%; width: 0; background: var(--ok); }
.sito-conta {
  text-align: right;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.sito-conta.ok { color: var(--ok); }
.sito-conta.warn { color: var(--warn); }
.sito-conta.danger { color: var(--danger); }

/* ---- griglia delle telecamere ---- */

.gruppo-bottoni { display: flex; gap: 6px; }

.corpo-griglia {
  padding: 12px 16px 16px;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.sito-blocco { display: flex; flex-direction: column; gap: 6px; }

.sito-intestazione {
  display: flex;
  align-items: center;
  gap: 8px;
  padding-bottom: 4px;
  border-bottom: 1px solid var(--border);
}
.sito-titolo { font-size: 12px; font-weight: 600; }

.pastiglie { display: flex; flex-wrap: wrap; gap: 5px; }

/* una pastiglia per telecamera: piccola abbastanza da farle stare tutte
   sotto gli occhi, grande abbastanza da leggerne il nome */
.pastiglia {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  max-width: 190px;
  padding: 4px 9px 4px 7px;
  border-radius: 14px;
  font-size: 11px;
  line-height: 1.3;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  border: 1px solid var(--border);
  background: var(--bg);
  color: var(--text-secondary);
  cursor: default;
  transition: transform 0.12s ease;
}
.pastiglia::before {
  content: "";
  width: 7px;
  height: 7px;
  border-radius: 50%;
  flex-shrink: 0;
}
.pastiglia:hover { transform: translateY(-1px); }

.pastiglia.online { border-color: var(--ok-bg); background: var(--ok-bg); color: var(--ok); }
.pastiglia.online::before { background: var(--ok); }
.pastiglia.offline {
  border-color: var(--danger-bg);
  background: var(--danger-bg);
  color: var(--danger);
  font-weight: 600;
}
.pastiglia.offline::before { background: var(--danger); }

.stato-sereno.senza-bordo { padding: 1rem 0; }

@media (max-width: 900px) {
  .telecamere-plancia {
    grid-template-columns: 1fr;
    height: auto;
  }
  .colonna-grafici { grid-template-rows: auto auto; }
  .corpo-griglia, .corpo-siti { overflow: visible; }
}

/* ===================== pagina rete: pannello porte ===================== */

.titolo-sito { margin-top: 1.5rem; }
.scheda-apparato { margin-bottom: 14px; }
.corpo-apparato { padding: 16px 18px; }

/* Il pannello imita il frontale dell'apparato: prese raggruppate a quattro,
   LED che segue la velocita' negoziata, alloggiamenti in fibra separati.
   Non e' decorazione: chi cerca una porta in sala macchine la conta sullo
   switch, e ritrovare la stessa disposizione evita di sbagliare presa. */

.pannello-porte { max-width: 100%; overflow-x: auto; padding: 2px 2px 16px; }

.chassis {
  display: inline-flex;
  align-items: stretch;
  gap: 14px;
  padding: 14px 16px;
  border-radius: 12px;
  background: linear-gradient(180deg, #2b3037 0%, #1e2227 100%);
  border: 1px solid #383e46;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.06),
              0 2px 10px rgba(0, 0, 0, 0.18);
}

.gruppo-rame, .gruppo-fibra { display: flex; flex-direction: column; gap: 7px; }
.gruppo-fibra { position: relative; }

.separatore-chassis {
  width: 1px;
  background: linear-gradient(180deg, transparent, #454c55 20%, #454c55 80%, transparent);
}

.etichetta-gruppo {
  position: absolute;
  bottom: -13px;
  left: 0;
  right: 0;
  text-align: center;
  font-size: 8px;
  letter-spacing: 0.14em;
  color: #6b7480;
}

.fila-porte { display: flex; gap: 10px; }
.blocco-porte { display: flex; gap: 3px; }

.porta {
  position: relative;
  width: 30px;
  padding: 3px 0 2px;
  border-radius: 4px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  background: #14171b;
  border: 1px solid #333941;
  cursor: default;
  flex-shrink: 0;
  transition: transform 0.14s ease, box-shadow 0.14s ease, border-color 0.14s ease;
}

/* la presa: sagoma della bocca RJ45 con la tacca del fermo in alto */
.porta-presa {
  position: relative;
  width: 19px;
  height: 15px;
  background: #0a0c0e;
  border: 1px solid #2a3037;
  border-radius: 2px;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  padding-bottom: 1px;
}
.porta-presa::after {
  content: "";
  position: absolute;
  top: -1px;
  left: 50%;
  transform: translateX(-50%);
  width: 7px;
  height: 4px;
  background: #14171b;
  border: 1px solid #2a3037;
  border-top: none;
  border-radius: 0 0 2px 2px;
}

/* l'alloggiamento in fibra e' una feritoia, non una bocca RJ45 */
.porta.fibra .porta-presa { border-radius: 1px; background: #0d1116; }
.porta.fibra .porta-presa::after {
  top: 50%;
  transform: translate(-50%, -50%);
  width: 13px;
  height: 3px;
  background: #05070a;
  border: none;
  border-radius: 1px;
}

.porta-led {
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: #22282f;
  position: relative;
  z-index: 1;
}
.porta-led.pieno {
  background: #35d17a;
  box-shadow: 0 0 5px rgba(53, 209, 122, 0.75);
}
.porta-led.ridotto {
  background: #f0b429;
  box-shadow: 0 0 5px rgba(240, 180, 41, 0.7);
}
.porta-led.spento { background: #232930; box-shadow: none; }

.porta-num {
  font-size: 9px;
  font-weight: 600;
  color: #79828d;
  font-variant-numeric: tabular-nums;
  line-height: 1;
}

.porta.su { border-color: #3f4a55; background: #171c22; }
.porta.su .porta-num { color: #c8d2dc; }
.porta.disabilitata { border-color: #6d2f34; background: #241417; }
.porta.disabilitata .porta-num { color: #b0757a; }

/* barretta ambra sotto la presa: la porta sta erogando corrente */
.porta.poe::after {
  content: "";
  position: absolute;
  left: 6px;
  right: 6px;
  bottom: -1px;
  height: 2px;
  border-radius: 1px;
  background: #f0a92b;
  box-shadow: 0 0 4px rgba(240, 169, 43, 0.6);
}

.porta:hover {
  transform: translateY(-3px);
  border-color: var(--accento);
  box-shadow: 0 5px 14px rgba(0, 0, 0, 0.45),
              0 0 0 1px var(--accento-alone);
}

/* porta con traffico: il LED respira, come la spia di attivita' */
.porta.attiva .porta-led.pieno,
.porta.attiva .porta-led.ridotto { animation: attivita 1.4s ease-in-out infinite; }

@keyframes attivita {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.4; }
}

/* segno del ruolo: la porta che sale verso la dorsale e quelle che scendono
   verso altri apparati non sono porte come le altre */
.porta-ruolo {
  position: absolute;
  top: -6px;
  right: -5px;
  width: 14px;
  height: 14px;
  border-radius: 4px;
  font-size: 8px;
  font-style: normal;
  line-height: 14px;
  text-align: center;
  color: #fff;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.45);
}
.porta-ruolo.uplink { background: var(--accento); }
.porta-ruolo.downlink { background: #6b7684; }

.porta.uplink { border-color: var(--accento); }
.porta.uplink .porta-presa { border-color: #2b6c8c; }
.porta.downlink { border-color: #5b6672; }

.segno-ruolo {
  width: 14px;
  height: 14px;
  border-radius: 4px;
  font-size: 8px;
  font-style: normal;
  line-height: 14px;
  text-align: center;
  color: #fff;
  display: inline-block;
}
.segno-ruolo.uplink { background: var(--accento); }
.segno-ruolo.downlink { background: #6b7684; }

.pop-etichetta {
  font-size: 9px;
  font-weight: 600;
  letter-spacing: 0.06em;
  background: #2b3138;
  color: #b9c1ca;
  border-radius: 3px;
  padding: 1px 5px;
  margin-left: 4px;
  vertical-align: middle;
}

.pop-ruolo {
  margin-top: 4px;
  font-size: 11px;
  font-weight: 600;
}
.pop-ruolo.uplink { color: #7fc9f0; }
.pop-ruolo.downlink { color: #a8b0ba; }

.porta-multi {
  position: absolute;
  top: -5px;
  right: -5px;
  min-width: 13px;
  height: 13px;
  border-radius: 7px;
  background: var(--accento);
  color: #fff;
  font-size: 9px;
  font-style: normal;
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 3px;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.4);
}

.legenda {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 16px;
  margin-top: 12px;
  font-size: 11px;
  color: var(--text-terziario);
}
.legenda span { display: flex; align-items: center; gap: 6px; }

.legenda-pagina {
  margin: 0 0 1rem;
  padding: 10px 14px;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 10px;
}
.legenda-nota { margin-left: auto; font-style: italic; }

.pallino-led {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  display: inline-block;
}
.pallino-led.pieno { background: #2bb26a; box-shadow: 0 0 4px rgba(43, 178, 106, 0.6); }
.pallino-led.ridotto { background: #d99b16; box-shadow: 0 0 4px rgba(217, 155, 22, 0.6); }
.pallino-led.spento { background: var(--text-terziario); }

.pallino-poe {
  width: 12px;
  height: 3px;
  border-radius: 2px;
  background: #f0a92b;
  display: inline-block;
}

.pallino-fibra {
  width: 12px;
  height: 8px;
  border-radius: 1px;
  background: #2b3037;
  display: inline-block;
  position: relative;
}
.pallino-fibra::after {
  content: "";
  position: absolute;
  inset: 3px 2px;
  background: #0a0c0e;
  border-radius: 1px;
}

@media (prefers-reduced-motion: reduce) {
  .porta.attiva .porta-led { animation: none; }
}

.porta { position: relative; }

.porta-multi {
  position: absolute;
  top: -4px;
  right: -4px;
  min-width: 13px;
  height: 13px;
  border-radius: 7px;
  background: var(--accento);
  color: #fff;
  font-size: 9px;
  font-style: normal;
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 3px;
}

/* ---- popup di dettaglio porta ---- */

.popup-porta {
  position: absolute;
  z-index: 50;
  display: none;
  min-width: 240px;
  max-width: 340px;
  padding: 11px 13px;
  border-radius: 10px;
  background: #1d2126;
  color: #e8eaed;
  font-size: 12px;
  line-height: 1.45;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.28);
  pointer-events: none;
  animation: comparsa 0.14s ease both;
}

.pop-titolo { font-weight: 600; font-size: 13px; margin-bottom: 2px; }
.pop-stato { color: #a8b0ba; }
.pop-traffico { color: #7fc9f0; font-variant-numeric: tabular-nums; margin-top: 2px; }

.pop-elenco {
  margin-top: 8px;
  padding-top: 8px;
  border-top: 1px solid #31363d;
  display: flex;
  flex-direction: column;
  gap: 5px;
}

.pop-riga { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; }
.pop-pallino {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: #4ea86f;
  flex-shrink: 0;
}
.pop-pallino.apparato { background: var(--accento); }
.pop-nome { font-weight: 600; }
.pop-ip { color: #9aa3ad; font-variant-numeric: tabular-nums; }
.pop-tipo {
  font-size: 10px;
  background: #2b3138;
  color: #b9c1ca;
  border-radius: 4px;
  padding: 1px 6px;
}
.pop-byte { color: #8a929c; font-size: 11px; margin-left: auto; white-space: nowrap; }
.pop-altri, .pop-vuoto { color: #8a929c; font-style: italic; margin-top: 6px; }

/* ---- schede access point ---- */

.corpo-ap { padding: 16px 18px; }

.ap-numeri {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  gap: 18px;
  margin-bottom: 16px;
}

.ap-etichetta { font-size: 12px; color: var(--text-terziario); margin-bottom: 4px; }
.ap-valore { font-size: 30px; font-weight: 600; line-height: 1; font-variant-numeric: tabular-nums; }

.barra-bande {
  display: flex;
  height: 7px;
  border-radius: 4px;
  overflow: hidden;
  background: var(--border);
  margin-top: 10px;
}
.segmento { width: 0; }
.segmento.due { background: var(--accento); }
.segmento.cinque { background: var(--evolve-verde); }

.legenda-bande {
  display: flex;
  gap: 14px;
  margin-top: 7px;
  font-size: 11px;
  color: var(--text-secondary);
}
.legenda-bande span { display: flex; align-items: center; gap: 5px; }
.pallino-banda { width: 8px; height: 8px; border-radius: 2px; display: inline-block; }
.pallino-banda.due { background: var(--accento); }
.pallino-banda.cinque { background: var(--evolve-verde); }

.nessun-client { font-size: 12px; color: var(--text-terziario); margin-top: 10px; }

.ap-banda {
  display: flex;
  gap: 16px;
  font-size: 19px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  margin-top: 2px;
}
.ap-banda small { font-size: 11px; font-weight: 500; color: var(--text-terziario); }
.ap-banda .giu { color: var(--accento); }
.ap-banda .su { color: var(--evolve-verde); }

.ap-totali { font-size: 11px; color: var(--text-terziario); margin-top: 8px; }

/* ---- grafico ad area ---- */

.grafico { margin-bottom: 12px; }

.area {
  width: 100%;
  height: 64px;
  display: block;
  overflow: visible;
}
.area-giu { fill: var(--accento-tenue); stroke: none; }
.linea-giu { fill: none; stroke: var(--accento); stroke-width: 1.6; vector-effect: non-scaling-stroke; }
.linea-su { fill: none; stroke: var(--evolve-verde); stroke-width: 1.6; vector-effect: non-scaling-stroke; }

.grafico-assi {
  display: flex;
  justify-content: space-between;
  font-size: 11px;
  color: var(--text-terziario);
  margin-top: 4px;
}

.grafico-vuoto {
  font-size: 12px;
  color: var(--text-terziario);
  font-style: italic;
  padding: 14px 0;
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
  margin-bottom: 12px;
}

/* ---- confronto tra access point ---- */

.riepilogo-ap { margin-bottom: 1rem; }
.corpo-riepilogo { padding: 14px 18px; display: flex; flex-direction: column; gap: 10px; }

.riga-confronto {
  display: grid;
  grid-template-columns: minmax(110px, 1.1fr) 3fr auto auto;
  align-items: center;
  gap: 12px;
  font-size: 12px;
}
.confronto-nome { font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.confronto-barra { height: 8px; border-radius: 4px; background: var(--bg); overflow: hidden; }
.confronto-barra span {
  display: block;
  height: 100%;
  border-radius: 4px;
  background: var(--accento);
  width: 0;
}
.confronto-valore { font-weight: 600; font-variant-numeric: tabular-nums; min-width: 24px; text-align: right; }
.confronto-banda {
  color: var(--text-terziario);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  min-width: 128px;
  text-align: right;
}

@media (max-width: 620px) {
  .riga-confronto { grid-template-columns: 1fr auto; }
  .confronto-barra, .confronto-banda { display: none; }
}

.avviso-configurazione { padding: 1.5rem 1.75rem; }
.avviso-titolo { font-weight: 600; margin-bottom: 0.75rem; }
.avviso-configurazione p { margin: 0 0 0.75rem; color: var(--text-secondary); line-height: 1.55; }
.avviso-nota { font-size: 12px; color: var(--text-terziario) !important; }
.avviso-configurazione code {
  background: var(--bg);
  padding: 1px 6px;
  border-radius: 4px;
  font-size: 12px;
}

/* ===================== pagina alert ===================== */

.gruppo-alert { margin-bottom: 14px; }
.corpo-gruppo { padding: 12px 14px; }
.corpo-gruppo .alert-row { box-shadow: none; }
.corpo-gruppo .alert-row:last-child { margin-bottom: 0; }

.riga-risolta { opacity: 0.55; }
.td-letto { width: 1%; white-space: nowrap; }

.barra-azioni {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 11px 14px;
  margin-bottom: 14px;
  background: var(--warn-bg);
  color: var(--warn);
  border-radius: 10px;
  font-size: 13px;
  font-weight: 600;
}
.barra-azioni button { background: var(--campo); }

.alert-corpo { flex: 1; min-width: 0; }

/* un alert gia' visionato resta visibile ma smette di reclamare attenzione */
.alert-row.letto { opacity: 0.62; }
.alert-row.letto .alert-dot { animation: none; }

/* un alert chiuso perde il bordo colorato: non e' piu' una cosa da fare */
.alert-row.chiuso {
  opacity: 0.7;
  border-left-color: var(--border);
}
.alert-row.chiuso .alert-dot { animation: none; }
.alert-dot.chiuso { background: var(--ok); }

.azioni-alert {
  display: flex;
  gap: 6px;
  align-self: flex-start;
  flex-shrink: 0;
}

.sezione-chiusi { margin-bottom: 1.75rem; }
.sezione-chiusi .corpo-gruppo { padding: 12px 14px; }
.sezione-chiusi .alert-row { box-shadow: none; }
.sezione-chiusi .alert-row:last-child { margin-bottom: 0; }

@media (max-width: 620px) {
  .alert-row { flex-wrap: wrap; }
  .azioni-alert { width: 100%; justify-content: flex-end; }
}
.td-quando { white-space: nowrap; color: var(--text-secondary); }

.stato-sereno {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 1.5rem 1.75rem;
}
.sereno-titolo { font-weight: 600; }
.sereno-sotto { font-size: 13px; color: var(--text-terziario); margin-top: 3px; }

/* spunta che si disegna da sola */
.cerchio-ok {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: var(--ok-bg);
  position: relative;
  flex-shrink: 0;
}
.cerchio-ok::after {
  content: "";
  position: absolute;
  left: 14px;
  top: 10px;
  width: 8px;
  height: 15px;
  border: solid var(--ok);
  border-width: 0 2.5px 2.5px 0;
  transform: rotate(45deg);
  transform-origin: center;
  animation: spunta 0.45s ease-out both;
}
@keyframes spunta {
  from { opacity: 0; transform: rotate(45deg) scale(0.4); }
  to   { opacity: 1; transform: rotate(45deg) scale(1); }
}

/* ===================== moduli e amministrazione ===================== */

.sidebar-user { flex-direction: column; align-items: flex-start; gap: 4px; }
.sidebar-user.senza-login { color: var(--text-terziario); font-size: 11px; font-style: italic; }

.utente-nome {
  color: var(--text) !important;
  text-decoration: none;
  font-weight: 600;
  display: flex;
  flex-direction: column;
  gap: 1px;
}
.utente-nome:hover { text-decoration: none !important; }
.utente-ruolo { font-size: 10px; font-weight: 500; color: var(--text-terziario); }

.avviso {
  padding: 11px 14px;
  border-radius: 10px;
  font-size: 13px;
  margin-bottom: 1rem;
  animation: comparsa 0.3s ease both;
}
.avviso.ok { background: var(--ok-bg); color: var(--ok); }
.avviso.errore { background: var(--danger-bg); color: var(--danger); }

.griglia-utenti {
  display: grid;
  grid-template-columns: minmax(0, 2.1fr) minmax(360px, 1fr);
  gap: 20px;
  align-items: start;
}

/* La tabella degli utenti: le colonne strette restano strette, e quella
   dei clienti si prende lo spazio avanzato invece di lasciarlo in fondo. */
.griglia-utenti .tabella { table-layout: fixed; width: 100%; }
.griglia-utenti .tabella th:nth-child(1),
.griglia-utenti .tabella td:nth-child(1) { width: 22%; }
.griglia-utenti .tabella th:nth-child(2),
.griglia-utenti .tabella td:nth-child(2) { width: 20%; }
.griglia-utenti .tabella th:nth-child(3),
.griglia-utenti .tabella td:nth-child(3) { width: 30%; }
.griglia-utenti .tabella th:nth-child(4),
.griglia-utenti .tabella td:nth-child(4) { width: 28%; }

.scheda-stretta { max-width: 420px; }

.modulo { padding: 16px 18px; }
.modulo label {
  display: block;
  font-size: 12px;
  color: var(--text-secondary);
  margin-bottom: 5px;
}
/* Le caselle di spunta vanno escluse: con width 100% e un margine sotto
   diventavano larghe quanto il modulo e mandavano a capo la propria
   etichetta, che e' il motivo per cui l'elenco dei clienti si leggeva a
   fatica. */
.modulo input:not([type="checkbox"]):not([type="radio"]), .modulo select {
  width: 100%;
  padding: 9px 11px;
  font-size: 14px;
  font-family: inherit;
  color: var(--text);
  background: var(--campo);
  border: 1px solid var(--border);
  border-radius: 8px;
  margin-bottom: 1rem;
}
.modulo input:focus, .modulo select:focus, .riga-azione select:focus {
  outline: none;
  border-color: var(--accento);
  box-shadow: 0 0 0 3px rgba(91, 91, 214, 0.14);
}
.modulo .nota-campo {
  font-size: 11px;
  color: var(--text-terziario);
  margin: -0.75rem 0 1rem;
}
.modulo button {
  width: 100%;
  padding: 10px;
  font-size: 14px;
  font-weight: 600;
  font-family: inherit;
  color: #fff;
  background: var(--accento);
  border: none;
  border-radius: 8px;
  cursor: pointer;
}
.modulo button:hover { background: var(--accento-premuto); }

.riga-azione { display: inline; margin: 0; }
.riga-azione select {
  padding: 5px 8px;
  font-size: 12px;
  font-family: inherit;
  color: var(--text);
  background: var(--campo);
  border: 1px solid var(--border);
  border-radius: 6px;
}

.azioni-riga { display: flex; gap: 6px; justify-content: flex-end; }

.bottone-piccolo {
  padding: 5px 11px;
  font-size: 12px;
  font-family: inherit;
  font-weight: 600;
  color: var(--text-secondary);
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 6px;
  cursor: pointer;
  white-space: nowrap;
}
.bottone-piccolo:hover { background: var(--hover); color: var(--text); }
.bottone-piccolo.pericolo { color: var(--danger); }
.bottone-piccolo.pericolo:hover { background: var(--danger-bg); }

.facoltativo {
  font-weight: 400;
  font-style: italic;
  color: var(--text-terziario);
}

.tu {
  font-size: 10px;
  font-weight: 600;
  background: var(--ok-bg);
  color: var(--ok);
  border-radius: 4px;
  padding: 1px 6px;
  margin-left: 7px;
}

.bottone-link {
  display: inline-block;
  margin-top: 1.25rem;
  padding: 9px 18px;
  font-size: 13px;
  font-weight: 600;
  color: #fff;
  background: var(--accento);
  border-radius: 8px;
  text-decoration: none;
}

@media (max-width: 900px) {
  .griglia-utenti { grid-template-columns: 1fr; }
}

/* ===================== pagina di accesso ===================== */

.login-body {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
  padding: 1.5rem;
  background: var(--bg);
}

.login-card {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 16px;
  padding: 2.25rem 2rem;
  width: 100%;
  max-width: 350px;
  box-shadow: 0 4px 16px rgba(16, 24, 40, 0.06);
}

/* l'ingresso della scheda, del marchio e dei campi lo compone anime.js
   in login.html: qui resterebbe solo a sovrapporsi */
.login-logo {
  width: 84px;
  height: 84px;
  display: block;
  margin: 0 auto 1rem;
}

.login-title {
  text-align: center;
  font-size: 14px;
  font-weight: 600;
  margin-bottom: 0.25rem;
}
.login-sub {
  text-align: center;
  font-size: 12px;
  color: var(--text-terziario);
  margin-bottom: 1.5rem;
}

.login-card label {
  display: block;
  font-size: 12px;
  color: var(--text-secondary);
  margin-bottom: 5px;
}

.login-card input {
  width: 100%;
  padding: 10px 12px;
  font-size: 14px;
  font-family: inherit;
  border: 1px solid var(--border);
  border-radius: 8px;
  margin-bottom: 1rem;
  background: var(--campo);
  color: var(--text);
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
.login-card input:focus {
  outline: none;
  border-color: var(--accento);
  box-shadow: 0 0 0 3px rgba(91, 91, 214, 0.14);
}

.login-card button {
  width: 100%;
  padding: 11px;
  font-size: 14px;
  font-weight: 600;
  font-family: inherit;
  color: #fff;
  background: var(--accento);
  border: none;
  border-radius: 8px;
  cursor: pointer;
  margin-top: 0.25rem;
  transition: background 0.15s ease;
}
.login-card button:hover { background: var(--accento-premuto); }

.login-error {
  background: var(--danger-bg);
  color: var(--danger);
  font-size: 13px;
  padding: 10px 12px;
  border-radius: 8px;
  margin-bottom: 1rem;
}

/* ===================== adattamento a schermi stretti ===================== */

@media (max-width: 1080px) {
  .griglia-principale { grid-template-columns: 1fr; }
  .colonna-stretta { position: static; }
}

@media (max-width: 760px) {
  .layout { flex-direction: column; }
  .sidebar {
    width: 100%;
    height: auto;
    position: static;
    flex-direction: row;
    align-items: center;
    gap: 1rem;
    padding: 0.85rem 1rem;
    border-right: none;
    border-bottom: 1px solid var(--border);
  }
  .sidebar-brand { padding: 0; }
  .brand-logo { max-width: 120px; }
  .brand-sub, .sidebar-nav { display: none; }
  .sidebar-footer { margin: 0 0 0 auto; padding: 0; border: none; }
  .main { padding: 1.25rem 1rem 2.5rem; }
}

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

/* ===================== modalita' chiosco ===================== */

/* Schermata per un monitor a parete: si legge da qualche metro, sta in una
   videata senza scorrere, e non ha nulla da cliccare. Le dimensioni sono in
   vmin cosi' il testo cresce con lo schermo: su un 55 pollici i numeri
   restano grandi come su un 24. */

.chiosco {
  height: 100vh;
  display: grid;
  grid-template-rows: auto auto minmax(0, 1fr);
  gap: 1.4vmin;
  padding: 1.6vmin 2vmin 2vmin;
  overflow: hidden;
}

.chiosco-testata {
  display: flex;
  align-items: center;
  gap: 2vmin;
}
.chiosco-logo { height: 3vmin; min-height: 26px; width: auto; }
.chiosco-titolo {
  font-size: 1.51vmin;
  font-weight: 600;
  letter-spacing: 0.02em;
  padding-left: 2vmin;
  border-left: 1px solid var(--border);
}
.chiosco-strumenti {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 1.6vmin;
  font-size: 1.08vmin;
  color: var(--text-terziario);
}
.chiosco-orologio {
  font-size: 1.87vmin;
  font-weight: 700;
  color: var(--text);
  font-variant-numeric: tabular-nums;
}
.chiosco-vivo { display: flex; align-items: center; gap: 0.9vmin; }

/* ---- fascia dei numeri ---- */

.chiosco-numeri {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  gap: 1.4vmin;
}

.chiosco-numero {
  padding: 1.8vmin 2vmin;
  border-radius: 1.4vmin;
  background: var(--card);
  border: 1px solid var(--border);
  border-left: 0.7vmin solid var(--text-terziario);
}
.chiosco-numero.ok { border-left-color: var(--ok); }
.chiosco-numero.attenzione { border-left-color: var(--warn); }
.chiosco-numero.guasto { border-left-color: var(--danger); }

.chiosco-cifra {
  font-size: 4.32vmin;
  font-weight: 700;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}
.chiosco-numero.ok .chiosco-cifra { color: var(--ok); }
.chiosco-numero.attenzione .chiosco-cifra { color: var(--warn); }
.chiosco-numero.guasto .chiosco-cifra { color: var(--danger); }

.chiosco-nome {
  font-size: 1.22vmin;
  font-weight: 600;
  margin-top: 0.8vmin;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-secondary);
}
.chiosco-nota { font-size: 0.79vmin; color: var(--text-terziario); margin-top: 0.3vmin; }

/* ---- corpo ---- */

.chiosco-corpo {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr) minmax(0, 1.35fr);
  gap: 1.4vmin;
  min-height: 0;
}

.chiosco-riquadro {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 1.4vmin;
  padding: 1.6vmin 1.8vmin;
  display: flex;
  flex-direction: column;
  min-height: 0;
}

.chiosco-etichetta {
  font-size: 1.08vmin;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--text-terziario);
  margin-bottom: 1.2vmin;
}

.chiosco-dispositivi, .chiosco-alert {
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 0.9vmin;
}

.chiosco-disp {
  display: flex;
  align-items: center;
  gap: 1.2vmin;
  padding: 1.1vmin 1.4vmin;
  border-radius: 1vmin;
  background: var(--bg);
  font-size: 1.37vmin;
}
.chiosco-spia {
  width: 1.3vmin;
  height: 1.3vmin;
  min-width: 9px;
  min-height: 9px;
  border-radius: 50%;
  flex-shrink: 0;
}
.chiosco-disp.su .chiosco-spia { background: var(--ok); }
.chiosco-disp.giu .chiosco-spia {
  background: var(--danger);
  animation: battito-punto 1.2s ease-out infinite;
}
.chiosco-disp-nome { font-weight: 600; }
.chiosco-disp-stato {
  margin-left: auto;
  font-size: 1.08vmin;
  color: var(--text-terziario);
}
.chiosco-disp.giu {
  background: var(--danger-bg);
}
.chiosco-disp.giu .chiosco-disp-stato { color: var(--danger); font-weight: 700; }

.chiosco-allarme {
  display: flex;
  align-items: center;
  gap: 1.2vmin;
  padding: 1.1vmin 1.4vmin;
  border-radius: 1vmin;
  background: var(--bg);
  font-size: 1.3vmin;
}
.chiosco-punto {
  width: 1vmin;
  height: 1vmin;
  min-width: 7px;
  min-height: 7px;
  border-radius: 50%;
  flex-shrink: 0;
}
.chiosco-allarme.danger { background: var(--danger-bg); }
.chiosco-allarme.danger .chiosco-punto { background: var(--danger); }
.chiosco-allarme.warning { background: var(--warn-bg); }
.chiosco-allarme.warning .chiosco-punto { background: var(--warn); }
.chiosco-testo {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.chiosco-quando {
  font-size: 1.01vmin;
  color: var(--text-terziario);
  font-variant-numeric: tabular-nums;
}
.chiosco-altri {
  font-size: 1.08vmin;
  color: var(--text-terziario);
  font-style: italic;
  padding: 0.6vmin 1.4vmin;
}

.chiosco-sereno {
  display: flex;
  align-items: center;
  gap: 1.6vmin;
  font-size: 1.58vmin;
  font-weight: 600;
  color: var(--ok);
  padding: 2vmin 0;
}
.chiosco-spunta {
  width: 4vmin;
  height: 4vmin;
  min-width: 30px;
  min-height: 30px;
  border-radius: 50%;
  background: var(--ok-bg);
  position: relative;
  flex-shrink: 0;
}
.chiosco-spunta::after {
  content: "";
  position: absolute;
  left: 36%;
  top: 24%;
  width: 22%;
  height: 42%;
  border: solid var(--ok);
  border-width: 0 0.35vmin 0.35vmin 0;
  transform: rotate(45deg);
}

/* su schermi stretti il chiosco torna una colonna sola */
@media (max-width: 900px) {
  .chiosco-corpo { grid-template-columns: 1fr; }
  .chiosco-numeri { grid-auto-flow: row; }
  .chiosco { height: auto; overflow: auto; }
}

.collegamento-chiosco {
  display: block;
  font-size: 11px;
  color: var(--accento) !important;
  text-decoration: none;
  margin-bottom: 10px;
}
.collegamento-chiosco:hover { text-decoration: underline; }

/* ===================== grafici del chiosco ===================== */

.chiosco-grafici {
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 1.2vmin;
}

.chiosco-anelli {
  display: flex;
  gap: 1.6vmin;
  justify-content: space-around;
  flex-wrap: wrap;
}

.chiosco-anello { text-align: center; }
.chiosco-anello svg { width: 9vmin; height: 9vmin; min-width: 66px; min-height: 66px; }

.anello-vuoto { fill: none; stroke: var(--traccia); stroke-width: 9; }
.anello-pieno {
  fill: none;
  stroke-width: 9;
  stroke-linecap: round;
  transform: rotate(-90deg);
  transform-origin: 42px 42px;
}
.anello-pieno.ok { stroke: var(--ok); }
.anello-pieno.guasto { stroke: var(--warn); }

.anello-testo {
  text-anchor: middle;
  font-size: 17px;
  font-weight: 700;
  fill: var(--text);
  font-variant-numeric: tabular-nums;
}

.chiosco-anello-nome {
  font-size: 1.15vmin;
  font-weight: 600;
  margin-top: 0.5vmin;
  color: var(--text-secondary);
}
.chiosco-anello-nota { font-size: 1vmin; color: var(--text-terziario); }
.chiosco-anello-nota.guasto { color: var(--danger); font-weight: 600; }

.chiosco-barre { display: flex; flex-direction: column; gap: 0.7vmin; }

.chiosco-riga-barra {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 5vmin 3.4vmin;
  align-items: center;
  gap: 0.8vmin;
  font-size: 1.05vmin;
}
.chiosco-barra-nome {
  color: var(--text-secondary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.chiosco-barra {
  height: 0.7vmin;
  min-height: 5px;
  border-radius: 3px;
  background: var(--danger);
  overflow: hidden;
}
.chiosco-barra span { display: block; height: 100%; background: var(--ok); }
.chiosco-barra-conta {
  text-align: right;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.chiosco-barra-conta.ok { color: var(--ok); }
.chiosco-barra-conta.guasto { color: var(--danger); }

/* ===================== scelta del cliente per il chiosco ============ */

.scelta-cliente { max-width: 420px; }

.bottone-cliente {
  display: block;
  padding: 12px 16px;
  margin-bottom: 8px;
  border-radius: 10px;
  border: 1px solid var(--border);
  background: var(--bg);
  color: var(--text);
  font-size: 15px;
  font-weight: 600;
  text-decoration: none;
  transition: border-color 0.15s ease, transform 0.12s ease;
}
.bottone-cliente:hover {
  border-color: var(--accento);
  transform: translateY(-1px);
}
.bottone-cliente-nota {
  display: block;
  font-size: 12px;
  font-weight: 400;
  color: var(--text-terziario);
  margin-top: 2px;
}

.scelta-nota {
  font-size: 12px;
  color: var(--text-terziario);
  margin-top: 1rem;
  line-height: 1.5;
}

/* ===================== sezioni trasversali della sidebar ============ */

.sidebar-globale {
  padding-left: 0;
  margin-top: 6px;
  padding-top: 6px;
  border-top: 1px solid var(--border);
}
.sidebar-admin { margin-top: 2px; }

/* ==========================================================================
   Pagina Integrazioni
   --------------------------------------------------------------------------
   Il modulo cambia forma secondo il tipo scelto: prima si sceglie che cosa
   si sta collegando, poi compaiono i campi di quel protocollo insieme alle
   istruzioni per prepararlo. Chi configura non deve sapere in anticipo se
   servira' una community SNMP o una coppia di chiavi OpenAPI.
   ========================================================================== */

.griglia-integrazioni {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(340px, 460px);
  gap: 14px;
  align-items: start;
}

@media (max-width: 1100px) {
  .griglia-integrazioni { grid-template-columns: 1fr; }
}

/* --- scelta del tipo ---------------------------------------------------- */

.scelta-tipo {
  display: grid;
  gap: 8px;
  margin-bottom: 6px;
}

.carta-tipo {
  display: block;
  cursor: pointer;
}

.carta-tipo input {
  position: absolute;
  opacity: 0;
  width: 0;
  height: 0;
}

.carta-tipo-corpo {
  display: block;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--campo);
  transition: border-color .15s ease, background .15s ease;
}

.carta-tipo:hover .carta-tipo-corpo { background: var(--hover); }

/* il contorno segue il focus da tastiera, non solo il clic: questo modulo
   si compila spesso con il tastierino e senza indicatore ci si perde */
.carta-tipo input:focus-visible + .carta-tipo-corpo {
  outline: 2px solid var(--accento);
  outline-offset: 2px;
}

.carta-tipo input:checked + .carta-tipo-corpo {
  border-color: var(--accento);
  background: color-mix(in srgb, var(--accento) 9%, var(--campo));
}

.carta-tipo-nome {
  display: block;
  font-weight: 600;
  font-size: 13px;
  color: var(--text);
}

.carta-tipo-sommario {
  display: block;
  margin-top: 2px;
  font-size: 12px;
  line-height: 1.4;
  color: var(--text-secondary);
}

/* --- gruppo di campi del tipo ------------------------------------------- */

.gruppo-tipo {
  border: 0;
  padding: 0;
  margin: 14px 0 0;
  min-width: 0;    /* senza questo un fieldset non si stringe nella griglia */
}

.gruppo-tipo[hidden] { display: none; }

.guida {
  border: 1px solid var(--border);
  border-left: 3px solid var(--accento);
  border-radius: 8px;
  background: color-mix(in srgb, var(--accento) 5%, var(--card));
  padding: 10px 12px 10px 14px;
  margin-bottom: 14px;
}

.guida-titolo {
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--accento);
  margin-bottom: 6px;
}

.guida ol {
  margin: 0;
  padding-left: 18px;
  display: grid;
  gap: 6px;
}

.guida li {
  font-size: 12px;
  line-height: 1.5;
  color: var(--text-secondary);
}

.guida b { color: var(--text); font-weight: 600; }

.guida code {
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  font-size: 11px;
  padding: 1px 5px;
  border-radius: 4px;
  background: var(--traccia);
  color: var(--text);
}

.campo { margin-bottom: 12px; }

.campo label {
  display: block;
  font-size: 12px;
  font-weight: 600;
  margin-bottom: 4px;
  color: var(--text);
}

/* la spaziatura la governa .campo: i margini di .modulo, pensati per campi
   sciolti, qui si sommerebbero a quello del contenitore */
.campo input, .campo select { margin-bottom: 0 !important; }
.campo .nota-campo { margin: 5px 0 0 !important; }

/* i parametri che quasi nessuno tocca restano visibili ma in secondo piano:
   nasconderli dietro un pannello a scomparsa li renderebbe introvabili
   proprio nelle rare volte che servono */
.campo-avanzato label { color: var(--text-secondary); font-weight: 500; }

.interruttore {
  display: flex !important;
  align-items: center;
  gap: 8px;
  font-weight: 500 !important;
  color: var(--text-secondary) !important;
  cursor: pointer;
}

.interruttore input { width: auto; margin: 0; }

.parte-comune { display: contents; }

/* l'azione principale in mezzo a pulsanti secondari (es. "Salva" nella
   mappa accanto a "Sposta"/"Togli"): senza risalto passerebbe inosservata */
.bottone-piccolo.accento {
  color: var(--accento);
  border-color: color-mix(in srgb, var(--accento) 45%, var(--border));
  font-weight: 600;
}
.bottone-piccolo.accento:hover {
  background: color-mix(in srgb, var(--accento) 10%, transparent);
}
/* ==========================================================================
   Consumabili e spazio, raggruppati per dispositivo
   --------------------------------------------------------------------------
   Con piu' di una stampante i nomi delle metriche si ripetono identici
   ("Toner ciano", "Cassetto 1"): senza un'intestazione per macchina non si
   capisce quale toner sta finendo, che e' l'unica cosa che serve sapere.
   ========================================================================== */

.gruppo-risorse { display: flex; flex-direction: column; }

/* la riga di separazione solo fra un gruppo e l'altro, non sopra al primo */
.gruppo-risorse + .gruppo-risorse {
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px solid var(--border);
}

.gruppo-risorse-testa {
  display: flex;
  align-items: baseline;
  gap: 7px;
  flex-wrap: wrap;
}

.gruppo-risorse-nome {
  font-size: 12px;
  font-weight: 600;
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* riassunto accanto al nome: piccolo, per non rubare l'occhio agli anelli */
.chip-risorsa {
  font-size: 10px;
  font-weight: 600;
  line-height: 1;
  padding: 3px 6px;
  border-radius: 5px;
  color: var(--text-secondary);
  background: var(--traccia);
  white-space: nowrap;
}
.chip-risorsa.ok { color: var(--ok); background: var(--ok-bg); }
.chip-risorsa.warn { color: var(--warn); background: var(--warn-bg); }
.chip-risorsa.danger { color: var(--danger); background: var(--danger-bg); }

/* dentro un gruppo gli anelli stanno piu' stretti: il padding pensato per il
   riquadro intero, moltiplicato per ogni dispositivo, farebbe scorrere la
   pagina - e la panoramica deve stare in una schermata */
.gruppo-risorse .tile-grid {
  padding: 8px 0 4px;
  grid-template-columns: repeat(auto-fill, minmax(84px, 1fr));
}
.gruppo-risorse .tile-label { font-size: 10px; }

/* riga dei filtri per tipo: sta sotto a quella dei clienti, leggermente
   staccata, perche' i due filtri si combinano e non si sostituiscono */
.riepilogo-filtro.riga-tipi {
  margin-top: 6px;
  padding-top: 6px;
  border-top: 1px dashed var(--border);
}
.bottone-piccolo.filtro-tipo { font-size: 11px; }

/* ==========================================================================
   Livello informativo
   --------------------------------------------------------------------------
   Azzurro del marchio: qualcosa da sapere, non un guasto. Tenerlo distinto
   dal rosso serve a proteggere il rosso: se anche le notizie neutre fossero
   rosse, il colore che deve far alzare dalla sedia diventerebbe ordinario.
   Niente battito sul pallino, per lo stesso motivo.
   ========================================================================== */

.chip.info { background: var(--accento-tenue); color: var(--accento-testo); }
.chip-risorsa.info { background: var(--accento-tenue); color: var(--accento-testo); }
.alert-dot.info { background: var(--accento); }
.alert-row.info { border-left: 3px solid var(--accento); }
.chiosco-allarme.info { background: var(--accento-tenue); }
.chiosco-allarme.info .chiosco-punto { background: var(--accento); }

/* ==========================================================================
   Pagina Alert: tre famiglie separate
   --------------------------------------------------------------------------
   Critici, avvisi e dispositivi nuovi richiedono tre azioni diverse: agire,
   tenere d'occhio, archiviare. Prima erano mescolati nello stesso elenco
   ordinato per dispositivo, e per trovare i critici bisognava rileggere
   tutto. I filtri in cima permettono di vederne una sola alla volta.
   ========================================================================== */

.filtro-gravita-riga { margin-bottom: 10px; }

/* il pallino colorato sul pulsante dice di quale famiglia si parla prima
   ancora di leggere l'etichetta */
.bottone-piccolo.filtro-gravita::before {
  content: "";
  display: inline-block;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  margin-right: 6px;
  vertical-align: middle;
  background: var(--text-terziario);
}
.bottone-piccolo.filtro-gravita[data-gravita=""]::before { display: none; }
.bottone-piccolo.filtro-gravita.danger::before { background: var(--danger); }
.bottone-piccolo.filtro-gravita.warning::before { background: var(--warn); }
.bottone-piccolo.filtro-gravita.info::before { background: var(--accento); }

.sezione-gravita { margin-bottom: 18px; }

.testa-sezione {
  display: flex;
  align-items: baseline;
  gap: 8px;
  padding: 0 2px 8px;
  flex-wrap: wrap;
}

.punto-sezione {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  align-self: center;
  flex-shrink: 0;
}
.sezione-gravita.danger .punto-sezione { background: var(--danger); }
.sezione-gravita.warning .punto-sezione { background: var(--warn); }
.sezione-gravita.info .punto-sezione { background: var(--accento); }

.titolo-sezione {
  font-size: 14px;
  font-weight: 600;
  color: var(--text);
}
.sotto-sezione { font-size: 12px; color: var(--text-secondary); }
.conta-sezione {
  margin-left: auto;
  font-size: 11px;
  color: var(--text-terziario);
  white-space: nowrap;
}

/* le schede dentro una sezione stanno piu' vicine fra loro che fra sezioni */
.sezione-gravita .gruppo-alert { margin-bottom: 10px; }

/* ==========================================================================
   VETRO LIQUIDO
   --------------------------------------------------------------------------
   Le superfici diventano materiale: traslucide, con la luce che scorre sul
   bordo superiore e un'ombra morbida che le stacca dal fondo.

   Tre regole che mi sono dato, perche' questa e' una dashboard e non una
   vetrina:

   1. Si sfoca solo cio' che e' GRANDE - schede, sidebar, testata. Il
      backdrop-filter costa caro e va ricalcolato a ogni ridisegno: metterlo
      su ogni riga di alert o su ogni pastiglia significherebbe centinaia di
      sfocature ricalcolate ogni tre secondi, su un pannello che si aggiorna
      da solo.
   2. Sotto il vetro ci sono numeri da leggere. L'opacita' resta alta
      abbastanza da non far competere lo sfondo con i dati.
   3. Chi ha chiesto meno trasparenza o meno movimento riceve superfici
      piene: e' un'impostazione di accessibilita', non una preferenza
      estetica da ignorare.
   ========================================================================== */

/* --- superfici sfocate: solo le grandi ---------------------------------- */

.card,
.sidebar,
.kpi,
.device-card,
.login-card,
.scheda-estesa,
.gruppo-alert {
  background: var(--vetro);
  backdrop-filter: var(--sfuma);
  -webkit-backdrop-filter: var(--sfuma);
  border: 1px solid var(--vetro-bordo);
  border-radius: var(--raggio);
  box-shadow: var(--ombra-vetro);
  position: relative;
}

/* il riflesso: una riga di luce sul bordo alto, che e' cio' che fa leggere
   una superficie come vetro invece che come rettangolo semitrasparente */
.card::before,
.kpi::before,
.device-card::before,
.login-card::before {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 1px;
  border-radius: var(--raggio) var(--raggio) 0 0;
  background: linear-gradient(90deg,
    transparent, var(--vetro-luce) 22%, var(--vetro-luce) 78%, transparent);
  pointer-events: none;
}

/* elementi piccoli: traslucidi ma SENZA sfocatura, per le ragioni dette */
.alert-row,
.empty,
.pill,
.chip,
.bottone-piccolo {
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}

.pill {
  background: var(--vetro-alto);
  border: 1px solid var(--vetro-bordo);
  border-radius: 999px;
}

/* --- sidebar: vetro piu' denso, sta ferma e ci si legge dentro --------- */

.sidebar {
  background: var(--vetro-alto);
  border-right: 1px solid var(--vetro-bordo);
  border-radius: 0;
  box-shadow: 1px 0 0 var(--vetro-contorno);
}
.sidebar::before { display: none; }

.nav-item { border-radius: var(--raggio-piccolo); transition: background .15s ease; }

/* --- testata della pagina: si stacca dal contenuto che scorre sotto ----- */

.main-header {
  position: sticky;
  top: 0;
  z-index: 5;
  /* Niente padding aggiuntivo: l'altezza della Panoramica e' calcolata su
     100vh meno un valore fisso, e ogni pixel messo qui la fa uscire dallo
     schermo. Quella pagina deve stare in una schermata, era un requisito. */
  background: transparent;
}

/* Il velo dietro al titolo.
   Prima la testata aveva uno sfondo PIENO del colore della pagina, per
   coprire cio' che le scorre sotto: in tema scuro quel colore e' quasi
   nero, e il risultato era una banda scura in cima a una pagina di vetro.
   Ora e' un velo traslucido che sfoca invece di coprire, e sfuma in basso
   cosi' non lascia un bordo netto dove finisce.
   Sta in uno pseudo-elemento e non sulla testata perche' la sfumatura non
   deve toccare il testo: solo il velo. E deborda con 'inset' negativo, che
   allarga cio' che si vede senza aggiungere un pixel all'altezza - quella
   la Panoramica la conta al pixel. */
.main-header::before {
  content: "";
  position: absolute;
  inset: -16px -6px -18px -6px;
  z-index: -1;
  background: color-mix(in srgb, var(--bg) 52%, transparent);
  backdrop-filter: blur(20px) saturate(160%);
  -webkit-backdrop-filter: blur(20px) saturate(160%);
  -webkit-mask-image: linear-gradient(to bottom, #000 68%, transparent);
  mask-image: linear-gradient(to bottom, #000 68%, transparent);
  pointer-events: none;
}

/* --- pulsanti e campi: angoli e transizioni coerenti ------------------- */

.bottone-piccolo {
  border-radius: var(--raggio-piccolo);
  transition: background .15s ease, border-color .15s ease, color .15s ease;
}

.modulo input, .modulo select, .modulo button,
.campo input, .campo select {
  border-radius: var(--raggio-piccolo);
}

.chip { border-radius: 999px; }

/* --- lo sfondo: tre macchie invece di due, cosi' il vetro ha qualcosa da
       rifrangere anche al centro della pagina ------------------------- */

.macchia { filter: blur(84px); }

/* --- storico a scomparsa ------------------------------------------------ */

.a-scomparsa > summary {
  cursor: pointer;
  list-style: none;
  user-select: none;
}
.a-scomparsa > summary::-webkit-details-marker { display: none; }
.riga-scomparsa { display: flex; align-items: center; gap: 9px; }

.freccia-scomparsa {
  width: 0;
  height: 0;
  border-left: 4px solid currentColor;
  border-top: 3.5px solid transparent;
  border-bottom: 3.5px solid transparent;
  color: var(--text-terziario);
  transition: transform 0.18s ease;
  flex-shrink: 0;
}
.a-scomparsa[open] .freccia-scomparsa { transform: rotate(90deg); }
.a-scomparsa > summary:hover .card-titolo { color: var(--accento); }
.a-scomparsa .card-conteggio { margin-left: auto; }

/* --- chiosco: vetro senza sfocatura ------------------------------------
   Gira per giorni su un monitor a parete, spesso attaccato a un mini PC.
   La sfocatura andrebbe ricalcolata a ogni aggiornamento su tutta la
   superficie: li' il vetro si fa con la traslucenza e basta. */

.chiosco .card,
.chiosco .kpi,
.chiosco-allarme {
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  background: var(--vetro-alto);
}

/* --- rispetto delle preferenze di accessibilita' ----------------------- */

@media (prefers-reduced-transparency: reduce) {
  .card, .sidebar, .kpi, .device-card, .login-card,
  .scheda-estesa, .gruppo-alert, .pill, .main-header {
    background: var(--card);
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
  }
  .card::before, .kpi::before, .device-card::before, .login-card::before {
    display: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  .nav-item, .bottone-piccolo, .freccia-scomparsa { transition: none; }
}

/* la barra sopra gli alert e' larga quanto la pagina: senza trattarla come
   le altre superfici mostrava lo sfondo crudo, ed era la cosa piu' vistosa
   della pagina invece della meno importante */
.barra-azioni {
  background: var(--vetro);
  backdrop-filter: var(--sfuma);
  -webkit-backdrop-filter: var(--sfuma);
  border: 1px solid var(--vetro-bordo);
  border-radius: var(--raggio);
  box-shadow: var(--ombra-vetro);
}

/* Il bordo del vetro aggiunge un pixel per superficie, e queste due pagine
   hanno l'altezza calcolata al pixel per stare in una schermata sola senza
   scorrere - era un requisito esplicito. Il valore fisso va corretto della
   stessa quantita': misurata, 16px. */
.plancia-panoramica { height: calc(100vh - 384px); }
.telecamere-plancia { height: calc(100vh - 342px); }

/* Il riflesso obliquo. Serve piu' di quanto sembri: la sfocatura funziona
   solo dove dietro c'e' qualcosa di variegato, e sopra una zona di fondo
   uniforme una superficie traslucida sembra semplicemente un rettangolo
   chiaro. Questa striscia di luce la fa leggere come vetro comunque. */
.card::after,
.kpi::after,
.login-card::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  background: linear-gradient(115deg,
    rgba(255, 255, 255, 0.22) 0%,
    rgba(255, 255, 255, 0.06) 26%,
    rgba(255, 255, 255, 0) 52%);
}

:root[data-tema="scuro"] .card::after,
:root[data-tema="scuro"] .kpi::after,
:root[data-tema="scuro"] .login-card::after {
  background: linear-gradient(115deg,
    rgba(255, 255, 255, 0.10) 0%,
    rgba(255, 255, 255, 0.03) 26%,
    rgba(255, 255, 255, 0) 52%);
}

/* il contenuto deve stare sopra il riflesso */
@media (prefers-color-scheme: dark) {
  :root:not([data-tema="chiaro"]) .card::after,
  :root:not([data-tema="chiaro"]) .kpi::after,
  :root:not([data-tema="chiaro"]) .login-card::after {
    background: linear-gradient(115deg,
      rgba(255, 255, 255, 0.10) 0%,
      rgba(255, 255, 255, 0.03) 26%,
      rgba(255, 255, 255, 0) 52%);
  }
}

.card > *, .kpi > *, .login-card > * { position: relative; z-index: 1; }

/* ==========================================================================
   BARRE DI SCORRIMENTO E BARRA LATERALE IN VETRO
   --------------------------------------------------------------------------
   Le barre di scorrimento erano rimaste quelle di sistema: grigie, opache,
   con il loro binario pieno. In mezzo a superfici traslucide erano la cosa
   piu' vecchia della pagina, e si notavano proprio per quello.

   Qui diventano un binario appena accennato con un cursore di vetro nel
   colore d'accento. Restano larghe abbastanza da prenderle col mouse: una
   barra bella ma da due pixel e' una barra che non si afferra.
   ========================================================================== */

/* standard: lo capiscono Firefox e i browser recenti */
* {
  scrollbar-width: thin;
  scrollbar-color: var(--cursore) transparent;
}

/* WebKit: Chrome ed Edge, che qui sono quelli che contano */
::-webkit-scrollbar { width: 11px; height: 11px; }

::-webkit-scrollbar-track {
  background: var(--binario);
  border-radius: 999px;
}

::-webkit-scrollbar-thumb {
  background: var(--cursore);
  border-radius: 999px;
  /* il bordo trasparente con background-clip lascia aria intorno al
     cursore: senza, tocca i lati e sembra incastrato */
  border: 2px solid transparent;
  background-clip: padding-box;
  transition: background .15s ease;
}

::-webkit-scrollbar-thumb:hover { background: var(--cursore-attivo); }
::-webkit-scrollbar-thumb:active { background: var(--cursore-attivo); }

/* l'angolo fra barra orizzontale e verticale, che altrimenti resta grigio */
::-webkit-scrollbar-corner { background: transparent; }

/* Dentro le schede il binario sparisce del tutto: la scheda e' gia' una
   superficie, un secondo rettangolo dentro la confonde. Resta il cursore. */
.corpo-plancia::-webkit-scrollbar-track,
.tabella-scroll::-webkit-scrollbar-track,
.corpo-gruppo::-webkit-scrollbar-track,
.pannello-porte::-webkit-scrollbar-track {
  background: transparent;
}

/* --- barra laterale: vetro come le schede ------------------------------- */

.sidebar {
  /* piu' trasparente di prima: prima era quasi piena e restava l'unica
     superficie della pagina a non lasciar passare niente */
  background: var(--vetro);
  backdrop-filter: var(--sfuma);
  -webkit-backdrop-filter: var(--sfuma);
  border-right: 1px solid var(--vetro-bordo);
  box-shadow: inset -1px 0 0 var(--vetro-contorno);
}

/* riflesso verticale sul bordo destro: e' il taglio del vetro visto di
   profilo, e da' spessore alla barra invece di lasciarla piatta */
.sidebar::after {
  content: "";
  position: absolute;
  inset: 0 0 0 auto;
  width: 1px;
  background: linear-gradient(to bottom,
    transparent, var(--vetro-luce) 18%, var(--vetro-luce) 72%, transparent);
  pointer-events: none;
}

/* la voce attiva e' una lastra di vetro colorata, non un blocco pieno */
.nav-item.attivo {
  background: var(--accento-tenue);
  border: 1px solid color-mix(in srgb, var(--accento) 28%, transparent);
}

/* il piede della sidebar si stacca dal resto con una linea di luce */
.sidebar-footer { border-top: 1px solid var(--vetro-bordo); }

/* ==========================================================================
   VETRO SUI COMPONENTI RIMASTI FUORI
   --------------------------------------------------------------------------
   Il primo passaggio aveva coperto le superfici grandi. Restavano piene: i
   pulsanti, i campi dei moduli, le pastiglie, le schede a linguetta delle
   Telecamere, la legenda, il selettore del tema, i riquadri del chiosco e
   gli stati vuoti. In mezzo a schede di vetro erano i pezzi che tradivano
   l'eta' dell'interfaccia.

   Qui ricevono la stessa materia ma SENZA sfocatura: sono tanti e piccoli,
   e una sfocatura per ciascuno costerebbe a ogni ridisegno senza aggiungere
   niente che si veda. La traslucenza e il bordo di luce bastano.
   ========================================================================== */

/* --- pulsanti ----------------------------------------------------------- */

.bottone-piccolo,
.bottone-cliente,
.selettore-tema button {
  background: var(--vetro-tenue);
  border: 1px solid var(--vetro-tenue-bordo);
}
.bottone-piccolo:hover,
.bottone-cliente:hover,
.selettore-tema button:hover { background: var(--vetro-tenue-hover); }

.selettore-tema {
  background: var(--vetro-tenue);
  border: 1px solid var(--vetro-tenue-bordo);
  border-radius: 999px;
}
/* La voce scelta era accento su tinta d'accento: 3.76, sotto soglia. Nei
   componenti shadcn una voce scelta e' piena, con --primary-foreground
   sopra: qui si fa lo stesso, ed e' anche piu' leggibile da lontano. */
.selettore-tema button.attivo {
  background: var(--vetro-alto);
  box-shadow: inset 0 0 0 1px var(--primary);
  border-color: transparent;
  color: var(--text);
}

/* il pulsante in evidenza resta pieno: se fosse di vetro come gli altri non
   sarebbe piu' in evidenza */
.modulo button { border: 1px solid transparent; }

/* --- campi dei moduli --------------------------------------------------- */

.modulo input:not([type="checkbox"]):not([type="radio"]), .modulo select,
.campo input:not([type="checkbox"]):not([type="radio"]), .campo select,
.riga-azione select,
.carta-tipo-corpo,
.login-card input {
  background: var(--vetro-tenue);
  border: 1px solid var(--vetro-tenue-bordo);
}
.modulo input:focus, .modulo select:focus,
.campo input:focus, .campo select:focus,
.login-card input:focus {
  background: var(--vetro-tenue-hover);
  border-color: var(--accento);
}

/* --- pastiglie neutre --------------------------------------------------- */

.chip.neutro, .mini-chip, .scheda-conta, .confronto-barra, .nav-conteggio {
  background: var(--vetro-tenue);
  border: 1px solid var(--vetro-tenue-bordo);
}

/* --- schede a linguetta (Telecamere) ------------------------------------ */

.sottomenu { gap: 6px; }

.scheda-telecamere {
  background: var(--vetro-tenue);
  border: 1px solid var(--vetro-tenue-bordo) !important;
  border-radius: var(--raggio-piccolo);
  transition: background .15s ease, border-color .15s ease;
}
.scheda-telecamere:hover { background: var(--vetro-tenue-hover); }
.scheda-telecamere.attiva {
  background: var(--accento-tenue);
  border-color: color-mix(in srgb, var(--accento) 34%, transparent) !important;
  color: var(--accento-testo);
}

/* --- pannelli medi: questi la sfocatura se la meritano ------------------ */

.empty,
.legenda-pagina,
.pannello-porte,
.chiosco-riquadro,
.chiosco-numero {
  background: var(--vetro);
  backdrop-filter: var(--sfuma);
  -webkit-backdrop-filter: var(--sfuma);
  border: 1px solid var(--vetro-bordo);
  border-radius: var(--raggio);
}

/* il chiosco resta senza sfocatura: gira su un mini PC attaccato a un
   monitor a parete, e la ricalcolerebbe in continuazione */
.chiosco-riquadro, .chiosco-numero, .chiosco-disp, .chiosco-allarme {
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  background: var(--vetro-alto);
}

/* --- righe di alert e di tabella ---------------------------------------- */

.alert-row {
  background: var(--vetro-tenue);
  border-radius: var(--raggio-piccolo);
}
/* l'evidenziazione al passaggio del mouse era grigia: con il vetro sotto
   spariva, e su fondo chiaro sembrava una riga sporca */
.tabella tbody tr:hover { background: var(--accento-tenue); }

.tabella th {
  background: var(--vetro-tenue);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}

/* --- titoli -------------------------------------------------------------
   Piu' presenti e meglio spaziati. Il titolo di pagina prende una sfumatura
   che va dal colore del testo all'accento: e' l'unico punto dove me la
   concedo, perche' e' una parola sola e non si deve leggere a lungo. */

h1 {
  font-size: 22px;
  font-weight: 650;
  letter-spacing: -0.02em;
  color: var(--text);
}

/* La sfumatura sul titolo si applica SOLO dove il ritaglio sul testo
   funziona davvero. Scrivere 'color: transparent' fuori da questa
   condizione significherebbe, su un browser che non la supporta, un titolo
   perfettamente invisibile: un effetto non vale quel rischio. */
@supports ((-webkit-background-clip: text) or (background-clip: text)) {
  h1 {
    background: linear-gradient(100deg, var(--text) 30%, var(--accento));
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
  }
}

h2 {
  letter-spacing: 0.02em;
  text-transform: uppercase;
  font-size: 11px;
  font-weight: 700;
  color: var(--text-terziario);
}

.card-titolo { font-weight: 600; letter-spacing: -0.01em; }
.titolo-sezione { letter-spacing: -0.01em; }

/* --- l'intestazione di scheda si stacca con una linea di luce ----------- */

.card-header { border-bottom: 1px solid var(--vetro-bordo); }

/* il puntino sull'ultimo valore del grafico: pulsa piano, come un battito
   che dice che il dato e' vivo. Sta in HTML e non dentro l'SVG perche'
   quel disegno si allunga in larghezza senza mantenere le proporzioni, e
   un cerchio ci diventerebbe un ovale schiacciato. */
.grafico { position: relative; }

.punto-vivo {
  position: absolute;
  right: 0;
  width: 7px;
  height: 7px;
  margin: 0 -3px -3px 0;
  border-radius: 50%;
  background: var(--accento);
  box-shadow: 0 0 0 0 color-mix(in srgb, var(--accento) 60%, transparent);
  animation: battito-vivo 2.2s ease-out infinite;
  pointer-events: none;
}

@keyframes battito-vivo {
  0%   { box-shadow: 0 0 0 0 color-mix(in srgb, var(--accento) 55%, transparent); }
  70%  { box-shadow: 0 0 0 9px transparent; }
  100% { box-shadow: 0 0 0 0 transparent; }
}

@media (prefers-reduced-motion: reduce) {
  .punto-vivo { animation: none; }
}

/* ==========================================================================
   Pagina Consumi
   ========================================================================== */

.plancia-consumi {
  display: grid;
  grid-template-columns: minmax(0, 1.45fr) minmax(0, 1fr);
  gap: 16px;
  /* Niente altezza imposta. Panoramica e Telecamere hanno colonne che
     scorrono dentro di se' e quindi devono riempire lo schermo; qui il
     contenuto e' poco e fisso, e allungare le schede produceva solo un
     rettangolo vuoto sotto le fasi - misurati 333 pixel su 620. */
  align-items: start;
}

@media (max-width: 1000px) {
  .plancia-consumi { grid-template-columns: 1fr; height: auto; }
}

.grafico-consumi { margin-bottom: 14px; }

.fasi { display: flex; flex-direction: column; gap: 9px; margin: 14px 0; }

.riga-fase {
  display: grid;
  grid-template-columns: 62px minmax(0, 1fr) 72px;
  align-items: center;
  gap: 10px;
  font-size: 12px;
}
.etichetta-fase { color: var(--text-secondary); }
.valore-fase { text-align: right; font-weight: 600; }

.gruppo-sotto + .gruppo-sotto { margin-top: 14px; }

.titolo-sotto {
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .05em;
  color: var(--text-terziario);
  margin-bottom: 4px;
}

/* i sensori fermi a zero restano visibili ma smorzati: toglierli farebbe
   pensare che manchino, lasciarli pieni li metterebbe alla pari di quelli
   che stanno davvero consumando */
.metric-row.spento { opacity: 0.45; }

/* --- pagina Consumi: lettura grande, fasi, sottocontatori --------------- */

.lettura-grande {
  display: flex;
  align-items: baseline;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 4px;
}

.numero-grande {
  font-size: 40px;
  font-weight: 650;
  letter-spacing: -0.03em;
  line-height: 1.05;
  color: var(--accento);
  font-variant-numeric: tabular-nums;
}
.sotto-grande { font-size: 12px; color: var(--text-secondary); }

/* la barra unica con le tre fasi in proporzione: dice in un colpo d'occhio
   se il carico e' equilibrato, che su un trifase e' la cosa che conta */
.barra-fasi {
  display: flex;
  height: 12px;
  border-radius: 999px;
  overflow: hidden;
  background: var(--traccia);
  margin: 6px 0 12px;
}
.tratto-fase { display: block; width: 0; height: 100%; }

.pallino-fase {
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  margin-right: 6px;
  vertical-align: middle;
}

.riga-sotto {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 64px 92px;
  align-items: center;
  gap: 9px;
  padding: 5px 0;
  font-size: 12px;
}
.nome-sotto {
  color: var(--text-secondary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.valore-sotto { text-align: right; font-weight: 600; font-variant-numeric: tabular-nums; }
.riga-sotto.spento { opacity: 0.4; }

/* ==========================================================================
   Il flusso sulla linea del grafico
   --------------------------------------------------------------------------
   Un tratteggio che scorre lungo la curva, come la corrente che passa nel
   cavo. La velocita' arriva da --flusso, calcolata sul valore attuale: non
   e' decorazione, dice quanto sta passando anche senza leggere il numero.

   vector-effect tiene i trattini della stessa lunghezza ovunque: questo
   disegno si allunga in larghezza senza mantenere le proporzioni, e senza
   quella riga i trattini sarebbero stirati in modo diverso a ogni zoom.
   ========================================================================== */

.area .flusso {
  fill: none;
  stroke: var(--accento-chiaro, var(--accento));
  stroke-width: 2.4;
  stroke-linecap: round;
  stroke-dasharray: 5 17;
  vector-effect: non-scaling-stroke;
  opacity: 0.9;
  filter: drop-shadow(0 0 3px var(--accento));
  animation: scorre-flusso var(--flusso, 2s) linear infinite;
}

/* il periodo dell'animazione e' la somma del tratteggio (5 + 17): cosi' il
   giro si chiude esattamente dove era cominciato e non si vede lo scatto */
@keyframes scorre-flusso {
  from { stroke-dashoffset: 0; }
  to   { stroke-dashoffset: -22; }
}

@media (prefers-reduced-motion: reduce) {
  .area .flusso { animation: none; opacity: 0; }
}

/* --- la scheda dei sottocontatori sta stretta --------------------------
   Sono poche righe: allargata a tutta l'altezza della colonna sembrava
   mezza vuota. Con align-self si ferma all'altezza del contenuto invece di
   allungarsi per riempire la griglia. */

.plancia-consumi { grid-template-columns: minmax(0, 1.9fr) minmax(0, 1fr); }

.scheda-sottocontatori {
  align-self: start;
  max-height: 100%;
}
.scheda-sottocontatori .card-header { padding-top: 10px; padding-bottom: 10px; }
.scheda-sottocontatori .card-titolo { font-size: 12px; }
.scheda-sottocontatori .corpo-plancia { padding: 8px 12px 12px; }
.scheda-sottocontatori .titolo-sotto { font-size: 10px; margin-bottom: 2px; }
.scheda-sottocontatori .riga-sotto {
  grid-template-columns: minmax(0, 1fr) 48px 78px;
  gap: 7px;
  padding: 3px 0;
  font-size: 11px;
}

/* le due colonne si fermano al contenuto, e il corpo non deve piu' spingere
   per riempire l'altezza della scheda */
.plancia-consumi .colonna-plancia { height: auto; }
.plancia-consumi .corpo-plancia { flex: 0 0 auto; overflow: visible; }

/* recuperato lo spazio, il grafico puo' respirare un po' di piu': e' la
   cosa che si guarda, ed era il pezzo piu' schiacciato */
.grafico-consumi .area { height: 112px; }
.grafico-consumi { margin-bottom: 16px; }

/* ======================= AMBITO: CLIENTI PER UTENTE ======================= */
/* Chi vede cosa. La colonna resta compatta finche' non la si apre: in una
   tabella di utenti l'elenco dei clienti e' un dettaglio, non il titolo.   */

.ambito-fisso {
  display: inline-flex;
  flex-direction: column;
  gap: 2px;
  color: var(--text-secondary);
  font-size: 13px;
}

.ambito-perche {
  color: var(--text-terziario);
  font-size: 11px;
  font-style: italic;
}

.ambito > summary {
  cursor: pointer;
  list-style: none;
  padding: 4px 8px;
  border-radius: var(--raggio-piccolo);
  border: 1px solid transparent;
  transition: background 140ms ease, border-color 140ms ease;
}

.ambito > summary::-webkit-details-marker { display: none; }

.ambito > summary::before {
  content: 25B8;
  display: inline-block;
  margin-right: 6px;
  color: var(--text-terziario);
  transition: transform 160ms ease;
}

.ambito[open] > summary::before { transform: rotate(90deg); }

.ambito > summary:hover {
  background: var(--vetro-tenue-hover);
  border-color: var(--vetro-tenue-bordo);
}

/* un ambito ristretto si distingue a colpo d'occhio da tutti: e' la
   differenza che conta quando si scorre l'elenco cercando un errore */
.ambito-ora { font-size: 13px; color: var(--text-secondary); }
.ambito-ora.ristretto { color: var(--accento-chiaro); font-weight: 600; }

.modulo-ambito {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin: 8px 0 4px 18px;
  padding: 10px 12px;
  background: var(--vetro-tenue);
  border: 1px solid var(--vetro-tenue-bordo);
  border-radius: var(--raggio-piccolo);
}

.modulo-ambito .nota-campo { margin: 2px 0 6px; }
.modulo-ambito button { align-self: flex-start; }

.elenco-scelte {
  /* in colonna singola un cliente per riga fa crescere il modulo oltre la
     pagina; a due colonne ci stanno il doppio di nomi nella stessa altezza,
     e oltre un certo punto si scorre invece di sfondare la scheda */
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 4px 14px;
  max-height: 190px;
  overflow-y: auto;
  padding: 10px 12px;
  /* la nota sotto i campi sale di 0.75rem per attaccarsi all elemento
     precedente, che normalmente ha 1rem di margine sotto. Questo riquadro
     non e un campo: senza il suo margine la nota gli finiva sopra. */
  margin-bottom: 1rem;
  background: var(--vetro-tenue);
  border: 1px solid var(--vetro-tenue-bordo);
  border-radius: var(--raggio-piccolo);
}

.scelta-cliente {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  color: var(--text);
  cursor: pointer;
  padding: 2px 0;
}

.scelta-cliente input { accent-color: var(--accento); cursor: pointer; }
.scelta-cliente:hover span { color: var(--accento-chiaro); }


/* ---- voci delle tendine ------------------------------------------------
   color-scheme sopra fa il grosso del lavoro; questo serve ai browser che
   disegnano le voci con i colori dell'elemento invece che con quelli di
   sistema. Il fondo e' pieno, non di vetro: una tendina aperta sta sopra
   la pagina, non dentro una scheda. */
select option,
select optgroup {
  background: var(--card);
  color: var(--text);
}

/* ---- marchio: due versioni, una per tema -------------------------------
   Il logo Evolve ha la scritta in grigio scuro, e su fondo scuro sparisce.
   Non si puo' rimediare con un filtro senza perdere i tre colori del
   marchio, quindi ci sono due file e si mostra quello giusto. Chi non
   viene mostrato esce anche dalla lettura assistita, quindi il nome non
   viene annunciato due volte. */
:root .solo-scuro { display: none; }

:root[data-tema="scuro"] .solo-chiaro { display: none; }
:root[data-tema="scuro"] .solo-scuro { display: block; }

@media (prefers-color-scheme: dark) {
  :root:not([data-tema="chiaro"]) .solo-chiaro { display: none; }
  :root:not([data-tema="chiaro"]) .solo-scuro { display: block; }
}


/* ======================== BARRA DI STATO E SOTTOMENU =====================
   La navigazione era una colonna a sinistra larga 232 pixel. In alto occupa
   una riga sola, e restituisce quella larghezza al contenuto - che su questa
   dashboard e' quasi tutto tabelle e grafici, cioe' roba che sta meglio
   larga. I menu sono <details>: si aprono da tastiera senza codice.
   ======================================================================== */

.barra {
  position: sticky;
  top: 0;
  z-index: 40;
  display: flex;
  align-items: center;
  gap: 18px;
  padding: 0 20px;
  height: 56px;
  background: var(--vetro-alto);
  backdrop-filter: var(--sfuma);
  -webkit-backdrop-filter: var(--sfuma);
  border-bottom: 1px solid var(--vetro-bordo);
  box-shadow: var(--ombra-vetro);
}

.barra-marchio { display: flex; align-items: center; flex-shrink: 0; text-decoration: none; }
.barra-logo { height: 26px; width: auto; display: block; }

.barra-nav {
  display: flex;
  align-items: center;
  gap: 2px;
  flex: 1;
  min-width: 0;
  /* Niente overflow qui. Far scorrere la barra sembrava la risposta giusta
     con molti clienti, ma overflow crea un contesto di ritaglio: le tendine,
     che escono sotto la barra, venivano tagliate via e il menu si apriva su
     niente. Meglio che le voci si stringano. */
  flex-wrap: nowrap;
}

.barra-fine { display: flex; align-items: center; gap: 14px; flex-shrink: 0; }

/* ---- la voce di primo livello ------------------------------------------ */
.menu { position: relative; flex-shrink: 0; }

.menu > summary {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 7px 12px;
  border-radius: 8px;
  font-size: 13px;
  font-weight: 500;
  color: var(--text-secondary);
  cursor: pointer;
  white-space: nowrap;
  list-style: none;
  min-width: 0;
  max-width: 190px;
  overflow: hidden;
  transition: background 140ms ease, color 140ms ease;
}
.menu > summary::-webkit-details-marker { display: none; }
.menu > summary:hover { background: var(--vetro-tenue-hover); color: var(--text); }
.menu > summary:focus-visible { outline: 2px solid var(--accento); outline-offset: 1px; }

.menu-attivo > summary { color: var(--text); font-weight: 600; }
.menu-attivo > summary::before {
  content: "";
  width: 5px; height: 5px;
  border-radius: 50%;
  background: var(--accento);
  flex: none;
}

.menu-freccia {
  width: 0; height: 0;
  border-left: 3.5px solid transparent;
  border-right: 3.5px solid transparent;
  border-top: 4px solid currentColor;
  opacity: .55;
  transition: transform 160ms ease;
}
.menu[open] > summary { background: var(--vetro-tenue-hover); color: var(--text); }
.menu[open] .menu-freccia { transform: rotate(180deg); }

/* ---- la tendina --------------------------------------------------------- */
.tendina {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  min-width: 210px;
  padding: 6px;
  display: flex;
  flex-direction: column;
  gap: 1px;
  background: var(--card);
  border: 1px solid var(--vetro-bordo);
  border-radius: 12px;
  box-shadow: var(--ombra-vetro-alta, var(--ombra-vetro));
  z-index: 50;
}
.tendina-fine { left: auto; right: 0; }

.tendina .voce {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 8px 11px;
  border-radius: 8px;
  font-size: 13px;
  color: var(--text-secondary);
  text-decoration: none;
  white-space: nowrap;
  transition: background 120ms ease, color 120ms ease;
}
.tendina .voce:hover { background: var(--hover); color: var(--text); }
.tendina .voce-attiva { background: var(--accento-tenue); color: var(--text); font-weight: 600; }
.tendina .voce-uscita { color: var(--danger); }

.voce-conteggio {
  min-width: 18px;
  padding: 1px 6px;
  border-radius: 9px;
  background: var(--danger);
  color: #fff;
  font-size: 11px;
  font-weight: 600;
  text-align: center;
}
.voce-conteggio:empty { display: none; }
/* il colore segue la gravita' peggiore fra gli alert non letti: rosso se
   c'e' almeno un critico, ambra se sono solo avvisi */
.voce-conteggio.avviso { background: var(--warn); }
.summary-conteggio, .barra summary .voce-conteggio { margin-left: 6px; }

.tendina-intestazione {
  padding: 4px 11px 6px;
  font-size: 11px;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--text-terziario);
}
.tendina-separatore { height: 1px; background: var(--border); margin: 5px 4px; }

.menu-conto > summary { max-width: 170px; }

.senza-login { font-size: 12px; color: var(--text-terziario); }

/* ---- schermi stretti ---------------------------------------------------- */
@media (max-width: 860px) {
  .barra { gap: 10px; padding: 0 12px; }
  .barra-logo { height: 22px; }
  .link-status { display: none; }
  .main { padding: 1.25rem 1rem 2.5rem; }
}


/* ============================ SCHEDE DI SEZIONE ==========================
   Le pagine sorelle ripetute sotto il titolo. Nella barra in alto stanno
   in una tendina che va aperta ogni volta; qui sono a un click, che per il
   giro quotidiano fra le pagine di uno stesso cliente cambia parecchio.
   ======================================================================== */

.schede {
  display: flex;
  gap: 4px;
  margin: -4px 0 18px;
  padding-bottom: 2px;
  border-bottom: 1px solid var(--vetro-bordo);
  flex-wrap: wrap;
}

.scheda-tab {
  padding: 8px 15px;
  border-radius: 9px 9px 0 0;
  font-size: 13px;
  font-weight: 500;
  color: var(--text-secondary);
  text-decoration: none;
  border-bottom: 2px solid transparent;
  transition: background 130ms ease, color 130ms ease, border-color 130ms ease;
}
.scheda-tab:hover { background: var(--vetro-tenue-hover); color: var(--text); }

.scheda-attiva {
  color: var(--text);
  font-weight: 600;
  background: var(--vetro-tenue);
  border-bottom-color: var(--accento);
}

/* ============================== PAGINA: MAPPA ==============================
   La mappa occupa quasi tutta la pagina e il pannello degli apparati le sta
   a fianco: sono due cose che si guardano insieme, e metterle una sotto
   l'altra vorrebbe dire scorrere avanti e indietro a ogni segnaposto. */

.mappa-guscio {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 330px;
  gap: 1rem;
  /* barra, schede, intestazione e margini stanno sopra: il resto e' mappa */
  height: calc(100vh - 272px);
  min-height: 460px;
}

.mappa-tela {
  position: relative;
  border-radius: var(--raggio);
  overflow: hidden;
  border: 1px solid var(--border);
  box-shadow: var(--ombra-vetro);
  background: var(--traccia);
}

/* Il selettore e' piu' specifico del necessario di proposito: mapbox-gl
   mette sullo stesso nodo la classe .mapboxgl-map, che vale position:
   relative. A parita' di specificita' vincerebbe chi arriva dopo, e chi
   arriva dopo non lo decidiamo noi. */
.mappa-tela > .mappa-disegno { position: absolute; inset: 0; }

/* --- strumenti sopra la mappa --- */

.mappa-strumenti {
  position: absolute;
  top: 12px;
  left: 12px;
  z-index: 3;
  display: flex;
  flex-direction: column;
  gap: 8px;
  width: 320px;
  max-width: calc(100% - 90px);   /* i comandi di Mapbox stanno a destra */
}

.mappa-ricerca { position: relative; }

.mappa-ricerca input,
.mappa-lato-testa input {
  width: 100%;
  padding: 9px 12px;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--card);
  color: var(--text);
  font-size: 13px;
  box-shadow: var(--ombra);
}
.mappa-ricerca input:focus,
.mappa-lato-testa input:focus {
  outline: none;
  border-color: var(--accento);
  box-shadow: 0 0 0 3px var(--accento-alone);
}

.mappa-suggerimenti {
  position: absolute;
  top: calc(100% + 4px);
  left: 0;
  right: 0;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 10px;
  box-shadow: var(--ombra-vetro-alta);
  overflow: hidden;
  z-index: 4;
}
.mappa-suggerimento {
  display: block;
  width: 100%;
  padding: 8px 12px;
  border: 0;
  background: none;
  color: var(--text);
  font-size: 13px;
  text-align: left;
  cursor: pointer;
}
.mappa-suggerimento:hover { background: var(--hover); }

.mappa-stili {
  display: flex;
  gap: 4px;
  padding: 4px;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 10px;
  box-shadow: var(--ombra);
  width: fit-content;
}
.mappa-stili button {
  border: 0;
  background: none;
  padding: 5px 10px;
  border-radius: 7px;
  font-size: 12px;
  color: var(--text-secondary);
  cursor: pointer;
}
.mappa-stili button:hover { background: var(--hover); color: var(--text); }
.mappa-stili button.attivo { background: var(--accento); color: #fff; }

/* display:flex batte il display:none che il browser da' a [hidden]: gli stili
   dell'autore vincono sempre su quelli predefiniti, a qualunque specificita'.
   Senza questa riga il riquadro resta a schermo vuoto. */
.mappa-istruzione[hidden] { display: none; }

.mappa-istruzione {
  position: absolute;
  top: 12px;
  /* fra la colonna degli strumenti e i comandi di Mapbox: centrato sulla
     mappa finirebbe sopra il campo di ricerca */
  left: 352px;
  right: 60px;
  z-index: 3;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  padding: 9px 14px;
  border-radius: 10px;
  background: var(--accento);
  color: #fff;
  font-size: 13px;
  box-shadow: var(--ombra-vetro-alta);
}
.mappa-istruzione .bottone-piccolo {
  background: rgba(255, 255, 255, 0.18);
  border-color: transparent;
  color: #fff;
}
.mappa-istruzione .bottone-piccolo:hover { background: rgba(255, 255, 255, 0.3); }
.mappa-incatena { display: flex; align-items: center; gap: 5px; font-size: 12px; }
.mappa-incatena input { accent-color: #fff; }

.mappa-legenda {
  position: absolute;
  right: 12px;
  /* sopra la striscia di attribuzione di Mapbox, che per licenza deve
     restare leggibile: a 12px la copriva */
  bottom: 34px;
  z-index: 3;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 6px;
}
.mappa-legenda-voci,
.mappa-legenda-bottoni {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 6px 10px;
  border-radius: 10px;
  background: var(--card-vetro);
  border: 1px solid var(--border);
  box-shadow: var(--ombra);
  font-size: 12px;
  color: var(--text-secondary);
}
.mappa-legenda-voci span { display: flex; align-items: center; gap: 5px; }
.mappa-legenda-bottoni { padding: 5px; gap: 5px; }

/* --- il pannello a lato --- */

.mappa-lato {
  display: flex;
  flex-direction: column;
  min-height: 0;
  border: 1px solid var(--border);
  border-radius: var(--raggio);
  background: var(--card);
  box-shadow: var(--ombra-vetro);
  overflow: hidden;
}
.mappa-lato-testa { padding: 10px; border-bottom: 1px solid var(--border); }
.mappa-elenco { flex: 1; min-height: 0; overflow-y: auto; padding: 4px 0 10px; }

.mappa-titolo {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin: 12px 12px 6px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--text-terziario);
}
.mappa-titolo span {
  font-size: 11px;
  letter-spacing: 0;
  padding: 1px 7px;
  border-radius: 8px;
  background: var(--traccia);
  color: var(--text-secondary);
}

.mappa-voci { list-style: none; margin: 0; padding: 0; }
.mappa-voce {
  display: flex;
  align-items: center;
  gap: 9px;
  width: 100%;
  padding: 7px 12px;
  border: 0;
  background: none;
  text-align: left;
  cursor: pointer;
  color: var(--text);
}
.mappa-voce:hover { background: var(--hover); }
.mappa-voce.scelta { background: var(--accento-tenue); }
.mappa-voce-testo { display: flex; flex-direction: column; min-width: 0; }
.mappa-voce-nome {
  font-size: 13px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.mappa-voce-sotto {
  font-size: 11px;
  color: var(--text-terziario);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.mappa-lato-fondo { border-top: 1px solid var(--border); padding: 12px; }
.mappa-dettaglio { display: flex; flex-direction: column; gap: 9px; }
.mappa-dettaglio-testa { display: flex; align-items: center; gap: 10px; }
.mappa-dettaglio-testa strong { display: block; font-size: 14px; }
.mappa-stato { margin: 0; font-size: 12px; color: var(--text-secondary); }
.mappa-stato.stato-guasto { color: var(--danger); }
.mappa-stato.stato-avviso { color: var(--warn); }
.mappa-stato.stato-attivo { color: var(--ok); }

/* --- scheda che si apre cliccando un pallino --- */
/* sopra legenda e strumenti (z-index 3): li copre solo finche' e' aperta */
.scheda-pin { z-index: 4; }
.scheda-pin .mapboxgl-popup-content {
  background: var(--card);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 12px;
  box-shadow: var(--ombra-vetro-alta);
  padding: 14px 16px 12px;
  min-width: 260px;
  font-family: inherit;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.scheda-pin.mapboxgl-popup-anchor-bottom .mapboxgl-popup-tip,
.scheda-pin.mapboxgl-popup-anchor-bottom-left .mapboxgl-popup-tip,
.scheda-pin.mapboxgl-popup-anchor-bottom-right .mapboxgl-popup-tip { border-top-color: var(--card); }
.scheda-pin.mapboxgl-popup-anchor-top .mapboxgl-popup-tip,
.scheda-pin.mapboxgl-popup-anchor-top-left .mapboxgl-popup-tip,
.scheda-pin.mapboxgl-popup-anchor-top-right .mapboxgl-popup-tip { border-bottom-color: var(--card); }
.scheda-pin.mapboxgl-popup-anchor-left .mapboxgl-popup-tip { border-right-color: var(--card); }
.scheda-pin.mapboxgl-popup-anchor-right .mapboxgl-popup-tip { border-left-color: var(--card); }
.scheda-pin .mapboxgl-popup-close-button {
  color: var(--text-secondary);
  font-size: 18px;
  padding: 2px 8px;
  border-radius: 0 12px 0 8px;
}
.scheda-pin .mapboxgl-popup-close-button:hover { background: var(--hover); color: var(--text); }
.scheda-pin-testa { display: flex; align-items: center; gap: 10px; padding-right: 18px; }
.scheda-pin-testa strong { display: block; font-size: 14px; }
.scheda-pin-attesa { margin: 0; font-size: 12px; color: var(--text-terziario); }
.scheda-pin-righe {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 5px 14px;
  margin: 2px 0 0;
  padding-top: 8px;
  border-top: 1px solid var(--border);
  font-size: 12px;
}
.scheda-pin-righe dt { color: var(--text-secondary); white-space: nowrap; }
.scheda-pin-righe dd { margin: 0; font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
.scheda-pin-alert { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 4px; }
.scheda-pin-alert li {
  font-size: 12px;
  padding: 5px 8px;
  border-radius: 6px;
  border-left: 3px solid var(--warn);
  background: color-mix(in srgb, var(--warn) 10%, transparent);
}
.scheda-pin-alert li.danger {
  border-left-color: var(--danger);
  background: color-mix(in srgb, var(--danger) 10%, transparent);
}
.scheda-pin-alert li.info {
  border-left-color: var(--accento);
  background: color-mix(in srgb, var(--accento) 10%, transparent);
}
.scheda-pin-alert li [data-ts] { color: var(--text-terziario); white-space: nowrap; }
.scheda-pin-alert li.altri { border: 0; background: none; color: var(--text-terziario); padding: 0 8px; }
.scheda-pin-piede {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding-top: 8px;
  border-top: 1px solid var(--border);
  font-size: 12px;
}
.scheda-pin-link { display: flex; gap: 12px; }
.scheda-pin-link a { color: var(--accento); text-decoration: none; font-weight: 600; white-space: nowrap; }
.scheda-pin-link a:hover { text-decoration: underline; }

.mappa-campo {
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-size: 12px;
  color: var(--text-secondary);
}
.mappa-campo input {
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: 9px;
  background: var(--campo);
  color: var(--text);
  font-size: 13px;
}
.mappa-campo input:focus {
  outline: none;
  border-color: var(--accento);
  box-shadow: 0 0 0 3px var(--accento-alone);
}
.mappa-bottoni { display: flex; flex-wrap: wrap; gap: 6px; }

/* --- i segnaposti --- */

/* il contenitore e' di mapbox-gl (posizione e trasformazione sono sue):
   qui solo cio' che serve a non deformare il pallino dentro */
.pin-segnaposto { line-height: 0; cursor: pointer; }
.pin-segnaposto.scelto { z-index: 2; }
.pin-segnaposto:focus-visible { outline: 2px solid var(--accento); outline-offset: 3px; border-radius: 50%; }

/* il pallino porta l'icona del tipo (telecamera, access point...) e si
   colora con lo stato: si legge cosa e' e come sta senza aprire niente */
.pin {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  border: 2px solid #fff;
  background: var(--text-terziario);
  color: #fff;
  box-shadow: 0 1px 4px rgba(16, 24, 40, 0.45);
  flex: none;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;
}
.pin svg { width: 16px; height: 16px; }
.pin-pezzo { width: 24px; height: 24px; }
.pin-pezzo svg { width: 14px; height: 14px; }
/* nell'elenco e nelle schede basta piu' piccolo */
.mappa-voce .pin, .scheda-pin-testa .pin, .mappa-dettaglio-testa .pin { width: 24px; height: 24px; }
.mappa-voce .pin svg, .scheda-pin-testa .pin svg, .mappa-dettaglio-testa .pin svg { width: 13px; height: 13px; }
/* la legenda resta a pallini semplici: dice solo i colori */
i.pin { width: 12px; height: 12px; }
.pin-attivo { background: var(--ok); }
.pin-avviso { background: var(--warn); }
.pin-guasto { background: var(--danger); }
.pin-ignoto { background: #8a90a3; }
.pin-scelto {
  box-shadow: 0 0 0 4px var(--accento-alone), 0 1px 4px rgba(16, 24, 40, 0.45);
  z-index: 2;
}
/* cio' che non risponde deve farsi notare senza che si debba cercarlo */
.pin-guasto { animation: pulsa-pin 2s ease-out infinite; }
@keyframes pulsa-pin {
  0%   { box-shadow: 0 0 0 0 rgba(220, 43, 43, 0.55), 0 1px 4px rgba(16, 24, 40, 0.45); }
  70%  { box-shadow: 0 0 0 10px rgba(220, 43, 43, 0), 0 1px 4px rgba(16, 24, 40, 0.45); }
  100% { box-shadow: 0 0 0 0 rgba(220, 43, 43, 0), 0 1px 4px rgba(16, 24, 40, 0.45); }
}
@media (prefers-reduced-motion: reduce) {
  .pin-guasto { animation: none; }
}
i.pin { cursor: default; }

/* --- scelta dell'icona di un punto --- */
.mappa-icone { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; }
.mappa-icona, .mappa-icona-auto {
  height: 32px;
  border-radius: 8px;
  border: 1px solid var(--border);
  background: var(--campo);
  color: var(--text-secondary);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.mappa-icona { width: 32px; padding: 0; }
.mappa-icona svg { width: 17px; height: 17px; }
.mappa-icona-auto { padding: 0 10px; font-size: 12px; }
.mappa-icona:hover, .mappa-icona-auto:hover { background: var(--hover); color: var(--text); }
.mappa-icona[aria-pressed="true"], .mappa-icona-auto[aria-pressed="true"] {
  border-color: var(--accento);
  color: var(--accento);
  box-shadow: 0 0 0 3px var(--accento-alone);
}
.mappa-icona:focus-visible, .mappa-icona-auto:focus-visible { outline: 2px solid var(--accento); outline-offset: 2px; }

/* --- messaggi e richiesta del token --- */

#mappa-messaggio:empty { display: none; }
.mappa-messaggio {
  margin-top: 1rem;
  padding: 12px 16px;
  border-radius: var(--raggio);
  border: 1px solid var(--border);
  background: var(--card);
  color: var(--text-secondary);
  font-size: 13px;
}
.mappa-messaggio.buono { border-color: var(--ok); color: var(--ok); }
.mappa-messaggio.cattivo { border-color: var(--danger); color: var(--danger); }
.mappa-token { max-width: 620px; display: flex; flex-direction: column; gap: 10px; }
.mappa-token h2 { margin: 0; font-size: 17px; color: var(--text); }
.mappa-token p { margin: 0; line-height: 1.55; }
.mappa-token code {
  padding: 1px 5px;
  border-radius: 5px;
  background: var(--traccia);
  color: var(--text);
}
.mappa-token .bottone-piccolo { align-self: flex-start; }

/* --- comandi di Mapbox: il minimo perche' non stonino --- */

.mapboxgl-ctrl-group { border-radius: 10px !important; box-shadow: var(--ombra) !important; }
.mapboxgl-ctrl-attrib { font-size: 10px; }

@media (max-width: 1100px) {
  .mappa-guscio { grid-template-columns: minmax(0, 1fr) 280px; }
  .mappa-strumenti { width: 240px; }
  .mappa-istruzione { left: 272px; }
}
@media (max-width: 860px) {
  .mappa-guscio {
    grid-template-columns: minmax(0, 1fr);
    height: auto;
  }
  .mappa-tela { height: 60vh; min-height: 340px; }
  .mappa-istruzione { left: 12px; right: 12px; top: auto; bottom: 46px; }
  .mappa-lato { max-height: 50vh; }
  .mappa-legenda-voci { display: none; }
}

.mappa-errore { margin: 0; color: var(--danger); font-size: 13px; }
.mappa-errore:empty { display: none; }

/* --- anteprima della telecamera al passaggio del mouse ------------------- */

.mappa-anteprima {
  position: absolute;
  z-index: 60;
  display: none;
  width: 280px;
  padding: 6px;
  border-radius: var(--raggio);
  border: 1px solid var(--border);
  background: var(--popover);
  box-shadow: var(--ombra-vetro-alta);
  pointer-events: none;      /* non deve rubare il mouse al pallino */
}
.mappa-anteprima img {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  border-radius: var(--raggio-piccolo);
  background: var(--muted);
}
.mappa-anteprima-piede {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px 8px;
  padding: 6px 4px 2px;
  font-size: 12px;
  color: var(--text-secondary);
}
.mappa-anteprima-piede strong { color: var(--text); font-size: 13px; }
.mappa-anteprima-quando { margin-left: auto; color: var(--text-terziario); font-size: 11px; }
/* --- live di una telecamera dentro la scheda della mappa --- */
.scheda-pin-live { margin: 10px 0 4px; }
.scheda-pin-video {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  background: #000;
  border-radius: var(--raggio, 8px);
}
.scheda-pin-live .scheda-pin-attesa { margin-top: 6px; }
