/* ================================================================================
   Umana Planner — foglio di stile dell'applicazione.

   Tutti i colori passano da variabili CSS in :root e [data-bs-theme="dark"]. Nei
   componenti non si scrivono colori in linea: un colore letterale nella vista non
   regge il cambio di tema, e il tema scuro lo scoprirebbe solo a video.
================================================================================ */

/* ============ TEMA CHIARO ============ */
:root {
  --ink: #101623;
  --shell: #1a2231;
  --shell-2: #242e40;
  --shell-ink: #c9d1de;
  --shell-ink-dim: #8b97a9;
  --shell-hover: rgba(255, 255, 255, .06);
  --shell-active: rgba(226, 0, 26, .28);
  --shell-line: rgba(255, 255, 255, .07);
  --paper: #f4f5f7;
  --surface: #ffffff;
  --surface-2: #fafbfc;
  --surface-3: #f1f3f6;
  --line: #dfe3ea;
  --muted: #5d6779;
  --track: #eceff3;
  --backdrop: rgba(16, 22, 35, .38);

  /* Rosso del logo Umana. */
  --red: #e2001a;
  --red-dark: #b30015;
  --red-soft: #fdeaec;
  --red-ring: rgba(226, 0, 26, .14);

  --ok: #1e8a5f;
  --warn: #c98a00;
  --bad: #c7362f;

  /* Linea dell'ora attuale nella vista giorno. */
  --now: #1e8a5f;

  --bs-primary: var(--red);
  --bs-primary-rgb: 226, 0, 26;
  --bs-body-bg: var(--paper);
  --bs-body-color: var(--ink);
  --bs-emphasis-color: var(--ink);
  --bs-secondary-color: var(--muted);
  --bs-body-font-family: "IBM Plex Sans", "Segoe UI", system-ui, sans-serif;
  --bs-border-color: var(--line);
  --bs-border-radius: .4rem;
  --bs-link-color: var(--red-dark);
  --bs-link-hover-color: var(--red);
}

/* ============ TEMA SCURO ============ */
[data-bs-theme="dark"] {
  --ink: #e7eaf0;
  --shell: #0d1117;
  --shell-2: #171d26;
  --shell-ink: #aab4c2;
  --shell-ink-dim: #78828f;
  --shell-hover: rgba(255, 255, 255, .05);
  --shell-active: rgba(255, 74, 92, .22);
  --shell-line: rgba(255, 255, 255, .06);
  --paper: #12161d;
  --surface: #1a1f28;
  --surface-2: #1f242e;
  --surface-3: #151a22;
  --line: #2c3340;
  --muted: #95a0b0;
  --track: #262d38;
  --backdrop: rgba(0, 0, 0, .5);

  /* Sul fondo scuro il rosso pieno perde contrasto: si schiarisce, e il testo dei
     bottoni primari diventa scuro (vedi .btn-primary più sotto). */
  --red: #ff4a5c;
  --red-dark: #ff7a87;
  --red-soft: rgba(255, 74, 92, .16);
  --red-ring: rgba(255, 74, 92, .22);

  --ok: #34b37c;
  --warn: #e0a52a;
  --bad: #e8615a;

  --now: #ff9a3c;

  --bs-primary: var(--red);
  --bs-primary-rgb: 255, 74, 92;
  --bs-body-bg: var(--paper);
  --bs-body-color: var(--ink);
  --bs-emphasis-color: #fff;
  --bs-border-color: var(--line);
  --bs-link-color: var(--red-dark);
  --bs-link-hover-color: var(--red);
}

