:root {
  --sidebar-bg: #1b2a38;
  --sidebar-bg-active: #24384a;
  --sidebar-text: #c3cdd6;
  --sidebar-text-muted: #7c8b98;
  --accent: #2f5d62;
  --accent-dark: #244749;
  --content-bg: #f2f4f5;
  --border-color: #dfe3e6;
}

body {
  background: var(--content-bg);
  font-family: "Segoe UI", "Helvetica Neue", Arial, sans-serif;
  font-size: 0.925rem;
}

.color-field {
  margin-bottom: 0.65rem;
}

.color-field:last-child {
  margin-bottom: 0;
}

.color-field-hex {
  width: 5.25rem;
  font-family: "SFMono-Regular", Consolas, monospace;
  text-transform: lowercase;
}

.color-field-toggle {
  padding: 0.25rem 0.5rem;
  line-height: 1;
}

.color-field-advanced {
  margin-top: 0.4rem;
  padding: 0.5rem 0.6rem;
  background: #f8f9fa;
  border: 1px solid var(--border-color);
  border-radius: 6px;
  display: flex;
  gap: 0.9rem;
  flex-wrap: wrap;
}

.cmyk-input {
  width: 3rem;
}

.rgb-input {
  width: 3rem;
}

.lead-layout-item {
  cursor: grab;
}

.lead-layout-item:active {
  cursor: grabbing;
}

.lead-layout-item .bi-grip-vertical {
  cursor: grab;
}

.province-suggest {
  font-size: 0.72rem;
  margin-top: 0.25rem;
}

.province-suggest a {
  text-decoration: none;
  font-weight: 600;
}

.province-suggest a:hover {
  text-decoration: underline;
}

/* --- Scheda lead/cliente: sezioni impilate in un'unica colonna a tutta larghezza --- */
.lead-tiles {
  display: flex;
  flex-direction: column;
  gap: 0.9rem;
}

.lead-tile,
.lead-tile > .card {
  width: 100%;
}

.lead-tile .card-header .badge {
  font-weight: 500;
}

/* Compattazione: righe più basse, meno padding, header uniformi */
.lead-tile .card-header {
  padding: 0.5rem 0.85rem;
  font-weight: 600;
  font-size: 0.9rem;
}

.lead-tile .card-body {
  padding: 0.8rem 0.85rem;
}

.lead-tile .card-footer {
  padding: 0.55rem 0.85rem;
}

.lead-tile .table {
  --bs-table-cell-padding-y: 0.35rem;
  --bs-table-cell-padding-x: 0.6rem;
  font-size: 0.85rem;
}

.lead-tile .table thead th {
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  color: #6b7a86;
  font-weight: 600;
  white-space: nowrap;
}

.lead-tile .list-group-item {
  padding: 0.45rem 0.85rem;
}

/* --- Dati inseriti e dati da inserire: due cose diverse, e si devono vedere diverse ---------

   Prima i campi vuoti di un modulo (bianchi, con il bordo) risaltavano piu' dei dati veri
   (testo nudo), e il trattino di un campo non compilato aveva lo stesso peso di un valore.
   La gerarchia era rovesciata: si notava quello che mancava, non quello che c'era. */

/* Il vuoto si legge come vuoto. Tre livelli, non due: valore, valore secondario, niente. */
.lead-tile .dato-vuoto {
  color: #c2ccd3;
}

/* Un valore vero resta a piena forza anche nelle colonne di contorno: a spegnersi e' il
   trattino, non il dato. */
.lead-tile .table td.col-secondaria {
  color: #6b7a86;
}

/* Il modulo per aggiungere si dichiara. Da solo il .card-footer non basta: il suo fondo e'
   rgba(0,0,0,.03), cioe' #fafafa su bianco — una differenza che a monitor non si vede. */
.lead-tile .lead-aggiungi {
  background: #eaf1f1;
  border-top: 2px solid #cfdedd;
  padding: 0.7rem 0.85rem 0.8rem;
}

.lead-tile .lead-aggiungi-titolo {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  margin-bottom: 0.5rem;
  color: var(--accent);
  font-size: 0.75rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

/* Le etichette dei campi copiano le intestazioni della tabella sopra: stesso corpo, stesso
   maiuscoletto, stesso grigio. Cosi' il modulo si legge come "la riga nuova di quella
   tabella" invece che come un blocco a se'. */
.lead-tile .lead-aggiungi .form-label {
  display: block;
  margin-bottom: 0.15rem;
  font-size: 0.72rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  color: #6b7a86;
  line-height: 1.2;
}

/* Sul fondo tinto il bordo grigio chiaro dei campi sparirebbe. */
.lead-tile .lead-aggiungi .form-control,
.lead-tile .lead-aggiungi .form-select {
  border-color: #c3d3d3;
}

.lead-tile .lead-aggiungi .form-control:focus,
.lead-tile .lead-aggiungi .form-select:focus {
  border-color: var(--accent);
  outline: 2px solid rgba(47, 93, 98, 0.18);
  outline-offset: 0;
}

/* Il pulsante che apre il modulo non deve spingere in basso il titolo della sezione quando
   l'intestazione va a capo su schermi stretti. */
.lead-tile .card-header .js-apri-modulo {
  flex: 0 0 auto;
  font-weight: 500;
}

/* Anagrafica: coppie etichetta/valore su una griglia fitta che riempie la riga */
.anag-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(11.875rem, 1fr));
  gap: 0.5rem 0.9rem;
}

.anag-grid > div {
  min-width: 0;
}

.anag-grid .anag-label {
  display: block;
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  color: #6b7a86;
  line-height: 1.2;
}

.anag-grid .anag-value {
  font-size: 0.9rem;
  word-break: break-word;
}

.anag-grid .anag-full {
  grid-column: 1 / -1;
}

/* Compilazione checklist sopralluogo: voci compatte affiancate, note/foto a tutta riga */
.survey-checklist-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
  gap: 0.9rem 1.4rem;
  align-items: start;
}

.survey-checklist-grid .survey-checklist-item {
  min-width: 0;
}

.survey-checklist-grid .survey-item-full {
  grid-column: 1 / -1;
}

.survey-checklist-grid .survey-checklist-item .form-control,
.survey-checklist-grid .survey-checklist-item .form-select,
.survey-checklist-grid .survey-checklist-item .input-group {
  max-width: 21.25rem;
}

.survey-checklist-grid .survey-item-full .form-control {
  max-width: 100%;
}

@media (max-width: 575.98px) {
  .survey-checklist-grid {
    grid-template-columns: 1fr;
  }
}

/* Documentazione fotografica e video del sopralluogo */
.survey-media-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(10rem, 1fr));
  gap: 0.75rem;
}

.survey-media-tile img,
.survey-media-tile video {
  width: 100%;
  height: 8.75rem;
  object-fit: cover;
  border-radius: 6px;
  background: #000;
  display: block;
}

.survey-media-fallback {
  width: 100%;
  height: 8.75rem;
  border-radius: 6px;
  border: 1px dashed var(--border-color);
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 0.5rem;
  font-size: 0.8rem;
  color: #6b7a86;
}

.settings-breadcrumb {
  font-size: 0.82rem;
  color: #6b7a86;
  display: flex;
  align-items: center;
  gap: 0.4rem;
}

.settings-breadcrumb a {
  color: var(--accent-dark);
  text-decoration: none;
}

.settings-breadcrumb a:hover {
  text-decoration: underline;
}

.settings-breadcrumb-sep {
  color: #b7c0c7;
}

.settings-breadcrumb-current {
  color: #6b7a86;
}

/* --- Layout autenticato ---------------------------------------------- */
.app-shell {
  display: flex;
  min-height: 100vh;
}

.app-sidebar {
  width: 16.25rem;
  flex-shrink: 0;
  background: var(--sidebar-bg);
  color: var(--sidebar-text);
  display: flex;
  flex-direction: column;
}

