/* dashboard/css/20-layout.css — estratto da app.css (2026-07, split senza build). */
/* APP container — responsive single page */
.app { min-height: 100vh; display: flex; background: var(--bg); }
.app-sidebar { display: none; }
/* padding-bottom: libera l'ultimo contenuto (bottoni azione, ultima card) dalla
   .bottom-nav fissa (min-height 68 + padding 10 + safe-area). safe-area-aware. */
.app-main { flex: 1; min-width: 0; display: flex; flex-direction: column; padding-bottom: calc(104px + env(safe-area-inset-bottom, 0px)); }
.screen { display: none; }
.screen.active { display: block; }
.statusbar { display: none; }

/* Tablet+ (>= 768px): contenuto piu ampio. Stesso indent del mobile (18px), e padding
   piu generoso solo per .ios-header. Spazio extra prima delle sezioni successive. */
@media (min-width: 768px) {
  .app-main { padding: 0 0 calc(104px + env(safe-area-inset-bottom, 0px)); }
  .ios-header { padding: 20px var(--page-pad-x) 28px; border-bottom: 1px solid var(--line); }
  .ios-header h1 { font-size: 30px; }
  .machine-card { padding: 18px 22px; }
  .machine-card .id-circle { width: 60px; height: 60px; }
  .machine-card .name { font-size: 18px; }
  .domotica-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
  .template-grid { grid-template-columns: repeat(4, 1fr); }
  /* Aria sopra la prima sezione subito dopo l'ios-header */
  .ios-header + .mkt-intro,
  .ios-header + .section-title,
  .ios-header + .concept-note,
  .ios-header + .filter-row,
  .ios-header + .period-card { margin-top: 14px; }
  .mkt-intro { margin-top: 14px; }
}

/* Desktop (>= 1024px): sidebar fissa, no bottom-nav */
@media (min-width: 1024px) {
  /* App-shell (pattern Coolify): il documento NON scrolla; scorre solo il contenuto
     dentro .app-main. La sidebar sta FERMA fuori dallo scroll → niente rubber-band
     macOS che fa "bouncare" tutta la pagina (sidebar inclusa) all'overscroll. La
     sidebar ha la SUA scrollbar se il viewport verticale è basso, e finisce 16px
     prima del fondo → un velo di grigio (--bg) sotto "Gestore".
     CRUCIALE — .app-main deve restare un BLOCCO (display:block), NON flex: in
     WebKit/Safari uno sticky figlio diretto di un flex-container che scrolla collassa
     a ~1px d'altezza → i sub-tab .cli-subtabs di Andamento/Clienti "sparivano" (è il
     motivo del revert c1859d9). Mobile (<1024px) invariato: scroll sul documento. */
  html, body { height: 100%; overflow: hidden; }
  body { background: var(--bg); }
  .app { max-width: 1440px; margin: 0 auto; box-shadow: 0 0 40px rgba(0,0,0,0.04); background: var(--bg); height: 100vh; overflow: hidden; }
  .app-sidebar { display: flex; flex-direction: column; width: 240px; background: var(--surface); border-right: 1px solid var(--line); padding: 22px 14px; flex-shrink: 0; align-self: flex-start; height: calc(100vh - 16px); overflow-y: auto; overscroll-behavior: contain; }
  .app-main { display: block; height: 100vh; overflow-y: auto; overscroll-behavior: contain; padding-bottom: 28px; background: var(--bg); }
  .bottom-nav { display: none !important; }
  .domotica-grid { grid-template-columns: 1fr 1fr 1fr; gap: 14px; }
  .template-grid { grid-template-columns: repeat(4, 1fr); }
  .ios-header h1 { font-size: 32px; }
  .ios-header { padding-bottom: 22px; }
}

