/* ============================================================
 * BadgeBox v2 — main.php skin
 *
 * Re-skins the legacy markup emitted by main.php to match the v2
 * design language, without changing the HTML structure or the
 * JavaScript wiring. All rules are scoped under body.bbx-v2.
 *
 * Depends on tokens.css (CSS custom properties).
 * ============================================================ */

/* ----- Base typography + body ----- */
body.bbx-v2,
body.bbx-v2 * {
    font-family: var(--bbx-font);
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}
body.bbx-v2 {
    color: var(--bbx-gray-700);
    background: var(--bbx-gray-50);
}

body.bbx-v2 a { color: var(--bbx-blue-600); text-decoration: none; }
body.bbx-v2 a:hover { color: var(--bbx-blue-700); }

/* ============================================================
 *  SIDEBAR (#menu .menu-column)
 * ============================================================ */

/* RIMOSSE regole legacy body.bbx-v2 #logo-container — il logo del menu
 * è ora gestito interamente in style_main_refresh.css (unificato per
 * rail + non-rail, due stati: placeholder vuoto vs logo caricato). */

/* Agency selector (#select-agency, native <select>) */

/* User chip (#name-header) — preserve legacy interactions:
 *   - first .table-cell with onclick="selectButton(18,'')" → open profile
 *   - middle .table-cell → name/surname text
 *   - #messages-header .table-cell with onclick="openMessagesBox()" → mail
 * Restyle only the visual layer; keep markup, cursor, and click targets. */

/* Avatar cell is the profile trigger — keep it clickable */

/* Messages cell → mail icon trigger */

/* Dock timbratura: vive in style_main_refresh.css (§.bbx-dock-track) */

/* Search removed per design — hide legacy #search-content entirely */

/* Nav adapter + accordions — subtle scrollbar on the dark rail.
 * height:auto neutralizza l'inline height settato dal resetMenu()
 * di main.php (offset hardcoded 40 che non copre footer v2). */

/* ------------------------------------------------------------
 * Accordion — matches design_handoff/menu.png:
 *   group header 44px tall, 14px semi-bold, 20px outline icon,
 *   active group = rgba white 0.18 bg, chevron on the right,
 *   submenu rows 36px, text-only (no icon), indented ~28px,
 *   active sub-row = bold white (no bg), inactive = rgba white 0.65
 * ------------------------------------------------------------ */

/* Chevron via ::after — always pointing right (matches menu.png) */

/* Submenu — container is full width, no padding; indent lives on the rows */

/* Hide the icon column for submenu rows (menu.png = text only) */

/* Font-size fissa nelle SOTTO-VOCI del menu laterale (.menu-row + .menu-coloumn)
   per neutralizzare le regole responsive di .text-medium (@media 768px: 12pt).
   .accordion-title-section è ESCLUSA: la macro-label nel rail vive a 10px
   (style_main_refresh.css), nessuna regola di main-v2 deve sovrascriverla. */
#menu.menu-column .menu-row,
#menu.menu-column .menu-row .menu-coloumn {
    font-size: var(--bbx-fs-lg);
    line-height: 1.3;
}

/* Menu-bottom (exit / footer) — align with sidebar colour */

/* ============================================================
 *  LA TESTATA LEGACY NON STA PIU' QUI
 *
 *  Erano ~900 righe che vestivano #header.header: la fascia da 133px
 *  con .header-gradient, i tre #header-row-*, la tab bar #menu-switch,
 *  la pill #people-header, i filtri .menu-glass e #tag-header, la
 *  action bar #header-glass coi suoi #menu-buttons / #cluster-buttons.
 *  Descrivevano un disegno che non esiste piu' da quando la testata e'
 *  #bbx-header (style_main_refresh.css §HEADER GLASS + primitives
 *  §HEADER v2) e il titolo sta nella fascia: erano tenute spente da una
 *  riga sola in un altro file, e ogni indagine sulla testata partiva da
 *  qui. Tolte il 2026-09-10 insieme al ramo v1.
 *
 *  Restano piu' sotto le due cose che quel blocco conteneva e che sono
 *  ancora vive: i pannelli a tendina (dropdown/popover) e il visore
 *  persone #people-list-container, che su mobile bbx-header.js sposta
 *  dentro il bottom-sheet.
 * ============================================================ */

/* ============================================================
 *  Pannelli a tendina (dropdown, popover, datepicker, autocomplete)
 *   Un fondo leggibile va dichiarato: senza, prendono quello del
 *   contenitore che li ospita e su una superficie trasparente
 *   sparirebbero.
 * ============================================================ */
body.bbx-v2 .dropdown-menu,
body.bbx-v2 .bootstrap-select .dropdown-menu,
body.bbx-v2 .bs-popover-auto,
body.bbx-v2 .popover,
body.bbx-v2 .xdsoft_datetimepicker,
body.bbx-v2 .easy-autocomplete-container ul {
    background: var(--bbx-surface) !important;
    background-color: var(--bbx-surface) !important;
    border: 1px solid var(--bbx-gray-150) !important;
    border-radius: var(--bbx-r-md) !important;
    box-shadow: var(--bbx-shadow-lg) !important;
    color: var(--bbx-gray-800) !important;
    padding: 6px !important;
    font-family: var(--bbx-font);
    font-size: var(--bbx-fs-md);
}
body.bbx-v2 .dropdown-menu > li > a,
body.bbx-v2 .dropdown-menu .dropdown-item,
body.bbx-v2 .bootstrap-select .dropdown-menu li a,
body.bbx-v2 .easy-autocomplete-container ul li {
    background: transparent !important;
    color: var(--bbx-gray-700) !important;
    padding: 7px 10px !important;
    border-radius: var(--bbx-r-sm) !important;
    font-size: var(--bbx-fs-md) !important;
    line-height: 1.3 !important;
    border: none !important;
}
body.bbx-v2 .dropdown-menu > li > a:hover,
body.bbx-v2 .dropdown-menu > li > a:focus,
body.bbx-v2 .dropdown-menu .dropdown-item:hover,
body.bbx-v2 .dropdown-menu .dropdown-item.active,
body.bbx-v2 .bootstrap-select .dropdown-menu li a:hover,
body.bbx-v2 .bootstrap-select .dropdown-menu li.selected a,
body.bbx-v2 .easy-autocomplete-container ul li:hover,
body.bbx-v2 .easy-autocomplete-container ul li.selected {
    background: var(--bbx-blue-50) !important;
    color: var(--bbx-blue-700) !important;
}
/* Native <option> inherits browser styling — force readable colour */
body.bbx-v2 select option {
    background: var(--bbx-surface);
    color: var(--bbx-gray-800);
}


/* ============================================================
 *  People viewer  (rebuilt from scratch — v2)
 *
 *  Markup (dynamic content only, structure untouched):
 *    #people-list-container
 *      #people-viewer.people-head
 *        .people-detail
 *          .people-detail-left
 *            img#img-people-email
 *            #detail-people-avatar
 *          .people-detail-right
 *            #detail-people-name / #detail-people-surname
 *            #detail-people-supplier / #detail-people-job
 *
 *  (2026-09-23: erano dentro `.col-12 > .text-medium.text-gray`, cioe' una
 *  colonna di Bootstrap col rientro spento da `.no-padding`. La banda nera
 *  e la freccia erano gia' sparite dal markup.)
 * ============================================================ */

/* Panel — transparent, minimal, no borders */
body.bbx-v2 #people-list-container.people-list-container,
body.bbx-v2 #people-viewer,
body.bbx-v2 #people-viewer .people-detail,
body.bbx-v2 #people-viewer .people-detail > div {
    background: transparent;
    background-color: transparent;
    border: none;
    box-shadow: none;
}

body.bbx-v2 #people-list-container.people-list-container { padding: 0; }
body.bbx-v2 #people-viewer.people-head { padding: 0; }

/* Main row: avatar | text | mail icon */
body.bbx-v2 #people-viewer .people-detail {
    display: grid;
    grid-template-columns: auto 1fr auto;
    grid-template-rows: auto auto;
    align-items: start;
    gap: 4px 14px;
    padding: 16px 18px 14px;
    position: relative;
}

/* Avatar cell */
body.bbx-v2 #people-viewer .people-detail-left {
    grid-column: 1;
    grid-row: 1 / span 2;
    width: auto;
    padding: 0;
    position: relative;
    align-self: center;
}
body.bbx-v2 #people-viewer #detail-people-avatar {
    width: 44px;
    height: 44px;
    border-radius: var(--bbx-r-full);
    margin: 0;
}

/* Text column */
body.bbx-v2 #people-viewer .people-detail-right {
    grid-column: 2;
    grid-row: 1;
    padding: 0;
    min-width: 0;
}
body.bbx-v2 #people-viewer .people-detail-right { line-height: 1.25; }
body.bbx-v2 #people-viewer #detail-people-name {
    font-size: var(--bbx-fs-2xs);
    color: var(--bbx-gray-400);
    font-weight: 600;
    letter-spacing: 0.4px;
    text-transform: uppercase;
    line-height: 1.2;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
body.bbx-v2 #people-viewer #detail-people-surname {
    font-size: var(--bbx-fs-lg);
    font-weight: 600;
    color: var(--bbx-gray-800);
    line-height: 1.25;
    margin: 2px 0 3px;
    letter-spacing: -0.1px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
body.bbx-v2 #people-viewer #detail-people-supplier,
body.bbx-v2 #people-viewer #detail-people-job {
    font-size: var(--bbx-fs-xs);
    color: var(--bbx-gray-500);
    line-height: 1.3;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
body.bbx-v2 #people-viewer #detail-people-supplier:empty,
body.bbx-v2 #people-viewer #detail-people-job:empty { display: none !important; }

/* Mail icon — top-right corner */
body.bbx-v2 #people-viewer #img-people-email {
    grid-column: 3;
    grid-row: 1;
    position: static !important;
    width: 16px;
    height: auto;
    max-height: 16px;
    object-fit: contain;
    opacity: 0.55;
    cursor: pointer;
    align-self: start;
    margin-top: 2px;
    transition: opacity 120ms ease;
    filter: none;
}
body.bbx-v2 #people-viewer #img-people-email:hover { opacity: 1; }

/* La banda di stato (`.black-band` con presenza, messaggio e link alla
   scheda) — RIMOSSA il 2026-09-23: il markup non la scrive dal 2026-08-25,
   e le sue regole (undici, quasi tutte con `!important` per disfare i float
   legacy) stavano vestendo il nulla. */

body.bbx-v2 #people-viewer #people-detail {
    width: 16px !important;
    height: auto !important;
    max-height: 16px;
    object-fit: contain;
    opacity: 0.55;
    margin: 0 !important;
    float: none !important;
    cursor: pointer;
    transition: opacity 120ms ease;
    filter: none !important;
}
body.bbx-v2 #people-viewer #people-msg:hover,
body.bbx-v2 #people-viewer #people-detail:hover { opacity: 1; }

/* Connector arrow — hide (chip already conveys anchor) */
/* 2026-08-25 — rimossa col suo bersaglio (freccia e striscia legacy).
 * Per giunta era gia' inerte: il browser target non applica :has(). */

/* ============================================================
 *  People-list-container — dropdown panel with the people list
 *
 *  Structure:
 *    #people-list-container
 *      #people-viewer          (header: selected person detail)
 *      .people-switch          (segmented select: Interni/Esterni/Tutti)
 *      .people-functions
 *        .people-search        (search input + add icon)
 *      #people-body
 *        #people-content > #people-container  (dynamic list)
 *      #people-tail            (footer shrink handle)
 * ============================================================ */