/* La sezione del logo ha un fondo suo, staccato da quello della barra.
   Il logo e' un'immagine con lo sfondo trasparente, disegnata per stare su una tinta sola: su
   una barra colorata — verde, nella nostra — le lettere chiare ci si sciolgono dentro e il
   marchio diventa una macchia. Il colore si sceglie in Impostazioni > Aspetto; il testo sopra
   no, lo decide il contrasto (ColoreLeggibile), altrimenti prima o poi e' bianco su bianco. */
.app-sidebar .brand {
  display: block;
  text-decoration: none;
  padding: 1.2rem 1.3rem;
  font-weight: 600;
  font-size: 1.05rem;
  background: var(--brand-bg, #1b2a38);
  color: var(--brand-text, #fff);
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
  letter-spacing: 0.01em;
}

.app-sidebar .brand .brand-logo {
  display: block;
  max-width: 100%;
  max-height: 2.625rem;
}

.app-sidebar .brand small {
  display: block;
  font-weight: 400;
  font-size: 0.72rem;
  color: var(--brand-text-muted, var(--sidebar-text-muted));
  margin-top: 0.15rem;
}

.app-sidebar nav {
  flex: 1;
  overflow-y: auto;
  padding: 0.8rem 0 1.5rem;
}

.app-sidebar .nav-group {
  border-bottom: 1px solid transparent;
}

.app-sidebar .nav-group-header {
  display: flex;
  align-items: center;
}

.app-sidebar .nav-group-title-link,
.app-sidebar .nav-group-title-link.disabled {
  flex: 1;
  font-size: 0.68rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--sidebar-text-muted);
  padding: 0.9rem 0 0.9rem 1.3rem;
  text-decoration: none;
  display: flex;
  align-items: center;
  gap: 0.6rem;
}

/* Il titolo del gruppo e' scritto piccolo e maiuscolo: l'icona seguirebbe quel corpo e
   risulterebbe minuscola accanto a quelle delle voci. Qui torna alla loro misura. */
.app-sidebar .nav-group-title-link > i {
  font-size: 0.95rem;
  line-height: 1;
}

.app-sidebar .nav-group-title-link:hover {
  color: #fff;
}

.app-sidebar .nav-group-title-link.disabled {
  pointer-events: none;
  cursor: default;
}

.app-sidebar .nav-group.active > .nav-group-header .nav-group-title-link {
  color: #fff;
}

/* Quando il titolo del gruppo è anche la pagina aperta, si segna come si segna una voce: lì
   sotto non c'è nessuna riga che si illumini al posto suo, e senza questo non si capirebbe
   più dove si è. Il bordo sta a sinistra del titolo, cioè sulla stessa colonna di quello
   delle voci — che è l'unica cosa che lo fa leggere come parte dello stesso elenco. */
.app-sidebar .nav-group-header.nav-group-here {
  background: var(--sidebar-bg-active);
  border-left: 3px solid var(--accent);
}

.app-sidebar .nav-group-header.nav-group-here .nav-group-title-link {
  color: #fff;
  /* I 3px del bordo li mangia il padding, altrimenti l'icona si sposterebbe proprio quando
     si apre quella pagina. */
  padding-left: calc(1.3rem - 3px);
}

.app-sidebar .nav-group-toggle {
  background: none;
  border: none;
  color: var(--sidebar-text-muted);
  padding: 0.9rem 1.1rem;
  cursor: pointer;
  line-height: 1;
}

.app-sidebar .nav-group-toggle:hover {
  color: #fff;
}

.app-sidebar .nav-group-toggle i {
  transition: transform 0.15s ease;
  display: inline-block;
}

.app-sidebar .nav-group.expanded .nav-group-toggle i {
  transform: rotate(180deg);
}

.app-sidebar .nav-subgroup {
  overflow: hidden;
  max-height: 0;
}

.app-sidebar .nav-group.expanded .nav-subgroup {
  max-height: none;
}

/* Le voci rientrano rispetto al titolo del gruppo, come i punti di un elenco sotto la loro
   riga: allineate com'erano, l'icona di un gruppo e quella di una voce stavano sulla stessa
   colonna e si leggevano come se fossero dello stesso livello. Il rientro e' calcolato al
   netto dei 3px del bordo, che e' trasparente finche' la voce non e' quella aperta: senza
   toglierli, la voce attiva si sposterebbe di quei 3px proprio nel momento in cui la guardi. */
.app-sidebar .nav-link {
  color: var(--sidebar-text);
  padding: 0.45rem 1.3rem 0.45rem calc(2.9rem - 3px);
  font-size: 0.87rem;
  display: flex;
  align-items: center;
  gap: 0.6rem;
  border-left: 3px solid transparent;
}

.app-sidebar .nav-link:hover {
  background: rgba(255, 255, 255, 0.04);
  color: #fff;
}

.app-sidebar .nav-link.active {
  background: var(--sidebar-bg-active);
  color: #fff;
  border-left-color: var(--accent);
}

.app-sidebar .nav-link.disabled {
  color: var(--sidebar-text-muted);
  pointer-events: none;
}

.app-sidebar .nav-link .badge-soon {
  margin-left: auto;
  font-size: 0.6rem;
  background: rgba(255, 255, 255, 0.08);
  color: var(--sidebar-text-muted);
  padding: 0.1rem 0.4rem;
  border-radius: 999px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

.app-main {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
}

.app-topbar {
  background: #fff;
  border-bottom: 1px solid var(--border-color);
  padding: 0.7rem 1.5rem;
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.app-content {
  padding: 1.6rem;
  flex: 1;
}
/* Menu utente in alto a destra: contiene l'area personale, che nella barra di sinistra
   allungava l'elenco con dieci voci che riguardano solo chi le sta guardando. */
/* Le due metà della barra si restringono invece di spingersi fuori schermo: senza
   min-width:0 un elemento flex non scende mai sotto la larghezza del suo contenuto, e su un
   telefono il pulsante "Esci" finiva oltre il bordo destro. */
.app-topbar-left,
.app-topbar-right {
  min-width: 0;
}

.app-topbar-left {
  flex: 0 1 auto;
}

.app-company-name {
  display: inline-block;
  max-width: 16rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  vertical-align: middle;
}

/* Con più aziende il nome sta dentro un pulsante: anche quello si accorcia, altrimenti una
   ragione sociale lunga spinge fuori schermo tutto quello che ha a destra. */
.app-company-switch {
  max-width: 16rem;
  min-width: 0;
  display: inline-flex;
  align-items: center;
  gap: .35rem;
}

.app-company-switch-name {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.app-user-menu {
  padding: .25rem .4rem;
  font-size: .875rem;
  max-width: 16rem;
  min-width: 0;
  display: inline-flex;
  align-items: center;
  gap: .35rem;
}

.app-user-menu .app-user-name {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.app-user-dropdown {
  min-width: 15rem;
  /* Larghezza fissa: senza, un nome lungo nell'intestazione allarga la tendina finché
     sborda dal bordo destro della pagina. */
  max-width: min(20rem, calc(100vw - 1rem));
  max-height: calc(100vh - 4.5rem);
  overflow-y: auto;
}

.app-user-dropdown .dropdown-header > div {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.app-user-dropdown .dropdown-item.active {
  background: var(--accent, #0d6efd);
  color: #fff;
}

.app-user-dropdown .dropdown-item i {
  width: 1.1rem;
  margin-right: .35rem;
}


.card {
  border: 1px solid var(--border-color);
  box-shadow: 0 1px 2px rgba(20, 30, 40, 0.04);
  overflow-x: auto; /* una card più larga dello schermo scorre invece di tagliare i contenuti (es. tabelle) */
}

.card-header {
  background: #fff;
  border-bottom: 1px solid var(--border-color);
  font-weight: 600;
}

.btn-primary {
  background-color: var(--accent);
  border-color: var(--accent);
}

.btn-primary:hover,
.btn-primary:focus {
  background-color: var(--accent-dark);
  border-color: var(--accent-dark);
}

a {
  color: var(--accent-dark);
}

.avatar-initials {
  width: 2.375rem;
  height: 2.375rem;
  border-radius: 50%;
  background: color-mix(in srgb, var(--accent) 15%, transparent);
  color: var(--accent-dark);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 0.78rem;
  font-weight: 600;
  flex-shrink: 0;
}

.table thead th {
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: #6b7680;
  border-bottom-width: 1px;
}

/* --- Layout ospite (login) --------------------------------------------- */
.guest-shell {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  background: linear-gradient(160deg, #1b2a38 0%, #24384a 55%, #2f5d62 100%);
  padding: 1.5rem;
}

/*
 * Logo aziendale sopra il riquadro di accesso. Sta sul gradiente scuro, quindi si vede bene
 * se il logo e' chiaro o a colori; se fosse scuro su fondo trasparente andrebbe spostato
 * dentro il riquadro bianco (basta spostare il blocco .guest-brand dentro .guest-card
 * in layouts/guest.php).
 */
.guest-stack {
  width: 100%;
  max-width: 25rem;
}

.guest-brand {
  text-align: center;
  margin-bottom: 1.4rem;
}

.guest-brand img {
  max-height: 5rem;
  max-width: 100%;
  object-fit: contain;
}

.guest-brand--text {
  color: #fff;
  font-size: 1.35rem;
  font-weight: 600;
  letter-spacing: 0.01em;
  opacity: 0.95;
}

.guest-card {
  background: #fff;
  border-radius: 10px;
  box-shadow: 0 12px 40px rgba(10, 20, 30, 0.25);
  width: 100%;
  padding: 2.2rem 2rem;
}

.guest-card h1 {
  font-size: 1.25rem;
  font-weight: 600;
  margin-bottom: 0.2rem;
}

.guest-card .subtitle {
  color: #6b7680;
  font-size: 0.85rem;
  margin-bottom: 1.5rem;
}

/* --- Conversazione WhatsApp (stile chat) --------------------------------- */
.chat-thread {
  background: #e9edf0;
  border-radius: 10px;
  padding: 1.2rem;
  min-height: 20rem;
  max-height: 60vh;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.chat-bubble {
  max-width: 70%;
  padding: 0.55rem 0.8rem;
  border-radius: 10px;
  font-size: 0.88rem;
  line-height: 1.4;
  white-space: pre-wrap;
  box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);
}

.chat-bubble.in {
  align-self: flex-start;
  background: #fff;
  border-top-left-radius: 2px;
}

.chat-bubble.out {
  align-self: flex-end;
  background: #d9f2d4;
  border-top-right-radius: 2px;
}

.chat-bubble .meta {
  display: block;
  margin-top: 0.25rem;
  font-size: 0.68rem;
  color: #7c8b98;
}

/* Documento proposta (aree di Servizi erogati, sezioni narrative, box Investimento):
   condiviso tra la vista interna (quotes/show) e il partial incluso in quotes/print,
   che essendo una pagina autonoma senza app.css ripete queste regole nel suo <style>.

   I tre box Investimento hanno lo stesso scheletro di righe, tutte ad altezza fissa tranne
   la descrizione: e' quella ad assorbire la differenza di testo fra una colonna e l'altra,
   cosi' cifra, nota del prezzo, totale e casella di scelta cadono sempre alla stessa altezza
   in tutte e tre. Per lo stesso motivo il box "Popolare" non e' piu' sollevato: si riconosce
   dalla fascia e dal bordo verdi, non dalla posizione. */
/* --- Il verde del documento ------------------------------------------------------------------
   Vive qui e nella copia gemella (l'altro fra app.css e quote-document-style), e da nessun'altra
   parte: prima stava in quattro punti con due valori diversi, e lo stesso documento usciva verde
   in stampa e verde-azzurro a video.

   Non e' --accent: quello e' il colore dell'applicazione, che non c'entra con la carta. */
:root {
  --quote-accent: #70b071;
}

/* --- Il fattore di spazio ------------------------------------------------------------------
   Un solo valore per tutto il documento: lo sceglie lo script di impaginazione misurando il
   contenuto, e da qui stringe o allarga insieme tutti i margini e le interlinee. Vale 1 se lo
   script non gira, e allora il documento resta esattamente com'era.

   --spc governa il pannello di chiusura (Investimento e firme). Segue --sp ma con un tetto:
   quel blocco e' un modulo a formato fisso, e allontanare fra loro due righe di firma non
   riempie la pagina, ci mette solo aria. */
:root {
  --sp: 1;
  --spc: min(1.15, var(--sp));
}

.quote-doc-section {
  margin-bottom: calc(1.15rem * var(--sp));
}

.quote-doc-section-title {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  font-size: 1.15rem;
  font-weight: 600;
  border-bottom: 2px solid var(--quote-accent, #70b071);
  padding-bottom: calc(0.35rem * var(--sp));
  margin-bottom: calc(0.55rem * var(--sp));
}

.quote-doc-section-title .icon {
  font-size: 1.35rem;
  color: var(--quote-accent, #70b071);
  width: 1.5rem;
  text-align: center;
  flex-shrink: 0;
}

.quote-doc-content {
  font-size: 0.92rem;
  /* L'interlinea segue il fattore di spazio ma non oltre 1,9: sopra quella soglia le righe
     smettono di sembrare un paragrafo e sembrano un elenco. */
  line-height: min(1.9, calc(0.62 + 0.8 * var(--sp)));
  color: #333;
}

.quote-doc-content p {
  margin-bottom: calc(0.6rem * var(--sp));
}

.quote-doc-content p:last-child {
  margin-bottom: 0;
}

/* --- Servizi erogati: un blocco per area, con il proprio elenco puntato --- */
.quote-doc-area {
  margin-bottom: calc(0.8rem * var(--sp));
  break-inside: avoid;
}

.quote-doc-area:last-child {
  margin-bottom: 0;
}

.quote-doc-area-head {
  display: flex;
  align-items: baseline;
  gap: 0.6rem;
  border-bottom: 1px solid #e8eaeb;
  padding-bottom: 0.22rem;
  margin-bottom: 0.35rem;
}

.quote-doc-area-name {
  font-weight: 700;
  font-size: 0.93rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: #1f2d2f;
  flex-grow: 1;
}

.quote-doc-area-vat {
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  padding: 0.12rem 0.5rem;
  border-radius: 999px;
  white-space: nowrap;
  background: #eef1f2;
  color: #56616b;
  border: 1px solid #dde2e3;
}

.quote-doc-area-vat.is-rc {
  background: #f3effa;
  color: #6f42c1;
  border-color: #e3d9f5;
}

.quote-doc-area-list {
  font-size: 0.88rem;
  line-height: 1.36;
  color: #333;
}

.quote-doc-area-list ul,
.quote-doc-area-list ol {
  margin: 0;
  padding-left: 1.15rem;
}

.quote-doc-area-list li {
  padding: calc(0.06rem * var(--sp)) 0;
}

.quote-doc-area-list p:last-child {
  margin-bottom: 0;
}

.quote-doc-investment-sub {
  font-size: 0.88rem;
  color: #555;
  margin: -0.3rem 0 calc(0.75rem * var(--spc));
}

/* --- Box Investimento ------------------------------------------------------------------------
   Tre colonne che devono farsi confrontare, non solo leggere. L'ordine in cui escono lo decide
   QuoteInvestmentPanelService (dalla piu' cara alla meno cara, salvo impostazione contraria):
   cosi' la prima cifra che l'occhio incontra fa da riferimento e le successive si leggono come
   sconti. Dentro ogni box l'ordine di lettura e' quello con cui si decide — prima perche'
   sceglierla, poi quanto costa, poi quanto costa in un anno, poi a chi e' adatta.

   Il verde chiaro sta su tutto cio' che e' forma: fascia, bordo, pallini, riga di sezione. */
.quote-doc-investment {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 0.9rem;
  align-items: stretch;
}

.quote-doc-tier {
  display: flex;
  flex-direction: column;
  border: 1px solid #dde5e5;
  border-radius: 7px;
  overflow: hidden;
  background: #fff;
  break-inside: avoid;
}

.quote-doc-tier.is-popular {
  border: 2px solid var(--quote-accent, #70b071);
  box-shadow: 0 6px 18px rgba(112, 176, 113, 0.22);
}

/* La fascia muta sugli altri due box non e' decorazione: tiene le tre teste alla stessa
   altezza, altrimenti la colonna consigliata scenderebbe di una riga rispetto alle altre. */
.quote-doc-tier-band {
  background: var(--quote-accent, #70b071);
  color: #fff;
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  text-align: center;
  padding: 0.3rem 0.2rem;
  min-height: 1.35rem;
}

.quote-doc-tier-band.is-muta {
  background: #eef2f2;
}

.quote-doc-tier-inner {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  padding: calc(0.7rem * var(--spc)) 0.75rem calc(0.75rem * var(--spc));
  /* Tutto centrato: le tre colonne si leggono come tre schede a confronto, non come tre
     paragrafi allineati a sinistra che l'occhio percorre uno per volta. */
  text-align: center;
}

/* Perche' sceglierla: il risparmio quando c'e', altrimenti la frase breve dell'operatore. */
.tier-benefit {
  font-size: 1rem;
  font-weight: 700;
  line-height: 1.15;
  color: #5b6b76;
}

.tier-benefit.is-risparmio {
  color: var(--quote-accent, #70b071);
}

.tier-benefit p {
  margin: 0;
}

.tier-duration {
  font-size: 0.74rem;
  color: #6b7a86;
  padding-bottom: calc(0.45rem * var(--spc));
  border-bottom: 1px solid #edf1f1;
}

/* Il totale per primo. L'imponibile e l'IVA stanno sotto, per chi li cerca: sopra la cifra
   erano un dosso, obbligavano a fare una somma per sapere quanto si paga. */
.tier-price-row {
  display: flex;
  align-items: baseline;
  justify-content: center;
  gap: 0.3rem;
  margin-top: calc(0.5rem * var(--spc));
}

.tier-price {
  font-size: 1.44rem;
  font-weight: 700;
  color: #16313a;
  letter-spacing: -0.01em;
}

.quote-doc-tier.is-popular .tier-price {
  color: var(--quote-accent, #70b071);
}

.tier-price-note,
.tier-price-note p {
  margin: 0;
  font-size: 0.72rem;
  color: #6b7a86;
}

.tier-vat {
  font-size: 0.66rem;
  color: #6b7a86;
  line-height: 1.4;
}

.tier-vat .is-rc {
  color: #8a5a1f;
}

.tier-annual {
  display: flex;
  justify-content: center;
  gap: 0.5rem;
  margin-top: calc(0.5rem * var(--spc));
  padding: 0.3rem 0.4rem;
  background: #f6f9f9;
  border-radius: 4px;
  font-size: 0.72rem;
  color: #5b6b76;
}

.tier-annual span:last-child {
  font-weight: 700;
  color: #16313a;
}

.tier-compare {
  margin-top: calc(0.4rem * var(--spc));
  font-size: 0.7rem;
  line-height: 1.35;
  color: #2f6b47;
}

.tier-compare.is-riferimento {
  color: #5b6b76;
}

.tier-incasso {
  margin-top: calc(0.4rem * var(--spc));
  border-top: 1px solid #edf1f1;
  padding-top: 0.3rem;
  font-size: 0.68rem;
  color: #5b6b76;
}

.tier-incasso .r {
  display: flex;
  justify-content: center;
  gap: 0.5rem;
  line-height: 1.25rem;
}

.tier-incasso .r.netto {
  font-weight: 700;
  color: #16313a;
}

.tier-deposit,
.tier-deposit p {
  margin: 0;
  font-size: 0.68rem;
  color: #6b7a86;
}

/* Il consiglio: e' la riga che trasforma un listino in un parere. */
.tier-fit {
  margin-top: calc(0.5rem * var(--spc));
  padding-top: calc(0.45rem * var(--spc));
  border-top: 1px dashed #e2e9e9;
  font-size: 0.72rem;
  line-height: 1.4;
  color: #4f5f6a;
}

.tier-fit-label {
  display: block;
  font-size: 0.6rem;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: #6b7a86;
}

/* Descrizione e modalita' di pagamento: restano, in tono minore, sotto il consiglio.
   flex:1 le fa spingere la casella di scelta in fondo, cosi' le tre caselle si allineano. */
.tier-body {
  flex: 1 1 auto;
  margin-top: calc(0.5rem * var(--spc));
  padding-top: calc(0.45rem * var(--spc));
  /* Lo stesso tratteggio che sta sopra "Adatta se": le condizioni sono un'altra cosa
     rispetto al consiglio, e il filo lo dice senza aggiungere una parola. */
  border-top: 1px dashed #e2e9e9;
  font-size: 0.7rem;
  line-height: 1.4;
  color: #6b7a86;
}

/* Una condizione per riga: dentro una colonna stretta due frasi di fila si leggono come un
   blocco unico, e nessuna delle due si vede. */
.tier-voce {
  margin-bottom: 0.2rem;
}

.tier-voce:last-child {
  margin-bottom: 0;
}

.tier-choose {
  display: block;
  margin-top: calc(0.6rem * var(--spc));
  text-align: center;
  font-size: 0.76rem;
  font-weight: 600;
  padding: 0.4rem 0.3rem;
  border: 1.5px solid #b9c7c7;
  border-radius: 5px;
  color: #4f5f6a;
}

/* Sulla soluzione consigliata l'azione e' piena: dice dove si va se non si ha un'opinione. */
.quote-doc-tier.is-popular .tier-choose {
  background: var(--quote-accent, #70b071);
  border-color: var(--quote-accent, #70b071);
  color: #fff;
}

.tier-choose input {
  margin-right: 0.35rem;
  vertical-align: middle;
}

/* --- Il riquadro comune sotto i tre box ---
   Quello che vale per tutte e tre esce dai box e si dice una volta sola: ripetuto tre volte
   identico occupava il posto piu' prezioso del documento e faceva sembrare uguali le tre
   soluzioni. */
.quote-doc-common {
  margin-top: calc(0.8rem * var(--spc));
  border: 1px solid #e4ebeb;
  border-radius: 6px;
  background: #fafcfc;
  padding: calc(0.6rem * var(--spc)) 0.8rem calc(0.65rem * var(--spc));
  break-inside: avoid;
}

.quote-doc-common-title {
  font-size: 0.66rem;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: #6b7a86;
  margin-bottom: 0.3rem;
}

.quote-doc-common-list {
  margin: 0;
  padding: 0;
  list-style: none;
  columns: 2;
  column-gap: 1.5rem;
  font-size: 0.74rem;
  line-height: 1.55;
  color: #4f5f6a;
}

.quote-doc-common-list li {
  padding-left: 0.8rem;
  position: relative;
  break-inside: avoid;
}

.quote-doc-common-list li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.55em;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--quote-accent, #70b071);
}

.quote-doc-common-validity {
  margin-top: 0.5rem;
  padding-top: 0.4rem;
  border-top: 1px solid #edf1f1;
  font-size: 0.72rem;
  color: #6b7a86;
  text-align: right;
}

.quote-doc-vat-recap {
  margin-top: 1.1rem;
  border: 1px solid #e6e9ea;
  border-radius: 8px;
  overflow: hidden;
  break-inside: avoid;
}

.quote-doc-vat-recap .h,
.quote-doc-vat-recap .r {
  display: grid;
  grid-template-columns: 1fr 5rem 7.5rem 7.5rem;
  gap: 0.8rem;
  padding: 0.45rem 0.85rem;
  font-size: 0.8rem;
  align-items: center;
}

.quote-doc-vat-recap .h {
  background: #f8f9fa;
  font-size: 0.68rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: #8b9295;
}

.quote-doc-vat-recap .h div:not(:first-child) {
  text-align: right;
}

.quote-doc-vat-recap .r {
  border-top: 1px solid #eef0f1;
}

.quote-doc-vat-recap .num {
  text-align: right;
  font-variant-numeric: tabular-nums;
  color: #495057;
  white-space: nowrap;
}

.quote-doc-vat-recap .is-rc {
  color: #6f42c1;
  font-weight: 600;
}

.quote-doc-vat-recap .muted {
  color: #8b9295;
}

.quote-doc-vat-recap .r.tot {
  background: #f6fbf8;
  border-top: 1px solid #cde9da;
  font-weight: 700;
  color: #157347;
}

.quote-doc-vat-recap .r.tot .num {
  color: #157347;
}

.quote-doc-vat-note {
  font-size: 0.76rem;
  color: #6c757d;
  margin: 0.6rem 0 0;
  line-height: 1.55;
}

@media (max-width: 768px) {
  .quote-doc-investment {
    grid-template-columns: 1fr;
  }

  .quote-doc-vat-recap .h,
  .quote-doc-vat-recap .r {
    grid-template-columns: 1fr 4rem 6rem;
    font-size: 0.74rem;
  }

  .quote-doc-vat-recap .h div:last-child,
  .quote-doc-vat-recap .r div:last-child {
    display: none;
  }
}

.quote-section-icon-picker {
  display: flex;
  align-items: center;
  gap: 0.6rem;
}

.quote-section-icon-picker .icon-preview {
  width: 2.625rem;
  height: 2.625rem;
  border: 1px solid #dee2e6;
  border-radius: 8px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.3rem;
  color: var(--quote-accent, #70b071);
  flex-shrink: 0;
}

.icon-picker-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(2.625rem, 1fr));
  gap: 0.4rem;
  max-height: 16.25rem;
  overflow-y: auto;
  border: 1px solid #eee;
  border-radius: 8px;
  padding: 0.5rem;
}

.icon-picker-grid button {
  border: 1px solid transparent;
  background: #f8f9fa;
  border-radius: 6px;
  height: 2.375rem;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.1rem;
  color: #444;
  cursor: pointer;
}

.icon-picker-grid button:hover {
  background: #e9ecef;
}

.icon-picker-grid button.selected {
  border-color: var(--quote-accent, #70b071);
  background: #e7f1ff;
  color: var(--quote-accent, #70b071);
}

/* Form Nuova/Modifica proposta: niente più larghezza fissa (era max-width:900px anche su
   schermi larghissimi) — usa lo spazio disponibile fino a un tetto ragionevole, così i campi
   dell'editor di testo nei box Investimento non restano schiacciati su schermi larghi. */
.quote-form {
  width: 100%;
  max-width: 87.5rem;
}

.quote-form .tox-tinymce {
  max-width: 100%;
}

@media (max-width: 575.98px) {
  .quote-section-icon-picker {
    flex-wrap: wrap;
  }
}

/* --- Termini e condizioni allegati alla proposta -------------------------------------------
   Il riferimento alla proposta deve comparire su OGNI pagina stampata: un foglio di condizioni
   che gira per conto suo, senza il numero della proposta di cui e' parte, non dice piu' di che
   contratto parli. La tabella non e' impaginazione — e' che il <thead> e' l'unico modo che
   tutti i browser ripetono davvero a ogni pagina; position: fixed lo fa solo su alcuni. */
.quote-terms {
  width: 100%;
  border-collapse: collapse;
}

.quote-terms thead th {
  text-align: left;
  font-weight: 400;
  padding: 0 0 0.45rem;
  border-bottom: 2px solid var(--quote-accent, #70b071);
}

.quote-terms-title {
  display: block;
  font-size: 1.15rem;
  font-weight: 600;
  color: #1d2b36;
  margin-bottom: 0.1rem;
}

.quote-terms-ref {
  display: block;
  font-size: 0.78rem;
  color: #6b7a86;
}

/* La firma di chi ha accettato, in verticale a destra dell'intestazione: sta qui dentro, e
   non in una fascia a margine come nel PDF, perche' il <thead> e' l'unico blocco che tutti i
   browser ripetono a ogni pagina stampata. Una fascia a margine vorrebbe position: fixed, che
   Chrome e Firefox ripetono e Safari no: la firma comparirebbe solo sulla prima pagina, che e'
   il caso che stiamo cercando di evitare. */
.quote-terms-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
}

.quote-terms-head-testo {
  flex: 1 1 auto;
  min-width: 0;
}

/* Il riquadro e' alto quanto la firma e' lunga, e largo quanto e' spessa: transform non dice
   al layout che l'ingombro si e' scambiato, e senza scambiarglielo a mano il testo accanto
   ci finirebbe sotto. */
.quote-terms-sigla {
  position: relative;
  flex: 0 0 auto;
  width: 3.1rem;
  height: 5.4rem;
}

.quote-terms-sigla img {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 5rem;
  height: auto;
  transform: translate(-50%, -50%) rotate(-90deg);
}

/* Si legge dal basso verso l'alto, come le costole dei libri: e' il verso in cui si gira la
   testa, non il foglio. */
.quote-terms-sigla-chi {
  position: absolute;
  top: 50%;
  right: 0;
  writing-mode: vertical-rl;
  transform: translateY(-50%) rotate(180deg);
  font-size: 0.6rem;
  line-height: 1;
  color: #6b7a86;
  white-space: nowrap;
}

.quote-terms-body {
  padding-top: 0.7rem;
  font-size: 0.9rem;
  line-height: 1.45;
  color: #333;
}

.quote-terms-body > *:first-child {
  margin-top: 0;
}

/* Firme in fondo al documento proposta (quotes/show, dentro app.css; quotes/print ripete le
   stesse classi nel proprio <style> perché è una pagina autonoma). */
.quote-doc-signatures {
  display: grid;
  grid-template-columns: 1fr 1fr;
  column-gap: 2rem;
  margin-top: calc(1.6rem * var(--spc));
  /* Il blocco delle firme non si spezza fra due pagine: una firma a cavallo del salto pagina
     non e' una firma. break-before: avoid le tiene attaccate a cio' che le precede, cioe'
     all'Investimento: la pagina di sole firme in coda nasceva proprio da questo distacco. */
  break-inside: avoid;
  break-before: avoid;
}

.sig-block {
  text-align: center;
}

/* Lo spazio della firma: la stessa altezza nelle due colonne, dentro cui sta la firma
   caricata, quella tracciata dal cliente, o niente — e allora e' lo spazio per la penna.
   E' questa altezza a far cadere i due tratti alla stessa riga: prima la colonna del fornitore
   aveva una riga di testo in piu' e quella del cliente un'immagine alta il doppio, e i due
   tratti finivano a 56 pixel di distanza. L'immagine si adatta al riquadro, non viceversa.

   Si stringe e si allarga con il resto del documento, come faceva lo spazio per la penna che
   sostituisce, e non scende sotto 1,6rem: il blocco delle firme chiude la proposta, e qualche
   pixel in piu' qui costa una pagina intera a un documento che sta al limite. */
.sig-firma {
  height: max(1.6rem, calc(1.2rem * var(--spc)));
  display: flex;
  align-items: flex-end;
  justify-content: center;
}

.sig-firma img {
  max-height: 100%;
  max-width: 100%;
}

/* Chi si impegna: l'azienda a sinistra, l'intestatario della proposta a destra. Sulla stessa
   riga, appena sopra il tratto. L'altezza e' fissa e la riga resta anche quando e' vuota —
   succede quando l'azienda firma solo con un'immagine — perche' se sparisse da una parte sola
   il tratto di quella colonna salirebbe. */
.sig-ente {
  height: 1.3rem;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  font-size: 0.95rem;
  line-height: 1.1;
  color: #1d2b36;
}

/* Il nome dell'azienda e' scritto a mano e ha un corpo piu' grande di quello del cliente: se
   le due righe si misurassero da sole finirebbero alte diverso, e i tratti tornerebbero
   sfasati di sette pixel. L'altezza la decide la riga, non il carattere che ci sta dentro. */
.sig-ente.is-scritta {
  font-family: 'Brush Script MT', cursive;
  font-size: 1.15rem;
}

/* Chi ha materialmente firmato, quando non e' l'intestatario: l'amministratore del condominio,
   il responsabile acquisti. La riga c'e' in tutte e due le colonne o in nessuna. */
.sig-chi {
  height: 1.05rem;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  font-size: 0.8rem;
  line-height: 1.1;
  color: #5a6875;
}

.sig-line {
  border-top: 1px solid #333;
  margin-top: 0.35rem;
}

.sig-label {
  font-size: 0.85rem;
  color: #444;
  margin-top: 0.4rem;
}

.sig-data {
  color: #6b7a86;
}

/* Trascinamento sezioni/righe nel form Nuova/Modifica proposta: il cursore "grab" compare solo
   sull'intestazione/maniglia, non su tutta la card (altrimenti sembra che si possa trascinare
   anche cliccando dentro un campo di testo). */
.quote-section-block > .card-header {
  cursor: grab;
}

.quote-drag-handle {
  cursor: grab;
}

.service-line-row {
  cursor: grab;
}

.service-line-row .form-control,
.service-line-row button {
  cursor: auto;
}

/* Icona "?" accanto a un'etichetta o a un titolo di sezione che dipende da un'impostazione
   configurabile nel pannello Impostazioni. Hover (o focus da tastiera / tap su mobile) apre
   una nuvoletta con la spiegazione e il link diretto alla pagina di impostazioni. */
.settings-hint {
  position: relative;
  display: inline-block;
  margin-left: .25rem;
  color: var(--bs-secondary-color, #6c757d);
  font-size: .78em;
  line-height: 1;
  cursor: help;
  vertical-align: super;
}
.settings-hint > i { pointer-events: none; }
.settings-hint:focus { outline: none; }
.settings-hint:hover,
.settings-hint:focus-within { color: var(--quote-accent, #70b071); }
.settings-hint-bubble {
  display: none;
  position: absolute;
  z-index: 1090;
  left: 0;
  top: calc(100% + 7px);
  width: 16.375rem;
  max-width: 62vw;
  padding: .5rem .65rem;
  font-size: .8125rem;
  font-weight: 400;
  line-height: 1.45;
  color: #212529;
  text-align: left;
  background: #fff;
  border: 1px solid rgba(0, 0, 0, .15);
  border-radius: .375rem;
  box-shadow: 0 .5rem 1rem rgba(0, 0, 0, .15);
  white-space: normal;
  cursor: auto;
}
.settings-hint-bubble::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: -9px;
  height: 9px;
}
.settings-hint:hover .settings-hint-bubble,
.settings-hint:focus-within .settings-hint-bubble,
.settings-hint.is-open .settings-hint-bubble { display: block; }
.settings-hint-bubble a { font-weight: 600; }
.settings-hint-bubble--end { left: auto; right: 0; }

/* --- Responsive: sidebar a scomparsa e adattamento su tablet/smartphone --------- */
.app-menu-toggle { display: none; }
.app-backdrop { display: none; }

@media (max-width: 991.98px) {
  .app-sidebar {
    position: fixed;
    top: 0;
    bottom: 0;
    left: 0;
    width: 82vw;
    max-width: 18.75rem;
    transform: translateX(-100%);
    transition: transform .25s ease;
    z-index: 1045;
  }
  .app-sidebar.open {
    transform: translateX(0);
    box-shadow: 0 0 40px rgba(0, 0, 0, .45);
  }
  .app-backdrop {
    display: block;
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, .4);
    opacity: 0;
    pointer-events: none;
    transition: opacity .25s ease;
    z-index: 1044;
  }
  .app-backdrop.show {
    opacity: 1;
    pointer-events: auto;
  }
  body.sidebar-open {
    overflow: hidden;
  }

  .app-menu-toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.5rem;
    height: 2.5rem;
    flex-shrink: 0;
    border: 1px solid var(--border-color);
    background: #fff;
    border-radius: .375rem;
    font-size: 1.2rem;
    line-height: 1;
    color: #2b3a45;
  }

  .app-topbar {
    padding: .6rem .85rem;
    gap: .5rem;
  }
  .app-topbar-right {
    gap: .6rem !important;
  }

  /* Sul telefono lo spazio in alto è tutto occupato: del pulsante resta l'omino, e il nome
     si legge dentro la tendina. Con il nome fuori, "Esci" finiva oltre il bordo destro. */
  .app-user-menu .app-user-name {
    display: none;
  }

  .app-company-name,
  .app-company-switch {
    max-width: 38vw;
  }

  .app-content {
    padding: 1rem .85rem;
  }

  /* Intestazioni di pagina "titolo + pulsante": vanno a capo invece di sovrapporsi. */
  .app-content .d-flex.justify-content-between {
    flex-wrap: wrap;
    gap: .5rem;
  }

  .app-content h1 {
    font-size: 1.3rem;
  }
}

/* --- Tablet e smartphone: calendario, tabelle, form, aree di tocco ------------- */
@media (max-width: 767.98px) {
  /* Le card non devono più scorrere in orizzontale: tabelle e form si impilano. */
  .app-content .card { overflow-x: hidden; }
  .app-content .card-body > .row { --bs-gutter-x: 0.75rem; }

  /* FullCalendar: barra strumenti che va a capo, titolo leggibile, pulsanti più grandi. */
  .fc .fc-toolbar {
    flex-wrap: wrap;
    gap: .4rem .5rem;
    row-gap: .5rem;
  }
  .fc .fc-toolbar.fc-header-toolbar {
    margin-bottom: .8rem;
  }
  .fc .fc-toolbar-chunk {
    display: flex;
    align-items: center;
    gap: .3rem;
  }
  .fc .fc-toolbar-title {
    font-size: 1rem !important;
    white-space: nowrap;
  }
  .fc .fc-button {
    padding: .45rem .7rem;
    font-size: .9rem;
  }
  .fc .fc-col-header-cell-cushion,
  .fc .fc-daygrid-day-number,
  .fc .fc-timegrid-slot-label-cushion {
    font-size: .78rem;
  }
  .fc-theme-standard .fc-scrollgrid { font-size: .82rem; }

  /* Selettore vista del calendario dedicato al mobile (bottoni ampi). */
  .cal-mobile-views { display: flex; gap: .4rem; margin: 0 0 .6rem; }
  .cal-mobile-views .btn { flex: 1; padding: .5rem .25rem; font-size: .85rem; }

  /* Legenda/filtri del calendario: due colonne invece di riga fluida stretta. */
  .calendar-widget > .d-flex.flex-wrap {
    display: grid !important;
    grid-template-columns: 1fr 1fr;
    gap: .5rem .75rem;
  }
  .calendar-widget .cal-filter { width: 1.1rem; height: 1.1rem; }

  /* Tabelle dentro le card: ogni riga diventa un blocco impilato con etichetta. */
  .app-content .card > .table-responsive > table.table,
  .app-content .card > table.table,
  .lead-tile .card .table {
    display: block;
  }
  .app-content .card table.table thead {
    position: absolute;
    width: 1px; height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
  }
  .app-content .card table.table tbody { display: block; }
  .app-content .card table.table tr {
    display: block;
    padding: .55rem .85rem;
    border-bottom: 1px solid var(--border-color);
  }
  .app-content .card table.table tr:last-child { border-bottom: 0; }
  .app-content .card table.table td {
    display: block;
    border: 0 !important;
    padding: .15rem 0 !important;
    text-align: left !important;
    white-space: normal !important;
    font-size: .9rem;
  }
  .app-content .card table.table td:empty { display: none; }
  .app-content .card table.table td[data-label]::before {
    content: attr(data-label) ": ";
    font-weight: 600;
    color: #6b7a86;
  }
  /* Le celle con solo un pulsante (azioni) a tutta larghezza. */
  .app-content .card table.table td form,
  .app-content .card table.table td .btn { display: block; }
  .app-content .card table.table td .btn { width: 100%; margin-top: .3rem; }

  /* Non impilare le tabelle "vere e proprie" a colonne larghe fuori dalle card lead
     (es. FullCalendar list view usa .fc-list-table, esclusa perché non è .table). */
}

@media (max-width: 575.98px) {
  .app-content {
    padding: .85rem .55rem;
  }
  .app-content .btn { white-space: normal; }
  .modal-dialog { margin: .5rem; }
  .modal-body { padding: 1rem .9rem; }

  /* I form nei footer delle card lead: un campo per riga. */
  .lead-tile .card-footer .row > [class*="col-"] {
    flex: 0 0 100%;
    max-width: 100%;
  }

  /* Aree di tocco più comode. */
  .app-content .btn-sm {
    padding: .4rem .7rem;
    font-size: .875rem;
  }
  .app-content .form-control,
  .app-content .form-select {
    font-size: max(16px, 1rem); /* sotto i 16px reali iOS zooma da solo sul campo */
    min-height: 2.625rem;
  }
  .app-content .form-check-input {
    width: 1.15rem;
    height: 1.15rem;
  }
  .card-header { flex-wrap: wrap; gap: .4rem; }
}

/* Versione pubblicata, in fondo al menu. Sta li' e non in alto perche' e' un'informazione
   che si va a cercare quando serve ("e' gia' online la modifica?"), non da tenere sott'occhio.
   La barra laterale e' gia' flex-column con nav in flex:1, quindi questo blocco resta in basso. */
.sidebar-version {
  padding: .6rem 1.3rem .9rem;
  border-top: 1px solid rgba(255, 255, 255, 0.08);
  font-size: .7rem;
  color: var(--sidebar-text-muted);
  display: flex;
  align-items: center;
  gap: .4rem;
  flex-wrap: wrap;
}

.sidebar-version-env {
  padding: .05rem .35rem;
  border-radius: 999px;
  background: #fff3cd;
  color: #664d03;
  font-weight: 700;
  letter-spacing: .03em;
}

/* Avviso dell'ambiente in alto: compare solo fuori produzione. Scambiare la prova per il
   gestionale vero significa correggere dati veri credendo di fare un esperimento, quindi
   resta visibile anche sul telefono, dove il menu laterale e' chiuso. */
.release-badge {
  font-size: .75rem;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  white-space: nowrap;
}

.release-badge-test {
  padding: .15rem .5rem;
  border-radius: 999px;
  background: #fff3cd;
  color: #664d03;
  border: 1px solid #ffe69c;
  font-weight: 600;
}

/* Impostazioni > Editor di testo: i pulsanti come "chip" trascinabili fra le due zone.
   La zona attiva ha un bordo che si accende al passaggio, cosi' si vede dove si sta lasciando. */
.editor-chips {
  display: flex;
  flex-wrap: wrap;
  gap: .5rem;
  min-height: 3.25rem;
  padding: .75rem;
  border: 1px solid var(--bs-border-color, #dee2e6);
  border-radius: .5rem;
  background: #fff;
  transition: border-color .15s, background .15s;
}
.editor-chips:empty::after {
  content: attr(data-empty);
  color: #8a8f98;
  font-size: .85rem;
  align-self: center;
}
.editor-chips-over { border-color: var(--accent, #1F6E76); background: #f3f8f8; }
.editor-chip {
  display: inline-flex;
  align-items: center;
  gap: .3rem;
  padding: .35rem .7rem;
  border: 1px solid #cfd4da;
  border-radius: .4rem;
  background: #fff;
  font-size: .85rem;
  color: #495057;
  cursor: grab;
  user-select: none;
  white-space: nowrap;
}
.editor-chip:active { cursor: grabbing; }
.editor-chip-dragging { opacity: .4; }
.editor-chips-active .editor-chip { border-color: #b8c2cc; background: #f8f9fa; }
.editor-chip-star { font-size: .65rem; color: #c9a227; }
.editor-chip-disabled { opacity: .45; cursor: not-allowed; }
.editor-chip-group-label {
  flex-basis: 100%;
  margin-top: .35rem;
  font-size: .7rem;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: #8a8f98;
}
.editor-chip-group-label:first-child { margin-top: 0; }

/* --- Base di conoscenza -------------------------------------------------- */

/* Una procedura si legge dal telefono, in piedi, con una mano. Testo più grande e righe più
   alte del resto del gestionale: qui si legge davvero, non si scorre un elenco. */
.kb-testo {
    font-size: 1.05rem;
    line-height: 1.7;
}
.kb-testo h2 { font-size: 1.35rem; margin-top: 1.5rem; }
.kb-testo h3 { font-size: 1.15rem; margin-top: 1.25rem; }
.kb-testo h2:first-child, .kb-testo h3:first-child { margin-top: 0; }
.kb-testo ol, .kb-testo ul { padding-left: 1.4rem; }
.kb-testo li { margin-bottom: .4rem; }
.kb-testo img { max-width: 100%; height: auto; border-radius: .375rem; }
.kb-testo table { width: 100%; margin-bottom: 1rem; }
.kb-testo th, .kb-testo td { border: 1px solid var(--bs-border-color); padding: .4rem .6rem; }
/* Una tabella larga scorre dentro la sua scatola invece di allargare la pagina. */
.kb-testo { overflow-x: auto; }

/* --- Semaforo del margine per cliente ------------------------------------------------------
   Tre lampade impilate dentro un corpo scuro, come un semaforo vero: e' la forma che si
   riconosce senza leggere l'intestazione della colonna. Costa qualche pixel di altezza alla
   riga, ed e' una scelta — la stessa cosa in orizzontale non si legge come un semaforo. */
.sem {
  display: inline-flex;
  flex-direction: column;
  gap: 2px;
  background: #39434b;
  padding: 3px;
  border-radius: 0.3rem;
  line-height: 1;
}

.sem-luce {
  width: 2.1rem;
  height: 1.05rem;
  border-radius: 0.2rem;
  /* Spenta: non grigia com'era il fondo, ma appena piu' chiara del corpo. Una lampada spenta
     si vede che c'e', altrimenti il semaforo sembra rotto invece che informativo. */
  background: #525c64;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 0.6rem;
  font-weight: 700;
  letter-spacing: -0.02em;
  color: #8a949c;
}

.sem-luce.accesa {
  color: #fff;
}

.sem-rosso.accesa {
  background: #d9534f;
}

.sem-arancio.accesa {
  background: #e8973a;
}

.sem-verde.accesa {
  background: #46a34d;
}

/* Nessuna ora presenziata: si dice, invece di accendere una luce che nessuno ha meritato. */
.sem-vuoto {
  color: #aab3ba;
  font-size: 0.78rem;
  white-space: nowrap;
}

/* --- La scheda orizzontale del cantiere -----------------------------------------------------
   Tutto quello che serve sapere prima di entrare in cantiere su una riga sola: chi ci va, quante
   ore, quali giorni, da quando a quando, a che ora. Prima erano sparsi fra la scheda anagrafica,
   il contratto e la proposta, e nessuno li vedeva insieme. */
.cant-testa {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  flex-wrap: wrap;
  padding: 0.85rem 1rem;
  border-bottom: 1px solid #e9edf0;
}

.cant-nome {
  font-size: 1.08rem;
  font-weight: 600;
  color: #1d2b36;
}

.cant-cli {
  font-size: 0.82rem;
  color: #6b7a86;
}

/* Le caselle si dispongono su piu' righe da sole: a schermo stretto sono una sotto l'altra, e
   su un telefono in cantiere e' l'unico modo in cui si leggono. */
.cant-striscia {
  display: flex;
  flex-wrap: wrap;
}

.cant-voce {
  flex: 1 1 11rem;
  min-width: 11rem;
  display: flex;
  align-items: flex-start;
  gap: 0.55rem;
  padding: 0.7rem 0.9rem;
  border-right: 1px solid #eef1f3;
  border-bottom: 1px solid #eef1f3;
}

.cant-voce i {
  font-size: 1.05rem;
  color: var(--quote-accent, #70b071);
  margin-top: 0.1rem;
  flex: none;
  width: 1.2rem;
  text-align: center;
}

.cant-et {
  display: block;
  font-size: 0.68rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: #8a97a3;
  font-weight: 600;
}

.cant-v {
  display: block;
  font-size: 0.88rem;
  color: #1d2b36;
  font-weight: 600;
  line-height: 1.3;
}

.cant-n {
  display: block;
  font-size: 0.74rem;
  color: #6b7a86;
  line-height: 1.3;
}

/* Quello che manca si vede che manca. Lasciarlo vuoto lo nasconderebbe, e date, orari e squadra
   sono lavoro che qualcuno deve ancora fare: e' la differenza fra un cantiere che esiste e uno
   che e' partito. */
.cant-voce.manca i {
  color: #d1a33a;
}

.cant-voce.manca .cant-v {
  color: #a67c14;
}

.cant-servizi {
  padding: 0.75rem 0.9rem;
}

.cant-servizi h6 {
  font-size: 0.68rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: #8a97a3;
  font-weight: 600;
  margin-bottom: 0.4rem;
}

.cant-serv {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  background: #f4f7f9;
  border: 1px solid #e4eaee;
  border-radius: 1rem;
  padding: 0.15rem 0.6rem;
  font-size: 0.8rem;
  color: #33424d;
  margin: 0 0.3rem 0.3rem 0;
}

.cant-serv i {
  color: var(--quote-accent, #70b071);
  font-size: 0.8rem;
}

.cant-avvia {
  padding: 0.85rem 0.9rem;
  border-top: 1px solid #eef1f3;
  background: #fbfcfd;
}

/* --- La griglia delle giornate di servizio ---------------------------------------------
 *
 * Undici colonne in una tabella stanno strette. Si leggono perche' sono raggruppate in
 * quattro blocchi — quando si va, chi ci va, ogni quanto, calcolato — e perche' il blocco
 * calcolato ha un fondo suo: quello che scrive il gestionale si distingue a colpo d'occhio
 * da quello che scrive chi compila, che e' l'unica cosa che conta capire subito.
 */
.griglia-giornate {
  font-size: 0.86rem;
}

.griglia-giornate td,
.griglia-giornate th {
  padding: 0.25rem 0.35rem;
  vertical-align: middle;
}

.griglia-giornate .form-control-sm,
.griglia-giornate .form-select-sm {
  font-size: 0.8rem;
  padding: 0.2rem 0.35rem;
}

.griglia-giornate .gruppi-griglia th {
  font-size: 0.64rem;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  font-weight: 700;
  color: #8a97a3;
  border-bottom: 0;
  padding-bottom: 0.05rem;
}

.griglia-giornate .stacco {
  border-left: 1px solid #e6eaed;
}

.griglia-giornate .calcolata {
  background: #f4f8f5;
}

.griglia-giornate .gruppi-griglia .calcolata {
  color: #4a7d6b;
}

/* Bloccato, non nascosto: chi compila deve vedere da che cosa nasce il costo anche —
   soprattutto — quando non l'ha scritto lui. */
.griglia-giornate .campo-bloccato {
  background: transparent;
  border-color: transparent;
  font-weight: 600;
  color: #24494b;
  box-shadow: none;
}

.griglia-giornate .cella-pausa {
  display: flex;
  align-items: center;
  gap: 0.2rem;
}

.griglia-giornate .bollino-pausa {
  --bs-btn-padding-x: 0.3rem;
  --bs-btn-padding-y: 0.05rem;
  --bs-btn-font-size: 0.7rem;
  font-weight: 700;
  line-height: 1.4;
}

.griglia-giornate .btn-check:not(:checked) + .bollino-pausa {
  color: #b3bcc3;
  border-color: #dfe3e6;
  text-decoration: line-through;
}

.griglia-giornate .fascia-suggerita {
  display: block;
  font-size: 0.68rem;
  line-height: 1.2;
  margin-top: 0.1rem;
}

/* Una riga nata dalla conversione di una proposta fatta prima delle giornate: vale quello
   che c'e' scritto, e aspetta che qualcuno le dia un orario. */
.griglia-giornate .riga-da-completare .campo-etichetta {
  border-style: dashed;
}

/* --- Giorni e orari del servizio -------------------------------------------------------
 *
 * Sotto l'elenco dei servizi: che cosa facciamo, e subito dopo quando lo facciamo. Le righe
 * nascono dalle stesse giornate che hanno prodotto il prezzo, quindi il quando scritto qui e
 * il canone non possono divergere.
 */
.quote-doc-orario {
  margin-top: calc(0.5rem * var(--sp));
}

.quote-doc-orario-title {
  font-size: 0.88rem;
  font-weight: 700;
  color: #1d2b36;
  margin-bottom: calc(0.28rem * var(--sp));
}

.quote-doc-orario-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.85rem;
}

.quote-doc-orario-table th {
  font-size: 0.66rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  font-weight: 700;
  color: #6b7a86;
  text-align: left;
  padding: 0 0.5rem calc(0.18rem * var(--sp)) 0;
  border-bottom: 1px solid #dfe3e6;
}

.quote-doc-orario-table td {
  padding: calc(0.2rem * var(--sp)) 0.5rem calc(0.2rem * var(--sp)) 0;
  color: #333;
  vertical-align: top;
}

.quote-doc-orario-table .is-quando {
  font-weight: 700;
  color: #1d2b36;
  white-space: nowrap;
}

.quote-doc-orario-table .is-ritmo {
  color: #6b7a86;
}

.quote-doc-orario-pausa {
  color: #6b7a86;
}

.quote-doc-orario-sum {
  font-size: 0.78rem;
  color: #6b7a86;
  margin-top: calc(0.25rem * var(--sp));
}

/* Una tabella di orari spezzata a meta' fra due fogli e' un orario che non si legge. */
@media print {
  .quote-doc-orario {
    break-inside: avoid;
    page-break-inside: avoid;
  }
}

/* --- I turni del cantiere, letti dalla proposta ----------------------------------------
 *
 * Stesso vestito del riquadro dei servizi qui sopra: sono la stessa cosa — quello che il
 * cliente ha firmato, riletto da chi deve andarci.
 */
.cant-turni {
  padding: 0.7rem 0.9rem;
  border-top: 1px solid #eef1f3;
  background: #fbfcfd;
}

.cant-turni h6 {
  font-size: 0.78rem;
  font-weight: 700;
  color: #6b7a86;
  margin-bottom: 0.35rem;
}

.cant-turni-tab {
  font-size: 0.82rem;
  border-collapse: collapse;
}

.cant-turni-tab td {
  padding: 0.12rem 1.1rem 0.12rem 0;
  color: #33424d;
  white-space: nowrap;
}

.cant-turni-tab .is-quando {
  font-weight: 600;
  color: #1d2b36;
}

.cant-turni-tab .is-orario {
  font-variant-numeric: tabular-nums;
}

/* --- A quanto vendiamo l'ora, dentro il modulo -----------------------------------------
 *
 * Non e' un suggerimento da applicare e infatti non ha nessun pulsante: e' il prezzo di
 * questa proposta accanto a quello a cui quei lavori li abbiamo venduti. La barra si
 * disegna solo dove le tre zone hanno un senso — con una mediana sola, o con le due
 * incrociate, sarebbe un disegno senza dati sotto.
 */
.storico-prezzo {
  border-top: 1px solid #eef1f3;
  padding-top: 0.6rem;
}

.storico-riga {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
  font-size: 0.85rem;
  color: #33424d;
}

.storico-zona:empty {
  display: none;
}

.storico-barra {
  display: flex;
  position: relative;
  height: 0.5rem;
  border-radius: 0.25rem;
  overflow: visible;
  margin: 0.45rem 0 0.3rem;
  background: #eef1f3;
}

.storico-tratto {
  height: 100%;
}

.storico-tratto:first-child {
  border-radius: 0.25rem 0 0 0.25rem;
}

.storico-tratto:last-child {
  border-radius: 0 0.25rem 0.25rem 0;
}

.storico-tratto.is-vinte {
  background: #a8d5ab;
}

.storico-tratto.is-incerta {
  background: #f0dca8;
}

.storico-tratto.is-perse {
  background: #e8bcbc;
}

/* La posizione del prezzo di adesso: una lancetta, non un colore in piu' — il colore lo
   dice gia' il tratto sotto. */
.storico-punta {
  position: absolute;
  top: -0.2rem;
  width: 0.14rem;
  height: 0.9rem;
  margin-left: -0.07rem;
  background: #1d2b36;
  border-radius: 0.1rem;
}

.storico-note {
  font-size: 0.78rem;
  color: #8a97a3;
}