[data-bs-theme="dark"] .form-control,
[data-bs-theme="dark"] .form-select,
[data-bs-theme="dark"] .input-group-text { background: var(--surface-2); color: var(--ink); border-color: var(--line); }
[data-bs-theme="dark"] .form-control::placeholder { color: #6f7a89; }
[data-bs-theme="dark"] .page-link { background: var(--surface); border-color: var(--line); color: var(--ink); }
[data-bs-theme="dark"] .page-item.active .page-link { background: var(--red); border-color: var(--red); color: #161b22; }
[data-bs-theme="dark"] .btn-close { filter: invert(1) grayscale(1) brightness(1.6); }

body { -webkit-font-smoothing: antialiased; }
.mono { font-family: "IBM Plex Mono", ui-monospace, monospace; font-variant-ligatures: none; }
:focus-visible { outline: 2px solid var(--red); outline-offset: 2px; }

/* ---------- struttura ---------- */
.shell { display: grid; grid-template-columns: 262px minmax(0, 1fr); min-height: 100vh; }
@media (max-width: 991.98px) { .shell { grid-template-columns: minmax(0, 1fr); } }

/* ---------- navigazione ---------- */
.main-nav {
  background: var(--shell); color: var(--shell-ink);
  display: flex; flex-direction: column; position: sticky; top: 0; height: 100vh; overflow-y: auto;
}
@media (max-width: 991.98px) { .main-nav { position: static; height: auto; } }
.brand { display: flex; gap: .7rem; align-items: center; padding: 1.15rem 1.25rem 1.25rem; }
.brand-mark {
  width: 34px; height: 34px; border-radius: 9px; flex: 0 0 auto;
  background: var(--red); color: #fff; display: grid; place-items: center; font-size: 1.05rem;
  box-shadow: inset 0 -2px 0 rgba(0, 0, 0, .22);
}
/* Il logo da LOGO_URL riempie il riquadro del marchio: senza vincolo, un file grande
   sfonderebbe l'intestazione della navigazione. */
.brand-mark img { width: 100%; height: 100%; object-fit: contain; border-radius: inherit; display: block; }
.brand-name { color: #fff; font-weight: 600; letter-spacing: -.01em; line-height: 1.1; }
.brand-org { font-size: .78rem; color: var(--shell-ink-dim); }
.nav-group { padding: 0 1rem; }
.nav-group + .nav-group { margin-top: 1rem; padding-top: 1rem; border-top: 1px solid var(--shell-line); }
.nav-title { font-size: .8rem; color: var(--shell-ink-dim); padding: 0 .7rem .4rem; }
.main-nav .nav-link {
  color: var(--shell-ink); border-radius: .45rem; padding: .5rem .7rem;
  display: flex; align-items: center; gap: .65rem; font-size: .92rem;
}
.main-nav .nav-link:hover { background: var(--shell-hover); color: #fff; }

/* Stato attivo: --shell-active, mai --red-soft, che in chiaro è rosa e sul navy del
   pannello risulta illeggibile. */
.main-nav .nav-link.active { background: var(--shell-active); color: #fff; font-weight: 500; box-shadow: inset 3px 0 0 var(--red); }
.main-nav .nav-link.active:hover { background: var(--shell-active); }
.main-nav .nav-link i { font-size: 1.02rem; color: var(--shell-ink-dim); }
.main-nav .nav-link.active i { color: #ff8a97; }
.nav-count { margin-left: auto; font-size: .75rem; background: rgba(255, 255, 255, .08); padding: .05rem .4rem; border-radius: .3rem; color: var(--shell-ink-dim); }
.nav-foot { margin-top: auto; padding: 1rem; border-top: 1px solid var(--shell-line); }
.who { display: flex; align-items: center; gap: .6rem; }
.who-name { font-size: .9rem; color: #fff; }
.avatar {
  width: 32px; height: 32px; border-radius: 50%; flex: 0 0 auto; display: grid; place-items: center;
  font-size: .78rem; font-weight: 600; color: #fff; background: #3b4759;
}
.avatar-red { background: var(--red); }

/* ---------- barra superiore ---------- */
.topbar {
  background: var(--surface); border-bottom: 1px solid var(--line);
  padding: .65rem 1.5rem; display: flex; align-items: center; gap: 1rem; position: sticky; top: 0; z-index: 5;
}
.breadcrumb { margin: 0; font-size: .9rem; }
.breadcrumb-item + .breadcrumb-item::before { content: "/"; color: var(--muted); }
.theme-switch { display: inline-flex; background: var(--track); border-radius: 2rem; padding: 2px; gap: 2px; }
.theme-switch button {
  border: 0; background: transparent; color: var(--muted);
  width: 32px; height: 28px; border-radius: 2rem; display: grid; place-items: center; font-size: .9rem;
}
.theme-switch button[aria-checked="true"] { background: var(--surface); color: var(--red); box-shadow: 0 1px 2px rgba(0, 0, 0, .12); }
.theme-switch button:hover { color: var(--ink); }

/* ---------- contenuto ---------- */
.work { padding: 1.5rem; display: block; }
.panel { background: var(--surface); border: 1px solid var(--line); border-radius: .6rem; }
.panel-head { padding: .85rem 1.1rem; border-bottom: 1px solid var(--line); display: flex; align-items: center; gap: .75rem; flex-wrap: wrap; }
.panel-head h2 { font-size: 1rem; font-weight: 600; margin: 0; }
.sub { font-size: .82rem; color: var(--muted); }

/* ---------- elenco a tabella ---------- */
.table-plan { margin: 0; font-size: .92rem; --bs-table-bg: transparent; --bs-table-color: var(--ink); }
.table-plan > :not(caption) > * > * { padding: .75rem 1rem; vertical-align: middle; border-color: var(--line); background: transparent; }
.table-plan thead th { font-weight: 500; font-size: .8rem; color: var(--muted); background: var(--surface-2); }
.table-plan tbody tr.riga:hover > * { background: var(--red-soft); }
.table-plan thead th a { color: var(--muted); text-decoration: none; }
.table-plan thead th a:hover { color: var(--ink); }
/* blocco di un account Zoom dentro un pannello: respiro attorno, tabella in riquadro */
.tenant-block { padding: 1rem 1.1rem 1.1rem; }
.tenant-block + .tenant-block { border-top: 1px solid var(--line); }
.tenant-block .table-responsive { border: 1px solid var(--line); border-radius: .5rem; overflow: hidden; }
.tenant-block .con-selezione th:first-child, .tenant-block .con-selezione td:first-child { width: 2.75rem; }
.tag { font-size: .75rem; border: 1px solid var(--line); border-radius: .3rem; padding: .05rem .35rem; color: var(--muted); }
.tag-bad { color: var(--bad); border-color: var(--bad); }
.tag-ok { color: var(--ok); border-color: var(--ok); }

/* ---------- chiavetta di colore ----------
   Identica in menu, filtri, elenco, scheda e scheduler: è il modo in cui si riconosce
   una licenza o un'aula senza leggerne il nome. */
.key { width: 9px; height: 9px; border-radius: 2px; flex: 0 0 auto; display: inline-block; background: var(--muted); }
.key-umana { background: #e2001a; }
.key-blu { background: #2f6fb5; }
.key-verde { background: #1e8a5f; }
.key-viola { background: #8a5cd1; }
.key-ciano { background: #0f9aa8; }
.key-magenta { background: #b5335f; }
.key-ambra { background: #c07000; }
.key-neutro { background: #7c879a; }
/* Colore esadecimale arrivato dai dati (categorie delle prenotazioni) nella variabile --col. */
.key-hex { background: var(--col); }

/* Tendina di radio (data-tendina): la voce scelta si riconosce senza il pallino della radio. */
.tendina > .form-select { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tendina-menu { max-height: 18rem; overflow-y: auto; }
.tendina-menu .dropdown-item { cursor: pointer; }
.tendina-menu .dropdown-item:has(input:checked) { background: var(--bs-tertiary-bg); font-weight: 600; }
.tendina-menu .dropdown-item:has(input:focus-visible) { outline: 2px solid var(--bs-focus-ring-color); outline-offset: -2px; }

.swatches { display: flex; flex-wrap: wrap; gap: .4rem; }
.swatch {
  width: 34px; height: 34px; border: 1px solid var(--line); border-radius: .4rem;
  display: grid; place-items: center; cursor: pointer;
}
.swatch .key { width: 16px; height: 16px; border-radius: 3px; }
.swatch:hover { border-color: var(--muted); }
.swatch:has(input:checked) { border-color: var(--red); box-shadow: 0 0 0 2px var(--red-ring); }
.swatch:has(input:focus-visible) { outline: 2px solid var(--red); outline-offset: 2px; }

/* ================================================================================
   SCHEDULER

   Griglia a due dimensioni: una colonna delle ore e N colonne di giorni o licenze.
   Le righe sono slot di durata fissa (PLANNER_SLOT_MINUTES), e i blocchi sono
   posizionati in assoluto dentro la colonna: l'altezza di un meeting è proporzionale
   alla durata, che è l'unico modo per vedere a colpo d'occhio una sovrapposizione.
================================================================================ */
.planner { background: var(--surface); border: 1px solid var(--line); border-radius: .6rem; overflow: hidden; }
.planner-head {
  display: flex; align-items: center; gap: .75rem; flex-wrap: wrap;
  padding: .75rem 1.1rem; border-bottom: 1px solid var(--line); background: var(--surface-2);
}
.planner-title { font-size: 1.05rem; font-weight: 600; margin: 0; text-transform: capitalize; }
.planner-views { display: inline-flex; background: var(--track); border-radius: 2rem; padding: 2px; gap: 2px; }
.planner-views button {
  border: 0; background: transparent; color: var(--muted); font-size: .85rem;
  padding: .25rem .85rem; border-radius: 2rem;
}
.planner-views button[aria-pressed="true"] { background: var(--surface); color: var(--red); font-weight: 500; box-shadow: 0 1px 2px rgba(0, 0, 0, .12); }

.planner-scroll { overflow: auto; max-height: calc(100vh - 13rem); }
/* min-content e non una misura fissa: senza, la griglia è larga quanto lo schermo e le
   colonne in più debordano dal suo box. Un elemento sticky non esce mai dal proprio
   blocco contenitore, quindi la colonna delle ore, scorrendo oltre quel box, se ne
   andrebbe con la griglia. */
.planner-grid { display: grid; min-width: min-content; position: relative; }
.planner-corner, .planner-col-head {
  position: sticky; top: 0; z-index: 3; background: var(--surface-2);
  border-bottom: 1px solid var(--line); border-left: 1px solid var(--line);
  padding: .45rem .6rem; font-size: .84rem; text-align: center;
}
.planner-corner { left: 0; z-index: 4; border-left: 0; }
.planner-col-head .giorno { font-weight: 600; text-transform: capitalize; }
.planner-col-head.oggi { box-shadow: inset 0 -3px 0 var(--red); }

/* La colonna delle ore resta ferma a sinistra: a metà settimana, senza, non si sa più
   a quale ora corrisponde una riga. Lo sfondo è obbligatorio: sticky non ritaglia
   niente, e su fondo trasparente il contenuto scorrerebbe sotto. */
.planner-hours { position: sticky; left: 0; z-index: 2; background: var(--surface); border-right: 1px solid var(--line); }
.planner-hour {
  font-size: .72rem; color: var(--muted); text-align: right; padding-right: .4rem;
  border-top: 1px solid var(--line); box-sizing: border-box;
}
.planner-hour.mezza { border-top-style: dotted; color: transparent; }

/* La stessa scala in fondo a destra. Nella vista giorno le colonne sono le licenze: con
   parecchie licenze la griglia è larga, e l'ultima resta lontana dall'unico riferimento
   orario. Ferma a destra invece che a sinistra, e i numeri appoggiati al bordo interno,
   cioè dalla parte da cui si legge la colonna accanto. */
.planner-corner.destra { left: auto; right: 0; border-left: 1px solid var(--line); }
.planner-hours.destra { left: auto; right: 0; border-right: 0; border-left: 1px solid var(--line); }
.planner-hours.destra .planner-hour { text-align: left; padding-right: 0; padding-left: .4rem; }

.planner-col { position: relative; border-left: 1px solid var(--line); }
.planner-slot { border-top: 1px solid var(--line); box-sizing: border-box; }
.planner-slot.mezza { border-top-style: dotted; }
.planner-slot:hover { background: var(--red-soft); }
.planner-col.oggi { background: var(--surface-2); }

/* Ora attuale: sopra gli slot e sotto i blocchi, che nel DOM vengono dopo. Trasparente
   ai clic, così trascinamento e selezione degli slot funzionano anche sulla linea. La
   posizione la scrive app.js, che la aggiorna ogni mezzo minuto. */
.ora-attuale {
    position: absolute; left: 0; right: 0; height: 0;
    border-top: 2px solid var(--now); pointer-events: none;
}

/* ---------- blocco di un meeting ---------- */
.evento {
  position: absolute; left: 2px; right: 2px; overflow: hidden; box-sizing: border-box;
  border-radius: .35rem; padding: .15rem .35rem; font-size: .76rem; line-height: 1.2;
  border: 1px solid var(--line); border-left: 3px solid var(--col, var(--muted));
  background: color-mix(in srgb, var(--col, var(--muted)) 14%, var(--surface));
  color: var(--ink); cursor: pointer;
  box-shadow: 0 1px 2px rgba(0, 0, 0, .08);
}
.evento:hover { box-shadow: 0 2px 8px rgba(0, 0, 0, .16); z-index: 2; }
.evento .ora { color: var(--muted); font-size: .7rem; }
.evento .titolo { font-weight: 500; display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.evento.trascinato { opacity: .75; z-index: 5; box-shadow: 0 6px 18px rgba(0, 0, 0, .25); }

/* Il colore della licenza è pieno sul bordo sinistro e tenue sul fondo: mescolato alla
   superficie del tema, il testo del titolo resta leggibile in entrambi i temi. */
.evento.col-umana { --col: #e2001a; }
.evento.col-blu { --col: #2f6fb5; }
.evento.col-verde { --col: #1e8a5f; }
.evento.col-viola { --col: #8a5cd1; }
.evento.col-ciano { --col: #0f9aa8; }
.evento.col-magenta { --col: #b5335f; }
.evento.col-ambra { --col: #c07000; }
.evento.col-neutro { --col: #7c879a; }

/* Blocco con un avviso (meeting non arrivato su Zoom, aula più piccola dei
   partecipanti): bordo tratteggiato. Il colore da solo non basta, perché il testo
   dell'avviso deve restare leggibile anche a chi non distingue i colori: infatti il
   blocco lo scrive. */
.evento.segnalato { border-style: dashed; border-color: var(--bad); }

/* Riunione già finita: resta nella griglia, perché quel tempo la licenza l'ha occupato,
   ma smorzata. Chi guarda la giornata deve distinguere a colpo d'occhio cosa resta da
   fare; il blocco scrive comunque "conclusa", perché lo smorzato è solo un colore. */
.evento.concluso { opacity: .62; }
.evento.concluso:hover { opacity: 1; }

/* Selezione in corso mentre si trascina sulle ore per creare. */
.planner-col .selezione {
  position: absolute; left: 2px; right: 2px; border-radius: .35rem;
  background: var(--red-soft); border: 1px dashed var(--red);
  pointer-events: none;
}
.planner-col .selezione span { font-size: .72rem; color: var(--red-dark); padding: .1rem .3rem; display: block; }
.evento .ricorrente { font-size: .65rem; color: var(--muted); }

/* Maniglia di ridimensionamento: due pixel in fondo al blocco. Su touch la zona utile
   è più alta di quella visibile, altrimenti sul telefono non si prende mai. */
.evento .maniglia {
  position: absolute; left: 0; right: 0; bottom: 0; height: 6px; cursor: ns-resize;
  touch-action: none;
}
.evento .maniglia::after {
  content: ""; display: block; width: 24px; height: 2px; margin: 2px auto 0;
  border-radius: 2px; background: var(--muted); opacity: .5;
}

/* ---------- vista settimana: righe per risorsa, tempo in orizzontale ----------

   Qui gli assi sono scambiati rispetto alla vista giorno: una riga è una licenza (o
   un'aula), e la settimana scorre da sinistra a destra, un gruppo di colonne per
   giorno. Il nome della risorsa resta fermo a sinistra e le due righe di intestazione
   restano ferme in alto.

   Le colonne delle ore si dividono lo spazio disponibile invece di avere una larghezza
   fissa: la settimana intera deve stare in una schermata, e sette giorni di ore a
   misura fissa sarebbero qualche migliaio di pixel da scorrere. Sotto la larghezza
   minima dichiarata dalla griglia la compressione si ferma e riparte lo scorrimento. */
.planner-timeline { display: grid; min-width: min-content; position: relative; --risorse-w: 150px; }

.tl-corner { display: flex; align-items: center; justify-content: center; text-transform: capitalize; }

.tl-giorno, .tl-ora {
  position: sticky; z-index: 3; background: var(--surface-2);
  border-bottom: 1px solid var(--line); text-align: center;
}
.tl-giorno {
  top: 0; height: 28px; line-height: 28px; font-size: .78rem; font-weight: 600;
  text-transform: capitalize; border-left: 2px solid var(--muted); overflow: hidden;
}
.tl-giorno.oggi { color: var(--red); box-shadow: inset 0 -3px 0 var(--red); }

/* Colonna d'ora larga una dozzina di pixel: il numero deborda da entrambi i lati e la
   cella non lo ritaglia, altrimenti resterebbe una cifra sola. Le ore senza numero
   danno comunque la scala con il loro bordo. */
.tl-ora {
  top: 28px; height: 18px; line-height: 18px; font-size: .62rem; color: var(--muted);
  border-left: 1px solid var(--line); overflow: visible; white-space: nowrap;
}
.tl-ora.primo { border-left: 2px solid var(--muted); }

.tl-risorsa {
  position: sticky; left: 0; z-index: 2; background: var(--surface);
  display: flex; align-items: center; gap: .4rem; overflow: hidden;
  padding: .3rem .5rem; font-size: .78rem;
  border-top: 1px solid var(--line); border-right: 1px solid var(--line);
}
.tl-nome { font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Le righe delle ore e i separatori dei giorni sono disegnati come sfondo: una cella
   vera per ogni ora di ogni giorno sarebbe un centinaio di nodi per risorsa, pagati
   a ogni ricarica dello scheduler. */
.planner-lane {
  position: relative; border-top: 1px solid var(--line); touch-action: none;
  background-image:
    repeating-linear-gradient(to right, var(--muted) 0 2px, transparent 2px var(--giorno-w)),
    repeating-linear-gradient(to right, var(--line) 0 1px, transparent 1px var(--ora-w));
}
.planner-lane:hover { background-color: var(--surface-2); }

.planner-lane .selezione {
  position: absolute; top: 2px; bottom: 2px; border-radius: .35rem;
  background: var(--red-soft); border: 1px dashed var(--red);
  pointer-events: none;
}
.planner-lane .selezione span { font-size: .72rem; color: var(--red-dark); padding: .1rem .3rem; display: block; }

/* Il blocco orizzontale scrive titolo e orario su una riga sola, e la maniglia passa
   sul bordo destro: la durata si legge in larghezza, quindi si tira di lato. */
.evento.orizzontale {
  display: flex; align-items: center; gap: .25rem; white-space: nowrap;
  padding: .1rem .25rem; font-size: .72rem;

  /* Un meeting di cinque minuti su una settimana intera è meno di un pixel: sotto
     questa misura resta comunque una cosa che si vede e si prende col dito. */
  min-width: 10px;
}
.evento.orizzontale .ricorrente { overflow: hidden; text-overflow: ellipsis; }
.evento.orizzontale .maniglia {
  left: auto; top: 0; bottom: 0; right: 0; width: 6px; height: auto; cursor: ew-resize;
}
.evento.orizzontale .maniglia::after {
  width: 2px; height: 24px; margin: auto 2px auto 0;
  position: absolute; top: 0; bottom: 0; right: 2px;
}

/* ---------- vista mese ---------- */
.mese { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); }
.mese-head {
  padding: .4rem; text-align: center; font-size: .8rem; color: var(--muted);
  background: var(--surface-2); border-bottom: 1px solid var(--line); text-transform: capitalize;
}
.mese-giorno {
  min-height: 7.5rem; border-top: 1px solid var(--line); border-left: 1px solid var(--line);
  padding: .3rem; display: flex; flex-direction: column; gap: .15rem;
}
.mese-giorno.fuori { background: var(--surface-3); }
.mese-giorno.oggi { box-shadow: inset 0 0 0 2px var(--red-ring); }
.mese-numero { font-size: .78rem; color: var(--muted); align-self: flex-end; }
.mese-giorno.oggi .mese-numero { color: var(--red); font-weight: 600; }
.mese .evento { position: static; left: auto; right: auto; }

/* ---------- caricamento, vuoto, avvisi ---------- */
.loading { padding: 2.5rem 1rem; text-align: center; color: var(--muted); }
.empty { padding: 2.5rem 1rem; text-align: center; color: var(--muted); }
.empty i { font-size: 1.6rem; display: block; margin-bottom: .5rem; }

.toast-area { position: fixed; right: 1rem; bottom: 1rem; z-index: 1090; display: grid; gap: .5rem; max-width: min(420px, 90vw); }
.avviso {
  background: var(--surface); border: 1px solid var(--line); border-left: 3px solid var(--muted);
  border-radius: .45rem; padding: .7rem .85rem; font-size: .9rem; box-shadow: 0 6px 18px rgba(0, 0, 0, .12);
}
.avviso.ok { border-left-color: var(--ok); }
.avviso.ko { border-left-color: var(--bad); }

/* ---------- bottoni ---------- */
.btn-primary {
  --bs-btn-bg: var(--red); --bs-btn-border-color: var(--red); --bs-btn-color: #fff;
  --bs-btn-hover-bg: var(--red-dark); --bs-btn-hover-border-color: var(--red-dark); --bs-btn-hover-color: #fff;
  --bs-btn-active-bg: var(--red-dark); --bs-btn-active-border-color: var(--red-dark);
  --bs-btn-focus-shadow-rgb: 226, 0, 26; font-weight: 500;
}

/* In tema scuro il testo del bottone primario diventa scuro: il bianco non tiene il
   contrasto sul rosso schiarito. */
[data-bs-theme="dark"] .btn-primary { --bs-btn-color: #14181f; --bs-btn-hover-color: #14181f; }
.btn-ghost {
  --bs-btn-color: var(--ink); --bs-btn-border-color: var(--line); --bs-btn-bg: transparent;
  --bs-btn-hover-bg: var(--surface-2); --bs-btn-hover-border-color: var(--muted); --bs-btn-hover-color: var(--ink);
  font-weight: 500;
}
.row-actions { display: flex; gap: .15rem; justify-content: end; }
.icon-btn {
  border: 0; background: transparent; color: var(--muted); width: 32px; height: 32px;
  border-radius: .35rem;
}
.icon-btn:hover { background: var(--red-soft); color: var(--red-dark); }

/* ---------- campi ---------- */
.campo {
  display: flex; align-items: center; gap: .5rem; background: var(--surface-2);
  border: 1px solid var(--line); border-radius: .45rem; padding: .5rem .7rem; font-size: .92rem;
}
.campo .val { flex: 1; min-width: 0; overflow-wrap: anywhere; }
.campo.segreto { border-left: 3px solid var(--red); }

.matrix { font-size: .88rem; margin: 0; --bs-table-bg: transparent; --bs-table-color: var(--ink); }
.matrix th, .matrix td { border-color: var(--line); background: transparent; text-align: center; vertical-align: middle; }
.matrix thead th { font-weight: 500; font-size: .78rem; color: var(--muted); background: var(--surface-2); }
.matrix tbody th { text-align: left; font-weight: 500; }
.matrix .form-check-input:checked { background-color: var(--red); border-color: var(--red); }

/* Matrice di abilitazione: molte colonne strette, quindi celle basse e la colonna degli
   utenti ferma a sinistra, così scorrendo in orizzontale si sa sempre di chi è la riga. */
.matrix-grant th, .matrix-grant td { padding: .35rem .6rem; }

/* Intestazioni in verticale: con più di cento licenze il nome orizzontale farebbe ogni
   colonna larga quanto il nome più lungo. Si legge dal basso verso l'alto; oltre 11rem
   il nome si tronca, e il title sulla cella lo mostra intero. */
.matrix-grant thead th.vert { vertical-align: bottom; padding: .5rem .2rem; width: 2rem; min-width: 2rem; }
.matrix-grant .vert-text {
    display: inline-block; writing-mode: vertical-rl; transform: rotate(180deg);
    max-height: 11rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    margin-top: .3rem;
}
.matrix-grant thead th.vert .key { display: block; margin: 0 auto; }
.matrix-grant tbody td { padding: .35rem .2rem; }
.matrix-grant tbody th, .matrix-grant thead th:first-child { position: sticky; left: 0; z-index: 1; background: var(--surface); min-width: 14rem; }
.matrix-grant thead th:first-child { background: var(--surface-2); }
.matrix-grant tbody tr:hover > * { background: var(--surface-2); }

.list-plain { list-style: none; margin: 0; padding: .3rem 0; }
.list-plain li { padding: .6rem 1.1rem; display: flex; align-items: center; gap: .7rem; font-size: .88rem; }
.list-plain li + li { border-top: 1px solid var(--line); }

/* ---------- pannello e finestra ---------- */
#pannello { --bs-offcanvas-width: min(760px, 100%); }
.offcanvas, .modal-content { background: var(--surface); color: var(--ink); }
.offcanvas-header, .modal-header, .modal-footer { border-color: var(--line); }
.modal-content { border: 1px solid var(--line); border-radius: .6rem; }

/* Il contenuto caricato avvolge intestazione, corpo e piede in un <form>: senza questa
   regola il form è l'unico figlio flessibile di .modal-content e il corpo non riceve
   il vincolo di altezza, quindi modal-dialog-scrollable non scorre. */
.modal-dialog-scrollable .modal-content > form {
  display: flex; flex-direction: column; max-height: 100%; overflow: hidden;
}
.modal-dialog-scrollable .modal-content > form > .modal-body { overflow-y: auto; }

/* Sfondo sfocato dietro la finestra. La velatura sta nel colore e non in opacity: con
   opacity sotto 1 il browser isola l'elemento e la sfocatura non si vede. */
.modal-backdrop.show {
  opacity: 1; background-color: var(--backdrop);
  backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
}

/* Contenitore che non disegna nulla: un fieldset che spegne i campi (data-when) senza toccare il layout. */
.d-contents { display: contents; }

/* ---------- accesso ---------- */
/* Separatore fra i modi di entrare: riga a sinistra, parola, riga a destra. */
.sep-o { display: flex; align-items: center; gap: .6rem; color: var(--muted); font-size: .8rem; }
.sep-o::before, .sep-o::after { content: ""; flex: 1; height: 1px; background: var(--line); }
.gate { min-height: 100vh; display: grid; place-items: center; padding: 1.5rem; background: var(--shell); }
.gate-card { width: min(430px, 100%); background: var(--surface); border: 1px solid var(--line); border-radius: .7rem; padding: 1.6rem; }
.meter { display: inline-flex; gap: 3px; align-items: center; }
.meter span { width: 14px; height: 6px; border-radius: 1px; background: var(--track); }
.meter[data-level="4"] span:nth-child(-n+4),
.meter[data-level="3"] span:nth-child(-n+3) { background: var(--ok); }
.meter[data-level="2"] span:nth-child(-n+2) { background: var(--warn); }
.meter[data-level="1"] span:nth-child(-n+1) { background: var(--bad); }
.meter-txt { font-size: .78rem; color: var(--muted); margin-left: .5rem; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { transition: none !important; animation: none !important; }
}

/* Heatmap utilizzo licenze: l'intensità del rosso aziendale segue --v (0..1). */
.table-heat .heat {
  text-align: center;
  font-size: .8125rem;
  white-space: nowrap;
  background: color-mix(in srgb, var(--red) calc(var(--v, 0) * 100%), transparent);
}
.table-heat .heat-na { color: var(--bs-secondary-color); background: transparent; }
.table-heat .heat-sub { font-size: .6875rem; opacity: .8; }