/* Root dropdown panel */
body.bbx-v2 #people-list-container.people-list-container {
    background: var(--bbx-surface);
    border-radius: var(--bbx-r-lg);
    border: 1px solid var(--bbx-gray-150);
    box-shadow: var(--bbx-shadow-lg);
    overflow: hidden;
    padding: 0;
    min-width: 280px;
    font-family: var(--bbx-font);
}

/* Segment switcher (Interni / Esterni / Tutti) */
body.bbx-v2 #people-list-container .people-switch {
    padding: 10px 14px 0;
    background: var(--bbx-surface);
}
body.bbx-v2 #people-list-container .people-switch select.segment-select,
body.bbx-v2 #people-list-container .people-switch select {
    width: 100%;
    padding: 7px 30px 7px 12px;
    min-height: 32px;
    font-size: var(--bbx-fs-input);
    font-weight: 500;
    color: var(--bbx-gray-700);
    background: var(--bbx-gray-50);
    background-color: var(--bbx-gray-50);
    border: 1px solid var(--bbx-gray-150);
    border-radius: var(--bbx-r-md);
    appearance: none;
    -webkit-appearance: none;
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%238b95a4' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M6 9l6 6 6-6'/></svg>") !important;
    background-repeat: no-repeat;
    background-position: right 10px center;
    outline: none;
    cursor: pointer;
    box-shadow: none;
    line-height: 1.2;
}
body.bbx-v2 #people-list-container .people-switch select:focus {
    border-color: var(--bbx-blue-500) !important;
    box-shadow: 0 0 0 3px rgba(0, 128, 246, 0.18) !important;
}

/* Search input row */
body.bbx-v2 #people-list-container .people-functions {
    padding: 10px 14px;
    background: var(--bbx-surface);
}
body.bbx-v2 #people-list-container .people-search .input-group {
    display: flex;
    align-items: stretch;
    background: var(--bbx-gray-50);
    border: 1px solid var(--bbx-gray-150);
    border-radius: var(--bbx-r-md);
    overflow: hidden;
    transition: border-color 120ms ease, box-shadow 120ms ease;
}
body.bbx-v2 #people-list-container .people-search .input-group:focus-within {
    border-color: var(--bbx-blue-500) !important;
    box-shadow: 0 0 0 3px rgba(0, 128, 246, 0.18);
}
body.bbx-v2 #people-list-container .people-search .input-group-text {
    background: transparent !important;
    background-color: transparent !important;
    border: none;
    padding: 0 10px;
    display: inline-flex;
    align-items: center;
    color: var(--bbx-gray-500);
    border-radius: 0 !important;
}
body.bbx-v2 #people-list-container .people-search .input-group-text .bi-search { font-size: var(--bbx-fs-lg); color: var(--bbx-gray-500); }
body.bbx-v2 #people-list-container .people-search .form-control,
body.bbx-v2 #people-list-container #search-people {
    background: transparent !important;
    border: none;
    box-shadow: none;
    height: 32px !important;
    padding: 6px 4px;
    font-size: var(--bbx-fs-input);
    color: var(--bbx-gray-800);
    flex: 1 1 auto;
    min-width: 0;
    outline: none;
}
body.bbx-v2 #people-list-container .people-search .people-add {
    width: 16px;
    height: 16px;
    background-size: contain;
    background-position: center;
    background-repeat: no-repeat;
    cursor: pointer;
    opacity: 0.7;
    transition: opacity 120ms ease;
}
body.bbx-v2 #people-list-container .people-search .people-add:hover { opacity: 1; }

/* People body (scrollable list area) */
body.bbx-v2 #people-list-container #people-body,
body.bbx-v2 #people-list-container .people-body {
    background: var(--bbx-surface);
    box-shadow: none;
    border-radius: 0;
    border-top: 1px solid var(--bbx-gray-100);
    padding: 0;
}
body.bbx-v2 #people-list-container #people-content {
    max-height: 320px;
    overflow-y: auto;
    padding: 6px 8px;
}
body.bbx-v2 #people-list-container #people-content::-webkit-scrollbar { width: 6px; }
body.bbx-v2 #people-list-container #people-content::-webkit-scrollbar-thumb { background: var(--bbx-gray-200); border-radius: var(--bbx-r-full); }

/* Any row that JS renders inside #people-container */
body.bbx-v2 #people-list-container #people-container > div {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px 10px;
    border-radius: var(--bbx-r-md);
    cursor: pointer;
    transition: background 120ms ease;
    margin: 1px 0;
}
body.bbx-v2 #people-list-container #people-container > div:hover { background: var(--bbx-gray-50); }
body.bbx-v2 #people-list-container #people-container > div .img-cover,
body.bbx-v2 #people-list-container #people-container > div .rounded-circle {
    width: 30px !important;
    height: 30px !important;
    border-radius: var(--bbx-r-full) !important;
    flex-shrink: 0;
}
body.bbx-v2 #people-list-container #people-container > div .text-bold,
body.bbx-v2 #people-list-container #people-container > div .text-black {
    font-size: var(--bbx-fs-md) !important;
    font-weight: 500 !important;
    color: var(--bbx-gray-800) !important;
    line-height: 1.25;
}
body.bbx-v2 #people-list-container #people-container > div .text-small,
body.bbx-v2 #people-list-container #people-container > div .text-gray {
    font-size: var(--bbx-fs-xs);
    color: var(--bbx-gray-500);
    line-height: 1.25;
}

/* Tail (collapsed detail + toggle handle) */
body.bbx-v2 #people-list-container #people-tail.people-tail {
    background: var(--bbx-gray-25);
    border-top: 1px solid var(--bbx-gray-100);
    padding: 10px 14px;
}
body.bbx-v2 #people-list-container #people-tail .people-detail {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 0;
    background: transparent;
}
body.bbx-v2 #people-list-container #people-tail #detail-people-avatar-tail {
    width: 32px;
    height: 32px;
    border-radius: var(--bbx-r-full);
    flex-shrink: 0;
}
body.bbx-v2 #people-list-container #people-tail .people-detail-right {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    align-items: center;
    gap: 8px;
}
body.bbx-v2 #people-list-container #people-tail .people-detail__text { flex: 1 1 auto; min-width: 0; }
body.bbx-v2 #people-list-container #people-tail #detail-people-name-tail {
    font-size: var(--bbx-fs-2xs);
    color: var(--bbx-gray-400);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.3px;
    line-height: 1.2;
}
body.bbx-v2 #people-list-container #people-tail #detail-people-surname-tail {
    font-size: var(--bbx-fs-md);
    font-weight: 600;
    color: var(--bbx-gray-800);
    line-height: 1.2;
}
body.bbx-v2 #people-list-container #people-tail #detail-people-job-tail {
    font-size: var(--bbx-fs-xs);
    color: var(--bbx-gray-500);
    line-height: 1.2;
}
body.bbx-v2 #people-list-container #people-tail .bi-list {
    font-size: var(--bbx-fs-title);
    color: var(--bbx-gray-500);
    padding: 6px;
    border-radius: var(--bbx-r-md);
    margin: 0 !important;
    transition: background 120ms ease, color 120ms ease;
    cursor: pointer;
}
body.bbx-v2 #people-list-container #people-tail .bi-list:hover {
    background: var(--bbx-gray-100);
    color: var(--bbx-gray-800) !important;
}

/* ============================================================
 *  BUTTONS (.btn / .btn-primary / .btn-corner)
 * ============================================================ */

body.bbx-v2 .btn,
body.bbx-v2 .btn.btn-corner {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    padding: 8px 14px;
    min-height: 34px;
    font-size: var(--bbx-fs-md);
    font-weight: 500;
    font-family: inherit;
    line-height: 1.2;
    border-radius: var(--bbx-r-md);
    border: 1px solid var(--bbx-gray-200);
    background: var(--bbx-surface);
    color: var(--bbx-gray-700);
    cursor: pointer;
    text-decoration: none;
    transition: background 120ms ease, border-color 120ms ease, color 120ms ease;
    white-space: nowrap;
    box-sizing: border-box;
    vertical-align: middle;
}
body.bbx-v2 .btn:hover { background: var(--bbx-gray-50) !important; color: var(--bbx-gray-800) !important; }
body.bbx-v2 .btn-sm,
body.bbx-v2 .btn.btn-sm {
    padding: 6px 12px;
    min-height: 28px;
    font-size: var(--bbx-fs-sm);
}
body.bbx-v2 .btn-lg {
    padding: 10px 18px !important;
    min-height: 40px;
    font-size: var(--bbx-fs-lg) !important;
}
body.bbx-v2 .btn-xs,
body.bbx-v2 .btn.btn-xs {
    padding: 4px 10px !important;
    min-height: 24px !important;
    font-size: var(--bbx-fs-xs) !important;
    line-height: 1.2 !important;
    border-radius: var(--bbx-r-md) !important;
}

/* Cluster "menu-buttons" — voci di menu inline (Inserisci, Riapplica
   Regole, Compensa Straordinari, …). Testo scuro, sfondo trasparente,
   overlay grigio chiaro al hover. Nessun bordo né primary. */

/* Generic .select-custom widget — pattern condiviso (timesheet, ecc.).
 * Reset minimo del widget legacy (triangolo CSS, padding eccessivo del
 * .select-custom-hidden). Lo styling visivo dentro pillbar/menu-filters
 * è in style_main_refresh.css; altre pagine ereditano questa base. */
body.bbx-v2 .select-custom {
    position: relative;
    display: inline-block;
    min-width: 120px;
    cursor: pointer;
}
body.bbx-v2 .select-custom .select-custom-hidden,
body.bbx-v2 .select-custom select.select-custom-hidden,
body.bbx-v2 .select-custom select.select-period {
    display: none;
}
/* Disabilita il triangolo border-color legacy: chevron gestito dal
 * contesto (pillbar usa ::after sulla cella, altrove dal wrapper). */
body.bbx-v2 .select-custom .select-custom-styled::after,
body.bbx-v2 .select-custom #select-period-text::after,
body.bbx-v2 .select-custom .select-custom-styled::before,
body.bbx-v2 .select-custom #select-period-text::before {
    content: none;
    display: none;
    border: none;
    background: none;
}

body.bbx-v2 .btn.max-content,
body.bbx-v2 .max-content.btn { width: max-content !important; }
/* Variante DOPPIA .btn.btn-primary: il base "body.bbx-v2 .btn.btn-corner"
 * (2 classi) batteva in specificità "body.bbx-v2 .btn-primary" (1 classe)
 * → i bottoni `btn btn-primary btn-corner` restavano BIANCHI. */
body.bbx-v2 .btn-primary,
body.bbx-v2 .btn.btn-primary {
    background: var(--bbx-accent-fill);
    border-color: var(--bbx-blue-500) !important;
    color: var(--bbx-ink-inverse);
}
body.bbx-v2 .btn-primary:hover,
body.bbx-v2 .btn.btn-primary:hover {
    background: var(--bbx-accent-hover) !important;
    border-color: var(--bbx-blue-600) !important;
    color: var(--bbx-ink-inverse) !important;
}
/* .dialog-body--wide — popup a DUE COLONNE che usa la larghezza del modale
 * large. Come `.bbx-wrdlg-body` (rapportino) è escluso dalla regola "una
 * colonna sola che scrolla" qui sopra e dichiara il proprio layout per
 * intero: lo scroll non sta sul body ma DENTRO le colonne, che scorrono
 * indipendenti — leggere i campi a sinistra non deve far scappare via
 * l'anteprima a destra, e viceversa.
 * Toglie anche il `max-width: 550px` della `.dialog-body` legacy
 * (style_popup.css), pensato per i popup a colonna singola: dentro un
 * modale large lasciava tutto il contenuto in una colonnina a sinistra.
 * (dialog_add_wr risolve gli stessi due problemi con `.bbx-wrdlg-body`:
 * quando lo si tocca, può adottare questa.) */