/* Sidebar desktop */
.sb-brand { display: flex; align-items: center; gap: 10px; padding: 4px 10px 18px; border-bottom: 1px solid var(--line); margin-bottom: 14px; }
.sb-brand .logo { width: 36px; height: 36px; background: var(--brand); color: #fff; border-radius: 9px; display: flex; align-items: center; justify-content: center; font-weight: 800; font-size: 16px; }
.sb-brand .text { display: flex; flex-direction: column; }
.sb-brand .name { font-size: 14px; font-weight: 800; line-height: 1.1; }
.sb-brand .store { font-size: 11px; color: var(--ink-3); display: inline-flex; align-items: center; gap: 4px; }
/* sb-brand cliccabile (multi-lavanderia switcher): aspetto pill, hover brand-soft */
/* margin-top:-15 + padding-top:15 = posizione logo invariata MA hover area
   estesa fino al top sidebar (copre i 15px di "vuoto" sopra il logo, evita
   tagli antiestetici sul hover background brand-soft). */
.sb-brand--btn { width: calc(100% + 28px); margin: -15px -14px 14px; padding: 15px 14px; border: 0; background: transparent; cursor: pointer; text-align: left; transition: background 120ms ease; border-bottom: 1px solid var(--line); }
.sb-brand--btn:hover { background: var(--brand-soft); }
.sb-brand--btn:hover .sb-store-chev { color: var(--brand); }
.sb-store-chev { color: var(--ink-3); transition: color 120ms ease; }

/* Lab-pill inline in ios-header (mobile only): sostituisce il subtitle Lavanderia X
   e sta sulla stessa riga della meta info (es. "8 canali · 6 sensori" a destra).
   min-height 28px = stessa altezza visiva di .lab-pill e .hdr-action per
   garantire allineamento ottico tra icona casa (sx) e icona euro (dx). */
.ios-header-row { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; min-height: 28px; }
.ios-header-row .meta { margin-left: auto; padding: 0; }

/* Riga titolo (h1 + meta opzionale) sotto la ios-header-row.
   Pattern: H1 a sx, meta opzionale a dx (margin-left:auto).
   margin-top 10px: lascia respiro ma mantiene la coesione del blocco header. */
.ios-title-row { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; margin-top: 18px; }
.ios-title-row h1 { margin: 0; }
.ios-title-row .meta { margin-left: auto; }
@media (min-width: 1024px) {
  .ios-header-row { display: none; }
  .ios-title-row { margin-top: 0; }
}

/* Header action mobile ("Rimborsa" nella ios-header-row).
   Stessa altezza visiva di .lab-pill (28px) — padding verticale e min-height
   identici per allineamento ottico perfetto tra icona casa e icona euro.
   Su desktop nascosto: l'azione vive in sidebar (.sb-action). */
.hdr-action { display: inline-flex; align-items: center; gap: 6px; padding: 5px 12px; min-height: 28px; background: transparent; border: 1px solid var(--brand); font-size: 13px; font-weight: 700; color: var(--brand); cursor: pointer; margin-left: auto; border-radius: 999px; transition: background 120ms ease; -webkit-tap-highlight-color: transparent; }
.hdr-action:hover { background: var(--brand-soft); }
.hdr-action:active { background: var(--brand-soft); opacity: .85; }
.hdr-action:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
.hdr-action svg { width: 13px; height: 13px; flex-shrink: 0; }
@media (min-width: 1024px) { .hdr-action { display: none; } }

/* Sidebar action button — outlined, distinto dalle voci nav.
   Desktop only. Margin-top generoso per stacco netto da Impostazioni.
   Selettore qualificato `.sb-nav .sb-action` per vincere su `.sb-nav button`
   (cascade: stessa altezza specificity altrimenti perde su color/font-size). */
/* Stesso stile di .hdr-action mobile: pill outlined brand, font 14/600 come voci nav. */
.sb-nav .sb-action { display: inline-flex; align-self: flex-start; align-items: center; padding: 6px 14px; min-height: 30px; margin-top: 32px; background: transparent; border: 1px solid var(--brand); border-radius: 999px; font-size: 14px; font-weight: 600; color: var(--brand); cursor: pointer; transition: background 120ms ease; width: auto; }
.sb-nav .sb-action:hover { background: var(--brand-soft); color: var(--brand); }
.sb-nav .sb-action svg { width: 14px; height: 14px; flex-shrink: 0; }

/* Reservations disclosure — collapsed di default, apre tabella stile Bloomest. */
.reservations-disclosure { margin: 12px 18px 24px; background: var(--surface); border-radius: 14px; box-shadow: var(--shadow-card); overflow: hidden; }
.reservations-disclosure summary { display: flex; align-items: center; gap: 8px; padding: 14px 16px; cursor: pointer; font-weight: 700; color: var(--ink); list-style: none; }
.reservations-disclosure summary::-webkit-details-marker { display: none; }
.reservations-disclosure summary::after { content: '+'; font-size: 22px; font-weight: 400; line-height: 1; color: var(--ink-3); margin-left: auto; transition: color 120ms ease; }
.reservations-disclosure[open] summary::after { content: '\00d7'; font-size: 24px; }
.reservations-disclosure summary:hover::after { color: var(--brand); }
.reservations-count { font-size: 12px; font-weight: 500; color: var(--ink-3); margin-left: 4px; vertical-align: baseline; }

/* "Altre azioni possibili" — disclosure soft sotto la mossa della settimana (Oggi). */
.oggi-altre-azioni { margin: 4px 18px 0; }
.oggi-altre-azioni summary { display: flex; align-items: center; padding: 10px 2px; cursor: pointer; font-weight: 600; font-size: 13px; color: var(--ink-3); list-style: none; }
.oggi-altre-azioni summary::-webkit-details-marker { display: none; }
.oggi-altre-azioni summary::after { content: '+'; font-size: 20px; font-weight: 400; line-height: 1; color: var(--ink-3); margin-left: auto; transition: color 120ms ease; }
.oggi-altre-azioni[open] summary::after { content: '\00d7'; font-size: 22px; }
.oggi-altre-azioni summary:hover { color: var(--brand); }
.oggi-altre-azioni summary:hover::after { color: var(--brand); }
.oggi-altre-azioni .u-mx-18-mt-12 { margin-left: 0; margin-right: 0; }
.reservations-empty { padding: 0 16px 18px; margin: 0; font-size: 13px; color: var(--ink-3); line-height: 1.5; }
.reservations-table-wrap { overflow-x: auto; border-top: 1px solid var(--line); }
.reservations-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.reservations-table th { text-align: left; color: var(--brand); font-weight: 700; padding: 12px 14px; border-bottom: 1px solid var(--line); white-space: nowrap; font-size: 12px; }
.reservations-table td { padding: 12px 14px; border-bottom: 1px solid var(--line); white-space: nowrap; vertical-align: middle; color: var(--ink); }
.reservations-table tbody tr:hover { background: var(--bg); }
.reservations-table tr:last-child td { border-bottom: none; }
.dev-badge { display: inline-flex; align-items: center; justify-content: center; width: 22px; height: 22px; border-radius: 50%; background: var(--ink); color: #fff; font-weight: 700; font-size: 11px; margin-right: 8px; vertical-align: middle; }
.status-dot { display: inline-block; width: 10px; height: 10px; border-radius: 50%; margin-right: 8px; vertical-align: middle; }
.status-dot.status-pending { background: #fbcfa4; }
.status-dot.status-confirmed { background: #9be3a8; }
.status-dot.status-cancelled { background: #f5c0c0; }
.status-dot.status-expired { background: #d4d4d4; }
.card-tag { display: inline-flex; align-items: center; gap: 4px; padding: 4px 10px; background: var(--brand); color: #fff; border-radius: 4px; font-family: monospace; font-size: 11px; font-weight: 600; margin-right: 6px; }
.user-tag { display: inline-flex; align-items: center; padding: 4px 10px; background: #2c7fd1; color: #fff; border-radius: 4px; font-size: 12px; font-weight: 500; }
.lab-pill { display: inline-flex; align-items: center; gap: 8px; padding: 4px 8px 4px 6px; margin-left: -8px; min-height: 28px; background: transparent; border: 0; cursor: pointer; font-size: 14px; font-weight: 700; color: var(--ink); border-radius: 999px; transition: background 120ms ease; -webkit-tap-highlight-color: transparent; }
.lab-pill:hover { background: var(--brand-soft); }
.lab-pill:active { background: var(--brand-soft); opacity: .85; }
.lab-pill:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
.lab-pill svg { color: var(--brand); flex-shrink: 0; }
.lab-pill .lab-pill-name { font-weight: 800; letter-spacing: -0.005em; }
.lab-pill .lab-pill-count { font-size: 11px; font-weight: 700; color: var(--ink-3); background: var(--bg); padding: 2px 7px; border-radius: 999px; font-variant-numeric: tabular-nums; letter-spacing: 0.01em; }
.lab-pill .lab-pill-chev { color: var(--ink-3); width: 12px; height: 12px; margin-left: -2px; transition: color 120ms ease, transform 120ms ease; }
.lab-pill:hover .lab-pill-chev { color: var(--brand); }
@media (min-width: 1024px) { .lab-pill { display: none; } .ios-header-row .meta { margin-left: 0; } }

/* Modal "Cambia sede" — lista 6 sedi con sede attiva evidenziata */
.lab-list { display: flex; flex-direction: column; gap: 8px; margin-top: 12px; }
.lab-row { display: flex; align-items: center; gap: 12px; padding: 12px 14px; border: 1px solid var(--line); border-radius: 12px; background: var(--surface); text-decoration: none; color: var(--ink); transition: border-color 120ms ease, background 120ms ease; }
.lab-row:hover { border-color: var(--brand); background: var(--brand-soft); }
.lab-row.is-active { border-color: var(--brand); background: var(--brand-soft); }
.lab-row .lab-ico { width: 36px; height: 36px; flex-shrink: 0; border-radius: 10px; background: var(--bg); color: var(--ink-3); display: inline-flex; align-items: center; justify-content: center; }
.lab-row.is-active .lab-ico { background: var(--brand); color: #fff; }
.lab-row .lab-body { flex: 1; min-width: 0; }
.lab-row .lab-name { font-size: 14px; font-weight: 700; color: var(--ink); }
.lab-row .lab-meta { font-size: 12px; color: var(--ink-3); margin-top: 2px; line-height: 1.4; }
.lab-row .lab-check { color: var(--brand); flex-shrink: 0; }
.lab-foot-note { margin-top: 14px; font-size: 11px; color: var(--ink-3); font-style: italic; text-align: center; }

/* Multi-select chip-row "APPLICA A:" — broadcast Promo su più sedi (no bordi, layout piatto) */
.lab-broadcast { padding: 4px 0 12px; }
/* In Crea/Attive il .cli-view parent non ha padding-x (lo hanno solo bonus-reg),
   quindi il broadcast partial va indentato esplicitamente. (Riordino W1: il tab
   "campagne" è diventato "crea" — qui vive l'"Applica a sedi".) */
.cli-view[data-promo-view="crea"] .lab-broadcast { padding-left: var(--page-pad-x); padding-right: var(--page-pad-x); }
.lab-broadcast-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; }
.lab-broadcast-label { font-size: 11px; font-weight: 800; letter-spacing: 0.06em; color: var(--ink-3); }
.lab-broadcast-count { font-size: 11px; font-weight: 700; color: var(--brand); background: var(--brand-soft); padding: 3px 8px; border-radius: 999px; }
.lab-broadcast-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.lab-chip { display: inline-flex; align-items: center; gap: 4px; padding: 6px 10px; border: 1px solid var(--line); border-radius: 999px; background: var(--surface); font-size: 13px; font-weight: 600; color: var(--ink-2); cursor: pointer; transition: border-color 120ms ease, background 120ms ease, color 120ms ease; }
.lab-chip:hover { border-color: var(--brand); color: var(--brand); }
.lab-chip.on { border-color: var(--brand); background: var(--brand); color: #fff; }
.lab-chip .lab-chip-check { display: none; }
.lab-chip .lab-chip-plus { color: var(--ink-3); }
.lab-chip.on .lab-chip-check { display: inline-flex; color: #fff; }
.lab-chip.on .lab-chip-plus { display: none; }
.lab-chip:hover .lab-chip-plus { color: var(--brand); }
.lab-chip.shake { animation: lab-chip-shake 320ms ease-in-out; }
@keyframes lab-chip-shake { 0%, 100% { transform: translateX(0); } 25% { transform: translateX(-3px); } 75% { transform: translateX(3px); } }
.sb-nav { display: flex; flex-direction: column; gap: 2px; }
.sb-nav button { display: flex; align-items: center; gap: 12px; padding: 10px 12px; border-radius: 10px; font-size: 14px; font-weight: 600; color: var(--ink-2); text-align: left; width: 100%; }
.sb-nav button:hover { background: var(--bg); }
.sb-nav button.active { background: var(--brand-soft); color: var(--brand); }
.sb-nav button .badge-n { margin-left: auto; background: var(--danger); color: #fff; font-size: 10px; padding: 2px 7px; border-radius: 999px; font-weight: 700; }
.sb-user { margin-top: auto; padding: 18px 14px; display: flex; align-items: center; gap: 10px; border-top: 1px solid var(--line); margin-left: -14px; margin-right: -14px; margin-bottom: -22px; }
.sb-user .av { width: 32px; height: 32px; border-radius: 50%; background: linear-gradient(135deg,#FFD3DC,#FFAFC0); display: flex; align-items: center; justify-content: center; font-weight: 700; color: var(--brand-dark); font-size: 13px; flex-shrink: 0; }
/* flex column: forza .name su riga 1 e .role su riga 2 (no spezzamento del role
   in più righe quando la traduzione è più lunga, es. EN "Manager · 6 locations"). */
.sb-user .text { display: flex; flex-direction: column; min-width: 0; }
.sb-user .text .name { font-size: 13px; font-weight: 700; }
.sb-user .text .role { font-size: 11px; color: var(--ink-3); white-space: nowrap; }

/* App header — stile iOS pulito.
   padding: 12px top / 16px bottom = aria simmetrica con line-height del lab-pill.
   border-bottom: hairline morbido per separare dal content senza pesare. */
.ios-header { background: var(--surface); padding: 12px var(--page-pad-x) 24px; border-bottom: 1px solid var(--line); }
.ios-header .clock-row { display: flex; justify-content: space-between; font-size: 13px; color: var(--ink-3); margin-bottom: 4px; }
.ios-header h1 { font-size: 26px; font-weight: 800; letter-spacing: -0.022em; line-height: 1.15; color: var(--ink); }
.ios-header .meta { display: flex; justify-content: space-between; align-items: baseline; margin-top: 4px; gap: 10px; }
.ios-header .meta .city { font-size: 12px; color: var(--ink-3); }
.ios-header .meta .city strong { color: var(--ink-2); font-weight: 600; }
.ios-header .meta .addr { font-size: 12px; color: var(--ink-3); text-align: right; }
.ios-header .meta .addr strong { color: var(--ink-2); font-weight: 600; display: block; }
.ios-header .meta .addr.compact { font-size: 12px; font-weight: 500; color: var(--ink-3); letter-spacing: 0.02em; }
.ios-header .meta .addr.compact strong { display: inline; font-weight: 700; color: var(--ink-2); font-variant-numeric: tabular-nums; letter-spacing: 0; }
.ios-header .meta .city strong { white-space: nowrap; }

/* Desktop ≥1024: padding calibrato per allineare verticalmente l'h1 "Macchine"
   con il logo "B" della sidebar (entrambi center Y ~40px) E il border-bottom
   della top bar con il border della .sb-brand (entrambi Y ~74px).
   DEVE stare dopo `.ios-header { padding: 12px var 24px }` base per vincere
   nel cascade (stessa specificity, ordine sorgente). */
@media (min-width: 1024px) {
  .ios-header { padding: 25px var(--page-pad-x) 18px; }
}

/* Bottom nav iOS-style */
/* min-height (NON height): in PWA standalone il padding-bottom della
   home-indicator si mangiava lo spazio interno (border-box) e le icone
   finivano schiacciate sul bordo superiore della barra. */
.bottom-nav { position: fixed; bottom: 0; left: 0; right: 0; background: var(--surface); border-top: 1px solid var(--line); display: flex; min-height: 68px; padding-bottom: env(safe-area-inset-bottom, 4px); padding-top: 10px; z-index: 50; }
.bottom-nav button { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px; font-size: 10px; color: var(--ink-3); font-weight: 600; position: relative; }
.bottom-nav button.active { color: var(--brand); }
.bottom-nav button.active span { font-weight: 800; }
/* "+" centrale (overflow nav) — FAB rosso pieno (brand) con un velo di glass:
   backdrop-filter dove supportato, fallback opaco. Icona bianca per contrasto.
   IA invariata: apre il bottom-sheet "Altro". */
.bottom-nav .nav-plus { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; }
.bottom-nav .nav-plus .plus-fab { width: 52px; height: 52px; margin-top: -14px; border-radius: 999px; background: rgba(140,0,20,0.88); color: #fff; display: flex; align-items: center; justify-content: center; box-shadow: 0 6px 18px rgba(140,0,20,0.30); border: 1px solid rgba(255,255,255,0.30); -webkit-backdrop-filter: blur(14px) saturate(1.3); backdrop-filter: blur(14px) saturate(1.3); transition: transform 80ms ease, box-shadow 120ms ease, border-color 120ms ease, background 120ms ease; }
.bottom-nav .nav-plus:hover .plus-fab { background: rgba(140,0,20,0.96); border-color: rgba(255,255,255,0.45); box-shadow: 0 8px 22px rgba(140,0,20,0.36); }
.bottom-nav .nav-plus:active .plus-fab { transform: scale(0.92); }
.bottom-nav .nav-plus .plus-fab .i { width: 22px; height: 22px; stroke: #fff; stroke-width: 2.25; fill: none; }
@supports not ((-webkit-backdrop-filter: blur(1px)) or (backdrop-filter: blur(1px))) {
  .bottom-nav .nav-plus .plus-fab { background: var(--brand); border-color: rgba(255,255,255,0.30); }
}
/* A11Y · prefers-reduced-transparency — se l'utente chiede meno trasparenza
   (iOS Reduce Transparency, Windows), spegniamo il velo glass e teniamo il FAB
   pieno e opaco. Coerente con design-system principi-design-mobile.md §6. */
@media (prefers-reduced-transparency: reduce) {
  .bottom-nav .nav-plus .plus-fab { -webkit-backdrop-filter: none; backdrop-filter: none; background: var(--brand); border-color: rgba(255,255,255,0.30); }
}
/* menu "+" (bottom-sheet con maniglia visibile + X) — sola NAVIGAZIONE, niente azioni */
.more-sheet .sheet-handle { display: block; }
.more-list { display: flex; flex-direction: column; gap: 4px; margin-top: 4px; }
.more-row { display: flex; align-items: center; gap: 14px; padding: 14px 12px; border-radius: 12px; color: var(--ink); text-decoration: none; transition: background 120ms ease, transform 80ms ease; }
.more-row:hover { background: var(--bg); }
.more-row:active { transform: scale(0.98); }
.more-row > .i:first-child { color: var(--ink-2); flex-shrink: 0; }
.more-row > span { flex: 1; font-weight: 600; font-size: 15px; }
.more-row .chev { opacity: 0.5; flex-shrink: 0; }

/* Bottone flottante "file pronto" (js/70-export.js): Safari rifiuta
   navigator.share ad activation scaduta (fetch lento) anche a file gia'
   scaricato — il tap sul bottone e' una nuova activation e salva il file.
   Sopra bottom-nav e bulk-bar (z-index 39). */
.export-ready-float { position: fixed; left: 50%; transform: translateX(-50%); bottom: calc(84px + env(safe-area-inset-bottom, 0px)); z-index: 60; box-shadow: 0 8px 24px rgba(15,20,25,0.25); }
@media (min-width: 1024px) { .export-ready-float { bottom: 24px; } }