/* Selettore a DUE classi di proposito: `#md-modal .md-content > .dialog-body`
 * (primitives §modal) vale 1,2,0 e impone `padding: 24px 24px 20px`. Prima la
 * regola generale qui sopra la batteva con `padding: 0 24px !important`; da
 * quando questo dialog ne è escluso, quel padding tornava a farsi sentire —
 * 24px sopra e 20px sotto in più. Pareggiando la specificità vince questo
 * file, che è caricato dopo primitives (main.php). Nessun !important. */
#md-content .dialog-body.dialog-body--wide {
    font-family: var(--bbx-font), system-ui, sans-serif;
    font-weight: 400;
    font-size: var(--bbx-fs-md);
    line-height: 1.45;
    color: var(--bbx-gray-700);
    padding: 0 24px;
    display: flex;
    flex-direction: column;
    overflow: hidden;                /* lo scroll sta nelle colonne */
    flex: 1 1 auto;
    min-height: 0;
    height: auto;
    float: none;
    width: 100%;
    max-width: 100%;
    max-height: 100%;
}
/* La catena fino alle colonne: ogni anello deve poter cedere altezza
 * (min-height:0), se no il flex non riesce a comprimere e lo scroll
 * interno non parte mai. */
#md-content .dialog-body--wide > [role="tabpanel"],
#md-content .dialog-body--wide > [role="tabpanel"] > form {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    min-height: 0;
    margin: 0;
}
/* Testata e piede non scorrono: restano ai due estremi. */
#md-content .dialog-body--wide > .md-header,
#md-content .dialog-body--wide > .bbx-form-error,
#md-content .dialog-body--wide > .md-footer {
    flex: 0 0 auto;
}
/* La riga d'errore non e' piu' un `.form-group` con dentro un
   `.text-red.text-small`: e' il componente `.bbx-form-error` (primitives),
   che a vuoto non occupa niente da se'. Qui non serve piu' niente. */

body.bbx-v2 .btn-white,
body.bbx-v2 .btn.btn-white { background: var(--bbx-surface); color: var(--bbx-gray-700); }
/* .btn-link — la TERZIARIA: testo e basta, fondo solo all'hover («Salta»,
 * «Indietro» nell'aiuto in sezione). Non esisteva nella shell: qui un
 * .btn-link cadeva sul base bianco col bordo. `!important` — cosa batte:
 * `body.bbx-v2 .btn` dichiara background/border/color con !important;
 * stessa forma delle skin sorelle .btn-gray / .btn-white. */
body.bbx-v2 .btn-link,
body.bbx-v2 .btn.btn-link { background: transparent; border-color: transparent; color: var(--bbx-gray-600); }
body.bbx-v2 .btn-link:hover,
body.bbx-v2 .btn.btn-link:hover { background: var(--bbx-gray-100); border-color: transparent; color: var(--bbx-gray-800); }
/* .btn-gray — SECONDARIA neutra: azioni di servizio dentro un form (reset,
 * "visualizza" di add_wr). Era una classe SENZA skin: cadeva sul base bianco
 * e in mezzo ai campi sembrava un bottone legacy non stilizzato.
 * (La base `body.bbx-v2 .btn` non ha piu' dal 2026-09-15: le
 * skin vincono per specificita', e nei dialog vince il componente delle
 * primitives, che ha l'id.) */
body.bbx-v2 .btn-gray,
body.bbx-v2 .btn.btn-gray {
    background: var(--bbx-gray-50);
    border-color: var(--bbx-gray-200);
    color: var(--bbx-gray-700);
}
body.bbx-v2 .btn-gray:hover,
body.bbx-v2 .btn.btn-gray:hover {
    background: var(--bbx-gray-100);
    border-color: var(--bbx-gray-300);
    color: var(--bbx-gray-800);
}
body.bbx-v2 .btn-danger,
body.bbx-v2 .btn.btn-danger {
    background: var(--bbx-red);
    border-color: var(--bbx-red);
    color: var(--bbx-ink-inverse);
}
body.bbx-v2 .btn-corner { border-radius: var(--bbx-r-md); }

/* ============================================================
 *  INPUTS (.form-control)
 * ============================================================ */

body.bbx-v2 .form-control {
    padding: 9px 12px;
    font-size: var(--bbx-fs-input);
    /* border/border-radius SENZA !important: grazie a @layer (legacy < v2), la
       regola v2 unlayered batte già il .form-control di Bootstrap legacy senza
       forzare. Lasciare l'!important impediva ai sotto-componenti v2 più
       specifici (es. .bbx-field__input-row > .form-control) di azzerare il bordo
       interno → doppio bordo. (L'!important era nato il 19/04, PRIMA dei layer
       dell'11/05, quando serviva a battere il legacy nello stesso piano.) */
    border: 1px solid var(--bbx-gray-200);
    border-radius: var(--bbx-r-md);
    /* background senza !important: vedi nota in #md-content input.form-control —
       l'input dentro .bbx-field__input-row deve restare trasparente. */
    background: var(--bbx-surface);
    color: var(--bbx-gray-800);
    box-shadow: none;
    line-height: 1.4;
    outline: none;
}
body.bbx-v2 .form-control:focus {
    border-color: var(--bbx-blue-500);
    box-shadow: 0 0 0 3px rgba(0, 128, 246, 0.18);
}

/* ============================================================
 *  CARDS / PANELS (.card / .card-shadow / .card-container)
 * ============================================================ */

body.bbx-v2 .card-shadow,
body.bbx-v2 .card-container.card-shadow {
    /* stessa ricetta card delle pagine (token in primitives) */
    box-shadow: var(--bbx-card-shadow);
    border-radius: var(--bbx-card-radius);
    border: var(--bbx-card-border) !important;
    background: var(--bbx-surface);
}
body.bbx-v2 .card,
body.bbx-v2 .card-container {
    background: var(--bbx-surface);
    border: var(--bbx-card-border);
    border-radius: var(--bbx-card-radius);
}

/* ============================================================
 *  WIDGETS — legacy modal + toastr + popup styling (subtle)
 * ============================================================ */

body.bbx-v2 .md-content {
    background: var(--bbx-surface);
    border-radius: var(--bbx-card-radius);   /* stesso raggio delle card in pagina */
    box-shadow: var(--bbx-shadow-lg);
    border: 1px solid var(--bbx-gray-150);
    font-family: var(--bbx-font);
}
body.bbx-v2 .md-overlay { background: rgba(15, 26, 46, 0.45); /* backdrop-filter: blur(2px); */ }

/* ---- Chiusura (X) — in alto a destra. Vive in #md-modal (fuori da
   #md-content che viene rigenerato a ogni load) quindi persiste; chiama
   removeModal(). z sopra title/footer sticky (1000) del componente. ---- */
body.bbx-v2 #md-modal .md-close {
    position: absolute;
    top: 10px;
    right: 10px;
    z-index: 1002;
    width: 32px;
    height: 32px;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    border: 0;
    border-radius: 8px;
    background: transparent;
    color: var(--bbx-gray-400);
    cursor: pointer;
    transition: background-color .12s ease, color .12s ease;
}
body.bbx-v2 #md-modal .md-close:hover { background: var(--bbx-gray-100); color: var(--bbx-gray-800); }
body.bbx-v2 #md-modal .md-close svg { display: block; }

/* ---- Bottom sheet (mobile ≤600px — breakpoint in modals.js::adaptModal) ----
   adaptModal() aggiunge .md-sheet azzerando gli inline di posizione: il
   layout è governato qui. Specificità #md-modal.md-sheet #md-content.md-content
   per battere le regole del componente (#md-modal #md-content.md-content,
   incluso padding:0 / overflow:hidden / border-radius). ---- */
body.bbx-v2 #md-modal.md-modal.md-sheet {
    top: auto;
    bottom: 0;
    left: 0;
    right: 0;
    width: 100%;
    min-width: 0;
    max-width: none;
    height: auto;
    padding-top: 0;       /* annulla il padding-top:50px mobile del brand (gap fantasma) */
}
body.bbx-v2 #md-modal.md-sheet #md-content.md-content {
    border-radius: var(--bbx-sheet-radius) var(--bbx-sheet-radius) 0 0;
    transform: translateY(100%);             /* slide-up: parte da sotto (transition da md-effect-3) */
}
body.bbx-v2 #md-modal.md-show.md-sheet #md-content.md-content {
    transform: translateY(0);
}
/* Contenuto FULL-BLEED nel sheet: il legacy .dialog-body ha max-width 550px
 * (corretto per la popup centrata, dove È il box a dare la larghezza) che
 * qui lasciava header/campi/footer staccati dal bordo destro del sheet. */
body.bbx-v2 #md-modal.md-sheet #md-content :is(.dialog-body, .alert-body) {
    max-width: none;
    width: 100%;
}
/* Maniglia: NON una banda separata sopra (creava un seam con l'header), ma
   vive DENTRO lo strip del titolo (stesso sfondo bianco sticky). Lo strip
   guadagna spazio in alto e ospita la maniglia come ::before. */
body.bbx-v2 #md-modal.md-sheet #md-content :is(.dialog-body, .alert-body) > .md-header:first-child {
    padding-top: 26px;
}
body.bbx-v2 #md-modal.md-sheet #md-content :is(.dialog-body, .alert-body) > .md-header:first-child::before {
    content: "";
    position: absolute;
    top: 9px;
    left: 50%;
    transform: translateX(-50%);
    width: 40px;
    height: 4px;
    border-radius: 999px;
    background: var(--bbx-gray-200);
    z-index: 1;
}
body.bbx-v2 #md-modal.md-sheet .md-close { top: 13px; right: 13px; }
/* CTA nel sheet: bottoni a larghezza uguale (niente spazio a sinistra). */
body.bbx-v2 #md-modal.md-sheet #md-content .md-footer .btn {
    flex: 1 1 auto;
    width: auto;
    min-width: 0;
}
/* Tre bottoni («Salva», «Chiudi ed emetti gli attestati», «Chiudi») a 390px
 * non stanno su una riga: con `flex: 1 1 0` si schiacciavano uno sull'altro
 * («ChiudiChiudi ed emetti gli atte»). La riga va a capo e la base e' il
 * contenuto, cosi' quello lungo si prende la sua riga. */
body.bbx-v2 #md-modal.md-sheet #md-content .md-footer,
body.bbx-v2 #md-modal.md-sheet #md-content .md-footer__row { flex-wrap: wrap; }
/* Legacy .row gutter margins: annulla nel modale (specificità > .row) */
/* Specificita' bassa apposta (1,0,1): la riga del titolo e il piede del
 * dialog sbordano di -24px con le loro regole (piu' sotto), che prima
 * vincevano su questa solo per !important. Batte comunque Bootstrap e il
 * bridge legacy, che stanno nel layer. */
#md-modal .row {
    margin-left: 0;
    margin-right: 0;
}
/* Legacy .move-right float: restringi nel modale flex context */
body.bbx-v2 #md-modal .move-right {
    float: none;
    margin-left: auto;
}
/* Spacing tra .bbx-field nel dialog/alert-body.
 * ESCLUSI i campi dentro .bbx-field-pair: lì lo spacing è del contenitore
 * (margin sulla pair) e un margin-bottom residuo sul primo campo — con
 * l'align-items:flex-end della pair che allinea i MARGIN-box — spingeva
 * il campo affiancato una riga più in basso. */
body.bbx-v2 #md-modal #md-content :is(.dialog-body, .alert-body) .bbx-field:not(.bbx-field-pair .bbx-field) {
    margin-bottom: 12px;
}
body.bbx-v2 #md-modal #md-content :is(.dialog-body, .alert-body) .bbx-field:last-child {
    margin-bottom: 0;
}
/* Toast refresh. Il selettore #toast-container > .toast-* del legacy
   toastr.css applica un background-image PNG con l'icona (i, ✓, ✗,
   !): senza `background-repeat: no-repeat` l'icona viene TILED su
   tutto il toast. Usiamo #toast-container (stessa specificità del
   legacy) per vincere il cascade. */
#toast-container > .toast {
    border-radius: 10px !important;
    border: 0 !important;
    padding: 12px 16px 12px 46px !important;
    font-family: var(--bbx-font);
    font-size: var(--bbx-fs-md) !important;
    font-weight: 500 !important;
    color: var(--bbx-ink-inverse) !important;
    opacity: 1 !important;
    box-shadow: 0 6px 16px rgba(15, 26, 46, 0.18) !important;
    background-repeat: no-repeat !important;
    background-position: 14px center !important;
    background-size: 20px 20px !important;
    min-width: 260px;
    max-width: 360px;
    margin-bottom: 6px;
}
#toast-container > .toast .toast-message {
    line-height: 1.45;
    word-wrap: break-word;
}
#toast-container > .toast.toast-success { background-color: var(--bbx-color-3) !important; }
#toast-container > .toast.toast-error   { background-color: var(--bbx-red) !important; }
#toast-container > .toast.toast-warning { background-color: var(--bbx-warn-strong) !important; color: var(--bbx-gray-900) !important; }
#toast-container > .toast.toast-info    { background-color: var(--bbx-blue-600) !important; }

/* ============================================================
 *  ANIMATION tweaks — keep legacy transitions snappy
 * ============================================================ */
body.bbx-v2 .flipInX { animation-duration: 160ms; }

/* BS5 `.d-sm-block { display: block !important }` vince sull'inline
   `style="display: none"` che il JS usa per nascondere elementi (es.
   i riepiloghi #graph-holy-container e #graph-out-container in modalità
   panoramica). Ripristiniamo la priorità dell'inline quando è !none.
   Match sia "display: none" sia "display:none" (senza spazio). */
.d-sm-block[style*="display: none"],
.d-sm-block[style*="display:none"],
.d-sm-flex[style*="display: none"],
.d-sm-flex[style*="display:none"],
.d-sm-inline-block[style*="display: none"],
.d-sm-inline-block[style*="display:none"],
.d-sm-inline[style*="display: none"],
.d-sm-inline[style*="display:none"],
.d-sm-table-cell[style*="display: none"],
.d-sm-table-cell[style*="display:none"] {
    display: none !important;
}

/* Blindatura con ID-specificity per i riepiloghi richieste —
   battono qualsiasi regola BS5 / legacy. */
#graph-holy-container[style*="display: none"],
#graph-holy-container[style*="display:none"],
#graph-out-container[style*="display: none"],
#graph-out-container[style*="display:none"] {
    display: none !important;
}

/* ============================================================
 *  MODAL · Componente canonico v2 (#md-modal / #md-content)
 *
 *  Struttura condivisa da TUTTI i popup (154 file in desk/alert/):
 *
 *    #md-modal
 *      └── #md-content.md-content              ← guscio (flex column)
 *            └── .container-fluid.dialog-body  ← body (scrollabile)
 *                │   (alias: .container-fluid.alert-body)
 *                ├── .md-header                ← TESTATA (sticky in alto)
 *                │     ├── .md-header__title   ← «Crea evento / …»
 *                │     └── [.nav-tabs]         ← le tab, dove ci sono
 *                ├── [campi, tab, ecc.]        ← corpo (scorre)
 *                └── .md-footer                ← PIEDE (sticky in basso)
 *                      ├── .btn.btn-primary    ← CTA primaria (a destra)
 *                      └── .btn.btn-orange     ← CTA secondaria
 *
 *  Un dialog a passi ha un piede a righe: .md-footer.md-footer--rows con
 *  un .md-footer__row per passo, e il JS ne mostra uno per volta
 *  (`display: ''`, mai `'block'`).
 *
 *  Layout flex column: title sticky in alto, footer sticky in basso,
 *  middle scroll. Padding orizzontale 24px uniforme su dialog-body →
 *  tutti i campi ancorati agli stessi edge sx/dx.
 *
 *  Entrambi gli alias .dialog-body e .alert-body sono supportati.
 * ============================================================ */

/* Layout flex column del modale — title sticky top, form scrollabile,
   cta sticky bottom. Richiede .md-content con height vincolata e
   overflow-y sul .dialog-body interno.

   IMPORTANTE: .md-modal legacy non ha max-height → .md-content cresce
   fino al contenuto, .dialog-body non scrolla mai (scroll va al window)
   e sticky bottom non attacca. Vincolo qui il modale a max 90vh e poi
   flex:1 sulla .dialog-body per far attivare l'overflow-y. */
#md-modal.md-modal,
.md-modal.md-show {
    max-height: 90vh;
    display: flex;
    flex-direction: column;
}
/* Stato "in caricamento" (.md-modal-loader: la mette e la toglie modals.js
   attorno al load del fragment; nessun altro la legge). Il guscio non
   dipinge nulla — spinner e velo sono il .loader.popup-loader dentro
   #md-content — ma deve avere un'altezza, altrimenti la scatola collassa
   e lo spinner sparisce finche' non arriva il contenuto. Assorbito da
   style_modal.css, che ci metteva anche un fondo bianco a 5px: era il
   secondo layer visibile sotto gli angoli del popup. */
#md-modal.md-modal.md-modal-loader {
    height: 80px;
}
#md-modal #md-content.md-content {
    display: flex;
    flex-direction: column;
    padding: 0;
    overflow: hidden;     /* scroll sta sul .dialog-body */
    max-height: 90vh;
    height: auto;
    min-height: 0;
    flex: 1 1 auto;
}

/* Body del modale — è il contenitore scrollabile. Niente padding
   verticale: title + footer "mangiano" i bordi; le form-group al
   centro hanno padding orizzontale uniforme.

   :not(.bbx-wrdlg-body) — I dialog a DUE COLONNE (oggi: rapportino,
   style_wr_document.css §DLG) non sono "una colonna che scrolla": lo
   scroll sta nelle colonne interne, che scorrono indipendenti. Invece di
   far riscrivere loro display/overflow con !important, la regola si
   restringe qui: chi porta .bbx-wrdlg-body dichiara il proprio layout
   per intero (stessa tipografia/padding, display:flex, overflow:hidden). */
#md-content :is(.dialog-body, .alert-body):not(.bbx-wrdlg-body):not(.dialog-body--wide) {
    font-family: var(--bbx-font), system-ui, sans-serif;
    font-weight: 400;
    font-size: var(--bbx-fs-md);
    line-height: 1.45;
    color: var(--bbx-gray-700);
    padding: 0 24px;
    float: none;
}
/* :not(.bbx-dlg--fill) — il corpo che RIEMPIE il modale a righe flex (oggi:
   popup timesheet) non e' «una colonna che scrolla»: lo scroll sta in un
   figlio, e il corpo prende l'altezza del modale. Stessa tecnica del
   rapportino: la regola si restringe, il modificatore dichiara il suo layout. */
#md-content :is(.dialog-body, .alert-body):not(.bbx-wrdlg-body):not(.dialog-body--wide):not(.bbx-dlg--fill) {
    overflow-y: auto;
    overflow-x: hidden;
    flex: 1 1 auto;
    min-height: 0;
    display: block;
    height: auto;
}
#md-content .dialog-body.bbx-dlg--fill {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    min-height: 0;
    height: auto;
    overflow: hidden;
}

/* (the title strip of the popups that still had a .row/.row-compatible
   first row is gone: every fragment carries .md-header now, 2026-09-22) */

/* ============================================================
 *  MODAL · Header canonico — .md-header
 *
 *  Banda UNICA in cima al modale che raggruppa TITOLO + (opzionale)
 *  TAB BAR, ancorata (sticky) con sfondo condiviso. È il componente di
 *  testata di TUTTI i popup standardizzati: una sola variante con/senza
 *  tab bar (se assente, semplicemente non c'è). La X di chiusura
 *  (.md-close) vive nello shell #md-modal (persiste tra i reload del
 *  #md-content) e galleggia DENTRO questa banda (z 1002 > header 1000),
 *  quindi titolo, tab bar e X condividono lo stesso sfondo ancorato.
 *
 *  Markup canonico (primo figlio della .dialog-body / .alert-body):
 *    <div class="md-header">
 *      <span class="md-header__title">…</span>
 *      <ul class="nav nav-tabs"> … </ul>          ← variante: assente se no tab
 *    </div>
 *
 *  - Variante SENZA tab: l'header chiude con il proprio border-bottom.
 *  - Variante CON tab: il bordo lo dà la tab bar (§ TABS, primitives).
 *  La tab bar non scorre più col contenuto: è ancorata insieme al titolo.
 * ============================================================ */
#md-content :is(.dialog-body, .alert-body) > .md-header {
    position: sticky;
    top: 0;
    z-index: 1000;
    background: var(--bbx-surface);
    margin: 0 -24px;          /* edge-to-edge oltre il padding 24px del body; stacco sotto: vedi §footer */
    padding: 18px 24px 0;
    border-bottom: 1px solid var(--bbx-gray-100);    /* gray-100 — variante senza tab */
    isolation: isolate;
    float: none;
    width: auto;
    height: auto;
}
/* The title: a block with room on the right so it never runs under the X,
   and the gap under it towards the tab bar or the border. Until 2026-09-22
   it was `.row > .col-xs-12 > span.text-big.text-black` (the BS3 strip). */
#md-content .md-header__title {
    display: block;
    margin: 0;
    padding: 0 40px 14px 0;
    font-size: var(--bbx-fs-title-sm);
    font-weight: 600;
    color: var(--bbx-gray-800);
    letter-spacing: -0.2px;
    line-height: 1.3;
}
/* Il CORPO di un popup di solo testo: la spiegazione sotto il titolo.
   Il titolo è la domanda («Vuoi inviare…?»), qui sta quello che serve per
   rispondere — cosa succede, e a chi. Prima non esisteva un posto dove
   metterlo: gli alert hanno solo testata e piede, e chi aveva qualcosa da
   spiegare lo infilava nel TITOLO, che così diventava un paragrafo in
   corpo 18 semibold (#115). */
#md-content .md-text {
    margin: 0;
    /* 2 e non 14: fra il filetto della testata e questo blocco il telaio
       mette gia' 16px di suo, e sommandoci un padding pieno il testo
       partiva a 30px dalla riga — misurato, non a occhio. */
    padding: 2px 0 10px;
    font-size: var(--bbx-fs-md);
    line-height: 1.5;
    color: var(--bbx-gray-700);
    /* Gli a capo arrivano come veri «a capo», non come <br>: getBB() passa
       ogni parametro da strip_tags(), quindi in un alert l'HTML non esiste —
       ci si era già cascati scrivendoci dentro <br> e <b>, spariti senza un
       segno. Così chi scrive il testo decide dove va a capo. */
    white-space: pre-line;
}
#md-content .md-text:empty { display: none; }

/* Variante CON tab bar: il bordo lo cede alla tab bar (che ha il suo da
   § TABS); la tab bar è edge-to-edge dentro la banda. */
#md-content .md-header:has(.nav-tabs) { border-bottom: 0; }
#md-content .md-header .nav-tabs {
    margin: 0 -24px 0;
    padding: 0 24px;
    clear: both;
}
/* Pannelli .tab-content vestigiali (vuoti, ids #t1… toggle Bootstrap)
   eventualmente rimasti nel wrapper [role=tabpanel] inglobato nell'header:
   non devono occupare spazio nella banda. Il contenuto vero vive sempre
   FUORI dall'header, nell'area scrollabile. */
#md-content .md-header .tab-content { display: none; }

/* Labels (.form-group-text.text-medium) uniformi: 12px/500/gray-700 */
#md-content .form-group-text,
#md-content .form-group-text.text-medium,
#md-content .form-group-text.text-black {
    font-size: var(--bbx-fs-sm);
    font-weight: 500;
    color: var(--bbx-gray-600);
    line-height: 1.4;
    margin: 0 0 4px 0;
    padding: 0;
}

/* Il ponte BS3 dentro al popup — RIMOSSO il 2026-09-23.
   Erano le regole che rimettevano in riga i campi scritti con la griglia di
   Bootstrap 3: la spaziatura di `.form-group`, la pseudo-tabella
   `.form-group > .table-head > .table-cell` (label sopra, campo sotto) e le
   label nelle celle. Nessun fragment di `desk/alert/` scrive piu' una di
   quelle classi: i campi sono `.bbx-field`, la riga d'errore e'
   `.bbx-form-error`, la label di un tab e' `.bbx-tab-label`. Misurato
   aprendo tutti e 154 i popup (`dialog-frame.mjs`, che conta anche le classi
   del ponte rimaste a schermo). */

/* Footer strip (CTA) — sticky bottom, bianco, border-top, allineato destra.
   Riordina i due bottoni con row-reverse (DOM: Aggiungi, Cancella →
   visual: Cancella | Aggiungi). z-index alto per stare SOPRA mappe
   Google Maps / Mapbox (che creano layer absolutely posizionati).
   SELETTORE DESCENDANT (non >): alcuni popup (expense, invoice, bonus)
   mettono il piede dentro <form>, non come figlio diretto di .dialog-body.
   Markup: <div class="md-footer"> coi bottoni figli diretti (il primo nel DOM
   e' la primaria, e finisce a destra); un dialog a passi ha piu' righe,
   .md-footer--rows > .md-footer__row, e il JS ne mostra una per volta. */
#md-content :is(.dialog-body, .alert-body) .md-footer {
    position: sticky;
    bottom: 0;
    z-index: 1000;
    background: var(--bbx-surface);
    margin: 0 -24px;          /* stacco verticale: vedi regola sotto */
    padding: 14px 24px;
    border-top: 1px solid var(--bbx-gray-100);       /* gray-100 */
    width: calc(100% + 48px);
    display: flex;
    flex-direction: row-reverse;
    justify-content: flex-start;
    align-items: center;
    gap: 8px;
    isolation: isolate;                  /* nuovo stacking context */
}
#md-content :is(.dialog-body, .alert-body) .md-footer--rows { display: block; }
#md-content :is(.dialog-body, .alert-body) .md-footer__row {
    display: flex;
    flex-direction: row-reverse;
    justify-content: flex-start;
    align-items: center;
    gap: 8px;
}
/* Stacco verticale header/footer ↔ contenuto.
   Sta QUI e non nelle regole sopra perché vale per i dialog a COLONNA
   SINGOLA, dove il contenuto sono campi che non devono attaccarsi ai
   bordi. Nei dialog a due colonne (.bbx-wrdlg-body) le colonne sono
   superfici piene — una col fondo grigio e il bordo di separazione — e
   con questi 16px restavano staccate da header e footer, come se il
   contenuto fosse tagliato prima di arrivarci. */
/* `.dialog-body--wide` era escluso: il suo contenuto restava incollato sotto le
   tab mentre in basso avanzava aria morta. Le due colonne sono comunque campi,
   non superfici piene come nel rapportino (che resta escluso). */
#md-content :is(.dialog-body, .alert-body):not(.bbx-wrdlg-body) > .md-header {
    margin-bottom: 16px;
}
#md-content :is(.dialog-body, .alert-body):not(.bbx-wrdlg-body) .md-footer {
    margin-top: 16px;
}

/* Two-column dialogs (.dialog-body--wide): the columns SCROLL, and a
   scrolling surface must reach the header and the footer — otherwise what
   scrolls is cut 16px before them, and the rule between the columns stops
   short of both. So the column takes the 16px of header/footer margin back
   with a negative margin and keeps the same 16px INSIDE, as padding: at
   rest nothing moves, scrolled content clips on the header's and footer's
   edge, the divider touches them. What does not scroll (a toolbar, a note
   above the columns) keeps its spacing as it was. */
#md-content .dialog-body--wide .bbx-split--wide > .bbx-split__main,
#md-content .dialog-body--wide .bbx-split--wide > .bbx-split__side,
#md-content .dialog-body--wide .bbx-chat-host > .bbx-split__side {
    margin-top: -16px;
    margin-bottom: -16px;
    padding-top: 16px;
    padding-bottom: 16px;
}
/* The conversation column: the scroller is .bbx-chat__flow inside it, so the
   top padding goes there (the messages clip on the header's edge) and the
   column keeps only the bottom one, under the composer. */
#md-content .dialog-body--wide .bbx-chat-host > .bbx-split__main {
    margin-top: -16px;
    margin-bottom: -16px;
    padding-bottom: 16px;
}
/* the chat columns are sized with height:100% (primitives §CHAT), so the
   negative margins alone would only shift them up: they must grow by the
   two margins to reach the footer as well */
#md-content .dialog-body--wide .bbx-chat-host > .bbx-split__side,
#md-content .dialog-body--wide .bbx-chat-host > .bbx-split__main {
    height: calc(100% + 32px);
}
#md-content .dialog-body--wide .bbx-chat-host .bbx-chat__flow { padding-top: 16px; }
/* Stacked (one column, the body scrolls): the columns are plain blocks
   again and the header/footer margins do their job. */
@media (max-width: 980px) {
    #md-content .dialog-body--wide .bbx-split--wide > .bbx-split__main,
    #md-content .dialog-body--wide .bbx-split--wide > .bbx-split__side {
        margin-top: 0;
        margin-bottom: 0;
        padding-bottom: 0;
    }
    #md-content .dialog-body--wide .bbx-split--wide > .bbx-split__main { padding-top: 0; }
}


/* ============================================================
 *  MODAL · Popup di SOLA conferma (titolo/messaggio + azioni, SENZA
 *  contenuto centrale: alert_safe, dialog, alert, …).
 *
 *  AUTO-RILEVATI via :has(): se la .alert-body NON contiene campi/form/tab/
 *  header, è un "ask". In quei casi il title-strip (border-bottom) e il footer
 *  (border-top) incorniciavano un'AREA-CONTENUTO VUOTA in mezzo (~50px con due
 *  righe) → sembrava previsto spazio per contenuto che non c'è. Qui tolgo le
 *  due righe e stringo lo spazio: messaggio e pulsanti restano vicini, modale
 *  alto quanto serve. Nessuna modifica al markup — vale per tutti questi popup.
 * ============================================================ */
#md-content .alert-body:not(:has(.bbx-field, .bbx-form-error, .form-control, textarea, select, input, .nav-tabs)) .md-footer {
    border-top: 0 !important;
    margin-top: 4px !important;
    padding-top: 6px !important;
}

/* Bottoni nel footer — dimensioni v2, flat, no float.
   Include anche input[type=submit].btn.btn-primary (usato in
   dialog_new_expense e simili).

   ATTENZIONE al raggio: i selettori .btn-primary NON sono limitati al piede,
   pescano ogni primary del CORPO del dialog e ne forzano la taglia a 36px con
   !important — taglia dichiarata compresa. È voluto (in una ventina di dialog
   la CTA sta fuori dal .md-footer), ma vuol dire che un primary
   piccolo dentro una tabella va riportato in scala a parte: vedi
   `.bbx-datagrid .btn.btn-primary` in style_bbx_primitives.css §E.0b-bis. */
/* Larghezza: nel piede i bottoni stanno in riga, ad auto. */
#md-content .md-footer .btn,
#md-content .md-footer input[type="submit"].btn { width: auto; flex: 0 0 auto; }

#md-content .md-footer .btn,
#md-content .md-footer input[type="submit"].btn,
#md-content :is(.dialog-body, .alert-body) .btn.btn-primary,
#md-content :is(.dialog-body, .alert-body) input[type="submit"].btn.btn-primary,
#md-content :is(.dialog-body, .alert-body) .btn.btn-orange,
#md-content :is(.dialog-body, .alert-body) .btn.cancel-button {
    height: 36px !important;
    padding: 0 16px;
    font-size: var(--bbx-fs-md) !important;
    font-weight: 600 !important;
    border-radius: var(--bbx-r-md) !important;
    min-width: 100px;
    line-height: 34px !important;
    margin: 0 !important;
    float: none !important;
    font-family: var(--bbx-font-sans) !important;
    text-align: center;
    cursor: pointer;
    -webkit-appearance: none !important;
    appearance: none;
}
/* Primary fill specifico su <input type=submit> (BS default ha styling
 * nativo user-agent — overrido esplicitamente). */
#md-content :is(.dialog-body, .alert-body) input[type="submit"].btn.btn-primary {
    background: var(--bbx-accent-fill);
    border: 1px solid var(--bbx-blue-500);
    color: var(--bbx-ink-inverse) !important;
}
#md-content :is(.dialog-body, .alert-body) input[type="submit"].btn.btn-primary:hover {
    background: var(--bbx-accent-hover) !important;
    border-color: var(--bbx-blue-600) !important;
}

/* Nav tabs dentro #md-content → lo STILE dei tab è nel blocco §6 unificato
 * di style_bbx_primitives.css + indicatore animato bbx-tabs.js. Qui solo il
 * POSIZIONAMENTO: la tab bar di primo livello fa parte dell'header, subito
 * SOTTO il titolo, edge-to-edge. In flusso (niente sticky con offset magico
 * fragile): scorre col contenuto. */
/* Il titolo .row-compatible è float:left: il wrapper [role=tabpanel] (div
   nudo) gli finirebbe ACCANTO a destra, comprimendo la flex ul a ~0px. Lo
   forziamo sotto al titolo a piena larghezza (clear:both + width:100%),
   come fanno le .form-group (width:100%). */
/* :not(.dialog-body--wide) — nei dialog a DUE COLONNE il titolo non è
 * float:left e il wrapper deve restare un anello FLEX della catena che porta
 * l'altezza alle colonne: `display:block` qui la spezzava. Stessa specificità
 * della regola del dialog a due colonne (1,2,0), ma questa viene dopo nel
 * file e vinceva per ordine — da cui l'esclusione invece di un !important. */
#md-content :is(.dialog-body, .alert-body):not(.dialog-body--wide) > [role="tabpanel"] {
    clear: both;
    width: 100%;
    display: block;
}
#md-content :is(.dialog-body, .alert-body) > [role="tabpanel"] > .nav-tabs,
#md-content :is(.dialog-body, .alert-body) > .nav-tabs {
    clear: both;                     /* anche se la nav-tabs è figlia diretta della body */
    margin: 0 -24px 12px;
    padding: 0 24px !important;
}
/* Niente gap/doppio bordo tra titolo e tab bar: quando lo strip del titolo è
 * seguito da una tab bar di primo livello, cede a essa il bordo inferiore
 * (la .nav-tabs ha già il suo border-bottom da §6). */
#md-content :is(.dialog-body, .alert-body):has(> [role="tabpanel"] > .nav-tabs) > :is(.row-compatible, .row):first-child,
#md-content :is(.dialog-body, .alert-body):has(> .nav-tabs) > :is(.row-compatible, .row):first-child {
    border-bottom: 0;
    margin-bottom: 0 !important;
}

/* ----------------------------------------------------------------
 *  LA GRIGLIA BS3 DENTRO AL POPUP — RIMOSSA il 2026-09-23
 *
 *  Erano ~350 righe che rimettevano in ordine i campi scritti con il ponte:
 *  `.row`/`.col-xs-*` resi flex, la coppia label|campo di
 *  `.form-group.row > .col-xs-4 + .col-xs-8` impilata, la pseudo-tabella
 *  `.table-head > .table-cell`, le righe con l'interruttore rimesse in
 *  linea, le label di riserva `.text-medium.text-black`. Quasi tutte con
 *  `!important` e `:has()`: erano il prezzo di vestire un markup che non
 *  era il nostro.
 *
 *  Nessun fragment di `desk/alert/` scrive piu' una di quelle classi — i
 *  campi sono `.bbx-field`, il piede `.md-footer`, la testata `.md-header`,
 *  la riga d'errore `.bbx-form-error`, la label di un tab `.bbx-tab-label`.
 *  Misurato aprendo tutti e 154 i popup: `dialog-frame.mjs` conta anche le
 *  classi del ponte rimaste a schermo, e sono zero.
 * ---------------------------------------------------------------- */

/* Textarea nel modale: stile v2 coerente con .form-control, ma più alta */
#md-content textarea.form-control {
    font-family: var(--bbx-font-sans);
    font-size: var(--bbx-fs-input);
    color: var(--bbx-gray-800);
    background: var(--bbx-surface);
    border: 1px solid var(--bbx-gray-200);
    border-radius: var(--bbx-r-md);
    padding: 9px 12px;
    width: 100%;
    min-height: 80px;
    resize: vertical;
    box-shadow: none;
    transition: border-color .15s, box-shadow .15s;
}
#md-content textarea.form-control:focus {
    border-color: var(--bbx-blue-500) !important;
    box-shadow: var(--bbx-focus-ring) !important;
    outline: none !important;
}
/* RIMOSSA (2026-08-25) la "blindatura" su #date e #h-from-container, che li
   forzava a `display:flex !important`. Serviva a mettere in riga i loro figli
   .col-xs-6 del markup legacy: da quando quei dialog (nuova/modifica richiesta,
   crea evento) usano .bbx-field-pair NESSUN #date/#h-from-container ha più
   figli .col-xs-6, e il flex rimasto trasformava gli altri figli in flex item
   shrink-to-fit — il primo a caderci è lo stepper .bbx-stepper "Durata", che
   si stringeva a min-content e impilava [-] slider [+] in verticale.
   (Il selettore prendeva anche gli <input id="date"> di checkin/checkout.) */

/* La pseudo-tabella dei campi (`.table-head > .table-cell`, la riga a quattro
   celle, il pattern annidato e lo stacking delle label) — RIMOSSA il
   2026-09-23 con il resto della griglia BS3: nessun popup la scrive piu'. */

/* Campi form nel modale — allineati 1:1 alle v2 primitives
   (#body-content .form-control / .bbx-input): altezza auto, padding
   8px 12px, radius --bbx-r-md (12px), border gray-200, focus ring v2.

   :not(.bbx-dense) — deroga di DENSITÀ per i campi dentro le righe di un
   repeater (oggi: giornate del rapportino), dove la riga è una griglia di
   4-5 input e il padding standard la fa esplodere. Marcatore esplicito
   sull'input: chi lo mette dichiara la propria altezza/padding senza
   !important. Tutto il resto (border, radius, focus ring, font) resta
   condiviso: la deroga è solo sulle misure. */
/* (a) PELLE — vale per TUTTI, .bbx-dense compreso: bordo, raggio, colore,
       font-family, transizione. Nessuna misura qui. */
#md-content input.form-control,
#md-content input.form-control.flatpickr-input,
#md-content select.form-control,
#md-content select.select-bb,
#md-content .form-select {
    font-family: var(--bbx-font-sans);
    color: var(--bbx-gray-800) !important;
    /* background SENZA !important: dentro .bbx-field__input-row l'input deve
       restare trasparente (lo sfondo bianco + radius lo porta il box); con
       !important l'input bianco a angoli quadrati tagliava l'angolo arrotondato
       del box a destra. Lo strip (background:transparent, 1,2,0) ora vince. */
    background-color: var(--bbx-surface);
    /* border/border-radius SENZA !important (come per body.bbx-v2 .form-control):
       grazie a @layer (legacy < v2) la regola v2 batte già il legacy senza
       forzare; l'!important impediva ai sotto-componenti più specifici
       (.bbx-field__input-row > .form-control, 1,2,0) di azzerare il bordo
       interno → doppio bordo nel prefix/suffix-select.
       TOKEN e non un hex: era `#d6dbe3` (gray-200) a mano, mentre
       .bbx-field__input-row e #body-content .form-control usano
       --bbx-input-border (gray-300). Nello stesso form i campi nudi
       risultavano più chiari di quelli con suffisso accanto. */
    border: var(--bbx-input-border);
    border-radius: var(--bbx-r-md);
    width: 100%;
    box-sizing: border-box;
    transition: border-color .15s, box-shadow .15s;
}
/* (b) MISURE — altezza/padding/tipografia standard, saltate da .bbx-dense. */
#md-content input.form-control:not(.bbx-dense),
#md-content input.form-control.flatpickr-input:not(.bbx-dense),
#md-content select.form-control:not(.bbx-dense),
#md-content select.select-bb:not(.bbx-dense),
#md-content .form-select:not(.bbx-dense) {
    height: auto;
    min-height: 0 !important;
    padding: 9px 12px !important;
    line-height: 1.4;
    font-size: var(--bbx-fs-input) !important;
}
#md-content input.form-control:focus,
#md-content select.form-control:focus,
#md-content select.select-bb:focus,
#md-content textarea.form-control:focus,
.bbx-bottom-sheet select.form-control:focus {
    border-color: var(--bbx-blue-500);                              /* blue-500 */
    box-shadow: var(--bbx-focus-ring);
    outline: none !important;
}
#md-content select.form-control,
#md-content select.select-bb,
#md-content .form-select,
/* stesse select v2 nel bottom-sheet (filtri mobile): fuori da #md-content
 * non prendevano lo scope del modale e restavano SENZA chevron */
.bbx-bottom-sheet select.form-control {
    padding-right: 32px;    /* spazio per il caret */
    cursor: pointer;
    /* chevron custom: stesso SVG delle primitives, forzato qui
     * perché il modale usa #md-content scope che vince sul body. */
    -webkit-appearance: none !important;
    appearance: none;
    background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23616b7b' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'%3e%3cpath d='M4 6l4 4 4-4'/%3e%3c/svg%3e") !important;
    background-repeat: no-repeat !important;
    background-position: right 10px center !important;
    background-size: 14px !important;
}
#md-content textarea.form-control {
    min-height: 80px;
    resize: vertical;
}
#md-content input.form-control::placeholder,
#md-content textarea.form-control::placeholder { color: var(--bbx-gray-400); }



/* ============================================================
 * Card commenti FLOTTANTE nel popup render-timesheet.
 * #table-comments viene spostata dal dialog in #md-content e vive
 * come overlay assoluto ancorato a #md-modal (positioned): default
 * in basso a destra, trascinabile dalla testata (drag inline nel
 * dialog, con clamp dentro il popup). Nel bottom-sheet mobile resta
 * nel flusso (niente overlay su schermi piccoli).
 * ============================================================ */
body.bbx-v2 #md-content .bbx-ts-comments {
    position: absolute;
    right: 22px;
    bottom: 76px;   /* sopra la fascia azioni del popup */
    z-index: 30;
    width: 330px;
    max-height: 60%;
    display: flex;
    flex-direction: column;
    background: var(--bbx-surface);
    border: 1px solid var(--bbx-gray-150);
    border-radius: var(--bbx-r-lg);
    box-shadow: 0 6px 24px rgba(33, 43, 54, .16), 0 1px 3px rgba(33, 43, 54, .1);
    overflow: hidden;
    /* la card è figlia di #md-content: la regola generica dei dialog le
     * appioppa 24px di padding che si SOMMANO a quelli interni → zero */
    padding: 0;
}
body.bbx-v2 #md-content .bbx-ts-comments__head {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 9px 12px;
    border-bottom: 1px solid var(--bbx-gray-100);
    background: var(--bbx-surface);
    user-select: none;
}
body.bbx-v2 #md-content .bbx-ts-comments__title {
    font-size: var(--bbx-fs-md);
    font-weight: 700;
    color: var(--bbx-gray-600);
}
body.bbx-v2 #md-content .bbx-ts-comments__title::first-letter { text-transform: uppercase; }
/* compose in colonna: campo a tutta larghezza, Invia sotto a destra.
 * Sta in FONDO alla card (la lista dei commenti gli scorre sopra) →
 * separatore in alto e altezza non comprimibile. */
body.bbx-v2 #md-content .bbx-ts-comments__compose {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 8px;
    padding: 10px 12px;
    flex: 0 0 auto;
    border-top: 1px solid var(--bbx-gray-150);   /* separatore dalla lista dei commenti */
}
body.bbx-v2 #md-content .bbx-ts-comments__compose textarea {
    width: 100%;
    min-height: 34px;
    max-height: 90px;
    resize: vertical;
}
body.bbx-v2 #md-content .bbx-ts-comments__compose .btn { align-self: flex-end; }
body.bbx-v2 #md-content .bbx-ts-comments__list {
    flex: 1 1 auto;      /* prende lo spazio tra testata e campo di scrittura */
    overflow-y: auto;
    padding: 10px 12px;
    min-height: 0;
}
/* senza commenti la lista non deve lasciare una fascia vuota */
body.bbx-v2 #md-content .bbx-ts-comments__list:empty { padding: 0; }
/* bottom-sheet mobile: aperta, la card prende TUTTO il foglio — una
 * pagina interna con la sua testata, la lista che scorre e il campo in
 * fondo; la X torna al cartellino. Nel flusso finiva in coda al popup,
 * dopo la tabella e sotto il piede sticky, e non si leggeva. Il popup
 * qui e' a riempimento (scorre #table-container, non #md-content), quindi
 * inset:0 sul #md-content posizionato e' il foglio intero. */
body.bbx-v2 #md-modal.md-sheet #md-content .bbx-ts-comments {
    inset: 0;
    width: auto;
    max-height: none;
    z-index: 40;   /* sopra il piede sticky del dialog */
    border: 0;
    border-radius: var(--bbx-sheet-radius) var(--bbx-sheet-radius) 0 0;
    box-shadow: none;
}
body.bbx-v2 #md-modal.md-sheet #md-content .bbx-ts-comments__head { padding: 6px 4px 6px 16px; }
/* la X e' un bersaglio da dito (§TOCCO) */
body.bbx-v2 #md-modal.md-sheet #md-content .bbx-ts-comments__close {
    width: 40px;
    height: 40px;
    align-items: center;
    justify-content: center;
}
body.bbx-v2 #md-modal.md-sheet #md-content .bbx-ts-comments__list { padding: 10px 16px; }
body.bbx-v2 #md-modal.md-sheet #md-content .bbx-ts-comments__compose { padding: 10px 16px 16px; }
/* commenti aperti sul telefono: il piede del dialog e la X del foglio
 * starebbero sopra la card (piede sticky, X del guscio): si spengono.
 * La classe la mette il dialog all'apertura e la toglie alla chiusura. */
body.bbx-v2 #md-modal.md-sheet.is-ts-comments .md-close,
body.bbx-v2 #md-modal.md-sheet.is-ts-comments #md-content .md-footer { visibility: hidden; }
/* il fumetto chiuso resta sopra il piede (69 sul telefono, non 60) */
body.bbx-v2 #md-modal.md-sheet #md-content .bbx-ts-fab { right: 16px; bottom: 84px; }

/* ============================================================
 * Render TIMESHEET nel popup (.bbx-tsr) — la TESTATA del cartellino
 * (chi, periodo, KPI, note, rimborsi) e la card dei commenti. La
 * tabella dei giorni NON e' piu' qui: e' il componente condiviso con
 * Dati d'ingresso (bbx-presence.js + primitives §PRESENCE, scope
 * `.bbx-presence` dentro #md-content), lo stesso DOM e lo stesso CSS;
 * il popup gli passa solo l'offset dello sticky (--bbx-presence-top,
 * l'altezza della testata qui sotto, misurata dal dialog).
 * ============================================================ */
/* La testata: chi a sinistra (48%), KPI e note a destra (52%) — le
 * stesse proporzioni della vecchia <table>, senza le sue righe vuote. */
#md-content .bbx-tsr .bbx-tsr-head { display: flex; align-items: flex-start; gap: 16px; }
#md-content .bbx-tsr .bbx-tsr-who { flex: 0 0 48%; min-width: 0; }
#md-content .bbx-tsr .bbx-tsr-side { flex: 1 1 0; min-width: 0; }
#md-content .bbx-tsr .bbx-tsr-who__name {
    font-size: var(--bbx-fs-2xl);
    font-weight: 600;
    color: var(--bbx-gray-900);
    line-height: 1.2;
    overflow-wrap: anywhere;
}
#md-content .bbx-tsr .bbx-tsr-who__sub { font-size: var(--bbx-fs-sm); color: var(--bbx-gray-700); margin-top: 2px; }
#md-content .bbx-tsr .bbx-tsr-who__sub--muted { color: var(--bbx-gray-500); }
#md-content .bbx-tsr .bbx-tsr-kpis { display: flex; align-items: flex-start; }
#md-content .bbx-tsr .bbx-tsr-kpis > .bbx-tsr-kpi { flex: 1 1 0; min-width: 0; }
/* le note sotto i KPI: maggiorazioni, straordinari, nota, note spese, errori */
#md-content .bbx-tsr .bbx-tsr-info {
    margin-top: 6px;
    font-size: var(--bbx-fs-sm);
    color: var(--bbx-gray-600);
    line-height: 1.4;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 4px 6px;
}
#md-content .bbx-tsr .bbx-tsr-info--list { display: block; }
#md-content .bbx-tsr .bbx-tsr-info--danger { color: var(--bbx-danger-ink); font-weight: 600; }
#md-content .bbx-tsr .bbx-tsr-info__lbl { font-weight: 600; color: var(--bbx-gray-800); }
#md-content .bbx-tsr .bbx-tsr-info__row { display: flex; gap: 12px; padding: 2px 0; }
#md-content .bbx-tsr .bbx-tsr-info__k { color: var(--bbx-gray-500); min-width: 0; overflow-wrap: anywhere; }
#md-content .bbx-tsr .bbx-tsr-info__v { color: var(--bbx-gray-800); font-weight: 600; white-space: nowrap; }
/* la percentuale come chip tenue: azzurra per le maggiorazioni, verde per gli straordinari */
#md-content .bbx-tsr .bbx-tsr-tag {
    display: inline-block;
    padding: 1px 6px;
    border-radius: var(--bbx-r-sm);
    font-size: var(--bbx-fs-xs);
    font-weight: 600;
    color: var(--bbx-gray-800);
    background: var(--bbx-blue-50);
}
#md-content .bbx-tsr .bbx-tsr-tag--overtime { background: var(--bbx-success-soft); }

/* ---- FAB commenti nel popup render-timesheet -------------------
 *  A riposo la card è chiusa: resta il fumetto (con conteggio) e
 *  l'anteprima dell'ultimo commento. Click → si apre la card. */
body.bbx-v2 #md-content .bbx-ts-comments.is-closed { display: none; }
/* coda di scroll: si arriva OLTRE il FAB, che non copre mai le ultime
 * righe della tabella (niente più drag della card: si chiude e basta) */
body.bbx-v2 #md-content #table-container { padding-bottom: 140px; }
body.bbx-v2 #md-content .bbx-ts-fab {
    position: absolute;
    right: 22px;
    bottom: 76px;   /* sopra la fascia azioni del popup (Scarica/Cancella) */
    z-index: 30;
    display: flex;
    align-items: center;
    justify-content: flex-end;   /* fumetto SEMPRE a destra anche se il box viene stirato */
    gap: 10px;
    cursor: pointer;
    max-width: 380px;
    /* una regola generica di #md-content stira i figli a width:100% →
     * senza anteprima il fumetto finiva a metà popup */
    width: max-content;
    /* …e gli dà 24px di padding: il fumetto risultava rientrato di 24px
     * rispetto a right/bottom dichiarati qui */
    padding: 0;
}
body.bbx-v2 #md-content .bbx-ts-fab__btn {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    flex: 0 0 auto;
    border-radius: 999px;
    background: var(--bbx-accent-fill);
    color: var(--bbx-ink-inverse);
    box-shadow: 0 6px 18px rgba(0, 128, 246, .35);
    order: 2;   /* fumetto a destra, anteprima alla sua sinistra */
}
body.bbx-v2 #md-content .bbx-ts-fab:hover .bbx-ts-fab__btn { background: var(--bbx-accent-hover); }
/* anteprima: testo dell'ultimo commento (clampato) e, se ce ne sono
 * altri, il conteggio su una riga sotto — NIENTE badge numerico sul
 * fumetto (sembrava una notifica di commenti nuovi) */
body.bbx-v2 #md-content .bbx-ts-fab__preview {
    order: 1;
    background: var(--bbx-surface);
    border: 1px solid var(--bbx-gray-150);
    border-radius: var(--bbx-r-lg);
    box-shadow: 0 4px 14px rgba(33, 43, 54, .12);
    padding: 8px 12px;
    font-size: var(--bbx-fs-sm);
    color: var(--bbx-gray-500);
    line-height: 1.35;
    overflow: hidden;
}
body.bbx-v2 #md-content .bbx-ts-fab__ptext {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
body.bbx-v2 #md-content .bbx-ts-fab__ptext b { color: var(--bbx-gray-800); font-weight: 700; }
body.bbx-v2 #md-content .bbx-ts-fab__more {
    display: block;
    margin-top: 3px;
    font-size: var(--bbx-fs-xs);
    font-weight: 600;
    color: var(--bbx-gray-400);
}
/* X di chiusura nella testata della card */
body.bbx-v2 #md-content .bbx-ts-comments__close {
    margin-left: auto;
    display: inline-flex;
    color: var(--bbx-gray-400);
    cursor: pointer;
    padding: 2px;
    border-radius: 6px;
}
body.bbx-v2 #md-content .bbx-ts-comments__close:hover { background: var(--bbx-gray-100); color: var(--bbx-gray-600); }
body.bbx-v2 #md-content .bbx-ts-comments__close svg { display: block; }

/* ---- Item commento v2 (.bbx-tsc) ------------------------------
 *  Avatar small (28px) in linea col nome, data piccola tenue, kebab
 *  elimina a destra, testo sotto. */
body.bbx-v2 #md-content .bbx-tsc { padding: 8px 0 2px; border-top: 1px solid var(--bbx-gray-100); }
body.bbx-v2 #md-content .bbx-tsc:first-child { border-top: 0; }
body.bbx-v2 #md-content .bbx-tsc__row { display: flex; align-items: center; gap: 8px; min-width: 0; }
body.bbx-v2 #md-content .bbx-tsc__avatar {
    width: 28px;
    height: 28px;
    flex: 0 0 auto;
    border-radius: 999px;
    background-color: var(--bbx-gray-100);
    background-size: cover;
    background-position: center;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}
body.bbx-v2 #md-content .bbx-tsc__avatar--init {
    font-size: var(--bbx-fs-xs);
    font-weight: 700;
    color: var(--bbx-gray-500);
    letter-spacing: .3px;
}
body.bbx-v2 #md-content .bbx-tsc__name {
    font-size: var(--bbx-fs-md);
    font-weight: 700;
    color: var(--bbx-gray-800);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    min-width: 0;
}
body.bbx-v2 #md-content .bbx-tsc__date {
    font-size: var(--bbx-fs-xs);
    color: var(--bbx-gray-400);
    white-space: nowrap;
    flex: 0 0 auto;
}
body.bbx-v2 #md-content .bbx-tsc__kebab { margin-left: auto; flex: 0 0 auto; }
body.bbx-v2 #md-content .bbx-tsc__kebab > summary.bbx-kebab__trigger { width: 24px; height: 24px; }
body.bbx-v2 #md-content .bbx-tsc__text {
    margin: 4px 0 4px 36px;   /* rientro sotto il nome (avatar 28 + gap 8) */
    font-size: var(--bbx-fs-md);
    color: var(--bbx-gray-600);
    line-height: 1.4;
    word-break: break-word;
}

/* ---- KPI testata (versione modal della number-table--kpi) --- */
#md-content .bbx-tsr .bbx-tsr-kpi { padding: 2px 6px 2px 0; }
#md-content .bbx-tsr .bbx-tsr-kpi__title {
    font-size: var(--bbx-fs-xs);
    font-weight: 700;
    letter-spacing: .4px;
    text-transform: uppercase;
    color: var(--bbx-gray-400);
}
#md-content .bbx-tsr .bbx-tsr-kpi__sub { font-size: var(--bbx-fs-xs); color: var(--bbx-gray-400); margin-top: 1px; }
#md-content .bbx-tsr .bbx-tsr-kpi__value {
    font-family: var(--bbx-font-mono);
    font-variant-numeric: tabular-nums;
    font-size: var(--bbx-fs-title-lg);
    font-weight: 600;
    color: var(--bbx-gray-800);
    margin-top: 1px;
}
#md-content .bbx-tsr .bbx-tsr-kpi__u { font-size: var(--bbx-fs-sm); color: inherit; }

/* Stato vuoto del popup cartellino: quando il payload non c'e' (approvato
 * mai compilato, o `value` vuoto) al posto della tabella va .bbx-empty.
 * Il componente si centra al proprio interno, ma il suo min-height (320px)
 * e' meno dell'altezza del popup e da solo resterebbe appiccicato in alto
 * con mezzo riquadro bianco sotto. Si centra il contenitore, che l'altezza
 * ce l'ha dal flex; la classe la mette il PHP, che gia' sa se e' vuoto. */
#md-content #table-container.is-empty {
    display: flex;
    align-items: center;
    justify-content: center;
}

/* STICKY dentro lo scroll del popup (#table-container, overflow-y:auto):
 * la testata del cartellino resta in cima; la tabella dei giorni aggancia
 * le sue bande (colonne, mese) sotto di lei via --bbx-presence-top. */
#md-content .bbx-tsr .bbx-tsr-headwrap {
    position: sticky;
    top: 0;
    z-index: 8;
    background: var(--bbx-surface);
    /* respiro sopra la testata: il padding vive DENTRO il wrap sticky
     * (sfondo bianco) così resta anche a scroll; --bbx-presence-top è
     * misurata da offsetHeight quindi gli offset delle bande si adattano */
    padding-top: 14px;
    padding-bottom: 6px;
    border-bottom: 1px solid var(--bbx-gray-150);
    margin-bottom: 6px;
}

/* Il telaio del popup timesheet: due righe flex. Il render prende
 * l'altezza che resta e scorre dentro #table-container; il piede e' quello
 * condiviso dei dialog; il corpo porta .bbx-dlg--fill (sopra). (Era un display:table con l'altezza dello scroll
 * calcolata da resizeTimesheet() a ogni resize.) */
#md-content #timesheet-render { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
#md-content #table-container { flex: 1 1 auto; min-height: 0; width: 100%; overflow-y: auto; }

/* periodo del timesheet nella testata */
#md-content .bbx-tsr .bbx-tsr-period {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    margin-top: 4px;
    font-size: var(--bbx-fs-sm);
    font-weight: 600;
    color: var(--bbx-gray-500);
}
#md-content .bbx-tsr .bbx-tsr-period svg { display: block; color: var(--bbx-gray-400); }

/* On the phone the two columns of the head (who 48% | KPIs and notes) were
 * ~150px each: the period broke after the arrow, the three KPI titles ran
 * into each other, «45h» and «18m» sat on two lines, and the name ran
 * under the sheet's close button. Here the head is a column: who and the
 * period on top (clear of the ×), the three KPIs on a row of their own at
 * full width — title, figure, the days below — then the notes. And it
 * stops being sticky: at that height it would hold a third of the sheet
 * still while the days scroll under it (the dialog does not lift
 * --bbx-presence-top when the head is not sticky). */
@media (max-width: 768px) {
    #md-content .bbx-tsr .bbx-tsr-headwrap { position: static; padding-top: 10px; padding-bottom: 12px; margin-bottom: 8px; }
    #md-content .bbx-tsr .bbx-tsr-head { flex-direction: column; align-items: stretch; gap: 14px; }
    #md-content .bbx-tsr .bbx-tsr-who { flex: 0 0 auto; padding-right: 40px; }
    #md-content .bbx-tsr .bbx-tsr-who__name { font-size: var(--bbx-fs-title-sm); }
    #md-content .bbx-tsr .bbx-tsr-period { white-space: nowrap; }
    #md-content .bbx-tsr .bbx-tsr-side { flex: 0 0 auto; }
    #md-content .bbx-tsr .bbx-tsr-kpis { align-items: stretch; gap: 12px; margin-bottom: 8px; }
    #md-content .bbx-tsr .bbx-tsr-kpi { display: flex; flex-direction: column; padding: 0; }
    /* a title that wraps grows, the figures below stay on one baseline */
    #md-content .bbx-tsr .bbx-tsr-kpi__title { flex: 1 0 auto; line-height: 1.3; }
    #md-content .bbx-tsr .bbx-tsr-kpi__value { order: 1; margin-top: 4px; font-size: var(--bbx-fs-title); white-space: nowrap; }
    #md-content .bbx-tsr .bbx-tsr-kpi__sub { order: 2; margin-top: 2px; white-space: nowrap; }
}

/* ============================================================
 *  §DOC-DIALOG — .bbx-doc-dlg
 *
 *  Condizioni d'uso e Privacy: documenti lunghi serviti dal backend come
 *  HTML nudo, avvolti al volo da bbxShowDocument (commons §DOC-DIALOG)
 *  nella struttura canonica del popup. Qui la tipografia: un documento
 *  non e' un form, quindi testo leggermente piu' piccolo del corpo dei
 *  dialog, riga alta, e una misura di lettura che non fa attraversare
 *  tutta la larghezza del popup all'occhio.
 * ============================================================ */
/* Nessuna variante di larghezza: il documento sta nel popup STANDARD, che
 * con il `max-width: 550px` della .dialog-body e il padding 24px da' ~500px,
 * cioe' le ~70 battute per riga che si leggono bene.
 * `margin: 0` neutralizza il `margin: 20px` che la skin legacy dei popup
 * mette ai blocchi dentro .md-content. */
#md-content .bbx-doc-dlg__body {
    margin: 0;
    padding: 4px 0 24px;
    font-size: var(--bbx-fs-md);
    line-height: 1.6;
    color: var(--bbx-gray-700);
}
#md-content .bbx-doc-dlg__body > *:first-child { margin-top: 0; }

#md-content .bbx-doc-dlg__body h1,
#md-content .bbx-doc-dlg__body h2,
#md-content .bbx-doc-dlg__body h3,
#md-content .bbx-doc-dlg__body h4,
#md-content .bbx-doc-dlg__body b,
#md-content .bbx-doc-dlg__body strong {
    color: var(--bbx-gray-800);
    font-weight: 600;
}
/* `.md-content h3` (style_modal, skin legacy dei popup) e' il TITOLO del
 * modale: 2.4em, centrato, su una banda grigia con gli angoli tondi. In un
 * documento gli h3 sono numeri di clausola, non titoli di finestra. */
#md-content .bbx-doc-dlg__body h1,
#md-content .bbx-doc-dlg__body h2,
#md-content .bbx-doc-dlg__body h3,
#md-content .bbx-doc-dlg__body h4 {
    background: none;
    text-align: left;
    padding: 0;
    border-radius: 0;
    opacity: 1;
}
#md-content .bbx-doc-dlg__body h1 { font-size: var(--bbx-fs-2xl); line-height: 1.3; margin: 22px 0 8px; }
#md-content .bbx-doc-dlg__body h2 { font-size: var(--bbx-fs-xl); line-height: 1.3; margin: 20px 0 6px; }
#md-content .bbx-doc-dlg__body h3,
#md-content .bbx-doc-dlg__body h4 { font-size: var(--bbx-fs-md); line-height: 1.35; margin: 18px 0 4px; }

#md-content .bbx-doc-dlg__body p { margin: 0 0 10px; }
#md-content .bbx-doc-dlg__body ul,
#md-content .bbx-doc-dlg__body ol { margin: 0 0 10px; padding-left: 20px; }
#md-content .bbx-doc-dlg__body li { margin-bottom: 4px; }
#md-content .bbx-doc-dlg__body li::marker { color: var(--bbx-gray-400); }

#md-content .bbx-doc-dlg__body a { color: var(--bbx-blue-600); }

/* ------------------------------------------------------------
 * TEMA — il documento se lo porta addosso, il colore
 *
 * Condizioni d'uso e Privacy arrivano dal backend come HTML nudo e
 * vecchio: quasi sempre con il colore scritto sull'elemento
 * (`style="color:#000"`, `<font color>`, `bgcolor` sulle tabelle). Su
 * fondo scuro quel nero resta nero, e il testo sparisce.
 *
 * Qui l'`!important` e' lecito perche' batte uno STILE INLINE — l'unico
 * caso previsto da CLAUDE.md §2 — ed e' anche l'unico modo: nessuna
 * specificita' raggiunge un attributo `style`. Sono esclusi i link, che
 * il loro colore ce l'hanno per un motivo.
 *
 * Vale in tutti e due i temi: in chiaro impone gli stessi valori che il
 * blocco sopra gia' dava per eredita', quindi non cambia niente.
 * ------------------------------------------------------------ */
#md-content .bbx-doc-dlg__body,
#md-content .bbx-doc-dlg__body :not(a) { color: var(--bbx-gray-700) !important; }

#md-content .bbx-doc-dlg__body h1,
#md-content .bbx-doc-dlg__body h2,
#md-content .bbx-doc-dlg__body h3,
#md-content .bbx-doc-dlg__body h4,
#md-content .bbx-doc-dlg__body b,
#md-content .bbx-doc-dlg__body strong { color: var(--bbx-gray-800) !important; }

#md-content .bbx-doc-dlg__body a { color: var(--bbx-blue-600) !important; }

/* i fondi che il documento si porta dietro: dentro il popup la superficie
 * e' quella del popup, non quella che il documento aveva sul suo sito */
#md-content .bbx-doc-dlg__body [bgcolor],
#md-content .bbx-doc-dlg__body [style*="background"] { background: transparent !important; }
#md-content .bbx-doc-dlg__body hr {
    border: 0;
    border-top: 1px solid var(--bbx-gray-100);
    margin: 18px 0;
}
#md-content .bbx-doc-dlg__body table { width: 100%; border-collapse: collapse; margin: 0 0 12px; }
#md-content .bbx-doc-dlg__body td,
#md-content .bbx-doc-dlg__body th {
    border: 1px solid var(--bbx-gray-150);
    padding: 6px 8px;
    vertical-align: top;
}
/* i documenti del backend portano dimensioni e font inline dell'editor:
 * qui conta la resa del popup, non quella del sorgente. */
#md-content .bbx-doc-dlg__body [style*="font-family"],
#md-content .bbx-doc-dlg__body [style*="font-size"] {
    font-family: inherit !important;
    font-size: inherit !important;
}

/* ============================================================
 *  Popup del luogo a due colonne — la mappa e' la colonna destra
 *
 *  La mappa qui non e' un'illustrazione: e' lo strumento con cui si
 *  decide il punto. Nella colonna si prende tutta l'altezza che avanza,
 *  con lo switch Mappa/Satellite sopra e le coordinate sotto.
 * ============================================================ */

/* La catena del flex fino alle due colonne. `.dialog-body--wide` (main-v2)
 * la costruisce per i dialog a tab — `> [role=tabpanel] > form` — ma qui il
 * <form> e' figlio diretto del body: senza questo anello nessuno cede
 * altezza e la mappa resta alta zero. */
#md-content .bbx-placedlg > form {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    min-height: 0;
    margin: 0;
}

#md-content .bbx-place-mappane {
    display: flex;
    flex-direction: column;
    gap: 10px;
    /* la colonna non scorre: dentro non c'e' una lista ma la mappa, che
       deve riempire — lo scroll sta nella colonna dei campi */
    overflow: hidden;
}
#md-content .bbx-place-mappane__seg { align-self: flex-start; }

#md-content .bbx-place-mappane #map {
    flex: 1 1 auto;
    min-height: 320px;
    width: 100%;
    border-radius: var(--bbx-r-md, 12px);
    overflow: hidden;
}
/* le coordinate restano in fondo, non si comprimono */
#md-content .bbx-place-mappane > .table-head { flex: 0 0 auto; }

/* La fascia dell'esito (cerco / ecco / non trovato) e' il componente
 * condiviso .bbx-geobox (primitives §GEOBOX): qui serve solo che non si
 * comprima insieme alla mappa. */
#md-content .bbx-place-mappane .bbx-geobox { flex: 0 0 auto; }

/* Sotto i 980px .bbx-split--wide si impila: la mappa torna a un'altezza
 * propria, se no in colonna singola collasserebbe. */
@media (max-width: 980px) {
    #md-content .bbx-place-mappane #map { min-height: 260px; height: 260px; }
}
