@import '_content/Blazor.Bootstrap/Blazor.Bootstrap.olwso25aue.bundle.scp.css';

/* /Components/Cards/AvailabilityTab.razor.rz.scp.css */
/* #572 (Cam) — Disponibilidad in the Menu Manager's page design. These rules were a <style> block in the component, global
   for as long as the tab was open (.empty-state, .status-badge, .card-header-compact…); scoped now, they reach only this
   tab. The table's header is the Menús tree's own (.mi-thead in app.css); the list bar and the hint copy Modificadores'
   (ModifierLibraryTab.razor.css), since scoped CSS can't reach into another component. */

/* The banners' tones are Existencias' (#463, inventory.css), copied: there they hang on .pt-admin, which never goes dark,
   and this page follows the OS's scheme. Each ink and the subtitle measured at AA on its fill (AvailabilityTabContractTests). */
.availability-tab[b-ozvrq0whi7] {
    --av-crit-ink: #a3304a;
    --av-crit-fill: #fbe3ea;
    --av-warn-ink: #7a520c;
    --av-warn-fill: #f4e9d4;
    --av-sub: #5b5b76;
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
}

@media (prefers-color-scheme: dark) {
    .availability-tab[b-ozvrq0whi7] {
        --av-crit-ink: #f8a7b8;
        --av-crit-fill: #33202a;
        --av-warn-ink: #d7a24e;
        --av-warn-fill: #33280f;
        --av-sub: #a2a2bd;
    }
}

/* ---- «Información», as the line under the tabs (Modificadores' .ml-hint) ------------------------------------------ */
.av-hint[b-ozvrq0whi7] {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin: 0;
    font-size: 0.8125rem;
    color: var(--text-secondary);
}

.av-hint > i[b-ozvrq0whi7] {
    flex-shrink: 0;
    color: var(--pt-coral, #ec607e);
}

/* ---- The banners: Existencias' shape (#463). A toggle in its tone's tint with a 3px bar in its ink; pressed, a ring and
   the chevron turned down. At least 300px each, never wider than the row. -------------------------------------------- */
.av-banners[b-ozvrq0whi7] {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(300px, 100%), 1fr));
    gap: 12px;
}

.av-banner[b-ozvrq0whi7] {
    display: flex;
    align-items: center;
    gap: 12px;
    width: 100%;
    margin: 0;
    padding: 13px 16px 13px 15px;
    border: 0;
    border-left: 3px solid;
    border-radius: 0;
    font: inherit;
    text-align: left;
    cursor: pointer;
}

.av-banner--crit[b-ozvrq0whi7] { background: var(--av-crit-fill); border-left-color: var(--av-crit-ink); color: var(--av-crit-ink); }
.av-banner--warn[b-ozvrq0whi7] { background: var(--av-warn-fill); border-left-color: var(--av-warn-ink); color: var(--av-warn-ink); }
.av-banner-glyph[b-ozvrq0whi7] { font-size: 24px; line-height: 1; }
.av-banner-n[b-ozvrq0whi7] { font-size: 30px; line-height: 36px; font-weight: 700; font-variant-numeric: tabular-nums; }
.av-banner-text[b-ozvrq0whi7] { display: flex; flex-direction: column; flex: 1 1 auto; min-width: 0; }
.av-banner-text b[b-ozvrq0whi7] { font-size: 15px; line-height: 20px; font-weight: 700; }
.av-banner-sub[b-ozvrq0whi7] { font-size: 12.5px; line-height: 18px; color: var(--av-sub); }
.av-banner-chev[b-ozvrq0whi7] { font-size: 14px; line-height: 1; transition: transform 0.2s ease; }
.av-banner:hover[b-ozvrq0whi7] { box-shadow: inset 0 0 0 1px currentColor; }
.av-banner[aria-pressed="true"][b-ozvrq0whi7] { box-shadow: inset 0 0 0 2px currentColor; }
.av-banner[aria-pressed="true"] .av-banner-chev[b-ozvrq0whi7] { transform: rotate(90deg); }
.av-banner:focus-visible[b-ozvrq0whi7] { outline: 3px solid var(--pt-coral, #ec607e); outline-offset: 2px; }

@media (prefers-reduced-motion: reduce) {
    .av-banner-chev[b-ozvrq0whi7] { transition: none; }
}

/* ---- The list bar: the search, the filters and «Acciones recientes» on ONE row (Cam). The search is narrower than
   Modificadores' 576px so the filters fit beside it; the bar wraps on a narrow screen. -------------------------------- */
.av-listbar[b-ozvrq0whi7] {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem 0.75rem;
}

.av-search[b-ozvrq0whi7] {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    flex: 0 1 20rem;
    min-width: 12rem;
    min-height: var(--pt-control-min-height);
    padding: 0 0.875rem;
    background: var(--surface-color);
    /* #593: the field border and the field focus, as the Menús tab's search; the filter tabs beside it rest on the same
       grey. */
    border: 2px solid var(--pt-field-border);
    border-radius: 0;
}

.av-search:focus-within[b-ozvrq0whi7] {
    border-color: var(--pt-field-focus);
}

.av-search > i[b-ozvrq0whi7] {
    color: var(--text-secondary);
    font-size: 1rem;
    flex-shrink: 0;
}

.av-search-input[b-ozvrq0whi7] {
    flex: 1;
    min-width: 0;
    border: none;
    outline: none;
    background: transparent;
    color: var(--text-primary);
    font-size: 0.95rem;
}

.av-search-input[b-ozvrq0whi7]::placeholder {
    color: var(--text-secondary);
}

.btn-clear[b-ozvrq0whi7] {
    background: none;
    border: none;
    padding: 0;
    cursor: pointer;
    color: var(--text-secondary);
}

.btn-clear:hover[b-ozvrq0whi7] {
    color: var(--text-primary);
}

.filter-tabs[b-ozvrq0whi7] {
    display: flex;
    gap: 0.5rem;
    flex-wrap: wrap;
}

.filter-tab[b-ozvrq0whi7] {
    min-height: 2.25rem;
    padding: 0.35rem 0.75rem;
    border: 1px solid var(--pt-field-border);
    border-radius: 0;
    background: var(--background-color);
    color: var(--text-secondary);
    font-size: 0.8rem;
    white-space: nowrap;
    cursor: pointer;
    transition: all 0.2s ease;
}

.filter-tab:hover[b-ozvrq0whi7] {
    border-color: var(--primary-color);
    color: var(--pt-navy-fg);
}

.filter-tab.active[b-ozvrq0whi7] {
    background: var(--primary-color);
    border-color: var(--primary-color);
    color: white;
}

.av-listbar-end[b-ozvrq0whi7] {
    margin-left: auto;
}

/* ---- The line over a banner's set or the Limitados filter: what is showing, the way back, and the reset --------- */
.av-viewbar[b-ozvrq0whi7] {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.25rem 0.75rem;
    font-size: 0.8125rem;
    color: var(--text-secondary);
}

.av-viewbar b[b-ozvrq0whi7] {
    color: var(--text-primary);
    font-weight: 600;
}

.av-viewbar-link[b-ozvrq0whi7] {
    padding: 0;
    font-size: inherit;
    vertical-align: baseline;
}

.av-viewbar-action[b-ozvrq0whi7] {
    margin-left: auto;
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    border-radius: 0;
    font-weight: 600;
}

/* ---- Selection actions --------------------------------------------------------------------------------------------- */
.selection-actions[b-ozvrq0whi7] {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.5rem 1rem;
    background: #e0f2fe;
    border: 1px solid #7dd3fc;
    flex-wrap: wrap;
}

.selection-count[b-ozvrq0whi7] {
    font-weight: 600;
    color: #0369a1;
    margin-right: 0.5rem;
}

.sel-btn[b-ozvrq0whi7] {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.4rem 0.75rem;
    font-size: 0.8rem;
    font-weight: 600;
    border-radius: 0;
    cursor: pointer;
    transition: all 0.2s ease;
    background: var(--surface-color);
}

.sel-btn:disabled[b-ozvrq0whi7] {
    opacity: 0.5;
    cursor: not-allowed;
}

.sel-btn-danger[b-ozvrq0whi7] { border: 1.5px solid #dc3545; color: #dc3545; }
.sel-btn-danger:hover:not(:disabled)[b-ozvrq0whi7] { background: #dc3545; color: white; }
.sel-btn-success[b-ozvrq0whi7] { border: 1.5px solid #10b981; color: #10b981; }
.sel-btn-success:hover:not(:disabled)[b-ozvrq0whi7] { background: #10b981; color: white; }
.sel-btn-primary[b-ozvrq0whi7] { border: 1.5px solid var(--primary-color, #000075); color: var(--primary-color, #000075); }
.sel-btn-primary:hover:not(:disabled)[b-ozvrq0whi7] { background: var(--primary-color, #000075); color: white; }
.sel-btn-secondary[b-ozvrq0whi7] { border: 1.5px solid var(--text-secondary, #6c757d); color: var(--text-secondary, #6c757d); }
.sel-btn-secondary:hover:not(:disabled)[b-ozvrq0whi7] { background: var(--text-secondary, #6c757d); color: white; }

/* ---- The table: the page's width, one grid for the header and the rows. Below its 44rem it scrolls sideways, as the
   tree does, rather than crushing the names. ------------------------------------------------------------------------- */
.av-table[b-ozvrq0whi7] {
    border: 1px solid var(--pt-card-border, var(--border-color));
    background: var(--surface-color);
    overflow-x: auto;
}

.av-row[b-ozvrq0whi7] {
    display: grid;
    grid-template-columns: 1.25rem 2.25rem minmax(14rem, 1fr) 7rem 7rem 7rem;
    align-items: center;
    gap: 0.75rem;
    min-width: 44rem;
    min-height: 3.5rem;
    padding: 0.5rem 0.75rem;
    border-top: 1px solid var(--pt-card-border, var(--border-color));
    background: var(--surface-color);
}

/* The header is the tree's .mi-thead; the row rules above would paint it as a row. */
.av-head[b-ozvrq0whi7] {
    min-height: 0;
    border-top: 0;
    background: var(--pt-subhead-bg);
}

.av-head + .av-row[b-ozvrq0whi7] {
    border-top: 0;
}

.av-row:not(.av-head):hover[b-ozvrq0whi7] {
    background: var(--background-color);
}

/* An unavailable row: the tree's marker for a dish off the menu (.mi-rowgroup.mi-inactive), an amber edge. */
.av-row.inactive[b-ozvrq0whi7] {
    box-shadow: inset 3px 0 0 #f59e0b;
}

.av-row.inactive .av-name[b-ozvrq0whi7] {
    color: var(--text-secondary);
}

.av-row.selected[b-ozvrq0whi7] {
    background: #e0f2fe;
}

.av-num[b-ozvrq0whi7] {
    text-align: right;
    font-variant-numeric: tabular-nums;
}

.av-center[b-ozvrq0whi7] {
    display: flex;
    justify-content: center;
    align-items: center;
}

.item-checkbox input[type="checkbox"][b-ozvrq0whi7] {
    width: 18px;
    height: 18px;
    cursor: pointer;
    accent-color: var(--primary-color);
}

/* Crear's tiles: the plate for an Artículo (.action-icon-item, app.css), the modifier's sliders for an Opción
   (.action-icon-modifier: white on #5b55d6, 5.8:1). */
.av-tile[b-ozvrq0whi7] {
    width: 2.25rem;
    height: 2.25rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}

.av-tile--option[b-ozvrq0whi7] {
    color: #fff;
    font-size: 1.05rem;
}

.item-details[b-ozvrq0whi7] {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

.item-name-row[b-ozvrq0whi7] {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    flex-wrap: wrap;
}

.av-name[b-ozvrq0whi7] {
    font-weight: 600;
    color: var(--text-primary);
    font-size: 0.9rem;
}

.av-price[b-ozvrq0whi7] {
    font-size: 0.875rem;
    color: var(--text-primary);
}

.item-path[b-ozvrq0whi7] {
    font-size: 0.75rem;
    color: var(--text-secondary);
    margin-top: 0.15rem;
    display: flex;
    align-items: center;
    gap: 0.25rem;
}

.item-path i[b-ozvrq0whi7] {
    font-size: 0.7rem;
}

.status-badge[b-ozvrq0whi7] {
    padding: 0.1rem 0.4rem;
    border-radius: 0;
    font-size: 0.65rem;
    font-weight: 600;
}

.status-badge.inactive[b-ozvrq0whi7] { background: #fee2e2; color: #b91c1c; }
.status-badge.soldout[b-ozvrq0whi7] { background: #e5e7eb; color: #374151; }
.status-badge.lowstock[b-ozvrq0whi7] { background: #ffedd5; color: #9a3412; }

.quantity-badge[b-ozvrq0whi7] {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    padding: 0.25rem 0.5rem;
    font-size: 0.85rem;
    font-weight: 600;
}

.quantity-badge.normal[b-ozvrq0whi7] { background: #dbeafe; color: #1d4ed8; }
.quantity-badge.lowstock[b-ozvrq0whi7] { background: #ffedd5; color: #9a3412; }
.quantity-badge.soldout[b-ozvrq0whi7] { background: #e5e7eb; color: #374151; }

.qty-value[b-ozvrq0whi7] {
    min-width: 20px;
    text-align: center;
}

.btn-edit-qty[b-ozvrq0whi7] {
    background: none;
    border: none;
    padding: 2px;
    cursor: pointer;
    color: inherit;
    opacity: 0.75;
    transition: opacity 0.2s;
}

.btn-edit-qty:hover[b-ozvrq0whi7] {
    opacity: 1;
}

.btn-set-qty[b-ozvrq0whi7] {
    width: 32px;
    height: 32px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--background-color);
    border: 1px dashed var(--border-color);
    border-radius: 0;
    color: var(--text-secondary);
    cursor: pointer;
    transition: all 0.2s ease;
}

.btn-set-qty:hover[b-ozvrq0whi7] {
    border-color: var(--primary-color);
    color: var(--pt-navy-fg);
    border-style: solid;
}

.empty-state[b-ozvrq0whi7] {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 3rem;
    color: var(--text-secondary);
}

.empty-state p[b-ozvrq0whi7] {
    margin-top: 1rem;
    font-size: 0.9rem;
}

.empty-state i[b-ozvrq0whi7] {
    font-size: 3rem;
    opacity: 0.5;
}

/* ---- The quantity dialogs ------------------------------------------------------------------------------------------ */
.quantity-modal-body[b-ozvrq0whi7] {
    padding: 0.5rem 0;
}

.quantity-input-group[b-ozvrq0whi7] {
    display: flex;
    flex-direction: column;
    gap: 1rem;
}

.input-with-button[b-ozvrq0whi7] {
    display: flex;
    gap: 0.5rem;
}

.input-with-button input[b-ozvrq0whi7] {
    flex: 1;
}

.quick-set-buttons[b-ozvrq0whi7] {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem;
}

.quick-label[b-ozvrq0whi7] {
    font-size: 0.85rem;
    color: var(--text-secondary);
}

.qty-quick-btn[b-ozvrq0whi7] {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 40px;
    padding: 0.35rem 0.65rem;
    font-size: 0.85rem;
    font-weight: 600;
    border: 1.5px solid var(--border-color, #dee2e6);
    border-radius: 0;
    background: var(--surface-color, #fff);
    color: var(--text-primary);
    cursor: pointer;
    transition: all 0.2s ease;
}

.qty-quick-btn:hover[b-ozvrq0whi7] {
    border-color: var(--primary-color, #000075);
    color: var(--primary-color, #000075);
    background: rgba(0, 0, 117, 0.05);
}

.qty-quick-btn.danger[b-ozvrq0whi7] { border-color: #dc3545; color: #dc3545; }
.qty-quick-btn.danger:hover[b-ozvrq0whi7] { background: #dc3545; color: white; }

/* ---- Dark ---------------------------------------------------------------------------------------------------------- */
@media (prefers-color-scheme: dark) {
    .filter-tab:hover[b-ozvrq0whi7] {
        border-color: var(--pt-coral, #ec607e);
        color: var(--pt-coral, #ec607e);
    }

    .filter-tab.active[b-ozvrq0whi7] {
        background: var(--pt-coral, #ec607e);
        border-color: var(--pt-coral, #ec607e);
        color: var(--pt-on-coral);
    }

    .status-badge.inactive[b-ozvrq0whi7] { background: #450a0a; color: #fca5a5; }
    .status-badge.soldout[b-ozvrq0whi7] { background: #1f2937; color: #d1d5db; }
    .status-badge.lowstock[b-ozvrq0whi7] { background: #431407; color: #fdba74; }

    .selection-actions[b-ozvrq0whi7] { background: #1e3a5f; border-color: #3b82f6; }
    .selection-count[b-ozvrq0whi7] { color: #93c5fd; }
    .av-row.selected[b-ozvrq0whi7] { background: #1e3a5f; }

    .quantity-badge.normal[b-ozvrq0whi7] { background: #1e3a8a; color: #bfdbfe; }
    .quantity-badge.lowstock[b-ozvrq0whi7] { background: #431407; color: #fdba74; }
    .quantity-badge.soldout[b-ozvrq0whi7] { background: #1f2937; color: #d1d5db; }
}

/* ---- Narrow -------------------------------------------------------------------------------------------------------- */
@media (max-width: 768px) {
    .av-search[b-ozvrq0whi7] {
        flex-basis: 100%;
    }

    .filter-tabs[b-ozvrq0whi7] {
        overflow-x: auto;
        flex-wrap: nowrap;
        padding-bottom: 0.25rem;
    }
}
/* /Components/Cards/ItemCustomizationModal.razor.rz.scp.css */
/* #532: a modifier from the library, in the dish panel, for this order only. */
.library-add[b-9ffqbxylb4] {
    margin-bottom: 1.5rem;
}

.library-add-open[b-9ffqbxylb4],
.library-add-row[b-9ffqbxylb4] {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    width: 100%;
    min-height: 44px;
    padding: 0.5rem 0.75rem;
    border: 1px solid var(--border-color);
    border-radius: 0;
    background: var(--surface-color);
    color: var(--modal-text);
    text-align: left;
    cursor: pointer;
}

.library-add-open[b-9ffqbxylb4] {
    justify-content: center;
    font-weight: 600;
}

.library-add-list[b-9ffqbxylb4] {
    max-height: 260px;
    margin-top: 0.5rem;
    overflow-y: auto;
}

.library-add-row + .library-add-row[b-9ffqbxylb4] {
    border-top: 0;
}

.library-add-meta[b-9ffqbxylb4],
.library-add-note[b-9ffqbxylb4] {
    color: var(--modal-text-secondary);
    font-size: 0.875rem;
}

.library-add-note[b-9ffqbxylb4] {
    margin-top: 0.5rem;
}

.library-add-retry[b-9ffqbxylb4] {
    border: 0;
    background: none;
    color: inherit;
    font-weight: 600;
    text-decoration: underline;
    cursor: pointer;
}

/* #612 Q2b: the ×1…max count under a chosen tile. A row of its own in the options grid, under the tile it counts. */
.option-count[b-9ffqbxylb4] {
    grid-column: 1 / -1;
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.25rem 0.25rem 0.5rem;
}

.option-count-label[b-9ffqbxylb4],
.option-count-max[b-9ffqbxylb4] {
    font-size: 0.8125rem;
    color: var(--text-muted, #6c757d);
}

.option-count-btn[b-9ffqbxylb4] {
    width: 36px;
    height: 36px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 1.5px solid #0066cc;
    border-radius: 0;
    background: #ffffff;
    color: #0066cc;
    font-size: 1.1rem;
}

.option-count-btn:disabled[b-9ffqbxylb4] {
    opacity: 0.4;
    cursor: not-allowed;
}

.option-count-value[b-9ffqbxylb4] {
    min-width: 2ch;
    text-align: center;
    font-weight: 700;
}
/* /Components/Cards/MasterAdmin/GroupCatalogInventoryMove.razor.rz.scp.css */
/* Chain Catalog P4.23b - «Mover inventario al grupo», the panel's «Creado desde» callout's child after its row. The
   callout is a column (P3.38b), so the card takes its width. It paints the surface colour itself, so what it says never
   depends on the callout's ground; the app.css tokens make light and dark read alike. The 44px and straight edges of
   its buttons are app.css's .btn; nothing here restates them. */

.gim[b-radvi04gog] {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    padding: 0.625rem 0.75rem;
    background: var(--surface-color, #ffffff);
    color: var(--text-primary, #1e293b);
    border: 1px solid var(--pt-card-border, #cbd5e1);
    font-size: 0.875rem;
}

.gim-title[b-radvi04gog] {
    font-weight: 600;
    color: var(--pt-navy-fg, #000075);
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
}

.gim-note[b-radvi04gog] {
    margin: 0;
    font-size: 0.8125rem;
    color: var(--text-secondary, #64748b);
}

.gim-small[b-radvi04gog] {
    font-size: 0.75rem;
}

.gim-muted[b-radvi04gog] {
    color: var(--text-secondary, #64748b);
    font-size: 0.8125rem;
}

.gim-error[b-radvi04gog] {
    color: var(--pt-destructive-fg, #dc2626);
    font-size: 0.8125rem;
}

.gim-label[b-radvi04gog] {
    font-size: 0.8125rem;
    font-weight: 600;
}

.gim-row[b-radvi04gog] {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem;
}

.gim .btn[b-radvi04gog] {
    white-space: normal;
}

/* Bootstrap's outline-danger red is under 4.5:1 on the dark surface; the destructive token reads 4.8:1 light and 5.3:1
   dark on the surface colour. */
.gim .btn-outline-danger[b-radvi04gog] {
    background-color: var(--surface-color, #ffffff);
    color: var(--pt-destructive-fg, #dc2626);
    border-color: var(--pt-destructive-fg, #dc2626);
}

.gim-report[b-radvi04gog],
.gim-confirm[b-radvi04gog] {
    padding: 0.625rem 0.75rem;
    border: 1px solid var(--pt-card-border, #cbd5e1);
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}

.gim-report-ok[b-radvi04gog] {
    border-left: 4px solid var(--pt-status-ready-border, #17804f);
}

.gim-report-fail[b-radvi04gog] {
    border-left: 4px solid var(--pt-destructive-fg, #dc2626);
}

.gim-report ul[b-radvi04gog] {
    margin: 0;
    padding-left: 1.25rem;
    overflow-wrap: anywhere;
}

.gim-counts[b-radvi04gog] {
    border-collapse: collapse;
    width: auto;
}

.gim-counts td[b-radvi04gog] {
    padding: 0.125rem 1rem 0.125rem 0;
}

.gim-counts td:last-child[b-radvi04gog] {
    font-weight: 600;
    text-align: right;
}

.gim-problems summary[b-radvi04gog] {
    cursor: pointer;
    font-weight: 600;
}

.gim-confirm[b-radvi04gog] {
    background: var(--pt-warning-bg, #fef3c7);
    border-color: var(--pt-warning-border, #fbbf24);
}

.gim-confirm p[b-radvi04gog] {
    margin: 0;
}

.gim-alert[b-radvi04gog] {
    padding: 0.5rem 0.75rem;
    border: 1px solid;
}

.gim-alert-error[b-radvi04gog] {
    border-color: var(--pt-destructive-fg, #dc2626);
    color: var(--pt-destructive-fg, #dc2626);
}

.gim-alert-ok[b-radvi04gog] {
    background: var(--pt-status-ready-bg, #d4edda);
    color: var(--pt-status-ready-fg, #155724);
    border-color: var(--pt-status-ready-border, #b7e0c6);
}
/* /Components/Cards/MasterAdmin/GroupCatalogPanel.razor.rz.scp.css */
/* Chain Catalog P3.3 / P3.21 / P3.38b — the «Menú del grupo» panel, inside Configuración's section (GroupCatalogSection's
   card body, under its picker). Scoped, on the app.css tokens so light and dark read alike. The 44px and straight edges of
   its buttons and fields are app.css's (.btn, .app-layout .form-select and .form-control); nothing here restates them. */
.gcp[b-819hhcg16g] {
    border-top: 1px solid var(--pt-card-border, #cbd5e1);
    padding-top: 1rem;
    display: flex;
    flex-direction: column;
    gap: 1rem;
}
.gcp-head[b-819hhcg16g] {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    flex-wrap: wrap;
}
.gcp-title[b-819hhcg16g] {
    font-size: 1.0625rem;
    font-weight: 600;
    color: var(--pt-navy-fg, #000075);
}
.gcp-subtitle[b-819hhcg16g] {
    font-weight: 600;
    color: var(--pt-navy-fg, #000075);
}
.gcp-note[b-819hhcg16g] {
    margin: 0;
    font-size: 0.875rem;
    color: var(--text-secondary, #64748b);
}
.gcp-small[b-819hhcg16g] {
    font-size: 0.8125rem;
}
.gcp-muted[b-819hhcg16g] {
    color: var(--text-secondary, #64748b);
    font-size: 0.875rem;
}
.gcp-label[b-819hhcg16g] {
    margin: 0;
    font-size: 0.875rem;
    font-weight: 600;
    color: var(--text-primary, #1e293b);
}
/* §3: a label above its field, the fields stacked, the action row after them. */
.gcp-form[b-819hhcg16g] {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
    max-width: 28rem;
}
.gcp-field[b-819hhcg16g] {
    display: flex;
    flex-direction: column;
    gap: 0.375rem;
}
.gcp-actions[b-819hhcg16g] {
    display: flex;
    flex-wrap: wrap;
    gap: 0.75rem;
}
/* The catalog's facts beyond its chip: a short list, label then value. */
.gcp-facts[b-819hhcg16g] {
    margin: 0;
    display: flex;
    flex-wrap: wrap;
    gap: 0.25rem 1.5rem;
    font-size: 0.875rem;
}
.gcp-fact[b-819hhcg16g] {
    display: flex;
    gap: 0.375rem;
}
.gcp-fact dt[b-819hhcg16g] {
    font-weight: 600;
    color: var(--text-secondary, #64748b);
}
.gcp-fact dd[b-819hhcg16g] {
    margin: 0;
    color: var(--text-primary, #1e293b);
}
.gcp-chip[b-819hhcg16g] {
    font-size: 0.75rem;
    font-weight: 600;
    padding: 0.125rem 0.5rem;
    border: 1px solid;
    white-space: nowrap;
}
.gcp-chip-empty[b-819hhcg16g] {
    background: var(--pt-status-done-bg, #e9ecef);
    color: var(--pt-status-done-fg, #41464b);
    border-color: var(--pt-status-done-border, #ced4da);
}
.gcp-chip-full[b-819hhcg16g],
.gcp-chip-linked[b-819hhcg16g] {
    background: var(--pt-status-ready-bg, #d4edda);
    color: var(--pt-status-ready-fg, #155724);
    border-color: var(--pt-status-ready-border, #b7e0c6);
}
.gcp-chip-warn[b-819hhcg16g] {
    background: var(--pt-status-pending-bg, #fff3cd);
    color: var(--pt-status-pending-fg, #856404);
    border-color: var(--pt-status-pending-border, #ffe69c);
}
/* «Creado desde»: neutral (the surface, the card's border, a navy rule), so its destructive «Deshacer» is the only red.
   A column: Inventory's P4.23b adds its step after the row ([371]). */
.gcp-callout[b-819hhcg16g] {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
    padding: 0.75rem 1rem;
    background: var(--surface-color, #ffffff);
    color: var(--text-primary, #1e293b);
    border: 1px solid var(--pt-card-border, #cbd5e1);
    border-left: 3px solid var(--pt-navy-fg, #000075);
    font-size: 0.875rem;
}
.gcp-callout-row[b-819hhcg16g] {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem 0.75rem;
}
.gcp-callout-text[b-819hhcg16g] {
    flex: 1 1 16rem;
}
/* On the surface the destructive token reads 4.8:1 light and 5.3:1 dark; Bootstrap's outline-danger red does not in dark. */
.gcp-callout .btn-outline-danger[b-819hhcg16g] {
    background-color: var(--surface-color, #ffffff);
    color: var(--pt-destructive-fg, #dc2626);
    border-color: var(--pt-destructive-fg, #dc2626);
}
/* Bootstrap's outline-secondary grey is about 3:1 on the dark surface. */
.gcp-location .btn-outline-secondary[b-819hhcg16g] {
    color: var(--text-secondary, #64748b);
    border-color: var(--pt-card-border, #cbd5e1);
}
.gcp-block[b-819hhcg16g] {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
}
.gcp-locations[b-819hhcg16g] {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
}
.gcp-location[b-819hhcg16g] {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem;
    padding: 0.375rem 0;
    border-bottom: 1px solid var(--pt-card-border, #cbd5e1);
}
.gcp-location:last-child[b-819hhcg16g] {
    border-bottom: none;
}
.gcp-location-name[b-819hhcg16g] {
    flex: 1 1 10rem;
    font-size: 0.875rem;
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    color: var(--text-primary, #1e293b);
}
.gcp-seed[b-819hhcg16g] {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
    padding-top: 1rem;
    border-top: 1px dashed var(--pt-card-border, #cbd5e1);
}
.gcp-menus[b-819hhcg16g] {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
}
.gcp-menu[b-819hhcg16g] {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    min-height: 44px;
    font-size: 0.875rem;
}
.gcp-menu input[b-819hhcg16g] {
    width: 1.25rem;
    height: 1.25rem;
}
.gcp-report[b-819hhcg16g],
.gcp-confirm[b-819hhcg16g] {
    padding: 0.75rem;
    border: 1px solid var(--pt-card-border, #cbd5e1);
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    font-size: 0.875rem;
}
.gcp-report-ok[b-819hhcg16g] {
    border-left: 4px solid var(--pt-status-ready-border, #17804f);
}
.gcp-report-fail[b-819hhcg16g] {
    border-left: 4px solid var(--pt-destructive-fg, #dc2626);
}
.gcp-report ul[b-819hhcg16g] {
    margin: 0;
    padding-left: 1.25rem;
}
.gcp-counts[b-819hhcg16g] {
    border-collapse: collapse;
    width: auto;
}
.gcp-counts td[b-819hhcg16g] {
    padding: 0.125rem 1rem 0.125rem 0;
}
.gcp-counts td:last-child[b-819hhcg16g] {
    font-weight: 600;
    text-align: right;
}
.gcp-problems summary[b-819hhcg16g] {
    cursor: pointer;
    font-weight: 600;
}
.gcp-problems ul[b-819hhcg16g] {
    font-family: var(--pt-font-mono, ui-monospace, "Cascadia Code", Consolas, monospace);
    font-size: 0.75rem;
    overflow-wrap: anywhere;
}
.gcp-confirm[b-819hhcg16g] {
    background: var(--pt-warning-bg, #fef3c7);
    border-color: var(--pt-warning-border, #fbbf24);
}
.gcp-confirm p[b-819hhcg16g] {
    margin: 0;
}
.gcp-alert[b-819hhcg16g] {
    padding: 0.5rem 0.75rem;
    font-size: 0.875rem;
    border: 1px solid;
}
.gcp-alert-error[b-819hhcg16g] {
    border-color: var(--pt-destructive-fg, #dc2626);
    color: var(--pt-destructive-fg, #dc2626);
}
.gcp-alert-ok[b-819hhcg16g] {
    background: var(--pt-status-ready-bg, #d4edda);
    color: var(--pt-status-ready-fg, #155724);
    border-color: var(--pt-status-ready-border, #b7e0c6);
}
/* A phone: the actions stack at the same full width, as the owner's do (P3.38a); a wrapped label keeps its icon on its
   first line. */
@media (max-width: 576px) {
    .gcp-action[b-819hhcg16g] {
        display: block;
        flex: 1 1 100%;
        text-align: center;
        white-space: normal;
    }
    .gcp-form[b-819hhcg16g] {
        max-width: none;
    }
}
/* /Components/Cards/MenuDisplayCard.razor.rz.scp.css */
    /* Search + view controls on ONE row. The toolbar used to sit on its own line below the
       search bar, which spent a full line on two short controls — on a tablet that is a line of
       the list the operator cannot see.

       #438: the search stops at 576px (below), so on a wide screen the controls would stop beside it.
       space-between keeps them at the bar's end, with the white space between the two that Cam asked
       for. The Modificadores tab's list bar does the same. */
    .menu-listbar[b-26vwipkkos] {
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: 0.5rem;
        margin-bottom: 1rem;
    }

    /* With Crear beside Columnas (#411 page), a phone has no room left for the search field, which
       would shrink to its icon. Below 576px the field takes its own line and the controls follow. */
    @media (max-width: 575.98px) {
        .menu-listbar[b-26vwipkkos] {
            flex-wrap: wrap;
        }

        .menu-listbar > .menu-search-bar[b-26vwipkkos] {
            flex-basis: 100%;
        }
    }

    /* Menu item search bar */
    /* No vertical padding: the min-height below IS the height (#411 page). At 0.625rem the input's
       line box plus padding came to 48.8px, 4.8px proud of Columnas and Crear beside it, which is
       the "nearly lines up" the comment below says this avoids. MenuCreateContractTests measured it. */
    .menu-search-bar[b-26vwipkkos] {
        display: flex;
        align-items: center;
        gap: 0.5rem;
        padding: 0 0.875rem;
        background: var(--surface-color);
        /* The field border, as every select and every other search bar (#593, Cam: "should match across all
           pages"); «Columnas» beside it takes it too. */
        border: 2px solid var(--pt-field-border);
        border-radius: 0;

        /* Takes the row, up to 576px; the controls beside it are intrinsically sized.
           #438 (Cam): "We don't really need the search bar to maintain the full width, and it would
           look better there's more gap/white space between the search bar and buttons on the right. Can
           we set a max width on this that only goes as far as it needs to, maybe like 900px?" At 900px
           (2026-09-25): "Let's reduce the max width even more so it stops growing about here", marked at
           578px on his screenshot. */
        flex: 1;
        min-width: 0;
        max-width: 576px;

        /* Shares the control height so the row reads as one line rather than three things that
           nearly line up — the button/input height pairing UI consistency guide §5 asks for. */
        min-height: var(--pt-control-min-height);
    }

    /* Navy, as every field and the Pedidos search (#375, #395). Coral against the field border is 2.2:1, under the 3:1
       a focus indicator needs (#593). */
    .menu-search-bar:focus-within[b-26vwipkkos] {
        border-color: var(--pt-field-focus);
    }

    .menu-search-icon[b-26vwipkkos] {
        color: var(--text-secondary);
        font-size: 1rem;
        flex-shrink: 0;
    }

    .menu-search-input[b-26vwipkkos] {
        flex: 1;
        border: none;
        outline: none;
        background: transparent;
        color: var(--text-primary);
        font-size: 0.95rem;
        min-width: 0;
    }

    .menu-search-input[b-26vwipkkos]::placeholder {
        color: var(--text-secondary);
    }

    .menu-search-clear[b-26vwipkkos] {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        width: 28px;
        height: 28px;
        border: none;
        background: transparent;
        color: var(--text-secondary);
        cursor: pointer;
        border-radius: 0;
        flex-shrink: 0;
    }

    .menu-search-clear:hover[b-26vwipkkos] {
        color: var(--pt-coral, #ec607e);
    }

    /* =============================================================================================
       #411 — THE TREE TABLE
       =============================================================================================
       One table: menus, categories and dishes are rows of it, under one header, on one track list
       (--mi-cols, published by MenuDisplayCard on .mt-table). Cam's grammar, row by row:

         menu      chevron · navy tile · name + status tag / schedule-and-counts line · — · ⋮
         category  (indented) chevron · light-blue tile · name / dish count        · — · ⋮
         dish      (indented) handle · thumbnail · name · price · availability … · ›

       What this REPLACED, so nobody goes looking for it: the stacked .menu-tab-section /
       .category-section cards with a pencil and a right-hand chevron on each header; the green
       active-menu frame (GH-256) and its gradient header — the mockup marks status with the tag
       alone; and the three badges — Menu Activo, Menu Inactivo, and the schedule chip that was
       purple, then navy (card 174), then grey (#414). The schedule is metadata under the name now.

       The badges' one durable lesson carries over: #415 found the flattened green failing AA the
       whole time it was a gradient. The status tags below are dark ink on a pale fill in both
       schemes, and MenuTreeTableContractTests measures them. */

    /* The scroller. overflow-x only — see the note in the markup on why the collapse below uses
       clip rather than hidden: a hidden ancestor would pin every Name cell to a box that never
       scrolls. */
    .mt-scroll[b-26vwipkkos] {
        overflow-x: auto;
        border: 1px solid var(--pt-card-border, var(--border-color));
        background: var(--surface-color);
    }

    .mt-table[b-26vwipkkos] {
        min-width: max(100%, var(--mt-min, 0px));
    }

    .mt-row[b-26vwipkkos] {
        display: grid;
        grid-template-columns: var(--mi-cols);
        align-items: center;
        gap: 0.5rem;
        padding: 0 0.75rem;
        border-top: 1px solid var(--pt-card-border, var(--border-color));
        background: var(--surface-color);
        cursor: pointer;
    }

    .mt-row--menu[b-26vwipkkos] {
        min-height: 4.25rem;
    }

    /* #508 (Cam): the menu row's height, for "more breathing room and easier with touch". The dish row
       takes it in app.css (.mt-dishes .mi-row). */
    .mt-row--category[b-26vwipkkos] {
        min-height: 4.25rem;
    }

    .mt-row:hover[b-26vwipkkos] {
        background: var(--background-color);
    }

    .mt-row:focus-visible[b-26vwipkkos] {
        outline: 3px solid var(--pt-coral, #ec607e);
        outline-offset: -3px;
    }

    /* The Name cell, PINNED. Its background follows the row's (inherit), so under a hover the
       pinned cell tints with the row instead of staying a white block over it.

       It takes the ROW's left padding into itself (negative margin, equal padding). The padding is
       the row's, and the row scrolls away — so a pinned cell that did not own it sat flush against
       the table's edge, "NOMBRE" and every chevron touching the border. Owning it, the cell starts
       at the row's own edge, pins there without a jump, and keeps its inset. */
    .mt-name[b-26vwipkkos] {
        position: sticky;
        left: 0;
        margin-left: -0.75rem;
        padding-left: 0.75rem;
        z-index: 1;
        --mt-name-gap: 0.5rem;
        display: flex;
        align-items: center;
        gap: var(--mt-name-gap);
        min-width: 0;
        align-self: stretch;
        background: inherit;
    }

    /* The category's indent: one chevron's width, so its chevron sits under the menu's tile —
       the step Cam's tree draws. */
    .mt-row--category .mt-name[b-26vwipkkos] {
        padding-left: 2.75rem;
    }

    .mt-head .mt-name[b-26vwipkkos] {
        position: sticky;
        left: 0;
        z-index: 1;
        margin-left: -0.75rem;
        padding-left: 0.75rem;
        background: inherit;
    }

    .mt-chevron[b-26vwipkkos] {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        width: 2rem;
        height: 2rem;
        flex-shrink: 0;
        color: var(--text-primary);
        font-size: 1rem;
        transition: transform var(--transition-slow);
    }

    .mt-chevron--open[b-26vwipkkos] {
        transform: rotate(90deg);
    }

    @media (prefers-reduced-motion: reduce) {
        .mt-chevron[b-26vwipkkos] {
            transition: none;
        }
    }

    .mt-tile[b-26vwipkkos] {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        flex-shrink: 0;
        border-radius: 0;
    }

    /* #436: the glyph as a block with a 1em line, so its em box is what the tile centres. Seated as a
       Bootstrap Icon beside words (`vertical-align: -.125em`), it painted 1px high in both tiles.
       The rule and its reasons are PtOverflowMenu's .pt-om-tile, whose Crear tiles match these. */
    .mt-tile > i[b-26vwipkkos] {
        display: block;
        line-height: 1;
    }

    .mt-tile > i[b-26vwipkkos]::before {
        display: block;
        vertical-align: 0;
        line-height: 1;
    }

    /* Navy with white, as before — the menu's tile is the tree's anchor. */
    .mt-tile--menu[b-26vwipkkos] {
        width: 2.75rem;
        height: 2.75rem;
        background: var(--pt-navy, #000075);
        color: #ffffff;
        font-size: 1.125rem;
    }

    /* Light blue with navy (#411, Cam: "change Category icon color to light blue with navy icon for
       better visual hierarchy with menu icon"). It was amber (--warning-color) with white — louder
       than the menu it belongs to. */
    .mt-tile--category[b-26vwipkkos] {
        width: 2.25rem;
        height: 2.25rem;
        background: #dbeafe;
        color: var(--pt-navy, #000075);
        font-size: 1rem;
    }

    .mt-text[b-26vwipkkos] {
        display: flex;
        flex-direction: column;
        gap: 0.1875rem;
        min-width: 0;
    }

    /* #507 (Cam): the text "feels a bit too close to the icon". 14px, as a dish's name from its photo
       (app.css). On the text and not the row's gap, which also stands between the chevron and the tile:
       raising that would move every tile and the step between a menu and its categories. Inside .mt-name
       only: the reorder list has a gap of its own. */
    .mt-name > .mt-tile + .mt-text[b-26vwipkkos] {
        margin-left: 0.375rem;
    }

    .mt-titleline[b-26vwipkkos] {
        display: flex;
        align-items: center;
        gap: 0.625rem;
        min-width: 0;
    }

    .mt-title[b-26vwipkkos] {
        min-width: 0;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
        font-weight: 600;
        font-size: 0.875rem; /* #654 (Cam): a menu's and a category's name are both 14px semibold */
        color: var(--text-primary);
    }

    .mt-meta[b-26vwipkkos] {
        display: flex;
        align-items: center;
        gap: 0.375rem;
        min-width: 0;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
        font-size: 0.75rem; /* #654: schedule, counts and every other fact of a row: 12px */
        color: var(--text-secondary);
    }

    /* Chain Catalog P3.7 (R4): «Menú del grupo», the first fact of a group menu's second line. The line's own color, a
       heavier weight, and it never gives way: the schedule and counts after it do. */
    .mt-from-group[b-26vwipkkos] {
        flex-shrink: 0;
        font-weight: 600;
    }

    .mt-from-group[b-26vwipkkos]::after {
        content: "·";
        margin-left: 0.375rem;
        font-weight: 400;
    }

    /* The status tag (#411: "only tag shown is for menu status... I prefer the Active tag color in
       the mockup vs. solid green"). A dot and a word on a pale fill. Square, like every tag here. */
    .mt-status[b-26vwipkkos] {
        display: inline-flex;
        align-items: center;
        gap: 0.375rem;
        flex-shrink: 0;
        padding: 0.125rem 0.5rem;
        border-radius: 0;
        font-size: 0.75rem;
        font-weight: 600;
        line-height: 1.4;
    }

    .mt-status[b-26vwipkkos]::before {
        content: "";
        width: 0.4375rem;
        height: 0.4375rem;
        border-radius: 50%;
        background: currentColor;
    }

    .mt-status--active[b-26vwipkkos] {
        background: #dcfce7;
        color: #166534;
    }

    .mt-status--inactive[b-26vwipkkos] {
        background: #f1f5f9;
        color: #475569;
    }

    .mt-dash[b-26vwipkkos] {
        color: var(--text-muted);
    }

    /* The subtree's collapse: the same animatable grid row the stacked sections used, clipped with
       `overflow-y: clip`. Clip, not hidden — hidden would make this a scroll container and break the
       pinned Name cells inside it. minmax(0, …) because a bare 0fr is floored by the content's
       min-content size (see the history at .menu-tab-content in app.css). */
    .mt-sub[b-26vwipkkos] {
        display: grid;
        grid-template-rows: minmax(0, 0fr);
        transition: grid-template-rows var(--transition-slow);
    }

    .mt-sub.expanded[b-26vwipkkos] {
        grid-template-rows: minmax(0, 1fr);
    }

    .mt-sub-inner[b-26vwipkkos] {
        min-height: 0;
        overflow-x: visible;
        overflow-y: clip;
    }

    @media (prefers-reduced-motion: reduce) {
        .mt-sub[b-26vwipkkos] {
            transition: none;
        }
    }

    .mt-empty[b-26vwipkkos] {
        padding: 0.875rem 0.75rem 0.875rem 6.25rem;
        border-top: 1px solid var(--pt-card-border, var(--border-color));
        font-size: 0.8125rem;
        color: var(--text-muted);
    }

    @media (prefers-color-scheme: dark) {
        /* Navy is nearly the dark ground (#000075 on #1e293b), so the menu's tile — the tree's anchor —
           read as a hole while the category's pale tile stood out more than the menu it belongs to.
           MenuTreeTableContractTests measured the inversion. The old stacked tree had the same flaw
           (--primary-color is navy in both schemes); the new contract is what surfaced it. Indigo
           keeps the hue, clears the ground, and holds the white glyph at ~6.5:1. */
        .mt-tile--menu[b-26vwipkkos] {
            background: #4338ca;
        }

        .mt-tile--category[b-26vwipkkos] {
            background: rgba(147, 197, 253, 0.18);
            color: var(--pt-navy-fg, #a5b4fc);
        }

        .mt-status--active[b-26vwipkkos] {
            background: rgba(34, 197, 94, 0.16);
            color: #86efac;
        }

        .mt-status--inactive[b-26vwipkkos] {
            background: #334155;
            color: #cbd5e1;
        }
    }

/* =================================================================================================
   Drag to reorder (#178)
   =================================================================================================
   Started as the Tables.razor treatment, which is the one already validated on the Elo. One property
   of it still holds: nothing here changes a row's box, so no row shifts as the indicator toggles under
   the pointer - on a touchscreen that shift reads as the list twitching away from your finger. The
   indicator itself is no longer Tables' inset shadow, and since #442 there is no line either: the drag is
   SortableJS's, and the gap it opens where the row will land is the indicator (app.css, .pt-sort-gap). */

.pt-drag-handle[b-26vwipkkos] {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    /* 44px is the touch floor this codebase holds itself to; the grip glyph is much smaller than
       its target on purpose. */
    min-width: 44px;
    min-height: 44px;
    margin-inline-end: 0.25rem;
    color: var(--text-secondary, #64748b);
    cursor: grab;
    /* A touch on the handle is never a scroll: said up front, so the browser does not start a pan and
       then have to give it up. SortableJS also cancels the page's touchmove while it drags (#442), and
       either alone keeps a finger's drag; MenuSortableContractTests drags by touch. */
    touch-action: none;
    flex: 0 0 auto;
}

/* #401's .pt-drag-slot lived here — the slot a menu or category handle sat in, gliding closed as the
   list expanded, because those handles were offered only while everything was collapsed. #411's
   reorder mode replaced that rule: menus and categories are reordered in their own flat list, the
   tree carries no handle on those rows, and there is nothing left to glide. */

.pt-drag-handle:active[b-26vwipkkos] {
    cursor: grabbing;
}

.pt-drag-handle:focus-visible[b-26vwipkkos] {
    outline: 2px solid var(--pt-coral, #ec607e);
    outline-offset: -2px;
}

/* The gutter that keeps the dish table aligned lives in app.css, NOT here - see the GH-178 block
   there. It has to reach .mi-rowgroup, which MenuItemCard owns, and scoped CSS stamps THIS
   component's id onto the last element of every selector, so a rule written here can never match a
   child component's element. That is not a style preference: the first version of this shipped as
   `.menu-item-wrapper > :last-child` from this file, compiled to `> :last-child[b-<id>]`, matched
   nothing, and every dish row lost its columns. */

/* The row that just landed (#442). It arrives LIFTED, as the drag's clone was (app.css, .pt-sort-lifted:
   scaled up a little and shadowed), and sets itself down, so the drop reads as the row being put in its
   place rather than as the clone vanishing and the row appearing. Cam: "the drop action smoothly settles
   it into place". The shadow is an OUTER one, which the row's children cannot cover (an inset one, as
   GH-251 found, they covered completely).

   It keeps the lifted row's colours all the way down, its opacity included: nothing is painted over it.
   The coral wash that used to follow it, the old flash kept as an "it went here" cue, went on 2026-09-25.
   Cam: "It looks like when the drop is triggered the row becomes red and flashes. When dropping the row
   keep the color treatment the same as it settles into place". */
.pt-row-settled[b-26vwipkkos] {
    position: relative;
    isolation: isolate;
    animation: pt-row-land-b-26vwipkkos 0.32s cubic-bezier(0.2, 0, 0, 1);
}

@keyframes pt-row-land-b-26vwipkkos {
    from {
        opacity: 0.94;
        scale: 1.02;
        box-shadow: 0 12px 28px rgba(15, 23, 42, 0.22), 0 2px 6px rgba(15, 23, 42, 0.12);
    }

    to {
        opacity: 1;
        scale: 1;
        box-shadow: 0 0 0 rgba(15, 23, 42, 0), 0 0 0 rgba(15, 23, 42, 0);
    }
}

/* Reorder feedback strip. */
.menu-reorder-note[b-26vwipkkos] {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.625rem 0.875rem;
    margin-bottom: 0.75rem;
    font-size: 0.875rem;
    border-radius: 0;
}

.menu-reorder-success[b-26vwipkkos] {
    background: rgba(34, 197, 94, 0.12);
    color: #15803d;
    border-inline-start: 3px solid #22c55e;
}

.menu-reorder-error[b-26vwipkkos] {
    background: rgba(236, 96, 126, 0.12);
    color: #9f1239;
    border-inline-start: 3px solid var(--pt-coral, #ec607e);
}

@media (prefers-color-scheme: dark) {
    .pt-drag-handle[b-26vwipkkos] {
        color: var(--text-secondary, #94a3b8);
    }

    /* Both note colours are re-stated rather than inherited: #15803d on the dark panel measures
       about 2.4:1 and #9f1239 about 1.9:1, so the light-mode ink would be a correctness bug here,
       not merely a dull one. */
    .menu-reorder-success[b-26vwipkkos] {
        background: rgba(34, 197, 94, 0.16);
        color: #86efac;
    }

    .menu-reorder-error[b-26vwipkkos] {
        background: rgba(236, 96, 126, 0.16);
        color: #fda4af;
    }
}

/* =================================================================================================
   #411 — REORDER MODE
   =================================================================================================
   Cam's two mockups: a bar ("Drag categories to reorder", Cancel, ✓ Save) over a flat list of the
   scope, and for categories the menu above it with a back arrow. The list reuses the tree's tiles and
   type so a row reads as the same thing it was a moment ago in the tree, and the drag handle is the
   tree's (.pt-drag-handle above) so the drag, the gap and the settle come with it. */
.mt-reorder[b-26vwipkkos] {
    border: 1px solid var(--pt-card-border, var(--border-color));
    background: var(--surface-color);
}

.mt-reorder-context[b-26vwipkkos] {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.625rem 0.75rem;
    background: var(--pt-subhead-bg, var(--background-color));
    border-bottom: 1px solid var(--pt-card-border, var(--border-color));
}

.mt-reorder-back[b-26vwipkkos] {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    flex-shrink: 0;
    padding: 0;
    border: none;
    border-radius: 0;
    background: transparent;
    color: var(--text-primary);
    font-size: 1.125rem;
    cursor: pointer;
}

.mt-reorder-back:hover[b-26vwipkkos] {
    background: var(--background-color);
}

.mt-reorder-back:focus-visible[b-26vwipkkos] {
    outline: 3px solid var(--pt-coral, #ec607e);
    outline-offset: -3px;
}

.mt-reorder-bar[b-26vwipkkos] {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    flex-wrap: wrap;
    padding: 0.625rem 0.75rem;
    background: var(--background-color);
    border-bottom: 1px solid var(--pt-card-border, var(--border-color));
}

.mt-reorder-hint[b-26vwipkkos] {
    font-weight: 600;
    color: var(--text-primary);
}

.mt-reorder-actions[b-26vwipkkos] {
    display: flex;
    gap: 0.75rem;
}

/* Cancelar is outlined and Guardar filled, as in the mockup: Guardar is the one that changes anything,
   so it carries the weight. Both keep the 44px floor and the house's square corners. */
.mt-reorder-cancel[b-26vwipkkos],
.mt-reorder-save[b-26vwipkkos] {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    min-width: 8.5rem;
    min-height: 44px;
    padding-inline: 1.25rem;
    border-radius: 0;
    font-weight: 600;
}

.mt-reorder-cancel[b-26vwipkkos] {
    border: 2px solid var(--text-secondary);
    background: var(--surface-color);
    color: var(--text-primary);
}

.mt-reorder-cancel:hover:not(:disabled)[b-26vwipkkos] {
    background: var(--background-color);
}

.mt-reorder-save[b-26vwipkkos] {
    border: 2px solid var(--pt-navy, #000075);
    background: var(--pt-navy, #000075);
    color: #ffffff;
}

.mt-reorder-save:hover:not(:disabled)[b-26vwipkkos] {
    background: #00005a;
    border-color: #00005a;
}

.mt-reorder-row[b-26vwipkkos] {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    min-height: 4rem;
    padding: 0.5rem 0.75rem;
    border-top: 1px solid var(--pt-card-border, var(--border-color));
    background: var(--surface-color);
}

.mt-reorder-row:first-child[b-26vwipkkos] {
    border-top: none;
}

.mt-reorder-row .mt-tile--category[b-26vwipkkos] {
    margin-left: 0.25rem;
}

@media (prefers-color-scheme: dark) {
    /* Navy is nearly the dark ground — the same trap and answer as .og-action-btn and the menu tile. */
    .mt-reorder-save[b-26vwipkkos] {
        border-color: #c7d2fe;
        background: #c7d2fe;
        color: #111827;
    }

    .mt-reorder-save:hover:not(:disabled)[b-26vwipkkos] {
        border-color: #e0e7ff;
        background: #e0e7ff;
    }
}

/* #442: the landed row does not set itself down for an operator who asked the system for less motion, and
   js/pt-sortable.js turns SortableJS's gliding rows off on the same query. */
@media (prefers-reduced-motion: reduce) {
    .pt-row-settled[b-26vwipkkos] {
        animation: none;
    }
}
/* /Components/Cards/MenuItemCard.razor.rz.scp.css */
/* Chain Catalog P3.7 — a marked dish's name with its mark beneath (MenuItemCard renders it only for a marked row). A
   column that may shrink to the Name cell, so the name takes the ellipsis app.css gives .mi-title and the mark wraps
   between its parts; two short lines sit inside the 44px thumbnail, so the row keeps its height. */

.mi-titles[b-ipucmrfxfg] {
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 0.125rem;
    min-width: 0;
}
/* /Components/Cards/ModifierCategoryEditor.razor.rz.scp.css */
/* The category drawer's content (#287). The drawer shell (.menu-item-panel, .item-drawer, the
   header and footer bands) comes from app.css. What is here matches the modifier editor's own
   content rules, which live in that component's style block and so exist only while it is mounted. */

.mce-body[b-pfgc2itqzo] {
    display: flex;
    flex-direction: column;
    gap: 1rem;
}

.mce-field[b-pfgc2itqzo] {
    display: flex;
    flex-direction: column;
    gap: 0.375rem;
}

.mce-field label[b-pfgc2itqzo] {
    font-size: 0.8rem;
    font-weight: 600;
    color: var(--text-secondary);
}

.mce-field .form-control[b-pfgc2itqzo] {
    min-height: 44px;
    border-radius: 0;
}

.mce-footer[b-pfgc2itqzo] {
    justify-content: flex-end;
    gap: 0.5rem;
}

.mce-cancel[b-pfgc2itqzo],
.mce-save[b-pfgc2itqzo] {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    min-height: 44px;
    padding: 0.5rem 1.25rem;
    border-radius: 0;
    font-weight: 600;
    cursor: pointer;
}

.mce-cancel[b-pfgc2itqzo] {
    background: transparent;
    border: 1px solid var(--border-color);
    color: var(--text-secondary);
}

/* Navy with WHITE text (16:1). Hover keeps the fill and adds a coral ring rather than turning coral:
   white on coral is 3.21:1, under AA, and the modifier editor's Guardar is corrected the same way. */
.mce-save[b-pfgc2itqzo] {
    background: var(--pt-navy, #000075);
    border: none;
    color: #ffffff;
}

@media (hover: hover) {
    .mce-cancel:hover[b-pfgc2itqzo] {
        color: var(--text-primary);
        border-color: var(--text-primary);
    }

    .mce-save:hover:not(:disabled)[b-pfgc2itqzo] {
        box-shadow: inset 0 0 0 2px var(--pt-coral, #ec607e);
    }
}

.mce-save:active:not(:disabled)[b-pfgc2itqzo] {
    box-shadow: inset 0 0 0 2px var(--pt-coral, #ec607e);
}

.mce-save:disabled[b-pfgc2itqzo] {
    opacity: 0.6;
    cursor: not-allowed;
}

.mce-cancel:focus-visible[b-pfgc2itqzo],
.mce-save:focus-visible[b-pfgc2itqzo] {
    outline: 3px solid var(--pt-coral, #ec607e);
    outline-offset: 2px;
}
/* /Components/Cards/ModifierLibraryTab.razor.rz.scp.css */
/* The Modificadores tab (#287), in the Menús tree's grammar.

   Values are the tree's own (MenuDisplayCard.razor.css): the list bar, row heights, chevron, tile,
   title and meta type, and the dash in cells a parent row does not fill. They are copied rather than
   shared because scoped CSS cannot reach into another component. The header IS shared outright
   (.mi-thead in app.css). ModifierLibraryPageContractTests measures the pairs, so the copies cannot
   drift apart quietly. */

.ml-page[b-6uy7lb4hhe] {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
}

/* ---- The list bar: the Menús tab's, value for value -------------------------------------------- */

/* #438: the search stops at 576px, and space-between keeps Crear at the bar's end, as on the Menús
   tab (MenuDisplayCard.razor.css says why). */
.ml-listbar[b-6uy7lb4hhe] {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
}

.ml-search[b-6uy7lb4hhe] {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    flex: 1;
    min-width: 0;
    max-width: 576px;
    min-height: var(--pt-control-min-height);
    padding: 0 0.875rem;
    background: var(--surface-color);
    /* #593: the field border and the field focus, as the Menús tab's search. */
    border: 2px solid var(--pt-field-border);
    border-radius: 0;
}

.ml-search:focus-within[b-6uy7lb4hhe] {
    border-color: var(--pt-field-focus);
}

.ml-search-icon[b-6uy7lb4hhe] {
    color: var(--text-secondary);
    font-size: 1rem;
    flex-shrink: 0;
}

.ml-search-input[b-6uy7lb4hhe] {
    flex: 1;
    min-width: 0;
    border: none;
    outline: none;
    background: transparent;
    color: var(--text-primary);
    font-size: 0.95rem;
}

.ml-search-input[b-6uy7lb4hhe]::placeholder {
    color: var(--text-secondary);
}

.ml-search-clear[b-6uy7lb4hhe] {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    border: none;
    background: transparent;
    color: var(--text-secondary);
    cursor: pointer;
}

.ml-search-clear:focus-visible[b-6uy7lb4hhe] {
    outline: 3px solid var(--pt-coral, #ec607e);
    outline-offset: 0;
}

/* Below 576px the field takes its own line, as on the Menús tab. */
@media (max-width: 575.98px) {
    .ml-listbar[b-6uy7lb4hhe] {
        flex-wrap: wrap;
    }

    .ml-listbar > .ml-search[b-6uy7lb4hhe] {
        flex-basis: 100%;
    }
}

.ml-hint[b-6uy7lb4hhe] {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin: 0;
    font-size: 0.8125rem;
    color: var(--text-secondary);
}

.ml-hint > i[b-6uy7lb4hhe] {
    flex-shrink: 0;
    color: var(--pt-coral, #ec607e);
}

/* ---- The table ---------------------------------------------------------------------------------- */

.ml-scroll[b-6uy7lb4hhe] {
    overflow-x: auto;
    border: 1px solid var(--pt-card-border, var(--border-color));
    background: var(--surface-color);
}

/* Six columns want about 50rem. Below that the table scrolls sideways, as the tree does, rather
   than crushing the options column to nothing. */
.ml-table[b-6uy7lb4hhe] {
    min-width: max(100%, 50rem);
}

.ml-row[b-6uy7lb4hhe] {
    display: grid;
    grid-template-columns: var(--mi-cols);
    align-items: center;
    gap: 0.5rem;
    padding: 0 0.75rem;
    border-top: 1px solid var(--pt-card-border, var(--border-color));
    background: var(--surface-color);
    cursor: pointer;
}

/* #508: both the tree's row height. */
.ml-row--category[b-6uy7lb4hhe] {
    min-height: 4.25rem;
}

.ml-row--modifier[b-6uy7lb4hhe] {
    min-height: 4.25rem;
}

.ml-row:hover[b-6uy7lb4hhe] {
    background: var(--background-color);
}

.ml-name[b-6uy7lb4hhe] {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    min-width: 0;
}

/* A modifier sits under its category's tile: one chevron (2rem) plus the gap, the step the tree
   draws between a menu and its categories. */
.ml-row--modifier .ml-name[b-6uy7lb4hhe] {
    padding-left: 2.5rem;
}

.ml-chevron[b-6uy7lb4hhe] {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2rem;
    height: 2rem;
    flex-shrink: 0;
    color: var(--text-primary);
    font-size: 1rem;
    transition: transform var(--transition-slow);
}

.ml-chevron--open[b-6uy7lb4hhe] {
    transform: rotate(90deg);
}

@media (prefers-reduced-motion: reduce) {
    .ml-chevron[b-6uy7lb4hhe] {
        transition: none;
    }
}

.ml-tile[b-6uy7lb4hhe] {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    width: 2.25rem;
    height: 2.25rem;
    border-radius: 0;
    /* Half the tile's width, as Crear's folder is (Cam, 2026-09-25: "increase the size of the Folder
       icon", app.css .action-icon-modifier-folder): 18px of folder in 36px. It was 1rem, 16px. */
    font-size: 1.125rem;
}

/* #436's rules for a Bootstrap Icon in this tile went with the icon: the folder is Cam's PtIcon glyph now
   (#451), which the global .pt-icon rule seats as an exact 1em box, and the tile's flex centres that. A
   scoped rule here could not reach it anyway: PtIcon's element carries PtIcon's scope, not this page's. */

/* A modifier folder's tile (#451, Cam): #EEEFFD with the folder in #5B55D6, 4.9:1. It wore the menu
   tree's category blue until then; a folder of modifiers is its own thing, and Crear's entry for one
   wears the same pair (app.css, .action-icon-modifier-folder). */
.ml-tile--category[b-6uy7lb4hhe] {
    background: #eeeffd;
    color: #5b55d6;
}

/* "Sin categoría" is a group, not a category the operator made: neutral, so it never reads as one. */
.ml-tile--none[b-6uy7lb4hhe] {
    background: #f1f5f9;
    color: #475569;
}

.ml-text[b-6uy7lb4hhe] {
    display: flex;
    flex-direction: column;
    gap: 0.1875rem;
    min-width: 0;
}

/* #507: 14px from the folder to the text, as the tree. After a tile only: a modifier's row has none, and
   its name sits under its category's tile. */
.ml-tile + .ml-text[b-6uy7lb4hhe] {
    margin-left: 0.375rem;
}

.ml-title[b-6uy7lb4hhe] {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-weight: 600;
    font-size: 0.875rem; /* #654: the tree's category name, 14px */
    color: var(--text-primary);
}

.ml-row--inactive .ml-title[b-6uy7lb4hhe] {
    color: var(--text-secondary);
}

.ml-meta[b-6uy7lb4hhe] {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: 0.75rem; /* #654: the tree's metadata, 12px */
    color: var(--text-secondary);
}

.ml-dash[b-6uy7lb4hhe] {
    color: var(--text-muted);
}

.ml-num[b-6uy7lb4hhe] {
    text-align: right;
}

/* The usage column is centred. Right-aligned, "USADO EN" ran straight into the left-aligned
   "ACTIVO" beside it, and the parent row's two dashes read as one. */
.ml-center[b-6uy7lb4hhe] {
    text-align: center;
}

.ml-options[b-6uy7lb4hhe] {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: 0.8125rem;
    color: var(--text-secondary);
}

.ml-options--none[b-6uy7lb4hhe] {
    font-style: italic;
}

.ml-price[b-6uy7lb4hhe] {
    font-size: 0.875rem;
    font-weight: 600;
    color: var(--text-primary);
}

.ml-toggle[b-6uy7lb4hhe] {
    display: inline-flex;
    align-items: center;
}

.ml-act[b-6uy7lb4hhe] {
    display: inline-flex;
    justify-content: flex-end;
}

/* Secondary text, not muted: these are sentences the operator reads, and --text-muted is under the
   4.5:1 floor for text. */
.ml-group-empty[b-6uy7lb4hhe] {
    padding: 0.875rem 0.75rem 0.875rem 3.25rem;
    border-top: 1px solid var(--pt-card-border, var(--border-color));
    font-size: 0.8125rem;
    color: var(--text-secondary);
}

.ml-none[b-6uy7lb4hhe] {
    padding: 1rem 0.75rem;
    border-top: 1px solid var(--pt-card-border, var(--border-color));
    font-size: 0.875rem;
    color: var(--text-secondary);
}

.ml-empty[b-6uy7lb4hhe] {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.5rem;
    padding: 2.5rem 1rem;
    border: 1px solid var(--pt-card-border, var(--border-color));
    background: var(--surface-color);
    text-align: center;
    color: var(--text-secondary);
}

.ml-empty > i[b-6uy7lb4hhe] {
    font-size: 2rem;
    color: var(--text-secondary);
}

.ml-empty > p[b-6uy7lb4hhe] {
    margin: 0;
}

@media (prefers-color-scheme: dark) {
    /* The folder's tile in dark mode: its own indigo as a tint, with a light indigo folder, the way
       the tree's category tile goes dark. */
    .ml-tile--category[b-6uy7lb4hhe] {
        background: rgba(91, 85, 214, 0.28);
        color: #c4c1f7;
    }

    .ml-tile--none[b-6uy7lb4hhe] {
        background: #334155;
        color: #cbd5e1;
    }
}
/* /Components/Cards/RestaurantFeatureFlagsCard.razor.rz.scp.css */
    .current-font-badge[b-s8f8k05emh] {
        display: inline-flex;
        align-items: center;
        gap: 4px;
        margin-top: 6px;
        padding: 3px 8px;
        background: rgba(40, 167, 69, 0.15);
        color: #28a745;
        border-radius: 0;
        font-size: 0.8rem;
        font-weight: 500;
    }

    .current-font-badge i[b-s8f8k05emh] {
        font-size: 0.75rem;
    }
    
    .feature-icon.font-icon[b-s8f8k05emh] {
        background: linear-gradient(135deg, #6f42c1, #9b59b6) !important;
    }

    .feature-icon.call-waiter[b-s8f8k05emh] {
        background: linear-gradient(135deg, #ec607e, #e74c6f) !important;
    }

    .feature-icon.kitchen-ready[b-s8f8k05emh] {
        background: linear-gradient(135deg, #17a2b8, #138496) !important;
    }

    .feature-icon.kitchen-capacity[b-s8f8k05emh] {
        background: linear-gradient(135deg, #000075, #2c2ca3) !important;
    }

    .feature-icon.fee-system[b-s8f8k05emh] {
        background: linear-gradient(135deg, #28a745, #218838) !important;
    }

    .feature-icon.guest-approval[b-s8f8k05emh] {
        background: linear-gradient(135deg, #ec607e, #b8456a) !important;
    }

    .feature-icon.coursing[b-s8f8k05emh] {
        background: linear-gradient(135deg, #6f42c1, #5a32a3) !important;
    }

    .feature-icon.incremental-course-payment[b-s8f8k05emh] {
        background: linear-gradient(135deg, #fd7e14, #d96911) !important;
    }

    /* Navy, matching the "Transferencia" chip in TabDetailModal and the SPEI screen in
       the guest app — one tender, one colour across all three surfaces. */
    .feature-icon.bank-transfer[b-s8f8k05emh] {
        background: linear-gradient(135deg, #000075, #3a3ab5) !important;
    }

    .feature-icon.cfdi-invoicing[b-s8f8k05emh] {
        background: linear-gradient(135deg, #000075, #ec607e) !important;
    }

    .feature-icon.require-fulfillment[b-s8f8k05emh] {
        background: linear-gradient(135deg, #28a745, #1e7e34) !important;
    }

    .feature-icon.order-scheduling[b-s8f8k05emh] {
        background: linear-gradient(135deg, #000075, #ec607e) !important;
    }

    .feature-icon.require-open-shift[b-s8f8k05emh] {
        background: linear-gradient(135deg, #ec607e, #000075) !important;
    }

    .mutex-hint[b-s8f8k05emh] {
        display: flex;
        align-items: flex-start;
        gap: 6px;
        margin-top: 8px;
        padding: 8px 10px;
        background: rgba(108, 117, 125, 0.1);
        color: #6c757d;
        border-left: 3px solid #6c757d;
        border-radius: 0;
        font-size: 0.82rem;
        font-style: italic;
    }

    .mutex-hint i[b-s8f8k05emh] {
        font-size: 0.95rem;
        margin-top: 1px;
    }

    @media (prefers-color-scheme: dark) {
        .mutex-hint[b-s8f8k05emh] {
            background: rgba(173, 181, 189, 0.12);
            color: #adb5bd;
            border-left-color: #adb5bd;
        }
    }
    
    @media (prefers-color-scheme: dark) {
        .current-font-badge[b-s8f8k05emh] {
            background: rgba(40, 167, 69, 0.25);
        }
    }
/* /Components/Catalog/CatalogDishNotice.razor.rz.scp.css */
/* Chain Catalog P3.8 (S5a) — a group dish's notice in its editor. On the app.css tokens, as the strip above the tree:
   text --text-primary and --text-secondary on --surface-color, a navy edge on the left. */

.cdn[b-m8u5llasgv] {
    display: flex;
    gap: 0.625rem;
    align-items: flex-start;
    margin: 0 0 0.75rem;
    padding: 0.625rem 0.75rem;
    background: var(--surface-color, #ffffff);
    border: 1px solid var(--border-color, #e2e8f0);
    border-left: 4px solid var(--pt-navy-fg, #1e3a5f);
    color: var(--text-secondary, #64748b);
    font-size: 0.8125rem;
    line-height: 1.35;
}

.cdn-icon[b-m8u5llasgv] {
    color: var(--text-primary, #1e293b);
    font-size: 1rem;
    margin-top: 0.0625rem;
}

.cdn-text[b-m8u5llasgv] {
    display: flex;
    flex-direction: column;
    gap: 0.125rem;
    min-width: 0;
}

.cdn-text strong[b-m8u5llasgv] {
    color: var(--text-primary, #1e293b);
    font-weight: 600;
}

.cdn-hidden[b-m8u5llasgv] {
    color: var(--text-primary, #1e293b);
    font-weight: 600;
}
/* /Components/Catalog/CatalogGroupValue.razor.rz.scp.css */
/* Chain Catalog P3.8 (S5a) — the group's value under a field the location took over, or why the field is read-only. The
   field hint's own secondary text; «Restablecer» a text button in the navy the drawer's links use (--pt-navy-fg). */

.cgv[b-esr5zo6vrj] {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.25rem 0.5rem;
    font-size: 0.75rem;
    color: var(--text-secondary, #64748b);
}

.cgv-reset[b-esr5zo6vrj] {
    padding: 0;
    border: 0;
    background: none;
    font-size: 0.75rem;
    font-weight: 600;
    color: var(--pt-navy-fg, #1e3a5f);
    text-decoration: underline;
    cursor: pointer;
}

.cgv-reset:disabled[b-esr5zo6vrj] {
    cursor: default;
    opacity: 0.6;
}

/* P3.40 (#642): why «Restablecer» waits, on its own line, since a disabled button's tooltip needs a pointer. */
.cgv-blocked[b-esr5zo6vrj] {
    font-style: italic;
}
/* /Components/Catalog/CatalogLocationStrip.razor.rz.scp.css */
/* Chain Catalog P3.7 — what a linked location hid, above its menu tree. On the app.css tokens, as «Retirados» is, so
   light and dark read alike: names --text-primary, the rest --text-secondary, on --surface-color. Straight edges; the
   button is the house outline-navy at its small size. */

.cls[b-p3w6t2nvb5] {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    margin-bottom: 0.75rem;
    padding: 0.75rem 0.875rem;
    background: var(--surface-color, #ffffff);
    border: 1px solid var(--border-color, #e2e8f0);
    color: var(--text-secondary, #64748b);
    font-size: 0.875rem;
}

.cls--failed[b-p3w6t2nvb5] {
    flex-direction: row;
    align-items: center;
    border-left: 4px solid var(--pt-warning, #f59e0b);
    color: var(--text-primary, #1e293b);
}

.cls-title[b-p3w6t2nvb5] {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    font-weight: 600;
    color: var(--text-primary, #1e293b);
}

.cls-list[b-p3w6t2nvb5] {
    list-style: none;
    margin: 0;
    padding: 0;
}

.cls-item[b-p3w6t2nvb5] {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 0.375rem 1rem;
    padding: 0.375rem 0;
    border-top: 1px solid var(--border-color, #e2e8f0);
}

.cls-item:first-child[b-p3w6t2nvb5] {
    border-top: none;
}

.cls-what[b-p3w6t2nvb5] {
    display: flex;
    align-items: baseline;
    gap: 0.5rem;
    min-width: 0;
}

.cls-name[b-p3w6t2nvb5] {
    font-weight: 600;
    color: var(--text-primary, #1e293b);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.cls-kind[b-p3w6t2nvb5] {
    white-space: nowrap;
}
/* /Components/Catalog/CatalogMark.razor.rz.scp.css */
/* Chain Catalog P3.7 — a row's catalog mark, under the row's name (MenuItemCard's .mi-titles, the library's .ml-text). The
   tree's own secondary text (--text-secondary, as .mt-meta), so it reads as a fact about the row rather than a second
   tag, in light and dark alike. Its parts never break inside; a mark wider than its cell wraps between them. */

.cat-mark[b-hyqg1673wb] {
    display: inline-flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.125rem 0.375rem;
    min-width: 0;
    font-size: 0.75rem;
    font-weight: 500;
    line-height: 1.2;
    color: var(--text-secondary, #64748b);
}

.cat-mark-part[b-hyqg1673wb] {
    white-space: nowrap;
}

.cat-mark-part--hidden[b-hyqg1673wb] {
    font-weight: 700;
}

.cat-mark-part + .cat-mark-part[b-hyqg1673wb]::before {
    content: "·";
    margin-right: 0.375rem;
    font-weight: 500;
}
/* /Components/Catalog/CatalogNotice.razor.rz.scp.css */
/* Chain Catalog P3.8 (S5c) — a group row's notice in its editor, as a group dish's (CatalogDishNotice): text
   --text-primary and --text-secondary on --surface-color, a navy edge on the left. */

.ctn[b-943ezx06go] {
    display: flex;
    gap: 0.625rem;
    align-items: flex-start;
    margin: 0 0 0.75rem;
    padding: 0.625rem 0.75rem;
    background: var(--surface-color, #ffffff);
    border: 1px solid var(--border-color, #e2e8f0);
    border-left: 4px solid var(--pt-navy-fg, #1e3a5f);
    color: var(--text-secondary, #64748b);
    font-size: 0.8125rem;
    line-height: 1.35;
}

.ctn-icon[b-943ezx06go] {
    color: var(--text-primary, #1e293b);
    font-size: 1rem;
    margin-top: 0.0625rem;
}

.ctn-text[b-943ezx06go] {
    display: flex;
    flex-direction: column;
    gap: 0.125rem;
    min-width: 0;
}

.ctn-text strong[b-943ezx06go] {
    color: var(--text-primary, #1e293b);
    font-weight: 600;
}
/* /Components/Catalog/CatalogRowHideToggle.razor.rz.scp.css */
/* Chain Catalog P3.8 (S5b) — «Ocultar» / «Oculto · Mostrar» in place of a group modifier's or option's remove button. A
   text button in the drawer's link navy, so it does not read as the red remove it replaces; «Oculto» the drawer's own text. */

.crh[b-en9h7fsy28] {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    white-space: nowrap;
}

.crh-hidden[b-en9h7fsy28] {
    font-size: 0.75rem;
    font-weight: 700;
    color: var(--text-primary, #1e293b);
}

.crh-btn[b-en9h7fsy28] {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    min-height: 32px;
    padding: 0 0.5rem;
    border: 1px solid var(--pt-navy-fg, #1e3a5f);
    background: transparent;
    font-size: 0.75rem;
    font-weight: 600;
    color: var(--pt-navy-fg, #1e3a5f);
    white-space: nowrap;
    cursor: pointer;
}

.crh-btn:disabled[b-en9h7fsy28] {
    cursor: default;
    opacity: 0.6;
}
/* /Components/Catalog/GroupCatalogSection.razor.rz.scp.css */
/* Chain Catalog P3.22, P3.38 — the «Menú del grupo» section. The section frame is Config's own (config-group, config-section,
   and the card whose body Config pads to 1.25rem, as every section's content); these are the parts inside it, on the app.css
   tokens so light and dark read alike, like the panel's. The actions' and the picker's 44px and straight edges are app.css's
   (.btn and .app-layout .form-select); nothing here restates them. */

.gcs-pick[b-0hioj43411] {
    display: flex;
    flex-direction: column;
    gap: 0.375rem;
    max-width: 28rem;
    margin-bottom: 1rem;
}

.gcs-label[b-0hioj43411] {
    margin: 0;
    font-size: 0.875rem;
    font-weight: 600;
    color: var(--text-primary, #1e293b);
}

.gcs-owner[b-0hioj43411] {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
}

.gcs-owner-head[b-0hioj43411] {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
}

.gcs-name[b-0hioj43411] {
    font-size: 1.0625rem;
    font-weight: 600;
    color: var(--pt-navy-fg, #000075);
}

.gcs-meta[b-0hioj43411] {
    display: flex;
    align-items: center;
    font-size: 0.875rem;
    color: var(--text-secondary, #64748b);
}

.gcs-note[b-0hioj43411] {
    margin: 0;
    font-size: 0.875rem;
    color: var(--text-secondary, #64748b);
}

.gcs-actions[b-0hioj43411] {
    display: flex;
    flex-wrap: wrap;
    gap: 0.75rem;
}

.gcs-muted[b-0hioj43411] {
    color: var(--text-secondary, #64748b);
    font-size: 0.875rem;
}

/* A phone: the two actions stack at the same full width. A label may wrap there (the section is ~286px wide), so the button
   is a block and its icon flows with the words, on the first line, instead of standing beside the wrapped label. */
@media (max-width: 576px) {
    .gcs-action[b-0hioj43411] {
        display: block;
        flex: 1 1 100%;
        text-align: center;
        white-space: normal;
    }
}
/* /Components/Catalog/GroupDishSalesCard.razor.rz.scp.css */
/* Chain Catalog P5.6 — «Ventas por platillo». Scoped, on the app.css tokens like the page it sits in (PG5d-7), so light and
   dark read alike. The period's fields and «Ver» are app.css's .form-control and .btn, 44px and straight-edged as they come
   (GroupDishSalesContractTests measures it). A wide group scrolls inside .gds-scroll, never the page, and the dish column
   stays in view while it does. */
.gds[b-au0usirfr9] {
    display: flex;
    flex-direction: column;
    gap: 1rem;
}
.gds-head[b-au0usirfr9] {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
}
.gds-title[b-au0usirfr9] {
    margin: 0;
    font-size: 1.125rem;
    font-weight: 600;
    color: var(--pt-navy-fg, #000075);
}
.gds-note[b-au0usirfr9] {
    margin: 0;
    font-size: 0.875rem;
    color: var(--text-secondary, #64748b);
}

.gds-period[b-au0usirfr9] {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: 0.75rem;
}
.gds-field[b-au0usirfr9] {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    margin: 0;
}
.gds-label[b-au0usirfr9] {
    font-size: 0.875rem;
    color: var(--text-secondary, #64748b);
}

.gds-state[b-au0usirfr9] {
    padding: 0.75rem 1rem;
    background: var(--surface-color, #ffffff);
    color: var(--text-primary, #1e293b);
    border: 1px solid var(--pt-card-border, #cbd5e1);
}
.gds-failed[b-au0usirfr9] {
    padding: 0.75rem 1rem;
    background: var(--surface-color, #ffffff);
    color: var(--pt-field-invalid-text, #b91c1c);
    border: 1px solid var(--pt-card-border, #cbd5e1);
    border-left: 3px solid var(--pt-field-invalid, #ef4444);
}

.gds-scroll[b-au0usirfr9] {
    max-width: 100%;
    overflow-x: auto;
    border: 1px solid var(--pt-card-border, #cbd5e1);
    background: var(--surface-color, #ffffff);
}
.gds-table[b-au0usirfr9] {
    width: 100%;
    border-collapse: collapse;
    color: var(--text-primary, #1e293b);
    font-variant-numeric: tabular-nums;
}
.gds-table th[b-au0usirfr9],
.gds-table td[b-au0usirfr9] {
    padding: 0.5rem 0.75rem;
    border-bottom: 1px solid var(--pt-card-border, #cbd5e1);
    vertical-align: top;
}
.gds-table thead th[b-au0usirfr9] {
    font-size: 0.8125rem;
    font-weight: 600;
    color: var(--text-secondary, #64748b);
    white-space: nowrap;
}
.gds-dish[b-au0usirfr9] {
    position: sticky;
    left: 0;
    z-index: 1;
    min-width: 10rem;
    text-align: left;
    font-weight: 500;
    background: var(--surface-color, #ffffff);
}
.gds-member-name[b-au0usirfr9] {
    display: block;
    color: var(--text-primary, #1e293b);
}
.gds-coverage[b-au0usirfr9] {
    display: block;
    margin-top: 0.125rem;
    font-weight: 400;
    color: var(--pt-status-pending-fg, #856404);
}
.gds-units[b-au0usirfr9] {
    text-align: right;
    white-space: nowrap;
}
.gds-none[b-au0usirfr9] {
    color: var(--text-secondary, #64748b);
}
.gds-total[b-au0usirfr9] {
    font-weight: 600;
}
.gds-table tfoot th[b-au0usirfr9],
.gds-table tfoot td[b-au0usirfr9] {
    border-bottom: 0;
    border-top: 2px solid var(--pt-card-border, #cbd5e1);
}
/* /Components/Catalog/GroupMenuBanner.razor.rz.scp.css */
/* Chain Catalog P3.2 — the group menu's banner. On the app.css tokens, so light and dark read alike:
   the title is --pt-navy-fg on --surface-color (16.7:1 light, 7.3:1 dark), the note --text-secondary
   (4.8:1 light, 9.9:1 dark), and the navy rule is a 4px edge, not text. */

.gm-banner[b-ma4mv01bll] {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem 1rem;
    margin-bottom: 0.75rem;
    padding: 0.625rem 0.875rem;
    background: var(--surface-color, #ffffff);
    border: 1px solid var(--border-color, #e2e8f0);
    border-left: 4px solid var(--pt-navy-fg, #000075);
}

.gm-text[b-ma4mv01bll] {
    display: flex;
    flex-direction: column;
    gap: 0.125rem;
    min-width: 0;
}

.gm-title[b-ma4mv01bll] {
    font-weight: 600;
    color: var(--pt-navy-fg, #000075);
}

.gm-note[b-ma4mv01bll] {
    font-size: 0.8125rem;
    color: var(--text-secondary, #64748b);
}

/* P3.23: the switch to the other group place sits beside the way out, and wraps under it on a phone. */
.gm-actions[b-ma4mv01bll] {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
}

.gm-leave[b-ma4mv01bll],
.gm-switch[b-ma4mv01bll] {
    min-height: 44px;
}
/* /Components/Catalog/GroupMenuPublishTab.razor.rz.scp.css */
/* Chain Catalog P3.10 — the group menu's «Publicación», beside «Retirados» (gmr-*) and on the same app.css tokens, so light
   and dark read alike. The chips are the order board's status pairs (#379): ready green, pending amber and done grey,
   each 4.5:1 or better in both themes. A failure is an outline in --pt-destructive with --pt-destructive-fg text on the
   surface (4.83:1 light, 5.29:1 dark), never red on a red fill. The banner is the warning callout: --text-primary on
   --pt-warning-bg. Straight edges; the main buttons are 44px high. */

.gmp[b-4qv0jtwqq1] {
    display: flex;
    flex-direction: column;
    gap: 1rem;
}

.gmp-note[b-4qv0jtwqq1],
.gmp-sub[b-4qv0jtwqq1] {
    margin: 0;
    font-size: 0.875rem;
    color: var(--text-secondary, #64748b);
}

.gmp-section[b-4qv0jtwqq1] {
    display: flex;
    flex-direction: column;
    gap: 0.625rem;
    padding: 0.875rem;
    background: var(--surface-color, #ffffff);
    border: 1px solid var(--border-color, #e2e8f0);
}

.gmp-h[b-4qv0jtwqq1] {
    margin: 0;
    font-size: 1rem;
    font-weight: 600;
    color: var(--text-primary, #1e293b);
}

.gmp-bar[b-4qv0jtwqq1] {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem 1rem;
}

.gmp-publish[b-4qv0jtwqq1] {
    justify-content: flex-start;
    padding-top: 0.5rem;
    border-top: 1px solid var(--border-color, #e2e8f0);
}

.gmp-btn[b-4qv0jtwqq1] {
    min-height: 44px;
    border-radius: 0;
    white-space: nowrap;
}

.gmp-banner[b-4qv0jtwqq1] {
    display: flex;
    flex-wrap: wrap;
    gap: 0.25rem 0.5rem;
    padding: 0.75rem 0.875rem;
    color: var(--text-primary, #1e293b);
    background: var(--pt-warning-bg, #fef3c7);
    border-left: 4px solid var(--pt-warning-border, #fbbf24);
}

.gmp-failed[b-4qv0jtwqq1] {
    padding: 0.75rem 0.875rem;
    color: var(--pt-destructive-fg, #dc2626);
    background: var(--surface-color, #ffffff);
    border: 1px solid var(--pt-destructive, #ef4444);
    border-left-width: 4px;
}

.gmp-state[b-4qv0jtwqq1] {
    padding: 0.75rem 0.875rem;
    color: var(--text-secondary, #64748b);
    border: 1px dashed var(--border-color, #e2e8f0);
}

/* ---- Destinos: the menus-by-locations grid scrolls sideways inside its section, never the page. */

.gmp-grid-wrap[b-4qv0jtwqq1] {
    overflow-x: auto;
}

.gmp-grid[b-4qv0jtwqq1] {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.875rem;
    color: var(--text-primary, #1e293b);
}

.gmp-grid th[b-4qv0jtwqq1],
.gmp-grid td[b-4qv0jtwqq1] {
    padding: 0.5rem 0.625rem;
    border-bottom: 1px solid var(--border-color, #e2e8f0);
    vertical-align: middle;
}

.gmp-grid thead th[b-4qv0jtwqq1] {
    font-weight: 600;
    text-align: center;
    white-space: nowrap;
    background: var(--pt-subhead-bg, #fafbfd);
}

.gmp-grid thead th:first-child[b-4qv0jtwqq1],
.gmp-menu[b-4qv0jtwqq1] {
    text-align: left;
    font-weight: 600;
}

.gmp-pick[b-4qv0jtwqq1] {
    text-align: center;
}

.gmp-row-actions[b-4qv0jtwqq1] {
    text-align: right;
    white-space: nowrap;
}

.gmp-row-actions .btn[b-4qv0jtwqq1] {
    border-radius: 0;
    margin-left: 0.25rem;
}

.gmp-row-failed[b-4qv0jtwqq1] {
    font-size: 0.8125rem;
}

/* ---- Estaciones (P3.11): the location picker; the panel styles itself (gms-*) */

.gmp-stations-pick[b-4qv0jtwqq1] {
    justify-content: flex-start;
}

.gmp-select[b-4qv0jtwqq1] {
    flex: 0 1 20rem;
    min-height: 44px;
    border-radius: 0;
}

.gmp-map[b-4qv0jtwqq1] {
    align-self: flex-start;
    border-radius: 0;
}

/* ---- the preview's locations and the publications */

.gmp-list[b-4qv0jtwqq1],
.gmp-targets[b-4qv0jtwqq1],
.gmp-lines[b-4qv0jtwqq1] {
    list-style: none;
    margin: 0;
    padding: 0;
}

.gmp-list[b-4qv0jtwqq1] {
    border: 1px solid var(--border-color, #e2e8f0);
}

.gmp-item[b-4qv0jtwqq1] {
    display: flex;
    flex-direction: column;
    gap: 0.375rem;
    padding: 0.75rem 0.875rem;
    border-top: 1px solid var(--border-color, #e2e8f0);
}

.gmp-item:first-child[b-4qv0jtwqq1] {
    border-top: none;
}

.gmp-head[b-4qv0jtwqq1] {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.25rem 0.625rem;
}

.gmp-what[b-4qv0jtwqq1] {
    font-weight: 600;
    color: var(--text-primary, #1e293b);
    overflow-wrap: anywhere;
}

.gmp-name[b-4qv0jtwqq1] {
    font-weight: 500;
    color: var(--text-primary, #1e293b);
    overflow-wrap: anywhere;
}

.gmp-when[b-4qv0jtwqq1],
.gmp-detail[b-4qv0jtwqq1] {
    font-size: 0.8125rem;
    color: var(--text-secondary, #64748b);
    overflow-wrap: anywhere;
}

.gmp-retry[b-4qv0jtwqq1] {
    margin-left: auto;
    border-radius: 0;
}

.gmp-targets[b-4qv0jtwqq1] {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    padding-left: 0.875rem;
    border-left: 2px solid var(--border-color, #e2e8f0);
}

.gmp-target[b-4qv0jtwqq1] {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
}

.gmp-chip[b-4qv0jtwqq1],
.gmp-tag[b-4qv0jtwqq1] {
    display: inline-block;
    padding: 0.125rem 0.5rem;
    font-size: 0.75rem;
    font-weight: 600;
    line-height: 1.4;
    border: 1px solid transparent;
}

.gmp-tag[b-4qv0jtwqq1] {
    color: var(--pt-status-done-fg, #41464b);
    background: var(--pt-status-done-bg, #e9ecef);
    border-color: var(--pt-status-done-border, #ced4da);
}

.gmp-chip--ready[b-4qv0jtwqq1] {
    color: var(--pt-status-ready-fg, #155724);
    background: var(--pt-status-ready-bg, #d4edda);
    border-color: var(--pt-status-ready-border, #b7e0c6);
}

.gmp-chip--pending[b-4qv0jtwqq1] {
    color: var(--pt-status-pending-fg, #856404);
    background: var(--pt-status-pending-bg, #fff3cd);
    border-color: var(--pt-status-pending-border, #ffe69c);
}

.gmp-chip--done[b-4qv0jtwqq1] {
    color: var(--pt-status-done-fg, #41464b);
    background: var(--pt-status-done-bg, #e9ecef);
    border-color: var(--pt-status-done-border, #ced4da);
}

.gmp-chip--bad[b-4qv0jtwqq1] {
    color: var(--pt-destructive-fg, #dc2626);
    background: var(--surface-color, #ffffff);
    border-color: var(--pt-destructive, #ef4444);
}

.gmp-issues[b-4qv0jtwqq1] {
    font-size: 0.8125rem;
    color: var(--text-primary, #1e293b);
}

.gmp-issues-title[b-4qv0jtwqq1] {
    font-weight: 600;
}

.gmp-lines li[b-4qv0jtwqq1] {
    padding-left: 0.75rem;
    overflow-wrap: anywhere;
}

.gmp-error summary[b-4qv0jtwqq1] {
    cursor: pointer;
    font-size: 0.8125rem;
    color: var(--text-secondary, #64748b);
}

.gmp-error pre[b-4qv0jtwqq1] {
    margin: 0.25rem 0 0;
    padding: 0.5rem 0.625rem;
    max-height: 12rem;
    overflow: auto;
    font-family: monospace;
    font-size: 0.75rem;
    white-space: pre-wrap;
    overflow-wrap: anywhere;
    color: var(--text-primary, #1e293b);
    background: var(--pt-subhead-bg, #fafbfd);
    border: 1px solid var(--border-color, #e2e8f0);
}
/* /Components/Catalog/GroupMenuRetiredTab.razor.rz.scp.css */
/* Chain Catalog P3.26 — the group menu's «Retirados». On the app.css tokens, so light and dark read alike: the chip is
   the board's ENTREGADO pair (--pt-status-done-fg on -bg, 4.5:1 or better light, 8.84:1 dark), the headline
   --text-primary and the details --text-secondary on --surface-color. Straight edges; the button is 44px high. */

.gmr[b-022k8o9u0k] {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
}

.gmr-note[b-022k8o9u0k] {
    margin: 0;
    font-size: 0.875rem;
    color: var(--text-secondary, #64748b);
}

.gmr-state[b-022k8o9u0k] {
    padding: 1rem;
    background: var(--surface-color, #ffffff);
    border: 1px solid var(--border-color, #e2e8f0);
    color: var(--text-secondary, #64748b);
}

.gmr-state--failed[b-022k8o9u0k] {
    border-left: 4px solid var(--pt-destructive, #ef4444);
    color: var(--text-primary, #1e293b);
}

.gmr-list[b-022k8o9u0k] {
    list-style: none;
    margin: 0;
    padding: 0;
    border: 1px solid var(--border-color, #e2e8f0);
    background: var(--surface-color, #ffffff);
}

.gmr-item[b-022k8o9u0k] {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem 1rem;
    padding: 0.75rem 0.875rem;
    border-top: 1px solid var(--border-color, #e2e8f0);
}

.gmr-item:first-child[b-022k8o9u0k] {
    border-top: none;
}

.gmr-main[b-022k8o9u0k] {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    min-width: 0;
    flex: 1 1 18rem;
}

.gmr-head[b-022k8o9u0k] {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.25rem 0.625rem;
}

.gmr-chip[b-022k8o9u0k] {
    display: inline-block;
    padding: 0.125rem 0.5rem;
    font-size: 0.75rem;
    font-weight: 600;
    line-height: 1.4;
    color: var(--pt-status-done-fg, #41464b);
    background: var(--pt-status-done-bg, #e9ecef);
    border: 1px solid var(--pt-status-done-border, #ced4da);
}

.gmr-what[b-022k8o9u0k] {
    font-weight: 600;
    color: var(--text-primary, #1e293b);
    overflow-wrap: anywhere;
}

.gmr-when[b-022k8o9u0k] {
    font-size: 0.8125rem;
    color: var(--text-secondary, #64748b);
}

.gmr-took[b-022k8o9u0k] {
    font-size: 0.8125rem;
    color: var(--text-secondary, #64748b);
    overflow-wrap: anywhere;
}

.gmr-restore[b-022k8o9u0k] {
    min-height: 44px;
    border-radius: 0;
    white-space: nowrap;
}
/* /Components/Catalog/GroupMenuStationMapPanel.razor.rz.scp.css */
/* Chain Catalog P3.11 — one location's stations for the catalog's, inside «Publicación» › «Estaciones» (gmp-*). Scoped CSS
   does not reach a child component's markup, so the chips are this file's own, on the same tokens: the order board's
   ready green and pending amber pairs (#379), 4.5:1 or better in both themes. A refusal is an outline in --pt-destructive
   with --pt-destructive-fg text on the surface, as the tab's; the mismatch warning is the warning callout (--text-primary
   on --pt-warning-bg). Straight edges; the buttons and the select are 44px high. */

.gms[b-47wghnybv1] {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
}

.gms-list[b-47wghnybv1] {
    list-style: none;
    margin: 0;
    padding: 0;
    border: 1px solid var(--border-color, #e2e8f0);
}

.gms-row[b-47wghnybv1] {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    padding: 0.75rem 0.875rem;
    border-top: 1px solid var(--border-color, #e2e8f0);
}

.gms-row:first-child[b-47wghnybv1] {
    border-top: none;
}

.gms-head[b-47wghnybv1] {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.25rem 0.625rem;
}

.gms-name[b-47wghnybv1] {
    font-weight: 600;
    color: var(--text-primary, #1e293b);
    overflow-wrap: anywhere;
}

.gms-detail[b-47wghnybv1] {
    font-size: 0.8125rem;
    color: var(--text-secondary, #64748b);
}

.gms-pick[b-47wghnybv1] {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem;
}

.gms-select[b-47wghnybv1] {
    flex: 1 1 14rem;
    max-width: 24rem;
    min-height: 44px;
    border-radius: 0;
}

.gms-btn[b-47wghnybv1] {
    min-height: 44px;
    border-radius: 0;
    white-space: nowrap;
}

.gms-bar[b-47wghnybv1] {
    display: flex;
    justify-content: flex-end;
}

.gms-chip[b-47wghnybv1],
.gms-tag[b-47wghnybv1] {
    display: inline-block;
    padding: 0.125rem 0.5rem;
    font-size: 0.75rem;
    font-weight: 600;
    line-height: 1.4;
    border: 1px solid transparent;
}

.gms-chip--ready[b-47wghnybv1] {
    color: var(--pt-status-ready-fg, #155724);
    background: var(--pt-status-ready-bg, #d4edda);
    border-color: var(--pt-status-ready-border, #b7e0c6);
}

.gms-chip--pending[b-47wghnybv1] {
    color: var(--pt-status-pending-fg, #856404);
    background: var(--pt-status-pending-bg, #fff3cd);
    border-color: var(--pt-status-pending-border, #ffe69c);
}

.gms-tag[b-47wghnybv1] {
    color: var(--pt-status-done-fg, #41464b);
    background: var(--pt-status-done-bg, #e9ecef);
    border-color: var(--pt-status-done-border, #ced4da);
}

.gms-note[b-47wghnybv1],
.gms-state[b-47wghnybv1] {
    font-size: 0.8125rem;
    color: var(--text-secondary, #64748b);
}

.gms-state[b-47wghnybv1] {
    padding: 0.75rem 0.875rem;
    border: 1px dashed var(--border-color, #e2e8f0);
}

.gms-warn[b-47wghnybv1] {
    padding: 0.5rem 0.75rem;
    font-size: 0.8125rem;
    color: var(--text-primary, #1e293b);
    background: var(--pt-warning-bg, #fef3c7);
    border-left: 4px solid var(--pt-warning-border, #fbbf24);
}

.gms-failed[b-47wghnybv1] {
    padding: 0.75rem 0.875rem;
    color: var(--pt-destructive-fg, #dc2626);
    background: var(--surface-color, #ffffff);
    border: 1px solid var(--pt-destructive, #ef4444);
    border-left-width: 4px;
}
/* /Components/Catalog/SharedDishLibraryPanel.razor.rz.scp.css */
/* Chain Catalog slice D (D4b1): the library a linked location pulls group dishes from, in the dish drawer's chrome.
   Text in --text-primary and --text-secondary on --surface-color, edges in --border-color, a navy left edge on a banner,
   as CatalogNotice; straight edges throughout. */

.sd-note[b-t5v86pf990] {
    color: var(--text-secondary, #64748b);
    font-size: 0.875rem;
    margin: 0.5rem 0;
}

.sd-banner[b-t5v86pf990] {
    margin: 0 0 0.75rem;
    padding: 0.625rem 0.75rem;
    background: var(--surface-color, #ffffff);
    border: 1px solid var(--border-color, #e2e8f0);
    border-left: 4px solid var(--pt-navy-fg, #1e3a5f);
    color: var(--text-primary, #1e293b);
    font-size: 0.875rem;
    line-height: 1.35;
}

.sd-banner-error[b-t5v86pf990] {
    border-left-color: var(--bs-danger, #dc3545);
}

.sd-target[b-t5v86pf990] {
    display: flex;
    flex-wrap: wrap;
    gap: 0.75rem;
    margin-bottom: 0.75rem;
}

.sd-field[b-t5v86pf990] {
    flex: 1 1 12rem;
    min-width: 0;
}

.sd-search[b-t5v86pf990] {
    margin-bottom: 0.75rem;
}

.sd-group[b-t5v86pf990] {
    margin: 1rem 0 0.375rem;
    color: var(--text-secondary, #64748b);
    font-size: 0.8125rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.02em;
}

.sd-list[b-t5v86pf990] {
    list-style: none;
    margin: 0;
    padding: 0;
    border: 1px solid var(--border-color, #e2e8f0);
}

.sd-row[b-t5v86pf990] {
    padding: 0.5rem 0.75rem;
    border-top: 1px solid var(--border-color, #e2e8f0);
    background: var(--surface-color, #ffffff);
}

.sd-row:first-child[b-t5v86pf990] {
    border-top: 0;
}

.sd-pick[b-t5v86pf990] {
    display: flex;
    align-items: center;
    gap: 0.625rem;
    min-height: 44px;
    margin: 0;
    color: var(--text-primary, #1e293b);
    cursor: pointer;
}

.sd-name[b-t5v86pf990] {
    flex: 1 1 auto;
    min-width: 0;
}

.sd-price[b-t5v86pf990] {
    color: var(--text-secondary, #64748b);
    font-variant-numeric: tabular-nums;
}

.sd-tags[b-t5v86pf990] {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.375rem;
    margin: 0.25rem 0 0 1.875rem;
}

.sd-tag[b-t5v86pf990] {
    padding: 0.0625rem 0.375rem;
    border: 1px solid var(--border-color, #e2e8f0);
    color: var(--text-secondary, #64748b);
    font-size: 0.75rem;
}

.sd-components[b-t5v86pf990] {
    color: var(--text-secondary, #64748b);
    font-size: 0.75rem;
}

.sd-footer[b-t5v86pf990] {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}

.sd-actions[b-t5v86pf990] {
    display: flex;
    justify-content: flex-end;
    gap: 0.5rem;
}
/* /Components/Closeout/CashReconciliationCard.razor.rz.scp.css */
/* =============================================================================
   CashReconciliationCard — component-scoped CSS (isolation, #52)
   =============================================================================
   Moved verbatim from this component's inline <style>; every selector's first
   compound is markup this component authors, so all 31 rules scope cleanly and
   no ::deep is needed.

   WHAT THIS FIXES. These rules were global while the component was mounted, so
   on /closeout they restyled classes owned by nobody in particular:

       .card-body     32 other components render it
       .card-header   30
       .is-invalid     9   (Bootstrap's validation class)
       .input-group    8
       .exact / .positive / .negative   6 / 4 / 3

   .card-header and .card-body are Bootstrap's. This is the same mechanism that
   made .summary-card break /closeout during the first extraction attempt — a
   component-local rule silently restyling a shared class page-wide. Scoping
   confines them by construction.
   ============================================================================= */

    .cash-reconciliation-card[b-d4q040a22u] {
        background: var(--surface-color);
        border: 1px solid var(--border-color);
        border-radius: var(--radius-lg);
        overflow: hidden;
    }

    .cash-reconciliation-card .card-header[b-d4q040a22u] {
        padding: 1rem 1.25rem;
        background: var(--background-color);
        border-bottom: 1px solid var(--border-color);
    }

    .cash-reconciliation-card .card-header h5[b-d4q040a22u] {
        margin: 0;
        font-size: 1.1rem;
        font-weight: 600;
        color: var(--text-primary);
        display: flex;
        align-items: center;
        gap: 0.5rem;
    }

    .cash-reconciliation-card .card-header h5 i[b-d4q040a22u] {
        color: var(--pt-navy-fg);
    }

    .cash-reconciliation-card .card-body[b-d4q040a22u] {
        padding: 1.25rem;
    }

    .help-text[b-d4q040a22u] {
        color: var(--text-secondary);
        font-size: 0.875rem;
        margin-bottom: 1.25rem;
    }

    .expected-cash[b-d4q040a22u] {
        display: flex;
        justify-content: space-between;
        align-items: center;
        padding: 1rem;
        background: var(--background-color);
        border-radius: var(--radius-md);
        margin-bottom: 1.25rem;
    }

    .expected-label[b-d4q040a22u] {
        font-weight: 500;
        color: var(--text-secondary);
    }

    .expected-value[b-d4q040a22u] {
        font-size: 1.5rem;
        font-weight: 700;
        color: var(--pt-navy-fg);
    }

    .input-section[b-d4q040a22u] {
        margin-bottom: 1.25rem;
    }

    .input-label[b-d4q040a22u] {
        display: block;
        font-weight: 500;
        color: var(--text-primary);
        margin-bottom: 0.5rem;
    }

    .input-group[b-d4q040a22u] {
        display: flex;
        align-items: center;
        max-width: 300px;
    }

    .input-prefix[b-d4q040a22u] {
        padding: 0.75rem 1rem;
        background: var(--background-color);
        border: 1px solid var(--border-color);
        border-right: none;
        border-radius: 0;
        font-weight: 600;
        color: var(--text-secondary);
    }

    .cash-input[b-d4q040a22u] {
        border-radius: 0;
        font-size: 1.25rem;
        font-weight: 600;
        padding: 0.75rem 1rem;
    }

    .cash-input.is-invalid[b-d4q040a22u] {
        border-color: var(--danger-color);
    }

    .input-hint[b-d4q040a22u] {
        display: block;
        margin-top: 0.375rem;
        color: var(--text-secondary);
        font-size: 0.75rem;
    }

    .variance-display[b-d4q040a22u] {
        padding: 1rem;
        border-radius: var(--radius-md);
        margin-bottom: 1.25rem;
    }

    .variance-display.positive[b-d4q040a22u] {
        background: rgba(16, 185, 129, 0.1);
        border: 1px solid var(--success-color);
    }

    .variance-display.negative[b-d4q040a22u] {
        background: rgba(239, 68, 68, 0.1);
        border: 1px solid var(--danger-color);
    }

    .variance-display.exact[b-d4q040a22u] {
        background: rgba(59, 130, 246, 0.1);
        border: 1px solid var(--primary-color);
    }

    .variance-row[b-d4q040a22u] {
        display: flex;
        justify-content: space-between;
        align-items: center;
        margin-bottom: 0.5rem;
    }

    .variance-label[b-d4q040a22u] {
        font-weight: 500;
        color: var(--text-primary);
    }

    .variance-value[b-d4q040a22u] {
        font-size: 1.5rem;
        font-weight: 700;
    }

    .variance-display.positive .variance-value[b-d4q040a22u] {
        color: var(--success-color);
    }

    .variance-display.negative .variance-value[b-d4q040a22u] {
        color: var(--danger-color);
    }

    .variance-display.exact .variance-value[b-d4q040a22u] {
        color: var(--pt-navy-fg);
    }

    .variance-message[b-d4q040a22u] {
        display: flex;
        align-items: center;
        gap: 0.5rem;
        font-size: 0.875rem;
    }

    .variance-display.positive .variance-message[b-d4q040a22u] {
        color: var(--success-color);
    }

    .variance-display.negative .variance-message[b-d4q040a22u] {
        color: var(--danger-color);
    }

    .variance-message.exact[b-d4q040a22u] {
        color: var(--pt-navy-fg);
    }

    .notes-section textarea[b-d4q040a22u] {
        resize: vertical;
        min-height: 80px;
    }
/* /Components/Closeout/RestaurantShiftDetailPanel.razor.rz.scp.css */
/* The closeout history drawer (2026-09-24).

   The drawer's chrome is app.css's, through PtCloseoutDrawer. This file styles only what sits in the body,
   and mirrors ShiftDetailPanel.razor.css value for value: those rules are scoped to that component, so
   they cannot be shared, and CloseoutShiftHistoryDrawerContractTests holds the two drawers' tiles equal.
   Section titles are app.css's .section-header. */

.rsdp-sections[b-76blbtib0g] {
    display: flex;
    flex-direction: column;
    gap: 1.5rem;
}

/* ---- Figures (as .sdp-tiles) ---------------------------------------------------------------- */

.rsdp-tiles[b-76blbtib0g] {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 0.75rem;
}

.rsdp-tiles--four[b-76blbtib0g] {
    grid-template-columns: repeat(4, minmax(0, 1fr));
}

.rsdp-tile[b-76blbtib0g] {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    padding: 0.75rem;
    background: var(--surface-color);
    border: 1px solid var(--modal-border);
}

.rsdp-label[b-76blbtib0g] {
    font-size: 0.75rem;
    color: var(--modal-text-secondary);
}

.rsdp-value[b-76blbtib0g] {
    display: flex;
    align-items: center;
    justify-content: space-between;
    font-size: 1.1rem;
    font-weight: 600;
    color: var(--modal-text);
    font-variant-numeric: tabular-nums;
}

/* A name, not a figure: it wraps rather than overflowing its tile. */
.rsdp-value--text[b-76blbtib0g] {
    overflow-wrap: anywhere;
}

/* ---- The accounts --------------------------------------------------------------------------- */

.rsdp-count[b-76blbtib0g] {
    margin-left: 0.25rem;
    color: var(--modal-text-secondary);
    font-weight: 500;
}

/* One waiter's accounts: a header naming them, with how many and what they came to. */
.rsdp-group + .rsdp-group[b-76blbtib0g] {
    margin-top: 1rem;
}

.rsdp-group-head[b-76blbtib0g] {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 1rem;
    padding: 0.5rem 0;
    border-bottom: 2px solid var(--modal-border);
}

.rsdp-group-name[b-76blbtib0g] {
    font-weight: 700;
    color: var(--modal-text);
    overflow-wrap: anywhere;
}

.rsdp-group-meta[b-76blbtib0g] {
    flex-shrink: 0;
    font-size: 0.875rem;
    font-weight: 600;
    color: var(--modal-text-secondary);
    font-variant-numeric: tabular-nums;
}

.rsdp-note[b-76blbtib0g] {
    margin: 0 0 0.5rem;
    font-size: 0.875rem;
    color: var(--modal-text-secondary);
}

/* (as .sdp-state) */
.rsdp-state[b-76blbtib0g] {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.5rem;
    padding: 1.5rem 1rem;
    text-align: center;
    color: var(--modal-text-secondary);
}

.rsdp-state > .bi[b-76blbtib0g] {
    font-size: 1.75rem;
}

.rsdp-state--error[b-76blbtib0g] {
    color: #b91c1c;
}

/* ---- The shift's cash drawer (#505) ---------------------------------------------------------

   Shown only on a shift that had a drawer. Every button here is a 44px target (Carmel's tablet is
   touch-only), by .btn's own floor. Amounts stay in the text colour, signed, rather than green and red: the sign carries the
   meaning, and a tinted figure is one more pair of colours to hold to AA in both schemes. A voided
   movement is struck through and says "Anulado", never faded, which would take its text under AA. */

.rsdp-cash-actions[b-76blbtib0g] {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin-bottom: 0.75rem;
}

/* No size of its own: app.css's .app-layout .btn is the one control for admin button height (44px), and
   the icon-only slip reaches 44px wide on .btn's padding. CloseoutShiftHistoryDrawerContractTests measures
   all four at 44x44, so a change on either side shows there. */
.rsdp-cash-btn[b-76blbtib0g] {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.375rem;
}

.rsdp-cash-error[b-76blbtib0g] {
    margin: 0 0 0.75rem;
    font-size: 0.875rem;
    color: #b91c1c;
}

.rsdp-cash-warning[b-76blbtib0g] {
    display: flex;
    align-items: baseline;
    gap: 0.5rem;
    margin: 0 0 0.75rem;
    font-size: 0.875rem;
    color: var(--modal-text);
}

.rsdp-cash-warning > .bi[b-76blbtib0g] {
    color: #b45309;
}

.rsdp-ledger[b-76blbtib0g] {
    margin: 0 0 1rem;
    font-variant-numeric: tabular-nums;
}

.rsdp-ledger-row[b-76blbtib0g] {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 1rem;
    padding: 0.4rem 0;
    border-bottom: 1px dotted var(--modal-border);
}

.rsdp-ledger-row dt[b-76blbtib0g] {
    font-size: 0.875rem;
    font-weight: 400;
    color: var(--modal-text-secondary);
}

.rsdp-ledger-row dd[b-76blbtib0g] {
    margin: 0;
    font-weight: 600;
    color: var(--modal-text);
    white-space: nowrap;
}

.rsdp-ledger-row--total[b-76blbtib0g] {
    border-top: 2px solid var(--modal-border);
}

.rsdp-ledger-row--total dt[b-76blbtib0g] {
    font-weight: 700;
    color: var(--modal-text);
}

.rsdp-moves[b-76blbtib0g] {
    list-style: none;
    margin: 0;
    padding: 0;
}

/* One flex line per movement: the reason takes whatever is left, so the amount and the slip keep to the
   right edge whatever the reason's length, and amounts line up down the list (the contract test measures
   two rows' amounts against each other, at a desktop and a phone width). */
.rsdp-move[b-76blbtib0g] {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.5rem 0;
    border-bottom: 1px solid var(--modal-border);
}

.rsdp-move:last-child[b-76blbtib0g] {
    border-bottom: none;
}

.rsdp-move-time[b-76blbtib0g] {
    flex: 0 0 2.75rem;
    font-size: 0.8rem;
    color: var(--modal-text-secondary);
    font-variant-numeric: tabular-nums;
}

.rsdp-move-what[b-76blbtib0g] {
    flex: 1 1 0;
    display: flex;
    flex-direction: column;
    min-width: 0;
}

.rsdp-move-amount[b-76blbtib0g],
.rsdp-move-slip[b-76blbtib0g] {
    flex: none;
}

.rsdp-move-reason[b-76blbtib0g] {
    font-size: 0.9rem;
    color: var(--modal-text);
    overflow-wrap: anywhere;
}

.rsdp-move-who[b-76blbtib0g] {
    font-size: 0.8rem;
    color: var(--modal-text-secondary);
    overflow-wrap: anywhere;
}

.rsdp-move-amount[b-76blbtib0g] {
    font-weight: 600;
    color: var(--modal-text);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.rsdp-move--voided .rsdp-move-reason[b-76blbtib0g],
.rsdp-move--voided .rsdp-move-amount[b-76blbtib0g] {
    text-decoration: line-through;
}

/* The drawer body is the one scroller (as .sdp-accounts): TabListCard caps its own list at 50vh, which
   inside a drawer would be a scroller within the scroller. */
.rsdp-accounts[b-76blbtib0g]  .tab-list {
    max-height: none;
    overflow: visible;
}

@media (max-width: 576px) {
    .rsdp-tiles[b-76blbtib0g],
    .rsdp-tiles--four[b-76blbtib0g] {
        grid-template-columns: 1fr;
    }
}

@media (min-width: 577px) and (max-width: 900px) {
    .rsdp-tiles--four[b-76blbtib0g] {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

@media (prefers-color-scheme: dark) {
    .rsdp-state--error[b-76blbtib0g],
    .rsdp-cash-error[b-76blbtib0g] {
        color: #fca5a5;
    }

    .rsdp-cash-warning > .bi[b-76blbtib0g] {
        color: #fbbf24;
    }
}
/* /Components/Closeout/ShiftDetailPanel.razor.rz.scp.css */
/* GH-255 — Detalle del Turno, as a drawer.

   The drawer's chrome (panel, header, body, footer) is app.css's, through PtCloseoutDrawer. This file
   styles only what sits in the body. It replaces the component's inline <style> block, which was global
   for as long as the component was mounted and declared .panel-header, .panel-body, .panel-footer,
   .avatar, .status and .empty-state — the drawer classes among them. Scoped and sdp-prefixed, so it
   reaches this component's markup and nothing else.

   Section titles are app.css's .section-header, the menu drawers' heading, rather than a copy of it. */

.sdp-sections[b-qh19d6ii3z] {
    display: flex;
    flex-direction: column;
    /* The item drawer's section rhythm (.edit-item-grid). */
    gap: 1.5rem;
}

/* ---- The waiter ---------------------------------------------------------------------------- */

.sdp-profile[b-qh19d6ii3z] {
    display: flex;
    align-items: center;
    gap: 1rem;
}

.sdp-avatar[b-qh19d6ii3z] {
    width: 56px;
    height: 56px;
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--pt-navy, #000075);
    color: #fff;
    font-weight: 700;
    font-size: 1.25rem;
}

.sdp-profile-info[b-qh19d6ii3z] {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    min-width: 0;
}

.sdp-name[b-qh19d6ii3z] {
    font-size: 1.25rem;
    font-weight: 700;
    color: var(--modal-text);
    overflow-wrap: anywhere;
}

/* Opaque grounds, not the 10% tints this used to be. #f59e0b and #10b981 text over their own tints
   measured about 2:1; these hold 4.5:1 or better in each theme. */
.sdp-status[b-qh19d6ii3z] {
    width: fit-content;
    padding: 0.25rem 0.75rem;
    font-size: 0.75rem;
    font-weight: 600;
}

.sdp-status--active[b-qh19d6ii3z] {
    background: #fef3c7;
    color: #92400e;
}

.sdp-status--closed[b-qh19d6ii3z] {
    background: #d1fae5;
    color: #065f46;
}

/* ---- Figures ------------------------------------------------------------------------------- */

.sdp-tiles[b-qh19d6ii3z] {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 0.75rem;
}

.sdp-tile[b-qh19d6ii3z] {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    padding: 0.75rem;
    background: var(--surface-color);
    border: 1px solid var(--modal-border);
}

.sdp-label[b-qh19d6ii3z] {
    font-size: 0.75rem;
    color: var(--modal-text-secondary);
}

.sdp-value[b-qh19d6ii3z] {
    display: flex;
    align-items: center;
    justify-content: space-between;
    font-size: 1.1rem;
    font-weight: 600;
    color: var(--modal-text);
    font-variant-numeric: tabular-nums;
}

.sdp-tile--link[b-qh19d6ii3z] {
    cursor: pointer;
}

.sdp-tile--link:hover[b-qh19d6ii3z] {
    border-color: var(--pt-navy-fg);
}

.sdp-tile-go[b-qh19d6ii3z] {
    font-size: 0.8rem;
    color: var(--pt-navy-fg);
}

.sdp-rows[b-qh19d6ii3z] {
    display: flex;
    flex-direction: column;
}

.sdp-row[b-qh19d6ii3z] {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 1rem;
    padding: 0.625rem 0;
    border-bottom: 1px solid var(--modal-border);
}

.sdp-row-label[b-qh19d6ii3z] {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    color: var(--modal-text-secondary);
}

.sdp-row-value[b-qh19d6ii3z] {
    font-weight: 600;
    color: var(--modal-text);
    font-variant-numeric: tabular-nums;
}

.sdp-row--total .sdp-row-label[b-qh19d6ii3z],
.sdp-row--total .sdp-row-value[b-qh19d6ii3z] {
    font-weight: 700;
    color: var(--modal-text);
}

/* What the waiter hands over. The one figure on this drawer that is an instruction. */
.sdp-remit[b-qh19d6ii3z] {
    display: flex;
    justify-content: space-between;
    gap: 1rem;
    margin-top: 0.75rem;
    padding: 0.75rem;
    background: #d1fae5;
    color: #065f46;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}

/* ---- The shift's accounts ------------------------------------------------------------------ */

.sdp-state[b-qh19d6ii3z] {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.5rem;
    padding: 1.5rem 1rem;
    text-align: center;
    color: var(--modal-text-secondary);
}

.sdp-state > .bi[b-qh19d6ii3z] {
    font-size: 1.75rem;
}

.sdp-state--error[b-qh19d6ii3z] {
    color: #b91c1c;
}

/* The drawer body is the one scroller, as in the menu editors. TabListCard caps its own list at 50vh
   and scrolls inside that, which inside a drawer is a scroller within the scroller — so under this
   section the list takes its natural height and scrolls with the body. ::deep because the list is
   TabListCard's markup, not this component's. */
.sdp-accounts[b-qh19d6ii3z]  .tab-list {
    max-height: none;
    overflow: visible;
}

@media (max-width: 576px) {
    .sdp-tiles[b-qh19d6ii3z] {
        grid-template-columns: 1fr;
    }
}

@media (prefers-color-scheme: dark) {
    /* Navy is nearly the dark panel, so the avatar inverts to the navy made for dark grounds. */
    .sdp-avatar[b-qh19d6ii3z] {
        background: var(--pt-navy-fg, #a5b4fc);
        color: var(--pt-navy, #000075);
    }

    .sdp-status--active[b-qh19d6ii3z] {
        background: #451a03;
        color: #fcd34d;
    }

    .sdp-status--closed[b-qh19d6ii3z],
    .sdp-remit[b-qh19d6ii3z] {
        background: #064e3b;
        color: #a7f3d0;
    }

    .sdp-state--error[b-qh19d6ii3z] {
        color: #fca5a5;
    }
}
/* /Components/Closeout/TabDetailPanel.razor.rz.scp.css */
    /* GH-255: the header, footer and scroll box that used to open this file are gone — the panel is a
       stacked PtCloseoutDrawer now, whose chrome is app.css's drawer rules. The body scrolled inside
       its own 60vh box, which inside a drawer is a scroller within the scroller. Section titles are
       app.css's .section-header, the menu drawers' heading. */
    .tdp-detail-section[b-u5ao1xgpd8] {
        margin-bottom: 1.5rem;
    }

    .tdp-detail-section:last-child[b-u5ao1xgpd8] {
        margin-bottom: 0;
    }

    .order-count[b-u5ao1xgpd8] {
        font-weight: 400;
        opacity: 0.7;
    }

    /* Customer Header */
    .customer-header[b-u5ao1xgpd8] {
        display: flex;
        justify-content: space-between;
        align-items: flex-start;
        padding: 1rem;
        background: var(--background-color);
        border-radius: var(--radius-md);
    }

    .customer-info[b-u5ao1xgpd8] {
        display: flex;
        flex-direction: column;
        gap: 0.25rem;
    }

    .customer-name[b-u5ao1xgpd8] {
        font-size: 1.25rem;
        font-weight: 700;
        color: var(--text-primary);
    }

    .customer-name .anonymous[b-u5ao1xgpd8] {
        font-weight: 400;
        font-style: italic;
        opacity: 0.6;
    }

    .tab-id[b-u5ao1xgpd8] {
        font-family: monospace;
        font-size: 0.75rem;
        color: var(--text-secondary);
    }

    .tab-status[b-u5ao1xgpd8] {
        display: flex;
        align-items: center;
        gap: 0.5rem;
        padding: 0.5rem 1rem;
        border-radius: 0;
        font-weight: 600;
        font-size: 0.875rem;
    }

    .tab-status.paid[b-u5ao1xgpd8] {
        background: rgba(16, 185, 129, 0.1);
        color: var(--success-color);
    }

    .tab-status.open[b-u5ao1xgpd8] {
        background: rgba(245, 158, 11, 0.1);
        color: var(--warning-color);
    }

    /* Abandoned write-off. Opaque, where .paid/.open above are 10% tints: this stylesheet ships
       no dark-mode block, so a tint paired with a mid-tone token reads in one theme and fails in
       the other. An amber-100 ground with amber-800 text holds contrast in both with no media
       query, and the border keeps a CLOSED uncollected tab visually distinct from the amber
       "Abierta" state it would otherwise resemble. */
    .tab-status.abandoned[b-u5ao1xgpd8] {
        background: #fef3c7;
        color: #92400e;
        border: 1px solid #fbbf24;
    }

    /* Info Grid */
    .info-grid[b-u5ao1xgpd8] {
        display: grid;
        grid-template-columns: repeat(2, 1fr);
        gap: 0.75rem;
    }

    .info-item[b-u5ao1xgpd8] {
        display: flex;
        flex-direction: column;
        padding: 0.75rem;
        background: var(--background-color);
        border-radius: var(--radius-md);
    }

    .info-item .label[b-u5ao1xgpd8] {
        font-size: 0.75rem;
        color: var(--text-secondary);
        margin-bottom: 0.25rem;
    }

    .info-item .value[b-u5ao1xgpd8] {
        font-weight: 600;
        color: var(--text-primary);
    }

    /* A split payment's breakdown (Igor, 2026-09-24) takes the grid's full width: a method and an amount a
       line, the amounts aligned at the right. */
    .info-item--wide[b-u5ao1xgpd8] {
        grid-column: 1 / -1;
    }

    .tdp-method-parts[b-u5ao1xgpd8] {
        list-style: none;
        margin: 0.5rem 0 0;
        padding: 0;
        display: flex;
        flex-direction: column;
        gap: 0.25rem;
    }

    .tdp-method-parts li[b-u5ao1xgpd8] {
        display: flex;
        justify-content: space-between;
        gap: 1rem;
        font-size: 0.875rem;
        color: var(--text-primary);
    }

    .tdp-method-amount[b-u5ao1xgpd8] {
        font-variant-numeric: tabular-nums;
        font-weight: 600;
    }

    /* Orders List
       GH-62: the old markup wrapped every order in an Orders.razor-style card — coloured
       left border, tinted header strip, duplicate status icon, per-order footer total.
       Stacked three deep inside an already-nested drawer that read as chrome around the
       one thing being reviewed. This is the tab modal's line language instead: a quiet
       time + status caption, then plain item rows.

       All selectors are tdp-prefixed. These component style blocks are GLOBAL (no Blazor
       CSS isolation in this project) and the previous names — .order-card, .order-item,
       .item-name, .item-price, .order-header, .order-total — are defined by several other
       components, so the old rules were reaching well outside this panel. */
    .orders-list[b-u5ao1xgpd8] {
        display: flex;
        flex-direction: column;
        gap: 1rem;
    }

    .tdp-order-caption[b-u5ao1xgpd8] {
        display: flex;
        align-items: center;
        gap: 0.5rem;
        margin-bottom: 0.375rem;
        padding-bottom: 0.375rem;
        border-bottom: 1px solid var(--border-color);
        font-size: 0.75rem;
        color: var(--text-secondary);
    }

    .tdp-order-time[b-u5ao1xgpd8] {
        display: flex;
        align-items: center;
        gap: 0.35rem;
    }

    .tdp-item-list[b-u5ao1xgpd8] {
        display: flex;
        flex-direction: column;
    }

    .tdp-item-row[b-u5ao1xgpd8] {
        display: grid;
        grid-template-columns: 2.25rem minmax(0, 1fr) auto;
        gap: 0.5rem;
        padding: 0.3rem 0;
        align-items: baseline;
    }

    /* The component's own count, beside its name rather than in the quantity column -- the two
       mean different things, and sharing a column made them read as one. */
    .tdp-child-count[b-u5ao1xgpd8] {
        margin-left: 0.375rem;
        font-weight: 600;
        font-variant-numeric: tabular-nums;
        color: var(--text-primary);
    }

    .tdp-item-qty[b-u5ao1xgpd8] {
        font-weight: 600;
        color: var(--pt-navy-fg);
        font-variant-numeric: tabular-nums;
    }

    .tdp-item-name[b-u5ao1xgpd8] {
        color: var(--text-primary);
        overflow-wrap: anywhere;
    }

    .tdp-item-price[b-u5ao1xgpd8] {
        font-weight: 600;
        color: var(--text-primary);
        white-space: nowrap;
        font-variant-numeric: tabular-nums;
    }

    /* Package rows: the header states the package and carries the rolled-up price; its
       components sit indented beneath it, marked "Incluido" rather than $0.00 — a price
       column full of zeroes reads as a pricing fault rather than as "part of the combo". */
    .tdp-item-row.is-package-child .tdp-item-name[b-u5ao1xgpd8] {
        padding-left: 0.75rem;
        color: var(--text-secondary);
    }

    .tdp-package-arrow[b-u5ao1xgpd8] {
        margin-right: 0.25rem;
        opacity: 0.6;
    }

    .tdp-package-chip[b-u5ao1xgpd8] {
        display: inline-flex;
        align-items: center;
        gap: 0.25rem;
        margin-right: 0.35rem;
        padding: 0.1rem 0.35rem;
        background: rgba(59, 130, 246, 0.12);
        color: var(--pt-navy-fg);
        border-radius: 0;
        font-size: 0.65rem;
        font-weight: 600;
        text-transform: uppercase;
        letter-spacing: 0.03em;
        white-space: nowrap;
    }

    .tdp-included[b-u5ao1xgpd8] {
        font-size: 0.75rem;
        font-weight: 500;
        font-style: italic;
        color: var(--text-secondary);
    }

    .tdp-item-modifier[b-u5ao1xgpd8] {
        display: flex;
        justify-content: space-between;
        gap: 0.5rem;
        padding-left: 2.75rem;
        font-size: 0.8rem;
        color: var(--text-secondary);
        font-style: italic;
    }

    .tdp-item-modifier.is-package-child[b-u5ao1xgpd8] {
        padding-left: 3.5rem;
    }

    .tdp-mod-price[b-u5ao1xgpd8] {
        font-style: normal;
        white-space: nowrap;
    }

    .tdp-item-note[b-u5ao1xgpd8] {
        padding-left: 2.75rem;
        font-size: 0.8rem;
        color: var(--warning-color);
        display: flex;
        align-items: center;
        gap: 0.5rem;
    }

    .tdp-item-note.is-package-child[b-u5ao1xgpd8] {
        padding-left: 3.5rem;
    }

    .no-orders[b-u5ao1xgpd8] {
        display: flex;
        flex-direction: column;
        align-items: center;
        padding: 2rem;
        color: var(--text-secondary);
        gap: 0.5rem;
    }

    .no-orders i[b-u5ao1xgpd8] {
        font-size: 2rem;
        opacity: 0.5;
    }

    /* Totals Section */
    .totals-breakdown[b-u5ao1xgpd8] {
        background: var(--background-color);
        border-radius: var(--radius-md);
        padding: 1rem;
    }

    .total-row[b-u5ao1xgpd8] {
        display: flex;
        justify-content: space-between;
        padding: 0.5rem 0;
        font-size: 0.9rem;
    }

    .total-row.tip[b-u5ao1xgpd8] {
        color: var(--text-secondary);
    }

    .total-row.grand-total[b-u5ao1xgpd8] {
        border-top: 2px solid var(--border-color);
        margin-top: 0.5rem;
        padding-top: 1rem;
        font-size: 1.25rem;
        font-weight: 700;
        color: var(--pt-navy-fg);
    }

    @media (max-width: 576px) {
        .info-grid[b-u5ao1xgpd8] {
            grid-template-columns: 1fr;
        }

        .customer-header[b-u5ao1xgpd8] {
            flex-direction: column;
            gap: 1rem;
        }
    }
/* /Components/Modals/ClaimConfirmModal.razor.rz.scp.css */
/* ClaimConfirmModal (Mesero close parity MC5). Scoped, so these names cannot collide with the Cuentas panel's or the
   drawer's own rules. Every colour is a theme token that swaps for dark mode; text sits on the modal's own surface.
   The total is --pt-navy-fg, not the coral the panel's old modal used (coral on white is 3.21:1, under AA). */

.claim-confirm-who[b-5f4ca3c6cw] {
    display: flex;
    flex-direction: column;
    gap: 0.125rem;
    margin-bottom: 0.75rem;
}

.claim-confirm-table[b-5f4ca3c6cw] {
    font-size: 0.8125rem;
    color: var(--modal-text-secondary);
}

.claim-confirm-payer[b-5f4ca3c6cw] {
    font-size: 1.05rem;
    font-weight: 700;
    color: var(--modal-text);
    overflow-wrap: anywhere;
}

.claim-confirm-note[b-5f4ca3c6cw] {
    margin: 0 0 0.75rem;
    color: var(--modal-text-secondary);
}

.claim-confirm-totals[b-5f4ca3c6cw] {
    margin-bottom: 0.75rem;
}

.claim-confirm-row[b-5f4ca3c6cw] {
    display: flex;
    justify-content: space-between;
    gap: 1rem;
    padding: 0.5rem 0;
    border-bottom: 1px solid var(--modal-border);
    color: var(--modal-text);
    font-variant-numeric: tabular-nums;
}

.claim-confirm-row:last-child[b-5f4ca3c6cw] {
    border-bottom: none;
}

.claim-confirm-total[b-5f4ca3c6cw] {
    font-size: 1.1rem;
    font-weight: 700;
}

.claim-confirm-total > span:last-child[b-5f4ca3c6cw] {
    color: var(--pt-navy-fg);
}

.claim-confirm-instruction[b-5f4ca3c6cw] {
    display: flex;
    align-items: flex-start;
    gap: 0.5rem;
    margin: 0;
    padding: 0.75rem;
    border-left: 3px solid var(--pt-warning-border);
    background: var(--pt-warning-bg);
    color: var(--modal-text);
    font-size: 0.875rem;
}

.claim-confirm-alert[b-5f4ca3c6cw],
.claim-confirm-error[b-5f4ca3c6cw],
.claim-confirm-stale[b-5f4ca3c6cw] {
    display: flex;
    align-items: flex-start;
    gap: 0.5rem;
    margin-bottom: 0.75rem;
    padding: 0.75rem;
    color: var(--modal-text);
    font-size: 0.875rem;
}

.claim-confirm-alert p[b-5f4ca3c6cw],
.claim-confirm-error p[b-5f4ca3c6cw],
.claim-confirm-stale p[b-5f4ca3c6cw] {
    margin: 0;
}

.claim-confirm-alert[b-5f4ca3c6cw] {
    border-left: 3px solid var(--pt-warning-border);
    background: var(--pt-warning-bg);
}

.claim-confirm-error[b-5f4ca3c6cw] {
    border-left: 3px solid var(--danger-color);
}

.claim-confirm-stale[b-5f4ca3c6cw] {
    border-left: 3px solid var(--modal-border);
}

.claim-confirm-retry[b-5f4ca3c6cw] {
    margin-top: 0.375rem;
    padding: 0;
    border: none;
    background: none;
    color: var(--pt-navy-fg);
    font-weight: 600;
    text-decoration: underline;
    cursor: pointer;
    min-height: 44px;
}

.claim-confirm-retry:disabled[b-5f4ca3c6cw] {
    opacity: 0.6;
    cursor: not-allowed;
}
/* /Components/Modals/DeviceRegistrationModal.razor.rz.scp.css */
/* =============================================================================
   DeviceRegistrationModal — component-scoped CSS (isolation pilot, #52)
   =============================================================================
   Every rule here styles markup THIS component authors, so the compiler rewrites
   each selector with the generated scope attribute and it can no longer reach
   any other component.

   That includes the footer buttons: content passed to PtModal as ChildContent /
   FooterContent is AUTHORED here, so Blazor stamps this component's scope onto
   it even though PtModal renders it. Scope follows where markup is written, not
   where it ends up in the DOM.

   FIVE RULES COULD NOT COME ACROSS — they style PtModal's shell (.modal-overlay,
   .custom-modal, .modal-header-custom/-body-custom/-footer-custom), which are
   ANCESTORS of this component's content. `::deep` compiles to `[b-xxx] .foo`, a
   DESCENDANT combinator, so it structurally cannot reach upward. Those rules stay
   in the component's inline <style> with an explanation. See the note there.

   Razor's `@@media` escapes are single `@` here — a .css file needs real at-rules.
   ============================================================================= */

/* Intro subtitle (moved from the old custom header into the PtModal body).
   Green registration header now comes from PtModal HeaderClass="bg-success". */
.device-reg-subtitle[b-bh3euhfl1l] {
    margin: 0 0 1rem 0;
    font-size: 0.85rem;
    color: var(--modal-text-secondary, #6c757d);
}

/* Body content styles */
.registering-state[b-bh3euhfl1l] {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 3rem;
    gap: 1rem;
    color: var(--text-secondary, #6c757d);
}

.device-form[b-bh3euhfl1l] {
    display: flex;
    flex-direction: column;
    gap: 1.25rem;
}

.form-group[b-bh3euhfl1l] {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}

.form-group label[b-bh3euhfl1l] {
    font-weight: 600;
    color: var(--text-primary, #212529);
    font-size: 0.9rem;
}

.form-control[b-bh3euhfl1l] {
    padding: 0.75rem 1rem;
    border: 2px solid var(--border-color, #dee2e6);
    border-radius: 0;
    font-size: 1rem;
    transition: border-color 0.2s ease;
}

.form-control:focus[b-bh3euhfl1l] {
    outline: none;
    border-color: var(--primary-color, #10b981);
    box-shadow: 0 0 0 3px rgba(16, 185, 129, 0.15);
}

.form-control.is-invalid[b-bh3euhfl1l] {
    border-color: #dc3545;
}

.invalid-feedback[b-bh3euhfl1l] {
    color: #dc3545;
    font-size: 0.8rem;
}

.form-text[b-bh3euhfl1l] {
    color: var(--text-muted, #6c757d);
    font-size: 0.75rem;
}

/* Suggested Names */
.suggested-names[b-bh3euhfl1l] {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}

.suggested-label[b-bh3euhfl1l] {
    font-size: 0.8rem;
    color: var(--text-secondary, #6c757d);
    font-weight: 500;
}

.suggested-buttons[b-bh3euhfl1l] {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
}

.suggested-btn[b-bh3euhfl1l] {
    padding: 0.375rem 0.75rem;
    border: 1px solid var(--border-color, #dee2e6);
    border-radius: 0;
    background: var(--surface-color, #ffffff);
    color: var(--text-secondary, #6c757d);
    font-size: 0.8rem;
    cursor: pointer;
    transition: all 0.2s ease;
}

.suggested-btn:hover[b-bh3euhfl1l] {
    border-color: var(--primary-color, #10b981);
    color: var(--primary-color, #10b981);
}

.suggested-btn.active[b-bh3euhfl1l] {
    background: var(--primary-color, #10b981);
    border-color: var(--primary-color, #10b981);
    color: white;
}

/* Device Info Section */
.device-info-section[b-bh3euhfl1l] {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    padding: 1rem;
    background: var(--bg-secondary, #f8f9fa);
    border-radius: 0;
    margin-top: 0.5rem;
}

.info-row[b-bh3euhfl1l] {
    display: flex;
    justify-content: space-between;
    align-items: center;
    font-size: 0.85rem;
}

.info-label[b-bh3euhfl1l] {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    color: var(--text-secondary, #6c757d);
}

.info-label i[b-bh3euhfl1l] {
    font-size: 0.75rem;
    width: 16px;
    text-align: center;
}

.info-value[b-bh3euhfl1l] {
    font-weight: 600;
    color: var(--text-primary, #212529);
}

.info-value.device-id[b-bh3euhfl1l] {
    font-family: monospace;
    font-size: 0.8rem;
    color: var(--text-muted, #6c757d);
}

/* Footer button overrides. These are safe to scope: the buttons are authored in
   this component's FooterContent, so they carry this component's scope attribute.
   Before isolation these three rules restyled EVERY .btn on the page while this
   modal was mounted. */
.btn[b-bh3euhfl1l] {
    padding: 0.625rem 1.25rem;
    border-radius: 0;
    font-weight: 600;
    font-size: 0.9rem;
    cursor: pointer;
    transition: all 0.2s ease;
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
}

.btn-secondary[b-bh3euhfl1l] {
    background: transparent;
    border: 2px solid var(--border-color, #dee2e6);
    color: var(--text-secondary, #6c757d);
}

.btn-secondary:hover[b-bh3euhfl1l] {
    border-color: var(--text-secondary, #6c757d);
    background: var(--bg-secondary, #f8f9fa);
}

.btn-primary[b-bh3euhfl1l] {
    background: linear-gradient(135deg, #10b981 0%, #059669 100%);
    border: none;
    color: white;
}

.btn-primary:hover:not(:disabled)[b-bh3euhfl1l] {
    transform: translateY(-1px);
    box-shadow: 0 4px 12px rgba(16, 185, 129, 0.35);
}

.btn-primary:disabled[b-bh3euhfl1l] {
    opacity: 0.5;
    cursor: not-allowed;
}

/* Dark Mode */
@media (prefers-color-scheme: dark) {
    .form-control[b-bh3euhfl1l] {
        background: var(--surface-color, #343a40);
        color: var(--text-primary, #ffffff);
    }

    .form-control:focus[b-bh3euhfl1l] {
        box-shadow: 0 0 0 3px rgba(16, 185, 129, 0.25);
    }
}

/* Responsive — the shell half of this breakpoint stays inline (see the note in
   the .razor); only the button rule owns markup this component authors. */
@media (max-width: 480px) {
    .btn[b-bh3euhfl1l] {
        width: 100%;
        justify-content: center;
    }
}

/* Reduced motion — likewise split. .modal-overlay / .custom-modal are PtModal's
   and remain inline; these three are ours. */
@media (prefers-reduced-motion: reduce) {
    .form-control[b-bh3euhfl1l],
    .suggested-btn[b-bh3euhfl1l],
    .btn[b-bh3euhfl1l] {
        transition: none;
    }
}
/* /Components/Modals/TabDetailModal.razor.rz.scp.css */
    /* Release-gate holds — surfaces active PendingGuestApproval +
       PendingWalletReAuth rows at the top of the tab-detail body. Mirrors
       the per-component pill styling used on the mesero side (memory:
       blazor-css-no-isolation — reuse pill/override-button classes,only
       lay out the row container here). Straight edges per PayTable 2025
       branding. */
    .release-gate-holds[b-m3f01laonm] {
        display: flex;
        flex-direction: column;
        gap: 8px;
        margin: 0;
    }

    .release-gate-hold-row[b-m3f01laonm] {
        display: flex;
        align-items: center;
        gap: 12px;
        flex-wrap: wrap;
        padding: 10px 12px;
        background: var(--modal-bg);
        border: 1px solid var(--modal-border, rgba(0, 0, 117, 0.12));
        border-left: 4px solid var(--pt-coral, #ec607e);
        border-radius: 0;
    }

    /* GH-252 — the account is the Cuentas page's drawer (PtAccountsDrawer). Its panel, navy header, X, body scroll
       and footer bar are app.css's menu-drawer rules, so nothing here positions or colours them. The rules that
       did — a fixed panel from the rail to the screen's edge, a light header with a round back button, the table
       and waiter badges beside the title — went with that markup, and a component rule could no longer reach the
       drawer's own elements anyway: they are rendered by PtAccountsDrawer, which carries no scope attribute of this
       component's. */

    /* One column. The drawer's body is the only scroller, as in every drawer; the two columns each scrolled on
       their own. */
    .tab-detail-content[b-m3f01laonm] {
        display: flex;
        flex-direction: column;
        gap: 0.75rem;
    }

    /* Cliente: the guest's name, then the card's rows.
       align-items is flex-start rather than center. The original reason is gone — there is no longer
       a two-row stack on the right, because the pencil moved to the CLIENTE header row — but the
       property stays deliberately: this row now holds one item, and flex-start is what keeps a
       wrapped name anchored to the top of its line rather than floating mid-row. */
    .client-headline[b-m3f01laonm] {
        display: flex;
        align-items: flex-start;
        justify-content: space-between;
        gap: 0.75rem;
        flex-wrap: wrap;
    }

    /* .client-headline-aside was deleted here (Igor, 2026-09-22) along with its element. The history
       in one line, because this control has now moved three times: #340's follow-up asked for the
       pencil in the card's top-right, stacked above the Abierta tag; #374 moved that tag to the
       drawer's header; and with the tag gone the wrapper held a single button whose "corner" was the
       body's, level with the guest's name. The pencil now rides the CLIENTE header row — see
       .right-card-header--with-action below — which is the card's corner rather than the body's. */

    /* 1.375rem, from 1.05 (#419). Cam's mockup sets the guest's name as the card's headline — about
       1.6x its facts — and at 1.05 it sat barely above them, so nothing on the card led. */
    .client-name[b-m3f01laonm] {
        font-size: 1.375rem;
        line-height: 1.25;
        font-weight: 700;
        color: var(--modal-text);
    }

    .client-anonymous[b-m3f01laonm] {
        font-style: italic;
        font-weight: 500;
        color: var(--modal-text-secondary);
    }

    /* #296 — a TAG, not a button. Cam: "the Open/Closed status tags ... are styled as buttons. These should
       follow the styling of non-interactive tags."

       It was a 2px border in the state's colour on the card's own surface, and 2px is precisely the admin's
       BUTTON edge (app.css `.btn { border: 2px solid }`), so an inert label sat beside the guest's name looking
       like something to press. The whole signal was in that border, which is why it had to be so loud.

       Now it is built like `.order-waiter-badge` — the pair app.css declares for the admin's non-interactive
       tags: a tint, a hairline, small caps-weight text. The STATE moved into the fill, so the edge can be a
       hairline and the tag still says what it says. Each state's text colour is stated with its tint rather than
       inherited, because a tint is exactly where a foreground gets forgotten (AccountClientCardContractTests
       measures all three, in both schemes, at 4.5:1). */
    .client-status[b-m3f01laonm] {
        display: inline-flex;
        align-items: center;
        padding: 2px 8px;
        font-size: 0.75rem;
        font-weight: 600;
        border: 1px solid transparent;
        border-radius: 0;
        white-space: nowrap;
    }

    /* GREEN for an open account (#376 follow-up, Igor). It reads as the live, healthy state, which
       is what green says everywhere else in this app; the indigo it swapped with now marks the
       settled one. The three values moved together, so the pair this contract measures is intact. */
    .client-status--open[b-m3f01laonm] {
        background: #e6f4ea;
        color: #12633a;
        border-color: #b7e0c6;
    }

    /* ...and the indigo Abierta used to wear goes to the settled states. Abandonada-cobrada keeps
       sharing it: it is a closed account that was collected, so it belongs with Cerrada rather than
       with the red that marks one which was not. */
    .client-status--closed[b-m3f01laonm],
    .client-status--abandoned-charged[b-m3f01laonm] {
        background: #e8eaf6;
        color: #1a237e;
        border-color: #c5cae9;
    }

    .client-status--abandoned[b-m3f01laonm] {
        background: #fdecea;
        color: #9b1c16;
        border-color: #f5c6c3;
    }

    /* #341 — an account reopened for a correction. Amber: a temporary condition to be resolved, not a
       settled outcome, and the one state in this set an operator most needs to pick out of Cuentas Activas.
       #78350f on #fef3c7 is the pair the drawer already uses for its warning hint (.client-edit-hint), so
       this borrows a tested combination rather than inventing a fifth palette. AA-measured in both schemes
       by AccountClientCardContractTests. */
    .client-status--reopened[b-m3f01laonm] {
        background: #fef3c7;
        color: #78350f;
        border-color: #f7d986;
    }

    /* #374 — the same chip, worn in the drawer's HEADER beside the title. Uppercase here rather than in
       the label string, so what the component says stays a word the rest of the app can read: "ABIERTA",
       "CERRADA", "RE-ABIERTA". */
    .client-status--header[b-m3f01laonm] {
        gap: 0.375rem;
        text-transform: uppercase;
        letter-spacing: 0.04em;
        font-size: 0.6875rem;
        padding: 3px 10px;
    }

    .client-status-dot[b-m3f01laonm] {
        width: 7px;
        height: 7px;
        border-radius: 50%;
        /* The chip's own ink — so the dot is correct in all four states and both schemes without a single
           rule of its own, and cannot drift from the word beside it. */
        background: currentColor;
        flex-shrink: 0;
    }

    /* Mesero, reassignable while the account is open. It was a dropdown in the header. */
    .waiter-reassign-section[b-m3f01laonm] {
        display: inline-flex;
        align-items: center;
        gap: 0.5rem;
    }

    /* #277 made this the admin's plain `.form-select` so it read as the same control as every other
       dropdown. Igor, 2026-09-22: "style the mesero drop down to blend into the background and just
       show an arrow to see the dropdown as well so that it looks more cohesive."

       So the BOX goes and the affordance stays. Inside this card the select sat as a bordered field
       among plain text values — Mesa, Pedidos, Creada are all bare — which made the one editable
       fact look like a form dropped into a summary. Transparent background and no border let it read
       as the value it is; the caret is what says it can be changed.

       WHAT IS DELIBERATELY KEPT:
       - the 44px touch target, via the inherited min-height. A borderless control is still a control
         and this ships on a touchscreen.
       - a visible focus indicator (below). A select with no border that also shows nothing on focus
         is #395's defect in a new place — and a keyboard operator would have no idea where they are.
       - the caret, which is .form-select's own background-image and is why this keeps that class
         rather than becoming a bare <select>. */
    .waiter-reassign-section .form-select[b-m3f01laonm] {
        min-width: 180px;
        max-width: 100%;
        cursor: pointer;
        background-color: transparent;
        border-color: transparent;
        /* Bootstrap's 0.75rem assumes a box. This one has none at rest but draws one on hover and
           focus, and at `padding-left: 0` — where this sat until Igor's edits_to_client_section —
           the value was flush against that box the moment it appeared.

           THE PADDING IS SPLIT BETWEEN THE BOX AND THE COLUMN, and the ratio is the whole point.
           Three passes got here:

             - all of it inward (padding alone): the value cleared the box, but the caption had to
               follow it and the column ended up 8px further from its glyph than the three facts
               beside it. Igor: "it's a little too indented."
             - all of it outward (padding plus an equal negative margin): the column stayed put and
               the box grew left instead — 8px left, against a glyph only 6.4px away, so the box
               drew over it. Igor: "the hover state shows over the icon which it shouldn't."

           So HALF each way. The box starts 4px left of the value and clears the glyph by 2.4px;
           the value and the caption sit 4px right of where the column's own edge is, which is
           10.4px from the glyph against the facts' 6.3px. Measured, and chosen from five rendered
           spacings rather than tuned blind.

           Both halves read one token, so nobody can retune the padding and leave the margin — or
           the caption — behind. The right side keeps its room for the caret. */
        padding-left: var(--waiter-field-indent, 0.5rem);
        margin-left: calc(-1 * var(--waiter-field-indent, 0.5rem) / 2);
        font-weight: 600;
    }

    /* Hover is how a pointer user discovers the control now that nothing else outlines it. */
    .waiter-reassign-section .form-select:hover:not(:disabled)[b-m3f01laonm] {
        border-color: var(--modal-border);
    }

    /* Focus draws the same navy line every other field in the app draws — the border alone, no ring
       (#395). Against the transparent resting state this is unmistakable. */
    .waiter-reassign-section .form-select:focus[b-m3f01laonm] {
        background-color: transparent;
        border-color: var(--pt-field-focus);
        box-shadow: none;
        outline: none;
    }

    /* Disabled while a reassignment is in flight: the caret would promise an interaction that is
       not available. */
    .waiter-reassign-section .form-select:disabled[b-m3f01laonm] {
        background-color: transparent;
        opacity: 0.6;
    }

    /* Toolbar for comp/remake buttons */
    .section-actions-toolbar[b-m3f01laonm] {
        display: flex;
        gap: 0.5rem;
        margin-bottom: 0.75rem;
        padding-bottom: 0.75rem;
        border-bottom: 1px solid var(--modal-border);
    }

    /* #82 / #83 — the action buttons are ONE set: navy outline, filling navy on hover.
       Rehacer / Cortesía / Descuento / Mover in this toolbar, and Imprimir / Fusionar in the
       actions card, all now carry `.btn-outline-primary` (solid `.btn-primary` when a mode is on).

       This block previously did the OPPOSITE. Three of the four toolbar buttons rendered
       BORDERLESS — app.css `.btn` declares `border: 2px solid transparent` and loads after
       Bootstrap (index.html: app.css after bootstrap), so at equal specificity it won on source
       order and flattened the variable-driven outline for -info / -warning / -secondary. Only
       `.btn-outline-primary` escaped, because app.css:770-773 pins `border-color: #000075
       !important`. Descuento therefore drew a hard navy box its three neighbours did not, and this
       rule stripped that border to make the odd one out match the flattened three.

       Levelling DOWN is what #82 asked us to undo ("add borders"). With every button on
       `.btn-outline-primary` the escape now applies to all of them, so deleting the strip is the
       whole fix: borders return, the four colours collapse to navy, the gray Mover/Fusionar go, and
       fill-on-hover comes free from app.css:777-781 (white on #000075).

       Theme-safe without a dark override: the label uses `--pt-navy-fg`, which app.css:338 remaps
       to #a5b4fc in dark (~7.6:1 on this modal's surface), while the border stays #000075 in both.
       The 2px width is unchanged from `.btn`, so no box shifts. */

    /* #314 — a tapped button must not be left looking active.
       Cam: "After closing it should return to it's default state (currently it stays filled until
       clicking elsewhere)." The class does flip back the moment the mode closes; what stays is the
       HOVER fill, because a touch screen has no way to leave an element and leaves :hover latched on
       the last thing tapped. Same root cause as the iPad lift-and-glow on the Turnos page. Gating the
       fill behind a real pointer is the fix; a mouse still gets it. */
    @media (hover: none) {
        .section-actions-toolbar .btn-outline-primary:hover[b-m3f01laonm] {
            background-color: transparent;
            color: var(--pt-navy-fg);
            border-color: var(--pt-navy-fg);
        }
    }

    /* #273: while a mode runs, the buttons it locks out wear ONE muted outline (Igor), so only the
       running mode and the buttons still open for use carry the navy. They used to disagree with
       each other — Bootstrap fades an outline button's own colour, app.css pins
       `.btn-outline-primary`'s border !important, and the two left a pale blue box on Rehacer beside
       a grey one on Mover Artículos. Stated here rather than left to opacity so both are one colour
       in both themes.

       #314 removed the lockout — the modes switch instead of disabling each other — so nothing in this
       toolbar is disabled today. Kept because the treatment is right for any disabled state that
       returns, and because it costs nothing while matching none. */
    .section-actions-toolbar .btn:disabled[b-m3f01laonm],
    .section-actions-toolbar .btn.disabled[b-m3f01laonm] {
        border-color: var(--modal-border) !important;
        color: var(--modal-text-secondary) !important;
        background-color: transparent !important;
        opacity: 1;
    }

    /* Category-based blended items */
    /* UX #48: give the items table left/right breathing room from the panel edge. */
    .blended-items-list[b-m3f01laonm] {
        display: flex;
        flex-direction: column;
        gap: 0.25rem;
        /* NO horizontal padding (#374 rev). Its 0.5rem was insetting every Pedido card 8px from
           the totals card below, which is what Cam read as the two containers being different
           widths. The cards carry their own margin; this wrapper only stacks them. */
        padding: 0.25rem 0;
    }

    /* #374 — ONE CARD PER PEDIDO.

       This replaces .category-group and .blended-category-header, which grouped the same rows by
       menu category. Both are gone rather than left behind: the component stopped emitting them in
       the same change, and a scoped rule for markup that is no longer rendered is the thing that
       makes the next person tune a section that cannot appear. */
    .orders-section-title[b-m3f01laonm] {
        font-size: 1rem;
        font-weight: 700;
        color: var(--modal-text);
        margin: 0.75rem 0.5rem 0.25rem;
    }

    .order-group[b-m3f01laonm] {
        /* 2px, matching .totals-card (#374 rev, Cam: "same border line width"). The two boxes stack
           on the same screen and were 1px and 2px, which reads as one of them being emphasised. */
        border: 2px solid var(--modal-border);
        border-radius: 0;
        margin-bottom: 0.75rem;
        /* NO overflow: hidden (#374, round 4). It was here to clip the header's fill, which has no
           radius to clip — every corner in this admin is square — and it would clip the accent bar,
           which now has to reach OUT over this border. Collapsing is a conditional render, not a
           height animation, so nothing else depended on it. */
    }

    /* A cancelled round still shows — it carries what the account was charged or credited — but it
       should not read as live. */
    .order-group-cancelled[b-m3f01laonm] {
        opacity: 0.72;
    }

    /* The whole header folds the card, so it IS the control: a real button, reset to look like a
       row. width/text-align/background are the UA defaults a <button> brings that a header must
       not keep. */
    .order-group-header[b-m3f01laonm] {
        display: flex;
        align-items: center;
        /* 0.75rem, from 0.5 (#374 rev): "add a bit more space between Pedido 1 and clock icon" and
           "add more space between order status tag and chevron icon" are the same gap, twice. */
        gap: 0.75rem;
        width: 100%;
        padding: 0.625rem 0.875rem;
        border: none;
        /* THE ACCENT BAR IS AN OVERLAY NOW (#374 round 4, Cam: "the left accent bar on the pedidos
           container header row should cover the left gray outline border of the container").

           As a border-left it sat INSIDE the card's 2px grey edge, so the header showed grey, then
           colour — a grey stripe down the outside of the bar. A child's border cannot paint over its
           parent's; an absolutely positioned ::before can, and at `left: -2px` it lands exactly on
           the card's border (§38's technique, for the same reason: a border cannot square off over
           a neighbour, an overlay can). `top: -2px` carries it over the corner so the bar's end is
           square with the card's top edge rather than notched by a 2px grey square.

           The colour is --ogh-accent, set by the status class below — still the chip's own token,
           so the bar and the chip cannot drift apart. The neutral here is for a status nobody has
           mapped. */
        position: relative;
        --ogh-accent: var(--modal-border);
        border-bottom: 1px solid var(--modal-border);
        background: var(--modal-header-bg);
        text-align: left;
        font: inherit;
        cursor: pointer;
        /* 44px floor: this is a touch target, and the drawer is used on iPads. */
        min-height: 44px;
    }

    .order-group-header:hover[b-m3f01laonm] {
        background: rgba(0, 0, 117, 0.04);
    }

    /* 4px from the card's outer edge: the card's 2px border it covers, and 2px inside it.
       #584 (Cam): "It should be the same thickness as the accent bars on the tabs grid view cards" —
       a grid card's bar is its 4px left border (TabCard, .tab-card--attention). It was 6px: the
       border plus the 4px the bar was before #374 round 4 moved it over the border.
       TabDrawerContractTests holds the two equal as painted. Pointer-transparent, so the header — a
       button — still takes the press all the way to its edge. */
    .order-group-header[b-m3f01laonm]::before {
        content: "";
        position: absolute;
        left: -2px;
        top: -2px;
        bottom: -1px;
        width: 4px;
        background: var(--ogh-accent);
        pointer-events: none;
    }

    /* The bar takes the status's own token. One value, two marks: the chip's fill and this edge.
       Matched on the STATUS class the header already carries beside .order-group-header. */
    .order-group-header.ogh--pending[b-m3f01laonm] {
        --ogh-accent: var(--pt-status-pending-border);
    }

    .order-group-header.ogh--ready[b-m3f01laonm] {
        --ogh-accent: var(--pt-status-ready-border);
    }

    .order-group-header.ogh--done[b-m3f01laonm] {
        --ogh-accent: var(--pt-status-done-border);
    }

    .order-group-header.ogh--cancelled[b-m3f01laonm] {
        --ogh-accent: var(--danger-color, #dc3545);
    }

    .ogh-title[b-m3f01laonm] {
        font-weight: 700;
        font-size: 0.875rem;
        color: var(--modal-text);
        flex-shrink: 0;
    }

    .ogh-meta[b-m3f01laonm] {
        display: flex;
        align-items: center;
        gap: 0.3rem;
        font-size: 0.75rem;
        color: var(--modal-text-secondary);
        /* Takes the slack so the badge and chevron stay pinned right. */
        flex: 1 1 auto;
        min-width: 0;
    }

    .ogh-sep[b-m3f01laonm] {
        opacity: 0.6;
    }

    /* LIGHT GREY (#374 rev, then round 4). The glyph is a unit marker for the time beside it, not a
       thing to read.

       Round 3 set #6b7280 and refused anything lighter, on a 3:1 floor: a lighter grey measured
       2.28:1 on this header. Cam asked again in round 4 ("make clock icon in pedido header row a
       lighter gray color"), and the ruling was wrong, not the ask. WCAG 1.4.11 covers graphics
       REQUIRED to understand the content. The time is printed beside this glyph and the glyph is
       aria-hidden; removing it loses nothing, so it is decoration, and decoration has no floor.
       #9ca3af is the grey-400 Cam's mockups use for this kind of mark.

       The TIME keeps its contrast. It is .ogh-meta's text, and that is where the meaning is. */
    .ogh-clock[b-m3f01laonm] {
        color: #9ca3af;
        flex-shrink: 0;
    }

    /* "Lighter" means QUIETER, and on a dark header that runs the other way: #9ca3af measured 6.99:1
       there, louder than the round-3 grey was on light. The dark end is the darker grey — the same
       pair the captions on the CLIENTE card use, swapped. */
    @media (prefers-color-scheme: dark) {
        .ogh-clock[b-m3f01laonm] {
            color: #4b5563;
        }
    }

    /* Size only. The COLOUR comes from the global .order-status-* class beside this one — the same
       four chips the Pedidos board uses — so the two surfaces cannot drift into two palettes for
       one set of states. */
    .ogh-status[b-m3f01laonm] {
        flex-shrink: 0;
        font-size: 0.6875rem;
        text-transform: uppercase;
        letter-spacing: 0.04em;
    }

    .ogh-chevron[b-m3f01laonm] {
        flex-shrink: 0;
        font-size: 0.75rem;
        color: var(--modal-text-secondary);
        /* On top of the row's gap (#374 rev): the chip is a filled box and the chevron a bare
           glyph, so the same gap reads tighter here than it does between two pieces of text. */
        margin-left: 0.25rem;
    }

    .order-group-actions[b-m3f01laonm] {
        /* A row, so the button can be narrower than the card and still be centred under it. */
        display: flex;
        justify-content: center;
        padding: 0.625rem 0.875rem 0.875rem;
    }

    /* NARROWER THAN THE CARD (#374 rev, Cam: "reduce width of 'Mark Ready' button to match
       mockup"). It was full width, on the reasoning that a narrow button floating under a list
       reads as belonging to the last item - centring it answers that without the button being the
       widest thing in the card.

       `width: auto` with a floor rather than a fixed width: the label is "Marcar como entregado" in
       one state and "Marcar listo" in another, and a fixed width would be a width for one of
       them.

       THEN IT WENT TOO FAR, and the numbers say why (Igor: "we made the order completion button too
       small now. Calculate the relative width to the modal"). `width: auto` meant the content
       decided, so `min-width: 14rem` WAS the width: 224px of a 780px card inside an 828px drawer —
       28.7% of its card, under a third. The first version spanned the card; this one was lost under
       it.

       A PROPORTION of the card, with the floor demoted to being a floor. 60% of the actions row
       (780 less the card's 2px borders and this row's 14px insets = 748) is ~449px, or 57.5% of the
       card itself — plainly reduced, plainly the card's primary action. `14rem` now only ever binds
       on a phone, where 60% of a ~340px card would be 204px and too narrow for "Marcar como
       entregado"; on the desktop drawer the percentage is always the larger of the two.

       The contract that let 224px through asserted `< card * 0.9`, which is true of 224 and true of
       700. It asserts a BAND now — the lower bound is the half that was missing. */
    .og-action-btn[b-m3f01laonm] {
        display: flex;
        align-items: center;
        justify-content: center;
        gap: 0.5rem;
        width: 60%;
        min-width: 14rem;
        max-width: 100%;
        padding-inline: 1.25rem;
        min-height: 44px;
        /* 2px (#374 round 4, Cam: "make the 'Mark as Ready' button border thicker"). The same weight
           as the card around it, which is what made the 1px outline read as a secondary control. */
        border: 2px solid var(--pt-navy, #000075);
        border-radius: 0;
        background: transparent;
        color: var(--pt-navy, #000075);
        font-weight: 600;
        font-size: 0.875rem;
    }

    .og-action-btn:hover:not(:disabled)[b-m3f01laonm] {
        background: var(--pt-navy, #000075);
        color: #ffffff;
    }

    .og-action-btn:disabled[b-m3f01laonm] {
        opacity: 0.6;
        cursor: not-allowed;
    }

    /* THE HELD STEP (#374 round 4, the undo). It takes the button's place, so the card does not grow
       or jump when the step is pressed: the same row, the same 44px, what was pressed on the left
       and the way back on the right. The label is quiet — nothing has been sent yet, so it must not
       read as a confirmation — and the way back is the loud thing, because for these few seconds it
       is the only action on the card. */
    .og-pending-step[b-m3f01laonm] {
        align-items: center;
        gap: 1rem;
    }

    .og-pending-label[b-m3f01laonm] {
        display: inline-flex;
        align-items: center;
        gap: 0.5rem;
        font-size: 0.875rem;
        color: var(--modal-text-secondary);
    }

    .og-undo-btn[b-m3f01laonm] {
        min-height: 44px;
        padding-inline: 1.25rem;
        border: 2px solid var(--pt-navy, #000075);
        border-radius: 0;
        background: transparent;
        color: var(--pt-navy, #000075);
        font-weight: 600;
        font-size: 0.875rem;
    }

    .og-undo-btn:hover[b-m3f01laonm] {
        background: var(--pt-navy, #000075);
        color: #ffffff;
    }

    /* Navy is nearly the dark modal's ground — the same trap, and the same answer, as .og-action-btn. */
    @media (prefers-color-scheme: dark) {
        .og-undo-btn[b-m3f01laonm] {
            border-color: #c7d2fe;
            color: #c7d2fe;
        }

        .og-undo-btn:hover[b-m3f01laonm] {
            background: #c7d2fe;
            color: #111827;
        }
    }

    /* DARK. Both rules above name --pt-navy directly, and navy is what the dark modal ground
       already nearly is (#000075 on #1f2937 measures about 1.2:1) — the button would have been a
       button-shaped hole. The same trap this batch hit twice: one declaration written for the light
       surface, serving both.

       #c7d2fe is the ink the nav uses for exactly this job, and the hover inverts the pair rather
       than filling with navy, which on this ground would be the same invisibility again. */
    @media (prefers-color-scheme: dark) {
        .order-group-header:hover[b-m3f01laonm] {
            background: rgba(255, 255, 255, 0.06);
        }

        .og-action-btn[b-m3f01laonm] {
            border-color: #c7d2fe;
            color: #c7d2fe;
        }

        .og-action-btn:hover:not(:disabled)[b-m3f01laonm] {
            background: #c7d2fe;
            color: #111827;
        }
    }

    /* UX #49: fixed line-height so the qty / name / price / status-chip share one baseline
       and the item text reads as vertically centered within the row. */
    .blended-item-row[b-m3f01laonm] {
        display: flex;
        align-items: center;
        gap: 0.5rem;
        padding: 0.375rem 0.25rem;
        font-size: 0.875rem;
        line-height: 1.35;
    }

    .blended-item-row:hover[b-m3f01laonm] {
        background: rgba(0, 0, 117, 0.03);
    }

    /* THE ROWS SIT UNDER THEIR HEADER (#374 round 4, Cam: "increase margin/padding on both sides of
       the items list within pedidos containers"). 0.25rem put "1 x" 4px from the card's edge while
       "Pedido 1" sat 14px in — the header's 0.875rem. One inset for both, so the quantity column
       starts under the title and the price ends under the chevron. */
    .order-group .blended-item-row[b-m3f01laonm] {
        padding-inline: 0.875rem;
    }

    /* Right Column Cards */
    .right-card[b-m3f01laonm] {
        background: var(--modal-header-bg);
        border: 1px solid var(--modal-border);
        border-radius: 0;
        padding: 0.75rem;
    }

    .right-card-header[b-m3f01laonm] {
        font-size: 0.75rem;
        font-weight: 700;
        color: var(--modal-text-secondary);
        text-transform: uppercase;
        letter-spacing: 0.03em;
        margin-bottom: 0.5rem;
        display: flex;
        align-items: center;
        gap: 0.375rem;
    }

    /* A header that carries a control on its row. Opt-in modifier rather than a change to
       .right-card-header itself, which the account's other card also uses with nothing to place —
       a blanket justify-content: space-between would push that one's icon and label apart.

       The title is wrapped so the icon and the word stay together as one flex child; without it
       space-between would put the icon hard left, the label in the middle and the button right. */
    .right-card-header--with-action[b-m3f01laonm] {
        justify-content: space-between;
        /* The button is 44px and the bare header is ~18px, so the row grows. Reserving the height
           unconditionally keeps this card's body starting at the same y as its neighbour's whether
           or not the pencil is rendered — it is hidden on a paid or closed account, and a header
           that changes height when a tab settles reads as the layout shifting under the operator. */
        min-height: var(--pt-control-min-height, 44px);
        margin-bottom: 0.25rem;
    }

    .right-card-header--with-action .right-card-header-title[b-m3f01laonm] {
        display: inline-flex;
        align-items: center;
        gap: 0.375rem;
    }

    /* Pull the button's own touch padding back to the card edge so the glyph lines up with the
       content below it rather than floating inset. The 44px target is untouched — this moves where
       the box sits, not how big it is. */
    .right-card-header--with-action .client-edit-btn[b-m3f01laonm] {
        margin-right: -0.5rem;
        flex-shrink: 0;
    }

    /* THE PENCIL (#419, Cam: "fix the position of the Edit icon"). Three things were wrong and one
       caused two of them: `.right-card-header i` below is written for the header's TITLE glyph —
       0.7rem and navy — and the pencil is an <i> in the same header, so it inherited both. It drew
       at 11px in the brand colour, the loudest-coloured and smallest thing on the card.

       Now: the drawer's quiet grey at 1.125rem, the size of the facts' glyphs. The BUTTON is a real
       44px square — the comment on the rule above said it was, and it measured 22x16 — and it is
       pulled right by exactly the air it puts around its glyph, so the glyph's right edge sits on
       the card's inner edge, level with the end of the strip below. */
    .right-card-header--with-action .client-edit-btn[b-m3f01laonm] {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        width: var(--pt-control-min-height, 44px);
        height: var(--pt-control-min-height, 44px);
        padding: 0;
        margin-right: calc((1.125rem - var(--pt-control-min-height, 44px)) / 2);
    }

    .right-card-header--with-action .client-edit-btn i[b-m3f01laonm] {
        font-size: 1.125rem;
        color: var(--modal-text-secondary);
    }

    .right-card-header--with-action .client-edit-btn:hover i[b-m3f01laonm] {
        color: var(--pt-navy-fg, #000075);
    }

    .right-card-header i[b-m3f01laonm] {
        color: var(--pt-navy-fg);
        font-size: 0.7rem;
    }

    .right-card-body[b-m3f01laonm] {
        display: flex;
        flex-direction: column;
        gap: 0.5rem;
    }

    /* Client Info Card */
    /* #296 (Igor) — the whole section reads tighter. Three short rows were carrying 0.25rem of their own padding
       top and bottom on top of the body's 0.5rem gap: 16px of air between two 18px lines, so the whitespace was
       as tall as the text it separated and the card spent most of its height on nothing. The rows keep their
       own padding at zero and the body gives them one small gap, which is the whole rhythm.
       Measured, not eyeballed: AccountClientCardContractTests asserts the air between two rows stays under half
       the height of the text in them. */
    /* #340 (Carmel) — correcting the guest name / table. Straight edges and the brand navy like the rest
       of this drawer; the pencil is quiet until hovered so it does not compete with the status badge. */
    .client-edit-btn[b-m3f01laonm] {
        background: none;
        border: none;
        padding: 0.15rem 0.35rem;
        color: var(--modal-text-secondary);
        cursor: pointer;
        line-height: 1;
    }

    .client-edit-btn:hover[b-m3f01laonm] {
        color: var(--pt-navy-fg, #000075);
    }

    /* The edit panel takes .comp-panel wholesale (surface, navy edge, padding, header, title, corner X) —
       Igor: "the edit container should also match the styling of the action button containers (Rehacer,
       Mover Articulos, etc.)". Only two things differ, and both are because .comp-panel-body is a wrapping
       flex ROW built for chips and buttons while this panel holds a field grid: its children take the full
       width, and it sits inside the Cliente card rather than the items list, so the family's
       margin-bottom: 1rem would push the info rows away from it. */
    .client-edit-panel[b-m3f01laonm] {
        margin-top: 0.5rem;
        margin-bottom: 0;
    }

    .client-edit-panel .comp-panel-body[b-m3f01laonm] {
        display: block;
    }

    /* Wraps to one column on a phone rather than squeezing three fields across. */
    .client-edit-fields[b-m3f01laonm] {
        display: grid;
        grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
        gap: 0.5rem;
    }

    .client-edit-field label[b-m3f01laonm] {
        display: block;
        font-size: 0.75rem;
        font-weight: 600;
        color: var(--modal-text-secondary);
        margin-bottom: 0.2rem;
    }

    .client-edit-field .form-control[b-m3f01laonm] {
        border-radius: 0;
        min-height: var(--pt-field-min-height, 44px);
        font-size: 1rem;
    }

    .client-edit-hint[b-m3f01laonm] {
        margin: 0.5rem 0 0;
        font-size: 0.8rem;
        color: #78350f;
        background: #fef3c7;
        border-left: 3px solid #f59e0b;
        padding: 0.4rem 0.6rem;
    }

    .client-edit-actions[b-m3f01laonm] {
        display: flex;
        justify-content: flex-end;
        gap: 0.5rem;
        margin-top: 0.75rem;
    }

    .client-edit-actions .btn[b-m3f01laonm] {
        border-radius: 0;
        min-height: 40px;
    }

    /* #374 — the account's facts as one condensed strip instead of three stacked label/value rows.

       WRAPS rather than scrolls: at a narrow drawer width the four facts drop onto a second line, which
       is what a strip of independent facts should do. A row-gap as well as a column-gap, so a wrapped
       line does not sit flush against the one above it. */
    /* EQUAL COLUMNS WITH HAIRLINES BETWEEN THEM (Igor, client_info_2).

       It was a content-sized row with the waiter pinned right, which bunched three short facts at
       the left and left a gulf before the control — "Mesa S8 | 1 pedido | 19/09 01:07" crammed
       together, then nothing, then a dropdown. Equal shares put the same space around each fact
       whatever its text says, and the rule between them is what makes that read as four fields
       rather than as one sentence running on.

       align-items: stretch, so the hairline spans the row's full height rather than the height of
       whichever fact it happens to sit beside. */
    /* ONE TYPE SCALE FOR THE FOUR VALUES (#419, Cam: "consistent font sizes needed across each
       column"). The facts were 13px and the waiter's select 16px — Bootstrap's size, never set
       here — so the one control was also the one loud value. Both read these two tokens now, and
       the line height is a token too, because the select's layout height is derived from it below. */
    .client-meta[b-m3f01laonm] {
        --client-value-size: 0.9375rem;
        --client-value-line: calc(var(--client-value-size) * 1.2);
        display: flex;
        flex-wrap: wrap;
        align-items: stretch;
        row-gap: 0.75rem;
        padding-top: 0.125rem;
    }

    .client-meta-item[b-m3f01laonm] {
        display: flex;
        align-items: center;
        /* 0.75rem, from 0.4 (#419): the glyphs are 20px now, and at 6px from their value they read
           as the value's first character rather than as its marker. */
        gap: 0.75rem;
        /* Equal share of the SPARE room, never less than the fact itself needs.
        
           `flex: 1 1 0` was the first attempt and it crushed them: at a narrow drawer width the
           columns divided the row evenly regardless of content, so "3 pedidos" became "3 pedid…",
           the date lost its year, and the waiter's select — which has a min-width of its own —
           simply overflowed the card.
        
           `max-content` as the floor means a column can grow to take its share but cannot shrink
           below its text, so a strip too narrow for four columns WRAPS instead of truncating. */
        flex: 1 1 auto;
        min-width: max-content;
        /* 1.125rem (#419). Cam's mockup spaces the columns wider than the 0.875rem this had; 1.25rem
           was tried first and left the strip ONE pixel from wrapping on a 720px drawer (the drawer is
           100% of the viewport below 828px, so that is a tablet in portrait). 1.125 keeps most of the
           air and ~13px of slack there. AccountClientCardContractTests pins the one-row fit. */
        padding: 0 1.125rem;
    }

    /* The divider is the SEPARATION — there is no column-gap — so it cannot drift away from the
       edge it marks. --modal-border is the drawer's own hairline; nothing new is introduced. */
    .client-meta-item + .client-meta-item[b-m3f01laonm] {
        border-left: 1px solid var(--modal-border);
    }

    .client-meta-item:first-child[b-m3f01laonm] {
        padding-left: 0;
    }

    .client-meta-item:last-child[b-m3f01laonm] {
        padding-right: 0;
    }

    /* The waiter's item is a labelled FIELD, not a fact — but it is laid out like every other item
       on the strip: glyph on the left, content beside it, both centred on one axis. It used to be a
       COLUMN with a .client-meta-head stacking the glyph over the caption, which is what Igor's
       "move the mesero icon to be centered to the left of the label and dropdown" undoes. The rule
       and the head are both gone: with the glyph a direct child again, the base .client-meta-item
       row gives exactly this, and `align-items: center` is what puts the glyph level with the
       two-line pair rather than at the top of it.

       What did NOT come back is the caption sitting beside or beneath the control. It stays above
       it — the field names itself before it offers itself. */

    /* The glyphs are quiet: they mark the fact, they are not the fact.
       1.25rem, from 0.8125 (#419). At 13px they sat at the height of one line of a two-line pair,
       too small to lead it; the mockup draws them the height of the pair. .pt-tables-icon is the
       Mesa glyph's own class — TablesIcon, not PtIcon — and without it here the one hand-drawn
       glyph would be the one that stayed small.

       ::deep, because TablesIcon is a CHILD COMPONENT: its <i> carries TablesIcon's scope, not this
       file's, so `.client-meta-item > .pt-tables-icon` compiles to a selector that can never match.
       Measured — without ::deep the table glyph rendered at 16px in the card's ink while the other
       three were 20px and grey. */
    .client-meta-item > i[b-m3f01laonm],
    .client-meta-item[b-m3f01laonm]  .pt-tables-icon {
        color: var(--modal-text-secondary);
        font-size: 1.25rem;
        flex-shrink: 0;
    }

    /* Caption over value — on every column now (#419), not only the two whose value did not name
       itself. The gap is the SAME for all four, and it is the whole of the space between them:
       Cam's "add space between label and main text... align spacing on labels/text across each
       column". The waiter's select is made to occupy exactly one value line below, so this gap is
       not quietly different in the one column that holds a control. */
    .client-meta-body[b-m3f01laonm] {
        display: flex;
        flex-direction: column;
        /* 0.4375rem, and not an arbitrary one: it is what lets the waiter's hover frame clear its
           caption (see the select's rule below — gap + inset has to exceed the select's overhang). */
        gap: 0.4375rem;
        line-height: 1.2;
        min-width: 0;
    }

    /* THE CONTROL'S BREATHING ROOM, SPLIT HALF IN AND HALF OUT (Igor, edits_to_client_section):
       "indent the content in the selector so when it's clicked it's not tight on the left. Ensure
       the Mesero label and the name stay aligned horizontally", then "it's a little too indented",
       then "the hover state shows over the icon which it shouldn't."

       The select carries the whole 0.5rem as padding and half of it back as a negative margin —
       see the rule near the top of this file for why, and for what the two extremes looked like.
       The caption takes the OTHER half here, which is what keeps it level with the name: the value
       ends up at the column's edge plus half, and so does this.

       The read-only value takes it too. A closed account shows the waiter's name as text where the
       control would be, and it has to line up under the same caption.

       Half is written as `/ 2` against the same token rather than as 0.25rem, so the two cannot be
       retuned apart — the failure this rule has already had twice. */
    .client-meta-item--waiter[b-m3f01laonm] {
        --waiter-field-indent: 0.5rem;
    }

    .client-meta-item--waiter .client-meta-label[b-m3f01laonm],
    .client-meta-item--waiter .client-meta-value[b-m3f01laonm] {
        padding-left: calc(var(--waiter-field-indent) / 2);
    }

    .client-meta-value[b-m3f01laonm] {
        font-size: var(--client-value-size);
        line-height: 1.2;
        font-weight: 600;
        color: var(--modal-text);
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }

    /* LIGHT GREY, UPPERCASE (#419). #6b7280 is the grey this drawer already uses for quiet marks
       (.staff-added-mark), 4.8:1 on the card — a caption is text, so it keeps the 4.5:1 floor
       that the decorative clock in the Pedido header does not need. The dark end is below. */
    .client-meta-label[b-m3f01laonm] {
        font-size: 0.6875rem;
        font-weight: 500;
        text-transform: uppercase;
        letter-spacing: 0.05em;
        color: #6b7280;
    }

    @media (prefers-color-scheme: dark) {
        .client-meta-label[b-m3f01laonm] {
            color: #9ca3af;
        }
    }

    /* THE WAITER SITS HARD RIGHT, and takes no more room than it needs.

       It was `flex: 1 1 11rem`, which handed it every spare pixel in the strip — so the one control
       among four facts sat second and split the row, pushing Pedidos and Creada to the far edge.
       `margin-left: auto` puts it at the end instead; `flex: 0 0 auto` stops it growing into the
       space the facts left.

       It is also the item that may WRAP to its own line first, which is right: a dropdown dropping
       below a row of text still reads as belonging to it, where a wrapped date does not. */
    /* No longer pinned right: client_info_2 asked for equal columns instead, and `margin-left: auto`
       is what created the gulf this replaces. Its column rules are with the others above. */

    /* 180px is the width the Mesero dropdown takes when it is a row of its own (#277). Inside this
       strip it is one of four things on one line, and at 180 it was wider than the three facts
       beside it put together. Scoped to the strip so the standalone control is untouched. */
    .client-meta .waiter-reassign-section .form-select[b-m3f01laonm] {
        min-width: 9rem;
    }

    /* THE SELECT TAKES ONE VALUE LINE, AND KEEPS ITS 44px (#419).

       Cam: "divider lines are too tall" and "align spacing on labels/text across each column". Both
       were this control. The hairlines stretch to the tallest column, and the tallest column was the
       one holding a 44px select under its caption: 57px, where the three facts needed ~35. And inside
       that column the value sat 13px lower than in the other three, because a 44px box centres its
       text in 44px.

       Shrinking the box would fix both and break the touch floor, so the box keeps its height and
       stops SPENDING it: negative block margins give it the layout height of one value line, so the
       column is exactly as tall as its neighbours and the text lands on the same line as theirs. The
       44px still exists to a finger — it overhangs its slot, invisibly, by 13px each way.

       Which means the hover and focus line cannot be the BORDER any more: a border is drawn at the
       box's edge, and that edge now reaches up through the caption. So the frame is an inset outline,
       drawn `--select-inset` inside the box, and the box is widened left by the same amount so the
       frame still starts where it did — 4px left of the value — and the value still clears it by
       8px (Igor's "not tight on the left", unchanged). The inset is one token for both jobs, so the
       frame and the widening cannot be retuned apart.

       THE ARITHMETIC THE FRAME DEPENDS ON. The box overhangs its one-line slot by (44 - 18) / 2 =
       13px each way, and the slot starts one caption-gap below the caption. So the frame's top sits
       at caption-bottom + gap - 13 + inset. At the first values tried (gap 4px, inset 6px) that was
       -3: the hover line crossed three pixels into the caption, level with its baseline. The old
       stacking contract caught it. At gap 7px and inset 8px it is +2, clear. Change either token
       and redo the sum. */
    .client-meta .waiter-reassign-section .form-select[b-m3f01laonm] {
        --select-inset: 0.5rem;
        /* THE SELECT FILLS ITS COLUMN rather than sizing to its options. Sized to its options it
           fits the waiter's name with nothing to spare (measured: 102px of text in 103px), so a
           slightly longer name clips; the column already has spare room, since the four share the
           strip's width, so the body grows into it (below) and the select takes all of it — about
           20px of slack for the same name. The extra is the negative margin-left handed back, so
           the right edge stays on the column's edge.

           CORRECTED (#411, 2026-09-23): this comment used to say Chromium sizes a select 9px short
           of its text. It does not. That was measured on a probe page served without a doctype —
           quirks mode — and did not reproduce in standards mode, which is what the app runs in. */
        width: calc(100% + var(--select-inset) + var(--waiter-field-indent, 0.5rem) / 2);
        min-width: 10rem;
        min-height: var(--pt-control-min-height, 44px);
        margin-block: calc((var(--client-value-line) - var(--pt-control-min-height, 44px)) / 2);
        padding-left: calc(var(--select-inset) + var(--waiter-field-indent, 0.5rem));
        margin-left: calc(-1 * (var(--select-inset) + var(--waiter-field-indent, 0.5rem) / 2));
        font-size: var(--client-value-size);
        line-height: 1.2;
        /* The caret, moved in with the frame: Bootstrap's 0.75rem from the box's edge would sit 4px
           inside a frame that is now 8px in. */
        background-position: right calc(var(--select-inset) + 0.5rem) center;
    }

    .client-meta-item--waiter .client-meta-body[b-m3f01laonm] {
        flex: 1 1 auto;
    }

    .client-meta .waiter-reassign-section[b-m3f01laonm] {
        display: flex;
    }

    .client-meta .waiter-reassign-section .form-select:hover:not(:disabled)[b-m3f01laonm] {
        border-color: transparent;
        outline: 1px solid var(--modal-border);
        outline-offset: calc(-1 * var(--select-inset));
    }

    .client-meta .waiter-reassign-section .form-select:focus[b-m3f01laonm] {
        border-color: transparent;
        outline: 1px solid var(--pt-field-focus);
        outline-offset: calc(-1 * var(--select-inset));
    }

    /* Only the client card tightens — the other right-cards hold rows that are not one-line pairs. */
    .tab-detail-client .right-card-body[b-m3f01laonm] {
        gap: 0.25rem;
    }

    /* MORE ROOM (#419, Cam: "need more margin/padding"). The card shared .right-card's 0.75rem with
       every other card in the drawer; this one now carries a headline and a four-column strip, and
       at 12px its content ran to within a glyph's width of the border. */
    .right-card.tab-detail-client[b-m3f01laonm] {
        padding: 1rem 1.5rem 1.25rem;
    }

    .tab-detail-client .client-headline[b-m3f01laonm] {
        margin-bottom: 0.75rem;
    }

    /* .client-info-row / -label / -value are GONE with the stacked rows they styled (#374). The
       component emits none of them now, and a scoped rule for markup that is never rendered is what
       makes the next person tune a section that cannot appear. */

    /* Totals Card */
    .totals-card[b-m3f01laonm] {
        background: var(--modal-header-bg);
        border: 2px solid var(--modal-border);
    }

    .totals-row[b-m3f01laonm] {
        display: flex;
        justify-content: space-between;
        align-items: center;
        padding: 0.25rem 0;
        font-size: 0.875rem;
        color: var(--modal-text-secondary);
    }

    .totals-final[b-m3f01laonm] {
        font-size: 1.25rem;
        font-weight: 700;
        color: var(--success-color);
        padding-top: 0.5rem;
        margin-top: 0.25rem;
        border-top: 2px solid var(--modal-border);
    }

    .totals-closed-badge[b-m3f01laonm] {
        display: flex;
        align-items: center;
        gap: 0.375rem;
        margin-top: 0.5rem;
        padding: 0.375rem 0.5rem;
        background: rgba(16, 185, 129, 0.1);
        color: #10b981;
        font-size: 0.75rem;
        font-weight: 600;
        text-align: center;
        justify-content: center;
    }

    /* Imprimir and Fusionar — a ROW, not a card (#380).

       It carried `.right-card` as well, which is this drawer's card chrome: a filled panel, a
       border and 0.75rem of padding. Cam: "remove the gray container around these buttons… this
       will help visually balance the bottom of the drawer so there's not a bunch of giant buttons
       with these + the footer." He is counting what stacks: these two full-width, then AGREGAR
       PEDIDO full-width, then two full-width Cerrar buttons. Four bars, of which two are a receipt
       and a merge.

       The class came off the MARKUP rather than being overridden here — it is not a card, and the
       class list should say so. (Deliberately the opposite of F80's fix, where the scoped rule had
       to answer every property of a chip a global rule was still drawing, because the class had to
       stay. Here it could go.) */
    .actions-card[b-m3f01laonm] {
        display: flex;
        justify-content: flex-end;
        gap: 0.5rem;
    }

    .btn-action-right[b-m3f01laonm] {
        /* AS WIDE AS WHAT IT SAYS. `flex: 1` divided the whole drawer between two buttons, which is
           what made them read as "giant" next to the work they do. */
        flex: 0 0 auto;
        display: inline-flex;
        align-items: center;
        justify-content: center;
        gap: 0.5rem;
        padding: 0.5rem 1rem;
        border-radius: 0;
        font-weight: 500;
        font-size: 0.8rem;
    }

    /* The drawer's footer bar lays its children out in a row; the account's footer is a column — an abandoned-
       account notice when there is one, the total, Agregar Pedido, the Cerrar buttons — so it arrives as one. */
    .account-footer[b-m3f01laonm] {
        display: flex;
        flex-direction: column;
        gap: 0.75rem;
        width: 100%;
    }

    /* The amount the Cerrar buttons close for, and what is still owed on a partly paid account (Igor, #252). */
    /* #321 — the summary line gets its own breathing room BELOW it.
       .footer-actions's 0.5rem column gap alone left 8px here: the bare minimum of the 8–12px Cam asked
       for, and with the hero carrying an extra 0.5rem the total sat 16px under Agregar Pedido and 8px
       above the closes — leaning against the buttons it introduces. 0.25rem on top of the gap makes it
       12px, the top of that range. */
    .footer-total[b-m3f01laonm] {
        display: flex;
        align-items: baseline;
        justify-content: space-between;
        gap: 1rem;
        flex-wrap: wrap;
        margin-bottom: 0.25rem;
    }

    .footer-total-amount[b-m3f01laonm] {
        font-size: 1.25rem;
        font-weight: 700;
        color: var(--modal-text);
        font-variant-numeric: tabular-nums;
    }

    /* #317 removed the footer's Saldo — a partly paid account states its balance in Pagos Recibidos, and
       once is enough in one view. `.footer-balance` went with it. */

    .footer-total-label[b-m3f01laonm] {
        margin-right: 0.35rem;
        font-size: 0.75rem;
        font-weight: 700;
        letter-spacing: 0.05em;
        color: var(--modal-text-secondary);
    }

    .footer-actions[b-m3f01laonm] {
        display: flex;
        flex-direction: column;
        gap: 0.5rem;
        width: 100%;
    }

    /* Hero Add Order Button */
    .footer-actions-hero[b-m3f01laonm] {
        width: 100%;
        margin-bottom: 0.5rem;
    }

    /* #317 — Cam: "There's a lot of different colors going on within this page. Making the primary buttons
       at the bottom blue will help the overall readability/flow." Igor scoped it: blue border, blue text and
       icons, and the fill comes off this one so it is an outline like the Cerrar buttons beside it.

       `--pt-navy-fg` rather than `--pt-navy`: app.css remaps it to a light periwinkle in dark, where a
       #000075 edge on a dark surface is very nearly invisible. Same token and same 2px weight as
       `.btn-outline-cash`, which is this component's existing navy close action (#304) — one navy-outline
       treatment here, not two that drift. TabDetailFooterColourContractTests compares them. */
    .btn-add-order[b-m3f01laonm] {
        width: 100%;
        display: flex;
        align-items: center;
        justify-content: center;
        gap: 0.75rem;
        /* #321 — the same height as the close buttons below it (Cam). Vertical padding is zeroed on both
           and the height comes from one shared min-height, so they match by construction rather than by
           two paddings and two font sizes happening to add up. They did not: 63px against 56px. */
        min-height: var(--pt-footer-action-height, 56px);
        padding: 0 1.5rem;
        background: transparent;
        border: 2px solid var(--pt-navy-fg, #000075);
        border-radius: 0;
        color: var(--pt-navy-fg, #000075);
        font-size: 1.125rem;
        font-weight: 700;
        text-transform: uppercase;
        letter-spacing: 0.05em;
        transition: all 0.2s ease;
    }

    .btn-add-order:hover[b-m3f01laonm] {
        background: rgba(0, 0, 117, 0.08);
        border-color: var(--pt-navy-fg, #000075);
        color: var(--pt-navy-fg, #000075);
        transform: translateY(-2px);
    }

    .btn-add-order:active[b-m3f01laonm] {
        transform: translateY(0);
    }

    .btn-add-order i[b-m3f01laonm] {
        font-size: 1.25rem;
    }

    .footer-actions-primary[b-m3f01laonm] {
        display: flex;
        gap: 0.75rem;
    }

    .footer-actions .btn-action[b-m3f01laonm] {
        display: inline-flex;
        align-items: center;
        gap: 0.5rem;
        padding: 0.5rem 1rem;
        border-radius: 0;
        font-weight: 500;
        font-size: 0.875rem;
    }

    .footer-actions .btn-close-tab[b-m3f01laonm] {
        flex: 1;
        display: inline-flex;
        align-items: center;
        justify-content: center;
        gap: 0.5rem;
        /* #321 — shared with .btn-add-order; see the note there. */
        min-height: var(--pt-footer-action-height, 56px);
        padding: 0 1.5rem;
        border-radius: 0;
        font-weight: 600;
        font-size: 1rem;
        transition: all 0.2s ease;
    }

    /* #317 took these off coral and onto navy. #321 then made them FILLED — Cam: "Make the Cerrar buttons
       filled navy with white text ... in the scenario where the Pay (Visa***) button is shown, the Cerrar
       buttons should just be the outline button design."

       Which is one filled button per row, always: whichever action actually closes the account leads and
       the rest step back. Without a card on file, closing in cash or on the terminal IS that action, and
       leaving them as outlines left the row with no primary at all.

       --pt-navy (not --pt-navy-fg) because this is a FILL and white sits on it: the foreground token
       remaps to a light periwinkle in dark, which would put white on a pale ground. Same split as #318's
       banner. White on #000075 is ~17:1 in both schemes. */
    .btn-cash[b-m3f01laonm] {
        background: var(--pt-navy, #000075);
        border: 2px solid var(--pt-navy, #000075);
        color: #ffffff;
    }

    .btn-cash:hover:not(:disabled)[b-m3f01laonm] {
        background: #000060;
        border-color: #000060;
        color: #ffffff;
        transform: translateY(-2px);
    }

    /* #327 — the capture takes a full row of its own, ABOVE the other two closes.
       Cam: "Currently with the 3 payment buttons side by side, the button text gets wrapped and looks off.
       I think we discussed making the Cerrar (Visa****) button show on it's own row above the other 2
       payment buttons, which would also solved the text wrapping issue."

       Three abreast in the 828px drawer gave each button ~257px, and "Cerrar (Terminal propia)" needs ~266px
       — so both it and the capture label ran to a second line. The min-height on .btn-close-tab absorbed the
       extra line without the buttons growing, which is why this looked like a text problem rather than a
       layout one.

       flex-wrap + a 100% basis on the capture, NOT a two-column grid: the own-terminal close is flag-gated,
       so with it switched off the lower row holds one button, and `flex: 1` spreads it across the full width
       the way it already does. A grid would leave a lone half-width Cerrar (Efectivo) beside empty space.
       The capture reaches the TOP row by being first in the DOM (see the razor). */
    .footer-actions-primary--capture[b-m3f01laonm] {
        flex-wrap: wrap;
    }

    .footer-actions-primary--capture .btn-paytable[b-m3f01laonm] {
        flex: 1 0 100%;
    }

    /* A card capture is in the row, so it is the primary and these give the fill back. */
    .footer-actions-primary--capture .btn-cash[b-m3f01laonm] {
        background: transparent;
        border-color: var(--pt-navy-fg, #000075);
        color: var(--pt-navy-fg, #000075);
    }

    .footer-actions-primary--capture .btn-cash:hover:not(:disabled)[b-m3f01laonm] {
        background: rgba(0, 0, 117, 0.08);
        border-color: var(--pt-navy-fg, #000075);
        color: var(--pt-navy-fg, #000075);
    }

    /* #304 — "Cerrar Sin Imprimir" had NO rule anywhere, so it fell through to app.css's
       `.btn { border: 2px solid transparent }` and rendered as bare text beside an icon, between a
       grey-outlined Cancelar and a coral-outlined Cerrar + Imprimir. Three buttons, three treatments, one of
       them invisible.

       Navy rather than a second coral: it is the plainer of the two close actions, and navy is the admin's
       standard action edge (`.btn-outline-primary`), so the row reads grey = dismiss, navy = close, coral =
       close and print. Same 2px weight as its neighbours — CloseConfirmDialogContractTests asserts all three
       share one. */
    .btn-outline-cash[b-m3f01laonm] {
        background: transparent;
        border: 2px solid var(--pt-navy-fg, #000075);
        color: var(--pt-navy-fg, #000075);
    }

    .btn-outline-cash:hover:not(:disabled)[b-m3f01laonm] {
        background: rgba(0, 0, 117, 0.08);
        border-color: var(--pt-navy-fg, #000075);
        color: var(--pt-navy-fg, #000075);
        transform: translateY(-2px);
    }

    .btn-paytable[b-m3f01laonm] {
        background: linear-gradient(135deg, var(--pt-navy, #000075) 0%, #000060 100%);
        border: none;
        color: white;
    }

    .btn-paytable:hover:not(:disabled)[b-m3f01laonm] {
        background: linear-gradient(135deg, #000060 0%, #000050 100%);
        color: white;
        transform: translateY(-2px);
        box-shadow: 0 4px 12px rgba(0, 0, 117, 0.4);
    }

    /* Paid Info */
    .paid-info[b-m3f01laonm] {
        display: flex;
        align-items: center;
        gap: 1rem;
        flex-wrap: wrap;
        color: var(--success-color);
        font-weight: 500;
        width: 100%;
    }

    .paid-info i[b-m3f01laonm] {
        font-size: 1.5rem;
    }

    .paid-tip[b-m3f01laonm],.paid-total[b-m3f01laonm] {
        padding: 0.25rem 0.75rem;
        background: rgba(16, 185, 129, 0.1);
        border-radius: 0;
    }

    .paid-total[b-m3f01laonm] {
        font-weight: 700;
    }

    /* Payment Intent Banner */
    .payment-intent-banner[b-m3f01laonm] {
        display: flex;
        align-items: center;
        gap: 1rem;
        padding: 0.75rem 1rem;
        border-radius: 0;
    }

    .payment-banner-cash[b-m3f01laonm] {
        background: linear-gradient(135deg, rgba(220, 53, 69, 0.1) 0%, rgba(220, 53, 69, 0.05) 100%);
        border: 2px solid #dc3545;
    }

    .payment-banner-paytable[b-m3f01laonm] {
        background: linear-gradient(135deg, rgba(16, 185, 129, 0.1) 0%, rgba(16, 185, 129, 0.05) 100%);
        border: 2px solid #10b981;
    }

    /* A STAFF-OPENED account is not an alert (#378, Igor's ruling). It has no card on file because
       nobody was ever asked for one — the waiter opened it and will collect at the table — so the
       red treatment was warning about the ordinary case and spending the colour that ought to mean
       "a guest declined to secure this". Neutral, and it still says what is true. */
    .payment-banner-neutral[b-m3f01laonm] {
        background: var(--modal-header-bg);
        border: 2px solid var(--modal-border);
    }

    /* LIGHTER (#374 round 4, Cam: "make the info icon in the top PAGO SIN DEFINIR banner a lighter
       gray color"). It was a dark-grey square with a white glyph — the heaviest mark in a banner
       that #378 made neutral on purpose. The square takes the drawer's hairline grey and the glyph
       the secondary text colour, which keeps the glyph well clear of 3:1 on its square (~7:1) while
       the square itself stops shouting. Both are tokens, so the dark end follows on its own. */
    .payment-banner-neutral .banner-icon[b-m3f01laonm] {
        background: var(--modal-border);
        color: var(--modal-text-secondary);
    }

    .banner-icon[b-m3f01laonm] {
        display: flex;
        align-items: center;
        justify-content: center;
        width: 48px;
        height: 48px;
        border-radius: 0;
        flex-shrink: 0;
    }

    .payment-banner-cash .banner-icon[b-m3f01laonm] {
        background: #dc3545;
        color: white;
    }

    .payment-banner-paytable .banner-icon[b-m3f01laonm] {
        background: #10b981;
        color: white;
    }

    .banner-icon i[b-m3f01laonm] {
        font-size: 1.25rem;
    }

    .banner-content[b-m3f01laonm] {
        flex: 1;
    }

    .banner-title[b-m3f01laonm] {
        font-weight: 700;
        font-size: 1rem;
    }

    .payment-banner-cash .banner-title[b-m3f01laonm] {
        color: #dc3545;
    }

    .payment-banner-paytable .banner-title[b-m3f01laonm] {
        color: #10b981;
    }

    .banner-subtitle[b-m3f01laonm] {
        font-size: 0.875rem;
        color: var(--modal-text-secondary);
        margin-top: 0.25rem;
    }

    /* #320 — the same "Saldo pendiente" figure, declared a THIRD time and with !important, which is why
       recolouring the two rules further down did not move it on its own. Body text here too; see
       .summary-authorized for why. */
    .summary-balance[b-m3f01laonm] {
        font-size: 1.25rem !important;
        font-weight: 700 !important;
        color: var(--modal-text) !important;
    }

    .item-qty[b-m3f01laonm] {
        color: var(--pt-navy-fg);
        font-weight: 600;
        min-width: 35px;
    }

    /* #274: app.css's global .item-name carries `margin-bottom: 0.5rem` for the Pedidos cards. In a
       centred row that margin is centred with the name, which lifted the name's text half of it —
       4px — above the "1 x" beside it, on every line of the account. The name owns no margin here. */
    .item-name[b-m3f01laonm] {
        flex: 1;
        margin: 0;
        color: var(--modal-text);
        /* POPPINS (#374 rev, Cam: "change font of order items to Poppins").
           --pt-font-logo is that face; the token is named for where it started, not for what it
           holds, and renaming it is tracked separately. Using the token rather than the literal so
           this row follows the family wherever it is defined. */
        font-family: var(--pt-font-logo);
    }

    .item-price[b-m3f01laonm] {
        color: var(--modal-text-secondary);
        font-weight: 500;
        min-width: 64px;
        text-align: right;
        font-variant-numeric: tabular-nums; /* prices form a right-aligned, digit-aligned column */
    }

    .empty-orders[b-m3f01laonm] {
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        padding: 2rem;
        color: var(--modal-text-secondary);
        text-align: center;
        background: var(--modal-header-bg);
        border-radius: 0;
        border: 2px dashed var(--modal-border);
    }

    .empty-orders i[b-m3f01laonm] {
        font-size: 2.5rem;
        margin-bottom: 0.75rem;
        opacity: 0.5;
    }

    .empty-orders p[b-m3f01laonm] {
        margin: 0;
        font-weight: 500;
    }

    .tip-options[b-m3f01laonm] {
        display: flex;
        gap: 0.75rem;
        flex-wrap: wrap;
    }

    /* #275: the button is the percentage; the amount is a caption under it. Keeping the amount out
       of the button is what makes the four buttons one size — Personalizado had no amount to put on
       its second line, so it stood as tall as the others around an empty half. */
    .tip-option[b-m3f01laonm] {
        display: flex;
        flex-direction: column;
        align-items: center;
        gap: 0.25rem;
    }

    /* #329 — Cam: "The green sub-text under the percentage tips buttons is difficult to read, it feels like
       the text is getting crammed in ... character spacing can be increased slightly."

       The colour is the half he could see but not name. --success-color is #10b981, which on this card's
       #f9fafb measures 2.43:1 — under AA for 12px text by a wide margin, so the figure was unreadable before
       any question of spacing. app.css already ruled on this exact token (the note above .action-icon-category):
       darken the light end one step on its own ramp, as a LITERAL, because --success-color is global and
       carries semantic meaning elsewhere.

       Two values because no single one works: #059669 is 3.61:1 here and 4.71:1 on the dark card, so it fails
       light and only scrapes dark. emerald-700 gives 5.25:1 in light; dark takes the #34d399 this component
       already uses for green text (.totals-closed-badge), at 9.23:1. Hue unchanged in both — it is still the
       green that says "this is what the tip adds". */
    .tip-amount[b-m3f01laonm] {
        font-size: 0.75rem;
        color: #047857;
        font-weight: 600;
        letter-spacing: 0.02em;
        /* One line, always: this is a currency figure, and "$42.60" over "MXN" reads as two facts. */
        white-space: nowrap;
    }

    /* #329 — Cam: "We may want to make the % buttons a bit longer, so the sub-text has some breathing room."
       At 85px the chip stood ~13px wider than the ~72px figure beneath it — six pixels a side, which is what
       made the caption look squeezed to fit the button rather than placed under it. 104px gives it ~15 a side.
       Four chips at this length plus the row's gaps come to ~452px inside the drawer's ~780px of content, so
       the row does not wrap; .tip-options wraps anyway if a narrower surface ever needs it. */
    .tip-option-btn[b-m3f01laonm] {
        display: flex;
        flex-direction: column;
        align-items: center;
        padding: 0.75rem 1rem;
        min-width: 104px;
        border: 2px solid var(--modal-border);
        border-radius: 0;
        background: var(--modal-bg);
        cursor: pointer;
        transition: all 0.2s ease;
    }

    .tip-option-btn:hover[b-m3f01laonm] {
        border-color: var(--primary-color);
        background: rgba(59, 130, 246, 0.05);
    }

    .tip-option-btn.active[b-m3f01laonm] {
        border-color: var(--success-color);
        background: rgba(16, 185, 129, 0.1);
    }

    .tip-percent[b-m3f01laonm] {
        font-weight: 700;
        font-size: 1rem;
        color: var(--modal-text);
    }

    .tip-calculated[b-m3f01laonm] {
        font-size: 0.875rem;
        color: var(--success-color);
        font-weight: 600;
        margin-top: 0.25rem;
    }

    .tip-custom-btn[b-m3f01laonm] {
        min-width: 120px;
    }

    .tip-custom-input[b-m3f01laonm] {
        display: flex;
        align-items: center;
        gap: 0.5rem;
        margin-top: 0.75rem;
    }

    .tip-symbol[b-m3f01laonm] {
        font-size: 1.25rem;
        font-weight: 600;
        color: var(--modal-text-secondary);
    }

    .tip-input[b-m3f01laonm] {
        max-width: 150px;
        text-align: right;
        font-size: 1.25rem;
        font-weight: 600;
    }

    .tip-currency[b-m3f01laonm] {
        font-size: 0.875rem;
        color: var(--modal-text-secondary);
    }

    /* `.btn-clear-tip` is gone with the control (#381) — the chips clear themselves now. Rules for
       an element nothing renders are how the next person comes to tune something that cannot
       appear; NavMenu's chevron and the logo's hover hint got the same treatment this batch. */

    /* Dark mode adjustments */
    @media (prefers-color-scheme: dark) {
    /* #320 — no dark amber override: --pt-navy-fg already remaps for this scheme. */

    .payment-banner-cash[b-m3f01laonm] {
            background: linear-gradient(135deg, rgba(248, 113, 113, 0.15) 0%, rgba(248, 113, 113, 0.05) 100%);
            border-color: #f87171;
        }

    .payment-banner-cash .banner-title[b-m3f01laonm] {
            color: #f87171;
        }

    .payment-banner-cash .banner-icon[b-m3f01laonm] {
            background: #ef4444;
        }
    }

    /* Phones: the drawer is the viewport, and the Cerrar buttons stack. The drawer itself goes full width in
       app.css and mobile.css. */
    @media (max-width: 768px) {
    .footer-actions-primary[b-m3f01laonm] {
            flex-direction: column;
        }

    .footer-actions .btn-close-tab[b-m3f01laonm] {
            width: 100%;
            justify-content: center;
        }
    }

    /* #82/#83 — ONE PayTable surface for every action panel.
       Cortesia was gold (#f59e0b), Rehacer sky blue (#0ea5e9), Descuento and Fusionar navy, and
       Mover inherited Cortesia's gold because it never had a rule of its own — so two panels were
       indistinguishable and the set read as four unrelated features. They are one feature family:
       an action opened from the toolbar above them. Navy is the brand, and it is the colour the
       buttons in these panels now use. */
    /* #322 — a flat surface, not a ramp. Cam: "We should not use a gradient background fill for this panel.
       Just make it a solid very light blue."

       #ededf5 is the old gradient's own MIDPOINT (navy at 7% over the drawer's white) composited and
       frozen, so the panel looks as it did minus the ramp. Opaque rather than a translucent navy wash, for
       the reason #296's status tints are opaque: the readability probes read background-color literally, so
       text on a translucent ground is measured against its alpha instead of against what the eye sees —
       and ActionPanelSurfaceContractTests now checks these titles clear AA.

       All four action panels take it. #82/#83 made them one family; flattening only the one Cam
       screenshotted would split the family those cards existed to join. */
    .comp-panel[b-m3f01laonm] {
        background: #ededf5;
        border: 2px solid var(--pt-navy, #000075);
        border-radius: 0;
        padding: 1rem;
        margin-bottom: 1rem;
    }

    /* Whole-tab discount panel. It is always written as `comp-panel discount-panel`, so it inherits the
       surface above; the background it used to restate here was byte-identical to it (#322 removed the
       duplicate rather than flattening the same colour twice). The comment about distinguishing it from
       "the gold Cortesía panel" predates #82/#83, which made every action panel navy — there is no gold
       left to differ from. */
    .discount-panel[b-m3f01laonm] {
        border-color: #000075;
    }

    .comp-panel-header[b-m3f01laonm] {
        display: flex;
        justify-content: space-between;
        align-items: center;
        margin-bottom: 0.75rem;
        flex-wrap: wrap;
        gap: 0.5rem;
    }

    /* --pt-navy-fg is #000075 in light and #a5b4fc in dark (app.css), so one declaration covers
       both schemes and the per-panel dark overrides below become unnecessary. */
    .comp-panel-title[b-m3f01laonm] {
        font-weight: 700;
        color: var(--pt-navy-fg);
        display: flex;
        align-items: center;
        gap: 0.5rem;
    }

    .comp-selection-info[b-m3f01laonm] {
        font-size: 0.875rem;
        font-weight: 600;
        color: var(--modal-text-secondary);
        background: var(--modal-bg);
        padding: 0.25rem 0.75rem;
        border-radius: 0;
    }

    .comp-panel-body[b-m3f01laonm] {
        display: flex;
        flex-wrap: wrap;
        gap: 0.75rem;
        align-items: center;
    }

    /* #314 — the X that closes a panel, in the corner the selection-count tag used to occupy.
       margin-left: auto pins it right whether or not anything else sits in the header (the Descuento
       panel keeps its "Actual: -$X"; the others now have only a title). */
    .action-panel-close[b-m3f01laonm] {
        margin-left: auto;
        display: inline-flex;
        align-items: center;
        justify-content: center;
        width: 28px;
        height: 28px;
        padding: 0;
        border: none;
        border-radius: 0;
        background: transparent;
        color: var(--modal-text-secondary);
        cursor: pointer;
        transition: color 0.15s ease, background-color 0.15s ease;
    }

    .action-panel-close:hover[b-m3f01laonm] {
        background: var(--modal-border);
        color: var(--modal-text);
    }

    /* #314 — "Restablecer" at the top of the items, offered only while something is staged. */
    .items-reset-row[b-m3f01laonm] {
        display: flex;
        justify-content: flex-end;
        margin-bottom: 0.5rem;
    }

    .items-reset-btn[b-m3f01laonm] {
        display: inline-flex;
        align-items: center;
        gap: 0.5rem;
        padding: 0.25rem 0.75rem;
        border: 1px solid var(--modal-border);
        border-radius: 0;
        background: transparent;
        color: var(--pt-navy-fg);
        font-size: 0.8125rem;
        font-weight: 600;
        cursor: pointer;
        transition: background-color 0.15s ease;
    }

    .items-reset-btn:hover[b-m3f01laonm] {
        background: var(--modal-border);
    }

    .comp-actions[b-m3f01laonm] {
        display: flex;
        gap: 0.5rem;
    }

    .comp-category-select[b-m3f01laonm] {
        display: flex;
        align-items: center;
        gap: 0.5rem;
    }

    .comp-category-select label[b-m3f01laonm] {
        font-size: 0.875rem;
        font-weight: 600;
        color: var(--modal-text);
        white-space: nowrap;
    }

    .comp-category-select select[b-m3f01laonm] {
        min-width: 180px;
    }

    .comp-reason-input[b-m3f01laonm] {
        display: flex;
        align-items: center;
        gap: 0.5rem;
        flex: 1;
        min-width: 200px;
    }

    .comp-reason-input label[b-m3f01laonm] {
        font-size: 0.875rem;
        font-weight: 600;
        color: var(--modal-text);
        white-space: nowrap;
    }

    .comp-reason-input input[b-m3f01laonm] {
        flex: 1;
    }

    .btn-apply-comp[b-m3f01laonm] {
        margin-left: auto;
        display: inline-flex;
        align-items: center;
        gap: 0.5rem;
    }

    /* "Cortesía total — cerrar en $0": its own full-width row under Aplicar, set apart by a rule because this one
       closes the tab. Touch targets stay at the 44px floor. */
    .courtesy-total[b-m3f01laonm] {
        flex: 1 0 100%;
        display: flex;
        flex-direction: column;
        gap: 0.5rem;
        border-top: 1px solid var(--modal-border);
        padding-top: 0.75rem;
        margin-top: 0.25rem;
    }

    .courtesy-total-start[b-m3f01laonm] {
        align-self: flex-start;
        display: inline-flex;
        align-items: center;
        gap: 0.5rem;
        min-height: 44px;
    }

    .courtesy-total-hint[b-m3f01laonm] {
        color: var(--modal-text-secondary);
    }

    .courtesy-total-confirm[b-m3f01laonm] {
        border-left: 4px solid var(--pt-coral, #ec607e);
        padding: 0.5rem 0.75rem;
    }

    .courtesy-total-message[b-m3f01laonm] {
        margin: 0 0 0.5rem;
        font-size: 0.875rem;
        color: var(--modal-text);
    }

    .courtesy-total-buttons[b-m3f01laonm] {
        display: flex;
        flex-wrap: wrap;
        justify-content: flex-end;
        gap: 0.5rem;
    }

    .courtesy-total-buttons .btn[b-m3f01laonm] {
        display: inline-flex;
        align-items: center;
        gap: 0.5rem;
        min-height: 44px;
    }

    /* #315 — Cam: "Need a bit more space between the icon and text in the top action buttons, and the
       buttons within the panel (the spacing in the Aplicar button is good)".

       So this IS the Aplicar button's treatment, applied to the rest: a real gap instead of the single
       collapsed space an inline-block leaves between a glyph and its label. `align-items: center` is the
       second half of the same report — "Fix 'X' icon vertical alignment in the 'Limpiar' button" — because
       a baseline-aligned glyph rides high against the taller text box beside it. One rule, both fixes.

       ActionPanelSpacingContractTests compares these to .btn-apply-comp rather than to a number, since
       matching it is the whole specification. */
    .section-actions-toolbar .btn[b-m3f01laonm],
    .comp-actions .btn[b-m3f01laonm],
    .remake-actions .btn[b-m3f01laonm],
    .comp-panel-body > .btn[b-m3f01laonm],
    .remake-panel-body > .btn[b-m3f01laonm] {
        display: inline-flex;
        align-items: center;
        gap: 0.5rem;
    }

    /* #316 — Motivo gets its own row in the Descuento panel, as it has in Cortesía all along.
       .comp-panel-body is a wrapping flex row, and the discount panel is the only one that puts THREE
       controls on it (Tipo, the amount, Motivo). With `flex: 1; min-width: 200px` the text field took
       whatever was left after the other two and was squeezed to the edge of the panel — Cam: "Descuento
       Motivo text field getting cut off". Basis 100% makes it wrap and then fill. */
    .discount-panel .reason-own-row[b-m3f01laonm] {
        flex: 1 0 100%;
    }

    /* Comp checkbox */
    .comp-checkbox[b-m3f01laonm] {
        display: flex;
        align-items: center;
        justify-content: center;
        position: relative;
        cursor: pointer;
        margin-right: 0.25rem;
    }

    .comp-checkbox input[b-m3f01laonm] {
        position: absolute;
        opacity: 0;
        cursor: pointer;
        height: 0;
        width: 0;
    }

    .comp-checkbox .checkmark[b-m3f01laonm] {
        width: 20px;
        height: 20px;
        border: 2px solid var(--border-color);
        border-radius: 0;
        background: var(--modal-bg);
        transition: all 0.2s ease;
    }

    .comp-checkbox input:checked ~ .checkmark[b-m3f01laonm] {
        background: var(--pt-navy, #000075);
        border-color: var(--pt-navy, #000075);
    }

    /* P2c-B: granular single-upcharge comp rows under an item */
    .comp-upcharge-list[b-m3f01laonm] {
        display: flex;
        flex-direction: column;
        gap: 2px;
        margin: 2px 0 6px 2.25rem;
    }

    .comp-upcharge-row[b-m3f01laonm] {
        display: flex;
        align-items: center;
        gap: 0.5rem;
        min-height: 32px;
        padding: 2px 6px;
        cursor: pointer;
        border-left: 2px solid var(--border-color);
        font-size: 0.85rem;
    }

    .comp-upcharge-row input[b-m3f01laonm] {
        width: 16px;
        height: 16px;
        accent-color: var(--pt-navy, #000075);
        cursor: pointer;
    }

    .comp-upcharge-row.upcharge-selected[b-m3f01laonm] {
        border-left-color: var(--pt-navy, #000075);
        background: rgba(0, 0, 117, 0.08);
    }

    .comp-upcharge-name[b-m3f01laonm] {
        flex: 1;
        color: var(--text-secondary, #6b7280);
    }

    .comp-upcharge-price[b-m3f01laonm] {
        font-weight: 600;
        color: var(--pt-navy-fg);
    }

    .comp-checkbox .checkmark[b-m3f01laonm]::after {
        content: '';
        position: absolute;
        display: none;
        left: 7px;
        top: 3px;
        width: 5px;
        height: 10px;
        border: solid white;
        border-width: 0 2px 2px 0;
        transform: rotate(45deg);
    }

    .comp-checkbox input:checked ~ .checkmark[b-m3f01laonm]::after {
        display: block;
    }

    /* Comp item states.

       A selected row (here, and Rehacer's and Mover's below) changes colour and nothing else (Igor,
       2026-09-25: "when an item is selected for REHACER, or MOVER ARTICULO, the highlight is bleeding
       outside of the container"). The three states carried `padding: 0.375rem 0.5rem; margin: 0.125rem
       -0.5rem`, to reach the 0.5rem the items list lost in #374's revision. Inside a Pedido card they
       outranked the card's own row inset by source order: the highlight ran 6px past the card's 2px
       border, the row's content jumped 14px left, and the card grew 4px. The row's box already spans
       the card, so its background alone is the highlight. */
    .blended-item-row.item-selected[b-m3f01laonm] {
        background: rgba(245, 158, 11, 0.15);
        border-radius: 0;
    }

    .blended-item-row.item-comped[b-m3f01laonm] {
        opacity: 0.7;
    }

    .text-strikethrough[b-m3f01laonm] {
        text-decoration: line-through;
        color: var(--modal-text-secondary) !important;
    }

    .comp-badge[b-m3f01laonm] {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        width: 20px;
        height: 20px;
        background: var(--pt-navy, #000075);
        color: white;
        border-radius: 0;
        font-size: 0.625rem;
        margin-right: 0.25rem;
        flex-shrink: 0;
    }

    /* Dark mode comp adjustments */
    @media (prefers-color-scheme: dark) {
        /* #322 — the dark gradient's midpoint (navy at 20% over #1f2937), frozen. */
        .comp-panel[b-m3f01laonm] {
            background: #192143;
        }

    .blended-item-row.item-selected[b-m3f01laonm] {
            background: rgba(245, 158, 11, 0.2);
        }

    }

    /* #322 — same flat surface as .comp-panel; see the note there. */
    .remake-panel[b-m3f01laonm] {
        background: #ededf5;
        border: 2px solid var(--pt-navy, #000075);
        border-radius: 0;
        padding: 1rem;
        margin-bottom: 1rem;
    }

    .remake-panel-header[b-m3f01laonm] {
        display: flex;
        justify-content: space-between;
        align-items: center;
        margin-bottom: 0.75rem;
        flex-wrap: wrap;
        gap: 0.5rem;
    }

    .remake-panel-title[b-m3f01laonm] {
        font-weight: 700;
        color: var(--pt-navy-fg);
        display: flex;
        align-items: center;
        gap: 0.5rem;
    }

    .remake-selection-info[b-m3f01laonm] {
        font-size: 0.875rem;
        font-weight: 600;
        color: var(--modal-text-secondary);
        background: var(--modal-bg);
        padding: 0.25rem 0.75rem;
        border-radius: 0;
    }

    .remake-panel-body[b-m3f01laonm] {
        display: flex;
        flex-wrap: wrap;
        gap: 0.75rem;
        align-items: center;
    }

    .remake-actions[b-m3f01laonm] {
        display: flex;
        gap: 0.5rem;
    }

    .remake-category-select[b-m3f01laonm] {
        display: flex;
        align-items: center;
        gap: 0.5rem;
    }

    .remake-category-select label[b-m3f01laonm] {
        font-size: 0.875rem;
        font-weight: 600;
        color: var(--modal-text);
        white-space: nowrap;
    }

    .remake-category-select select[b-m3f01laonm] {
        min-width: 180px;
    }

    .remake-reason-input[b-m3f01laonm] {
        display: flex;
        align-items: center;
        gap: 0.5rem;
        flex: 1;
        min-width: 200px;
    }

    .remake-reason-input label[b-m3f01laonm] {
        font-size: 0.875rem;
        font-weight: 600;
        color: var(--modal-text);
        white-space: nowrap;
    }

    .remake-reason-input input[b-m3f01laonm] {
        flex: 1;
    }

    .btn-apply-remake[b-m3f01laonm] {
        margin-left: auto;
        display: inline-flex;
        align-items: center;
        gap: 0.5rem;
    }

    /* Remake checkbox */
    .remake-checkbox[b-m3f01laonm] {
        display: flex;
        align-items: center;
        justify-content: center;
        position: relative;
        cursor: pointer;
        margin-right: 0.25rem;
    }

    .remake-checkbox input[b-m3f01laonm] {
        position: absolute;
        opacity: 0;
        cursor: pointer;
        height: 0;
        width: 0;
    }

    .remake-checkbox .checkmark[b-m3f01laonm] {
        width: 20px;
        height: 20px;
        border: 2px solid var(--border-color);
        border-radius: 0;
        background: var(--modal-bg);
        transition: all 0.2s ease;
    }

    .remake-checkbox input:checked ~ .checkmark[b-m3f01laonm] {
        background: var(--pt-navy, #000075);
        border-color: var(--pt-navy, #000075);
    }

    .remake-checkbox .checkmark[b-m3f01laonm]::after {
        content: '';
        position: absolute;
        display: none;
        left: 7px;
        top: 3px;
        width: 5px;
        height: 10px;
        border: solid white;
        border-width: 0 2px 2px 0;
        transform: rotate(45deg);
    }

    .remake-checkbox input:checked ~ .checkmark[b-m3f01laonm]::after {
        display: block;
    }

    /* Move-items (partial tab split) — mirrors the remake checkbox,coral accent so
       staff can tell the three selection modes apart at a glance. Class names are
       move-* prefixed because inline styles in a .razor file are GLOBAL,not scoped. */
    .move-checkbox[b-m3f01laonm] {
        display: flex;
        align-items: center;
        justify-content: center;
        position: relative;
        cursor: pointer;
        margin-right: 0.25rem;
    }

    .move-checkbox input[b-m3f01laonm] {
        position: absolute;
        opacity: 0;
        cursor: pointer;
        height: 0;
        width: 0;
    }

    .move-checkbox .checkmark[b-m3f01laonm] {
        width: 20px;
        height: 20px;
        border: 2px solid var(--border-color);
        border-radius: 0;
        background: var(--modal-bg);
        transition: all 0.2s ease;
    }

    .move-checkbox input:checked ~ .checkmark[b-m3f01laonm] {
        background: var(--pt-navy, #000075);
        border-color: var(--pt-navy, #000075);
    }

    .move-checkbox .checkmark[b-m3f01laonm]::after {
        content: '';
        position: absolute;
        display: none;
        left: 7px;
        top: 3px;
        width: 5px;
        height: 10px;
        border: solid white;
        border-width: 0 2px 2px 0;
        transform: rotate(45deg);
    }

    .move-checkbox input:checked ~ .checkmark[b-m3f01laonm]::after {
        display: block;
    }

    /* Colour only, as the comp state above says. */
    .blended-item-row.item-move-selected[b-m3f01laonm] {
        background: rgba(236, 96, 126, 0.15);
        border-radius: 0;
    }

    /* Comped / already-paid lines: visibly inert while move mode is on. */
    .blended-item-row.item-not-movable[b-m3f01laonm] {
        opacity: 0.5;
    }

    .move-blocked-badge[b-m3f01laonm],.move-package-child-badge[b-m3f01laonm] {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        width: 20px;
        height: 20px;
        color: var(--text-muted, #94a3b8);
        margin-right: 0.25rem;
        font-size: 0.75rem;
    }

    .move-package-child-badge[b-m3f01laonm] {
        color: var(--pt-navy-fg);
        opacity: 0.65;
    }

    /* Package identity in the blended item list (all modes) */
    .package-header-chip[b-m3f01laonm] {
        display: inline-flex;
        align-items: center;
        gap: 0.25rem;
        padding: 0.0625rem 0.375rem;
        margin-right: 0.375rem;
        background: rgba(0, 0, 117, 0.1);
        color: #000075;
        border-radius: 0;
        font-size: 0.6875rem;
        font-weight: 600;
        text-transform: uppercase;
        letter-spacing: 0.02em;
        white-space: nowrap;
    }

    .package-child-arrow[b-m3f01laonm] {
        color: var(--text-muted, #94a3b8);
        margin-right: 0.25rem;
    }

    .item-name.item-package-child[b-m3f01laonm] {
        padding-left: 0.5rem;
    }

    /* The component's own count, beside its name. Weightier than the affiliation text next to it
       -- it is a number the operator acts on -- but lighter than the .item-qty badge, which means a
       different thing. Tabular so 2 and 12 do not shift the name. */
    .package-child-count[b-m3f01laonm] {
        margin-left: 0.375rem;
        color: var(--modal-text);
        font-weight: 600;
        font-size: 0.8125rem;
        font-variant-numeric: tabular-nums;
    }

    /* A component's price column. Matches TabDetailPanel's .tdp-included, because the two components
       render the same tab and an operator moving between them should not have to notice which one
       they are looking at. Italic and muted: it is a statement about the row, not a figure. */
    .package-child-included[b-m3f01laonm] {
        font-size: 0.75rem;
        font-weight: 500;
        font-style: italic;
        color: var(--text-secondary, #64748b);
    }

    /* What a zero-priced line is paying for. Same muted, italic treatment as the child affiliation
       above it — both are statements ABOUT the row rather than part of its name, and a reader should
       be able to tell them apart from the dish at a glance. */
    .item-cost-driver[b-m3f01laonm] {
        margin-left: 0.375rem;
        color: var(--text-muted, #94a3b8);
        font-size: 0.75rem;
        font-style: italic;
        white-space: nowrap;
    }

    .package-child-affiliation[b-m3f01laonm] {
        margin-left: 0.375rem;
        color: var(--text-muted, #94a3b8);
        font-size: 0.75rem;
        font-style: italic;
        white-space: nowrap;
    }

    @media (max-width: 640px) {
        .package-child-affiliation[b-m3f01laonm] {
            display: none;
        }

    }

    /* WHICH one the guest chose (Igor, 1 Sep). A component row names the dish — "Margarita ×2" —
       and the flavour that was picked on it lived nowhere on this screen: the cost-driver chip is
       deliberately suppressed on package children, and `CustomizableModifiers` is read here only by
       the comp flow. So a tab showed two identical "Margarita ×2" rows for a Fresa and a Zarzamora.

       NOT muted italic like the affiliation beside it. That is a statement ABOUT the row; this is
       something the bar has to make. Same weight as the count, for the same reason — both are
       details the operator acts on rather than prose. Kept at 640px where the affiliation is
       dropped: on a phone the flavour matters more than which package it came from. */
    .package-child-choice[b-m3f01laonm] {
        margin-left: 0.375rem;
        color: var(--modal-text);
        font-weight: 500;
        font-size: 0.8125rem;
    }

    /* Mover was coral — a fifth accent, and 3.21:1 on white (the #46 white-on-coral defect).
       --pt-navy-fg carries the family colour and flips to #a5b4fc in dark. */
    .move-panel .comp-panel-title[b-m3f01laonm],.move-panel .comp-selection-info[b-m3f01laonm] {
        color: var(--pt-navy-fg);
    }

    .move-empty-warning[b-m3f01laonm] {
        display: flex;
        align-items: flex-start;
        gap: 0.5rem;
        padding: 0.5rem 0.625rem;
        margin-top: 0.5rem;
        background: rgba(0, 0, 117, 0.12);
        border-left: 3px solid var(--pt-navy, #000075);
        font-size: 0.8125rem;
        line-height: 1.35;
    }

    .qty-selector.move-qty .qty-value.qty-active[b-m3f01laonm] {
        color: var(--pt-navy-fg);
        font-weight: 700;
    }

    /* Remake item states. Colour only, as the comp state says. */
    .blended-item-row.item-remake-selected[b-m3f01laonm] {
        background: rgba(14, 165, 233, 0.15);
        border-radius: 0;
    }

    .blended-item-row.item-remake[b-m3f01laonm] {
        opacity: 0.85;
    }

    .remake-badge[b-m3f01laonm] {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        width: 20px;
        height: 20px;
        background: var(--pt-navy, #000075);
        color: white;
        border-radius: 0;
        font-size: 0.625rem;
        margin-right: 0.25rem;
        flex-shrink: 0;
    }

    .text-zero[b-m3f01laonm] {
        color: #0ea5e9 !important;
        font-weight: 600;
    }

    /* Dark mode remake adjustments */
    @media (prefers-color-scheme: dark) {
        .remake-panel[b-m3f01laonm] {
            background: #192143;
        }

    .blended-item-row.item-remake-selected[b-m3f01laonm] {
            background: rgba(14, 165, 233, 0.2);
        }
    }

    /* Responsive remake adjustments */
    @media (max-width: 768px) {
        .remake-panel-body[b-m3f01laonm] {
            flex-direction: column;
            align-items: stretch;
        }

    .remake-actions[b-m3f01laonm] {
            justify-content: center;
        }

    .remake-category-select[b-m3f01laonm] {
            flex-direction: column;
            align-items: stretch;
        }

    .remake-category-select select[b-m3f01laonm] {
            width: 100%;
        }

    .remake-reason-input[b-m3f01laonm] {
            flex-direction: column;
            align-items: stretch;
        }

    .btn-apply-remake[b-m3f01laonm] {
            width: 100%;
            justify-content: center;
            margin-left: 0;
            margin-top: 0.5rem;
        }
    }

    /* Responsive comp adjustments */
    @media (max-width: 768px) {
        .comp-panel-body[b-m3f01laonm] {
            flex-direction: column;
            align-items: stretch;
        }

    .comp-actions[b-m3f01laonm] {
            justify-content: center;
        }

    .comp-category-select[b-m3f01laonm] {
            flex-direction: column;
            align-items: stretch;
        }

    .comp-category-select select[b-m3f01laonm] {
            width: 100%;
        }

    .comp-reason-input[b-m3f01laonm] {
            flex-direction: column;
            align-items: stretch;
        }

    .btn-apply-comp[b-m3f01laonm] {
            width: 100%;
            justify-content: center;
            margin-left: 0;
            margin-top: 0.5rem;
        }
    }

    /* The merge panel is `class="right-card merge-panel"`, and a dark-mode `.right-card`
       rule sets border-color from --modal-border. Both are (0,1,0), so it won on source order and
       the panel went grey in dark while its four siblings stayed navy. Match on BOTH classes to
       outrank it without an !important. */
    .right-card.merge-panel[b-m3f01laonm] {
        border-color: var(--pt-navy, #000075);
    }

    /* Merge Panel Styles */
    /* #322 — same flat surface as .comp-panel; see the note there. */
    .merge-panel[b-m3f01laonm] {
        background: #ededf5;
        border: 2px solid var(--pt-navy, #000075);
        border-radius: 0;
        padding: 0.75rem;
    }

    .merge-panel-header[b-m3f01laonm] {
        display: flex;
        justify-content: space-between;
        align-items: center;
        margin-bottom: 0.75rem;
        flex-wrap: wrap;
        gap: 0.5rem;
    }

    /* --pt-navy-fg, NOT --pt-navy: the latter is #000075 in BOTH schemes, which measured 1.14:1
       on the dark modal surface once its dark-mode override was removed. */
    .merge-panel-title[b-m3f01laonm] {
        font-weight: 700;
        color: var(--pt-navy-fg);
        display: flex;
        align-items: center;
        gap: 0.5rem;
    }

    .merge-info[b-m3f01laonm] {
        font-size: 0.875rem;
        color: var(--modal-text-secondary);
    }

    .merge-panel-body[b-m3f01laonm] {
        display: flex;
        flex-direction: column;
        gap: 1rem;
    }

    .merge-target-select[b-m3f01laonm] {
        display: flex;
        flex-direction: column;
        gap: 0.5rem;
    }

    .merge-target-select label[b-m3f01laonm] {
        font-size: 0.875rem;
        font-weight: 600;
        color: var(--modal-text);
    }

    .merge-target-select select[b-m3f01laonm] {
        padding: 0.75rem;
        font-size: 1rem;
        border-radius: 0;
    }

    .merge-preview[b-m3f01laonm] {
        background: var(--modal-bg);
        border: 1px solid var(--modal-border);
        border-radius: 0;
        padding: 1rem;
    }

    .merge-preview-header[b-m3f01laonm] {
        font-weight: 600;
        color: var(--pt-navy, #000075);
        margin-bottom: 0.75rem;
        display: flex;
        align-items: center;
        gap: 0.5rem;
    }

    .merge-preview-content[b-m3f01laonm] {
        display: grid;
        grid-template-columns: 1fr auto 1fr;
        gap: 0.75rem;
        align-items: center;
    }

    .merge-source[b-m3f01laonm],.merge-target[b-m3f01laonm],.merge-result[b-m3f01laonm] {
        display: flex;
        flex-direction: column;
        gap: 0.25rem;
    }

    .merge-result[b-m3f01laonm] {
        grid-column: 1 / -1;
        text-align: center;
        padding-top: 0.75rem;
        border-top: 1px solid var(--modal-border);
        margin-top: 0.5rem;
    }

    .merge-label[b-m3f01laonm] {
        font-size: 0.75rem;
        font-weight: 600;
        color: var(--modal-text-secondary);
        text-transform: uppercase;
    }

    .merge-value[b-m3f01laonm] {
        font-size: 0.875rem;
        font-weight: 600;
        color: var(--modal-text);
    }

    .merge-total[b-m3f01laonm] {
        font-size: 1.25rem;
        color: var(--success-color);
    }

    .merge-arrow[b-m3f01laonm] {
        color: var(--pt-navy, #000075);
        font-size: 1.25rem;
    }

    .merge-no-tabs[b-m3f01laonm] {
        display: flex;
        align-items: center;
        gap: 0.5rem;
        padding: 1rem;
        background: var(--modal-bg);
        border-radius: 0;
        color: var(--modal-text-secondary);
    }

    .btn-apply-merge[b-m3f01laonm] {
        align-self: flex-end;
        display: inline-flex;
        align-items: center;
        gap: 0.5rem;
    }

    /* Dark mode merge adjustments */
    @media (prefers-color-scheme: dark) {
        .merge-panel[b-m3f01laonm] {
            background: #192143;
        }

    .merge-preview-header[b-m3f01laonm] {
            color: var(--pt-navy-fg);
        }

    .merge-arrow[b-m3f01laonm] {
            color: var(--pt-navy-fg);
        }
    }

    /* Responsive merge adjustments */
    @media (max-width: 768px) {
        .merge-preview-content[b-m3f01laonm] {
            grid-template-columns: 1fr;
        }

    .merge-arrow[b-m3f01laonm] {
            transform: rotate(90deg);
            justify-self: center;
        }

    .merge-result[b-m3f01laonm] {
            grid-column: 1;
        }

    .btn-apply-merge[b-m3f01laonm] {
            width: 100%;
            justify-content: center;
        }
    }

    /* Quantity Selector Styles */
    .qty-selector[b-m3f01laonm] {
        display: inline-flex;
        align-items: center;
        gap: 0.25rem;
        margin-right: 0.5rem;
        background: var(--modal-bg);
        border: 2px solid #f59e0b;
        border-radius: 0;
        padding: 0.125rem;
    }

    .qty-selector.remake-qty[b-m3f01laonm] {
        border-color: var(--pt-navy, #000075);
    }

    .qty-btn[b-m3f01laonm] {
        width: 24px;
        height: 24px;
        display: flex;
        align-items: center;
        justify-content: center;
        border: none;
        background: transparent;
        color: var(--modal-text-secondary);
        cursor: pointer;
        transition: all 0.15s ease;
        padding: 0;
    }

    .qty-btn:hover:not(:disabled)[b-m3f01laonm] {
        color: #f59e0b;
        background: rgba(245, 158, 11, 0.1);
    }

    .remake-qty .qty-btn:hover:not(:disabled)[b-m3f01laonm] {
        color: var(--pt-navy, #000075);
        background: rgba(0, 0, 117, 0.1);
    }

    .qty-btn:disabled[b-m3f01laonm] {
        opacity: 0.3;
        cursor: not-allowed;
    }

    .qty-btn i[b-m3f01laonm] {
        font-size: 0.625rem;
    }

    .qty-value[b-m3f01laonm] {
        min-width: 24px;
        text-align: center;
        font-size: 0.875rem;
        font-weight: 600;
        color: var(--modal-text-secondary);
    }

    .qty-value.qty-active[b-m3f01laonm] {
        color: #f59e0b;
    }

    .remake-qty .qty-value.qty-active[b-m3f01laonm] {
        color: var(--pt-navy, #000075);
    }

    /* STAFF-ADDED: a mark, not an alarm (#374).

       The row's coral tint and its coral left rail are GONE, with the POR MESERO chip that went with
       them. Igor: "remove the red highlighting of the row / bundle itself as well. We're removing how
       prominently this shows." Four signals — chip, chip border, row tint, row rail — all said one minor
       thing, in the colour this app keeps for what needs attention. Who added a line is provenance; it is
       answered when asked, not announced.

       .item-staff-added is still emitted on the row, deliberately: it is how a test, a future report or a
       kiosk stylesheet can still find these rows. It just paints nothing here. */
    .staff-added-mark[b-m3f01laonm] {
        /* LIGHTER THAN THE MONEY (Igor). It was var(--modal-text-secondary) — the exact token
           .item-price uses — so the mark carried the same weight on the row as the figure the
           operator is actually reading. #6b7280 is 4.8:1 on this ground against the price's 10.3:1.

           Still above the 3:1 floor for a graphic that carries meaning: the mark is supplementary
           (its title names the waiter, and a screen reader gets that either way), but it is not
           decoration, so it is not taken below what a sighted operator can pick out. */
        color: #6b7280;
        font-size: 0.6875rem;
        margin-left: 0.375rem;
        flex-shrink: 0;
        /* It sits at the end of a wrapping name, so it must not be what pushes the line over. */
        align-self: center;
    }

    /* Scheduled Orders (v1): held-future-order chip — navy on tinted navy,square edges (brand). */
    .tab-detail-scheduled-chip[b-m3f01laonm] {
        display: inline-flex;
        align-items: center;
        gap: 0.25rem;
        padding: 0.125rem 0.375rem;
        background: rgba(0, 0, 117, 0.10);
        border: 1px solid var(--pt-navy, #000075);
        color: var(--pt-navy, #000075);
        border-radius: 0;
        font-size: 0.625rem;
        font-weight: 600;
        white-space: nowrap;
        flex-shrink: 0;
        margin-left: 0.375rem;
    }

    .tab-detail-scheduled-chip i[b-m3f01laonm] {
        font-size: 0.5rem;
    }

    /* DARK. The mark names its own grey now rather than riding a token, so it needs the dark half
       said too: #9ca3af is 5.8:1 on the dark modal ground against the price's 9.9:1 — the same
       relationship, inverted for the surface. */
    @media (prefers-color-scheme: dark) {
        .staff-added-mark[b-m3f01laonm] {
            color: #9ca3af;
        }
    }

    /* Dark mode qty selector */
    @media (prefers-color-scheme: dark) {
        .qty-selector[b-m3f01laonm] {
            border-color: #fbbf24;
        }

    .qty-selector.remake-qty[b-m3f01laonm] {
            border-color: var(--pt-navy-fg);
        }

    .qty-btn:hover:not(:disabled)[b-m3f01laonm] {
            color: #fbbf24;
        }

    .remake-qty .qty-btn:hover:not(:disabled)[b-m3f01laonm] {
            color: var(--pt-navy-fg);
        }

    .qty-value.qty-active[b-m3f01laonm] {
            color: #fbbf24;
        }

    .remake-qty .qty-value.qty-active[b-m3f01laonm] {
            color: var(--pt-navy-fg);
        }
    }

    /* Cash-close / abandoned-tab confirm modals (migrated to PtModal). Overlay + shell
       now come from the canonical shell; only the body content styles below are local. */
    .cash-confirm-message[b-m3f01laonm] {
        font-size: 1rem;
        color: var(--modal-text);
        margin: 0 0 1.25rem 0;
        line-height: 1.5;
    }

    /* MC5 (D4): a card-secured tab closed in cash or on the terminal. The manager's PIN that case needed is gone, so
       the popup says what the close means, as the phone's close does. Amber: informational, not destructive. */
    .cash-confirm-card-notice[b-m3f01laonm] {
        display: flex;
        align-items: flex-start;
        gap: 0.5rem;
        margin: 0 0 1rem 0;
        padding: 0.75rem;
        border-left: 3px solid var(--pt-warning-border);
        background: var(--pt-warning-bg);
        color: var(--modal-text);
        font-size: 0.875rem;
        line-height: 1.4;
    }

    .cash-confirm-info[b-m3f01laonm] {
        background: var(--modal-header-bg);
        border: 1px solid var(--modal-border);
        border-left: 4px solid var(--pt-coral, #ec607e);
        padding: 1rem;
    }

    .cash-confirm-info .info-row[b-m3f01laonm] {
        display: flex;
        justify-content: space-between;
        align-items: center;
        padding: 0.375rem 0;
    }

    .cash-confirm-info .info-label[b-m3f01laonm] {
        font-size: 0.875rem;
        color: var(--modal-text-secondary);
    }

    .cash-confirm-info .info-value[b-m3f01laonm] {
        font-size: 0.875rem;
        font-weight: 600;
        color: var(--modal-text);
    }

    .cash-confirm-info .info-total[b-m3f01laonm] {
        font-size: 1.125rem;
        font-weight: 700;
        color: var(--success-color);
    }

    /* "Se cobra" — what actually gets collected, and by which tender. Igor: "provide a summary of
       what is collected (cash amount, terminal amount, or both rows if it's split)."

       Built as a SIBLING of .cash-confirm-info rather than more rows inside it, because the two
       blocks answer different questions: that one is the bill (what the guest owes), this one is the
       tender (what the operator handles). On a split they hold different numbers, and running them
       together in one bordered box is exactly how an operator reads the wrong figure into the
       drawer. The navy left edge rather than the coral one says "this is the action", not "this is
       the account". */
    .cash-collect-summary[b-m3f01laonm] {
        margin-top: 1rem;
        background: var(--modal-header-bg);
        border: 1px solid var(--modal-border);
        border-left: 4px solid var(--pt-navy, #000075);
        padding: 1rem;
    }

    .cash-collect-title[b-m3f01laonm] {
        font-size: 0.75rem;
        font-weight: 700;
        letter-spacing: 0.04em;
        text-transform: uppercase;
        color: var(--modal-text-secondary);
        margin-bottom: 0.25rem;
    }

    .cash-collect-summary .info-row[b-m3f01laonm] {
        display: flex;
        justify-content: space-between;
        align-items: center;
        padding: 0.375rem 0;
    }

    .cash-collect-summary .info-label[b-m3f01laonm] {
        font-size: 0.875rem;
        color: var(--modal-text-secondary);
    }

    /* The figures are the point of this block, so they carry more weight than the bill's rows do —
       and tabular-nums so a two-row split lines its decimals up rather than making the operator
       compare ragged numbers. */
    .cash-collect-summary .info-value[b-m3f01laonm] {
        font-size: 1rem;
        font-weight: 700;
        color: var(--modal-text);
        font-variant-numeric: tabular-nums;
    }

    /* ===== The split (Carmel): cash AND the restaurant's own terminal on one tab =====

       The block is now a COLUMN OF FIGURES the operator reads downward — Total, Efectivo,
       Terminal propia, Recibido, Cambio — so the two inputs are given one width and right-aligned
       with the text values beside them. Left at their intrinsic sizes they sat at different widths
       and the decimal points did not line up, which is exactly the reconciliation the operator is
       doing in their head. */
    .split-tender-row[b-m3f01laonm] {
        border-top: 1px solid var(--modal-border);
        margin-top: 0.5rem;
        padding-top: 0.625rem !important;
    }

    /* The whole row is the hit area, not the 13px box: this is pressed on an Elo touchscreen
       mid-service. 44px is the brand's minimum target. */
    .split-tender-toggle[b-m3f01laonm] {
        display: flex;
        align-items: center;
        gap: 0.5rem;
        flex: 1;
        min-height: 44px;
        margin: 0;
        cursor: pointer;
        font-size: 0.875rem;
        font-weight: 600;
        color: var(--modal-text);
    }

    .split-tender-toggle input[type="checkbox"][b-m3f01laonm] {
        width: 1.25rem;
        height: 1.25rem;
        flex: 0 0 auto;
        cursor: pointer;
        accent-color: var(--pt-navy, #000075);
    }

    .cash-confirm-info .split-cash-input[b-m3f01laonm],
    .cash-confirm-info .cash-tendered-input[b-m3f01laonm] {
        width: 8rem;
        text-align: right;
        font-weight: 600;
    }

    /* The derived leg. Read-only by construction — it is a <span>, not a disabled input, because a
       box the operator cannot type in still invites them to try. */
    .split-leg-row .info-value[b-m3f01laonm] {
        font-variant-numeric: tabular-nums;
    }

    .split-invalid-row[b-m3f01laonm] {
        justify-content: flex-end !important;
    }

    /* The tendered pair's own division, present only on a split — the same weight and colour as the
       divider above the toggle, because two separator weights would read as three unrelated groups
       instead of "the bill / the split / the drawer". */
    .cash-flow-divided[b-m3f01laonm] {
        border-top: 1px solid var(--modal-border);
        margin-top: 0.5rem;
        padding-top: 0.625rem !important;
    }

    /* Borrows the drawer's existing danger pair rather than inventing one: #991b1b on #fef2f2 is
       what .client-edit-error and .reopen-panel-error already use, and it measures 8.6:1. */
    .split-invalid-hint[b-m3f01laonm] {
        padding: 0.3rem 0.5rem;
        border-left: 3px solid #dc2626;
        background: #fef2f2;
        color: #991b1b !important;
        font-size: 0.75rem !important;
        font-weight: 600;
        line-height: 1.3;
    }

    .split-tip-choice[b-m3f01laonm] {
        display: flex;
        gap: 0.375rem;
    }

    .split-tip-choice .btn[b-m3f01laonm] {
        min-height: 2rem;
        padding: 0.25rem 0.75rem;
        font-size: 0.75rem;
    }

    /* Responsive cash confirm modal */
    @media (max-width: 576px) {
    }

    /* Partial Payments Section Styles */
    .partial-payments-loading[b-m3f01laonm] {
        display: flex;
        align-items: center;
        gap: 0.5rem;
        padding: 0.75rem;
        background: var(--modal-header-bg);
        border-radius: 0;
        color: var(--modal-text-secondary);
    }

    .partial-payments-section[b-m3f01laonm] {
        border-radius: 0;
        padding: 0.75rem;
        border: 2px solid;
    }

    .partial-payments-section.has-balance[b-m3f01laonm] {
        background: linear-gradient(135deg, rgba(245, 158, 11, 0.1) 0%, rgba(245, 158, 11, 0.05) 100%);
        border-color: #f59e0b;
    }

    .partial-payments-section.fully-paid[b-m3f01laonm] {
        background: linear-gradient(135deg, rgba(16, 185, 129, 0.1) 0%, rgba(16, 185, 129, 0.05) 100%);
        border-color: #10b981;
    }

    .partial-payments-header[b-m3f01laonm] {
        display: flex;
        justify-content: space-between;
        align-items: center;
        margin-bottom: 1rem;
        flex-wrap: wrap;
        gap: 0.5rem;
    }

    .partial-payments-title[b-m3f01laonm] {
        display: flex;
        align-items: center;
        gap: 0.5rem;
        margin: 0;
        font-size: 1rem;
        font-weight: 700;
    }

    /* #320 — Igor: "Change the yellow font to blue (leave the icon yellow) so it's better for accessibility
       reading." Amber #f59e0b on this card's pale amber ground is the classic low-contrast pairing: a
       warning colour doing the one job it is bad at, which is being read. The ICON keeps it — catching the
       eye is what a warning colour is for; carrying the sentence is not.

       --pt-navy-fg, so the words stay readable when the card goes dark. That also retires the dark-mode
       override this rule used to need. */
    .has-balance .partial-payments-title[b-m3f01laonm] {
        color: var(--pt-navy-fg, #000075);
    }

    .has-balance .partial-payments-title i[b-m3f01laonm] {
        color: #f59e0b;
    }

    .fully-paid .partial-payments-title[b-m3f01laonm] {
        color: #10b981;
    }

    .balance-due-badge[b-m3f01laonm] {
        display: flex;
        align-items: center;
        gap: 0.5rem;
        padding: 0.5rem 1rem;
        background: #f59e0b;
        color: white;
        border-radius: 0;
        font-weight: 700;
    }

    .balance-label[b-m3f01laonm] {
        font-size: 0.75rem;
        text-transform: uppercase;
        opacity: 0.9;
    }

    .balance-amount[b-m3f01laonm] {
        font-size: 1.125rem;
    }

    .partial-payments-body[b-m3f01laonm] {
        display: flex;
        flex-direction: column;
        gap: 1rem;
    }

    .payments-list[b-m3f01laonm] {
        display: flex;
        flex-direction: column;
        gap: 0.5rem;
    }

    .payment-item[b-m3f01laonm] {
        display: flex;
        align-items: center;
        gap: 0.75rem;
        padding: 0.75rem;
        background: var(--modal-bg);
        border: 1px solid var(--modal-border);
        border-radius: 0;
    }

    .payment-item-icon[b-m3f01laonm] {
        width: 36px;
        height: 36px;
        display: flex;
        align-items: center;
        justify-content: center;
        border-radius: 0;
        flex-shrink: 0;
    }

    .has-balance .payment-item-icon[b-m3f01laonm] {
        background: rgba(245, 158, 11, 0.15);
        color: #f59e0b;
    }

    .fully-paid .payment-item-icon[b-m3f01laonm] {
        background: rgba(16, 185, 129, 0.15);
        color: #10b981;
    }

    .payment-item-details[b-m3f01laonm] {
        flex: 1;
        display: flex;
        flex-direction: column;
        gap: 0.125rem;
        min-width: 0;
    }

    .payment-payer[b-m3f01laonm] {
        font-weight: 600;
        color: var(--modal-text);
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
    }

    .payment-method[b-m3f01laonm] {
        font-size: 0.75rem;
        color: var(--modal-text-secondary);
    }

    .payment-item-amount[b-m3f01laonm] {
        display: flex;
        flex-direction: column;
        align-items: flex-end;
        gap: 0.125rem;
    }

    .payment-amount[b-m3f01laonm] {
        font-weight: 700;
        color: var(--success-color);
    }

    .payment-tip[b-m3f01laonm] {
        font-size: 0.7rem;
        color: var(--modal-text-secondary);
    }

    .payments-summary[b-m3f01laonm] {
        display: flex;
        flex-direction: column;
        gap: 0.375rem;
        padding-top: 0.75rem;
        border-top: 1px solid var(--modal-border);
    }

    .payments-summary .summary-row[b-m3f01laonm] {
        display: flex;
        justify-content: space-between;
        font-size: 0.875rem;
        color: var(--modal-text-secondary);
    }

    .payments-summary .paid-amount[b-m3f01laonm] {
        font-weight: 600;
        color: var(--success-color);
    }

    /* #320 — the "Saldo pendiente" row was amber, then navy, and is body text after Cam's second pass;
       see .summary-authorized for why. It keeps its weight and size, which is what makes it the last line
       of the tally rather than another row of it. */
    .payments-summary .summary-balance[b-m3f01laonm] {
        font-weight: 700;
        font-size: 1rem;
        color: var(--modal-text);
        padding-top: 0.5rem;
        margin-top: 0.25rem;
        border-top: 1px dashed var(--modal-border);
    }

    .payments-summary .summary-balance .balance-amount[b-m3f01laonm] {
        color: var(--modal-text);
    }

    /* Dark mode partial payments adjustments */
    @media (prefers-color-scheme: dark) {
        .partial-payments-section.has-balance[b-m3f01laonm] {
            background: linear-gradient(135deg, rgba(245, 158, 11, 0.15) 0%, rgba(245, 158, 11, 0.05) 100%);
            border-color: #fbbf24;
        }

    .partial-payments-section.fully-paid[b-m3f01laonm] {
            background: linear-gradient(135deg, rgba(16, 185, 129, 0.15) 0%, rgba(16, 185, 129, 0.05) 100%);
            border-color: #34d399;
        }

    /* #320 — only the ICON keeps amber here. The title's own colour is --pt-navy-fg, which already remaps
       for this scheme, so it needs no dark override; overriding it would put the unreadable amber back. */
    .has-balance .partial-payments-title i[b-m3f01laonm] {
            color: #fbbf24;
        }

    .fully-paid .partial-payments-title[b-m3f01laonm] {
            color: #34d399;
        }

    .balance-due-badge[b-m3f01laonm] {
            background: #d97706;
        }

    .has-balance .payment-item-icon[b-m3f01laonm] {
            background: rgba(251, 191, 36, 0.2);
            color: #fbbf24;
        }

    .fully-paid .payment-item-icon[b-m3f01laonm] {
            background: rgba(52, 211, 153, 0.2);
            color: #34d399;
        }

    /* #320 removed the dark amber override for the Saldo pendiente row too — --pt-navy-fg carries it. */
    }

    /* Authorized Payment Styles */
    .payment-item.payment-authorized[b-m3f01laonm] {
        border: 1px dashed var(--pt-navy, #000075);
        background: rgba(0, 0, 117, 0.05);
    }

    .payment-icon-authorized[b-m3f01laonm] {
        background: rgba(0, 0, 117, 0.15) !important;
        color: var(--pt-navy, #000075) !important;
    }

    .payment-wallet-badge[b-m3f01laonm] {
        display: inline-block;
        margin-right: 0.375rem;
        padding: 0.125rem 0.375rem;
        background: #1a1a2e;
        color: white;
        border-radius: 0;
        font-size: 0.625rem;
        font-weight: 700;
        text-transform: uppercase;
        letter-spacing: 0.025em;
        vertical-align: middle;
    }

    /* "Terminal propia" (TPV propia) chip — restaurant's own bank terminal,a
       record-only tender. Coral to read distinctly from cash (green icon) and
       card. Straight edges per brand. */
    .payment-terminal-badge[b-m3f01laonm] {
        display: inline-block;
        padding: 0.125rem 0.375rem;
        background: var(--pt-coral, #ec607e);
        color: var(--pt-on-coral);
        border-radius: 0;
        font-size: 0.625rem;
        font-weight: 700;
        text-transform: uppercase;
        letter-spacing: 0.025em;
        vertical-align: middle;
    }

    .payment-terminal-badge i[b-m3f01laonm] {
        margin-right: 0.25rem;
    }

    /* "Transferencia" (SPEI) chip. Navy rather than the terminal chip's coral, so the two
       non-card tenders read distinctly when both appear on one tab. Navy + white matches
       .payment-status-badge, including its dark-mode lightening below — navy on a dark
       surface does not clear contrast on its own. */
    .payment-transfer-badge[b-m3f01laonm] {
        display: inline-block;
        padding: 0.125rem 0.375rem;
        background: var(--pt-navy, #000075);
        color: white;
        border-radius: 0;
        font-size: 0.625rem;
        font-weight: 700;
        text-transform: uppercase;
        letter-spacing: 0.025em;
        vertical-align: middle;
    }

    .payment-transfer-badge i[b-m3f01laonm] {
        margin-right: 0.25rem;
    }

    .payment-status-badge[b-m3f01laonm] {
        display: inline-block;
        margin-left: 0.5rem;
        padding: 0.125rem 0.375rem;
        background: var(--pt-navy, #000075);
        color: white;
        border-radius: 0;
        font-size: 0.625rem;
        font-weight: 700;
        text-transform: uppercase;
        letter-spacing: 0.025em;
    }

    .payment-amount-authorized[b-m3f01laonm] {
        color: var(--pt-navy, #000075) !important;
    }

    /* #320 (Cam's second pass) — the summary rows read as body text, not as navy: "instead of the navy
       color for the 'Pre-autorizado' and 'Saldo pendiente' text, we just use the dark gray/black font
       color that's used above this section."

       They are a running tally, not a callout. With the dashed Pre-Autorizado card sitting right above
       them in navy, three navy things in one card left nothing looking distinct — so the card keeps the
       colour (see .payment-amount-authorized) and the tally gives it up.

       --modal-text remaps for the dark palette on its own, which retires the override further down. */
    .summary-authorized[b-m3f01laonm] {
        color: var(--modal-text);
    }

    .authorized-amount[b-m3f01laonm] {
        font-weight: 600;
        color: var(--modal-text);
    }

    /* Dark mode authorized payment adjustments */
    @media (prefers-color-scheme: dark) {
        .payment-item.payment-authorized[b-m3f01laonm] {
            border-color: #6060c0;
            background: rgba(96, 96, 192, 0.1);
        }

    .payment-icon-authorized[b-m3f01laonm] {
            background: rgba(96, 96, 192, 0.2) !important;
            color: #8080d0 !important;
        }

    .payment-wallet-badge[b-m3f01laonm] {
            background: #4040a0;
        }

    .payment-status-badge[b-m3f01laonm] {
            background: #6060c0;
        }

    .payment-transfer-badge[b-m3f01laonm] {
            background: #6060c0;
        }

    /* The 10%-navy tint disappears against a dark surface; lift it the same way the
       authorized rows are lifted just above. */
    .pending-bank-transfers-section[b-m3f01laonm] {
            background: rgba(96, 96, 192, 0.12);
            border-color: #6060c0;
        }

    .payment-amount-authorized[b-m3f01laonm] {
            color: #8080d0 !important;
        }

    /* #320 (Cam's second pass) — no dark override for the summary rows: --modal-text already remaps.
       .payment-amount-authorized above KEEPS its #8080d0, because the dashed card stays navy. */
    }

    /* Responsive partial payments */
    @media (max-width: 576px) {
        .partial-payments-header[b-m3f01laonm] {
            flex-direction: column;
            align-items: flex-start;
        }

    .balance-due-badge[b-m3f01laonm] {
            width: 100%;
            justify-content: space-between;
        }

    .payment-item[b-m3f01laonm] {
            flex-wrap: wrap;
        }

    .payment-item-amount[b-m3f01laonm] {
            order: 3;
            width: 100%;
            flex-direction: row;
            justify-content: space-between;
            padding-top: 0.5rem;
            margin-top: 0.5rem;
            border-top: 1px dashed var(--modal-border);
        }
    }

    /* Pending Cash Claims Section Styles */
    .pending-cash-claims-section[b-m3f01laonm] {
        background: linear-gradient(135deg, rgba(236, 96, 126, 0.1) 0%, rgba(236, 96, 126, 0.05) 100%);
        border: 2px solid var(--pt-coral, #ec607e);
        border-radius: 0;
        padding: 0.75rem;
    }

    /* Live SPEI reference. Navy-tinted to match the transfer chip and to sit apart from the
       coral cash-claim block, which can legitimately appear on the same tab at the same time. */
    .pending-bank-transfers-section[b-m3f01laonm] {
        background: linear-gradient(135deg, rgba(0, 0, 117, 0.1) 0%, rgba(0, 0, 117, 0.05) 100%);
        border: 2px solid var(--pt-navy, #000075);
        border-radius: 0;
        padding: 0.75rem;
        margin-bottom: 0.75rem;
    }

    .pending-cash-claims-footer[b-m3f01laonm] {
        margin-top: 0.5rem;
        color: var(--pt-text-muted);
        line-height: 1.3;
    }

    .pending-cash-claims-header[b-m3f01laonm] {
        display: flex;
        justify-content: space-between;
        align-items: center;
        margin-bottom: 0.75rem;
    }

    .pending-cash-claims-title[b-m3f01laonm] {
        display: flex;
        align-items: center;
        gap: 0.5rem;
        margin: 0;
        font-size: 1rem;
        font-weight: 700;
        color: var(--pt-coral, #ec607e);
    }

    .pending-count-badge[b-m3f01laonm] {
        display: flex;
        align-items: center;
        justify-content: center;
        min-width: 24px;
        height: 24px;
        padding: 0 0.5rem;
        background: var(--pt-coral, #ec607e);
        color: var(--pt-on-coral);
        border-radius: 0;
        font-size: 0.75rem;
        font-weight: 700;
    }

    .pending-cash-claims-body[b-m3f01laonm] {
        display: flex;
        flex-direction: column;
        gap: 0.5rem;
    }

    .pending-claim-item[b-m3f01laonm] {
        display: flex;
        align-items: center;
        gap: 0.75rem;
        padding: 0.75rem;
        background: var(--modal-bg);
        border: 1px solid var(--modal-border);
        border-left: 3px solid var(--pt-coral, #ec607e);
        border-radius: 0;
        transition: all 0.2s ease;
    }

    /* Hover edge uses --pt-hover-border (navy in light,light silver in dark). The glow
       follows the border — a coral halo around a navy edge reads as two competing states. */
    .pending-claim-item:hover[b-m3f01laonm] {
        border-color: var(--pt-hover-border);
        box-shadow: 0 2px 8px rgba(0, 0, 117, 0.15);
    }

    .claim-item-icon[b-m3f01laonm] {
        width: 36px;
        height: 36px;
        display: flex;
        align-items: center;
        justify-content: center;
        background: rgba(236, 96, 126, 0.15);
        color: var(--pt-coral, #ec607e);
        border-radius: 0;
        flex-shrink: 0;
    }

    .claim-item-details[b-m3f01laonm] {
        flex: 1;
        display: flex;
        flex-direction: column;
        gap: 0.125rem;
        min-width: 0;
    }

    .claim-payer[b-m3f01laonm] {
        font-weight: 600;
        color: var(--modal-text);
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
    }

    .claim-method[b-m3f01laonm] {
        font-size: 0.75rem;
        color: var(--modal-text-secondary);
    }

    .claim-item-amount[b-m3f01laonm] {
        display: flex;
        flex-direction: column;
        align-items: flex-end;
        gap: 0.125rem;
    }

    .claim-amount[b-m3f01laonm] {
        font-weight: 700;
        color: var(--pt-coral, #ec607e);
    }

    .claim-tip[b-m3f01laonm] {
        font-size: 0.7rem;
        color: var(--modal-text-secondary);
    }

    .claim-item-actions[b-m3f01laonm] {
        display: flex;
        gap: 0.5rem;
        flex-shrink: 0;
    }

    .btn-claim-confirm[b-m3f01laonm],.btn-claim-cancel[b-m3f01laonm] {
        width: 32px;
        height: 32px;
        padding: 0;
        display: flex;
        align-items: center;
        justify-content: center;
        border-radius: 0;
    }

    .btn-claim-confirm[b-m3f01laonm] {
        background: #10b981;
        border-color: #10b981;
    }

    .btn-claim-confirm:hover:not(:disabled)[b-m3f01laonm] {
        background: #059669;
        border-color: #059669;
    }

    .btn-claim-cancel[b-m3f01laonm] {
        border-width: 2px;
    }

    /* Dark mode pending cash claims adjustments */
    @media (prefers-color-scheme: dark) {
        .pending-cash-claims-section[b-m3f01laonm] {
            background: linear-gradient(135deg, rgba(236, 96, 126, 0.15) 0%, rgba(236, 96, 126, 0.05) 100%);
        }

    .claim-item-icon[b-m3f01laonm] {
            background: rgba(236, 96, 126, 0.2);
        }

        /* Silver glow to match --pt-hover-border in dark (#cbd5e1). */
    .pending-claim-item:hover[b-m3f01laonm] {
            box-shadow: 0 2px 8px rgba(203, 213, 225, 0.25);
        }
    }

    /* Responsive pending cash claims */
    @media (max-width: 576px) {
        .pending-claim-item[b-m3f01laonm] {
            flex-wrap: wrap;
        }

    .claim-item-amount[b-m3f01laonm] {
            order: 3;
            flex-direction: row;
            gap: 0.5rem;
            width: calc(100% - 80px);
            padding-top: 0.5rem;
            margin-top: 0.5rem;
            border-top: 1px dashed var(--modal-border);
        }

    .claim-item-actions[b-m3f01laonm] {
            order: 4;
        }
    }

    /* Split Payment Badge Styles */
    .payment-split-badge[b-m3f01laonm] {
        display: inline-flex;
        align-items: center;
        gap: 0.25rem;
        margin-left: 0.5rem;
        padding: 0.125rem 0.5rem;
        border-radius: 0;
        font-size: 0.625rem;
        font-weight: 700;
        text-transform: uppercase;
        letter-spacing: 0.025em;
        vertical-align: middle;
    }

    .payment-split-badge i[b-m3f01laonm] {
        font-size: 0.5rem;
    }

    /* Divide mode badge - purple/violet color */
    .payment-split-divide[b-m3f01laonm] {
        /* iPad #10 — one flat tag purple (--pt-tag), no gradient. */
        background: var(--pt-tag-bg, rgba(139, 92, 246, 0.12));
        border: 1px solid var(--pt-tag, #8b5cf6);
        color: var(--pt-tag, #8b5cf6);
    }

    /* Links mode badge - teal color */
    .payment-split-links[b-m3f01laonm] {
        background: linear-gradient(135deg, rgba(20, 184, 166, 0.15) 0%, rgba(20, 184, 166, 0.1) 100%);
        border: 1px solid #14b8a6;
        color: #14b8a6;
    }

    /* Split payment item styling */
    .payment-item.payment-split[b-m3f01laonm] {
        border-left: 3px solid var(--pt-tag, #8b5cf6);
    }

    .payment-item.payment-split.payment-authorized[b-m3f01laonm] {
        border-left: 3px solid var(--pt-tag, #8b5cf6);
    }

    .pending-claim-item.claim-split[b-m3f01laonm] {
        border-left-color: var(--pt-tag, #8b5cf6);
    }

    /* Dark mode split payment adjustments */
    @media (prefers-color-scheme: dark) {
        .payment-split-divide[b-m3f01laonm] {
            background: linear-gradient(135deg, rgba(167, 139, 250, 0.2) 0%, rgba(167, 139, 250, 0.1) 100%);
            border-color: #a78bfa;
            color: #a78bfa;
        }

    .payment-split-links[b-m3f01laonm] {
            background: linear-gradient(135deg, rgba(45, 212, 191, 0.2) 0%, rgba(45, 212, 191, 0.1) 100%);
            border-color: #2dd4bf;
            color: #2dd4bf;
        }

    .payment-item.payment-split[b-m3f01laonm] {
            border-left-color: #a78bfa;
        }

    .pending-claim-item.claim-split[b-m3f01laonm] {
            border-left-color: #a78bfa;
        }
    }

    /* Responsive split payment badges */
    @media (max-width: 576px) {
        .payment-split-badge[b-m3f01laonm] {
            display: block;
            margin-left: 0;
            margin-top: 0.25rem;
            width: fit-content;
        }
    }

    /* Dark mode for new elements */
    @media (prefers-color-scheme: dark) {
        .blended-item-row:hover[b-m3f01laonm] {
            background: rgba(255, 255, 255, 0.03);
        }

    .right-card[b-m3f01laonm] {
            background: var(--modal-header-bg);
            border-color: var(--modal-border);
        }

    .totals-closed-badge[b-m3f01laonm] {
            background: rgba(52, 211, 153, 0.15);
            color: #34d399;
        }

    /* #329 — the tip figure's dark end. emerald-700 is right on the light card and 3.23:1 on this one, so it
       has to move; #34d399 is the green this file already uses for text on the dark card (just above), at
       9.23:1 on #111827. */
    .tip-amount[b-m3f01laonm] {
            color: #34d399;
        }

    /* #296 — the status tag's three tints, re-mapped for the dark card: a deep bed of the state's colour with
       the same colour lightened for the text. The light tints would read as three bright chips in a dark drawer.

       OPAQUE on purpose, where .totals-closed-badge above uses an alpha. A tag's contrast is checked all over
       this suite by reading its own background-color and comparing, and an alpha reports the tint WITHOUT the
       surface under it — AccountDrawerContractTests' readability probe computes a ratio against exactly that
       value. A solid colour is the same number wherever it lands and needs nobody to composite it first. */
    .client-status--open[b-m3f01laonm] {
            background: #12332a;
            color: #34d399;
            border-color: #1d5344;
        }

    .client-status--closed[b-m3f01laonm],
    .client-status--abandoned-charged[b-m3f01laonm] {
            background: #252a4a;
            color: #a5b4fc;
            border-color: #3a4170;
        }

    .client-status--abandoned[b-m3f01laonm] {
            background: #3a1f1f;
            color: #f87171;
            border-color: #5c2e2e;
        }

    /* #341 — the amber pair inverted for dark, same shape as the three above: a deep ground with the
       light-scheme hue brought up until it clears AA on it. */
    .client-status--reopened[b-m3f01laonm] {
            background: #3d2f12;
            color: #fbbf24;
            border-color: #5c4a1d;
        }

    /* The panel's refusal takes the same dark danger pair the row above it uses. */
    .reopen-panel-error[b-m3f01laonm] {
            background: #3a1f1f;
            color: #f87171;
        }

    /* Same pair for the split's out-of-range hint: #991b1b on a dark ground is unreadable, which is
       the one thing a warning must never be. */
    .split-invalid-hint[b-m3f01laonm] {
            background: #3a1f1f;
            color: #f87171 !important;
        }

    .blended-category-header[b-m3f01laonm] {
            border-bottom-color: var(--modal-border);
        }
    }

    /* #341 — the banner on an account reopened for a correction.
       Deliberately the SAME amber informational shape as .abandoned-tab-callout below: both say "a
       temporary condition somebody has to resolve", which is exactly what the drawer already uses amber
       for, and a fifth colour for a fifth state would be noise. No dark override, matching its sibling —
       the pale amber ground keeps dark text legible in either scheme, and giving this one a dark variant
       while the callout beside it has none would make the pair inconsistent instead of fixing anything. */
    .reopened-callout[b-m3f01laonm] {
        display: flex;
        align-items: flex-start;
        gap: 0.6rem;
        background: #fef3c7;
        border-left: 4px solid #f59e0b;
        border-radius: 0;
        padding: 12px 16px;
        font-family: 'Montserrat', sans-serif;
        color: #78350f;
    }

    .reopened-callout-text[b-m3f01laonm] {
        display: flex;
        flex-direction: column;
        gap: 2px;
        min-width: 0;
    }

    .reopened-callout-title[b-m3f01laonm] {
        font-weight: 600;
        font-size: 0.9rem;
        color: #92400e;
    }

    /* Who and why. The reason is the operator's own words and can be long, so it wraps rather than
       being clipped — a truncated motivo is the half a manager most needs. */
    .reopened-callout-detail[b-m3f01laonm] {
        font-size: 0.85rem;
        overflow-wrap: anywhere;
    }

    /* #341 — the reopen panel takes .comp-panel wholesale (surface, navy edge, padding, header, title,
       corner X), exactly as the #340 editor does. Only the body differs, for the same reason: the family's
       .comp-panel-body is a wrapping flex ROW built for chips and buttons, and this one holds a note, a
       field and an action pair. */
    .reopen-panel .comp-panel-body[b-m3f01laonm] {
        display: block;
    }

    .reopen-panel-note[b-m3f01laonm] {
        margin: 0 0 0.6rem;
        font-size: 0.85rem;
        color: var(--modal-text-secondary);
    }

    .reopen-reason-field label[b-m3f01laonm] {
        display: block;
        font-size: 0.75rem;
        font-weight: 600;
        color: var(--modal-text-secondary);
        margin-bottom: 0.2rem;
    }

    .reopen-reason-field .form-control[b-m3f01laonm] {
        border-radius: 0;
        min-height: var(--pt-field-min-height, 44px);
        font-size: 1rem;
    }

    .reopen-panel-actions[b-m3f01laonm] {
        display: flex;
        justify-content: flex-end;
        gap: 0.5rem;
        margin-top: 0.75rem;
    }

    /* The server's refusal, in the panel that asked for it (Igor: "I'm seeing an error in a toast
       notification when it should be appearing in the tab modal"). Borrows the drawer's existing danger
       pair rather than inventing one: #991b1b on #fef2f2 is what .client-edit-error already uses, and it
       measures 8.6:1. */
    .reopen-panel-error[b-m3f01laonm] {
        display: flex;
        align-items: flex-start;
        gap: 0.5rem;
        margin-top: 0.6rem;
        padding: 0.5rem 0.65rem;
        border-left: 3px solid #dc2626;
        border-radius: 0;
        background: #fef2f2;
        color: #991b1b;
        font-size: 0.8rem;
        line-height: 1.35;
    }

    /* The footer affordance on a settled account. An outline button, not a filled one: a closed account's
       footer should not lead with un-settling it. */
    /* #377 — "add space after icon, center icon vertically and make it visually proportionate size
       in the button".

       The button took .btn's own flex row, whose gap is --spacing-xs (4px) — enough between two
       words, tight between a glyph and a label. And the glyph rendered at the inherited 1rem beside
       a btn-sm's smaller text, so it read as oversized.

       The size is in `em`, not `rem`: it is then a proportion of whatever type size this button
       ends up carrying, which is what "visually proportionate" has to mean for a control whose own
       size is set elsewhere. line-height: 1 takes the glyph's own leading out of the row so
       align-items can actually centre it. */
    .btn-reopen-tab[b-m3f01laonm] {
        border-radius: 0;
        align-self: flex-start;
        display: inline-flex;
        align-items: center;
        gap: 0.5rem;
    }

    .btn-reopen-tab i[b-m3f01laonm] {
        font-size: 0.875em;
        line-height: 1;
    }

    /* PR 2 (course-as-Order,2026-05-19) — abandoned-tab recovery callout.
       Amber informational warning (NOT destructive red); per
       mesero-ui-modernization-plan §1 (semantic color). Sits above the
       primary close-actions row in the panel footer. */
    .abandoned-tab-callout[b-m3f01laonm] {
        background: #fef3c7;
        border-left: 4px solid #f59e0b;
        border-radius: 0;
        padding: 12px 16px;
        /* The account footer's column gap spaces it from the total below (#252). */
        margin: 0;
        font-family: 'Montserrat', sans-serif;
    }

    .abandoned-tab-callout__head[b-m3f01laonm] {
        display: flex;
        align-items: center;
        gap: 0.4rem;
        font-weight: 600;
        font-size: 0.9rem;
        color: #92400e;
        margin-bottom: 4px;
    }

    .abandoned-tab-callout__body[b-m3f01laonm] {
        font-size: 0.85rem;
        color: #78350f;
        margin-bottom: 10px;
    }

    /* #279: the two buttons fill the callout — side by side while both labels fit the row, a row
       each when they do not, as the shift card's pair does (#265). They used to sit at their own
       widths against the left edge, which left the callout ragged. */
    .abandoned-tab-callout__actions[b-m3f01laonm] {
        display: flex;
        gap: 8px;
        flex-wrap: wrap;
    }

    .abandoned-tab-callout__actions > .abandoned-tab-btn[b-m3f01laonm] {
        flex: 1 1 auto;
    }

    /* #326 — one action, so it sits BESIDE the message rather than under it. Cam: "can we have the button
       appear to the right of the text? that way it reduces vertical space used."

       Grid on the callout itself, addressing the three blocks it already has by area — no wrapper element,
       so the two-action callout above keeps byte-identical markup and the stacked shape #279 gave it. The
       text column takes the free space (1fr) and the button takes only what it needs (auto), which is what
       keeps a short label from stretching across half the callout.

       align-items: center rather than stretch: a button stretched over two rows of text reads as a panel,
       and this one is an action. */
    .abandoned-tab-callout--single[b-m3f01laonm] {
        display: grid;
        grid-template-columns: 1fr auto;
        grid-template-areas:
            "head actions"
            "body actions";
        align-items: center;
        column-gap: 16px;
    }

    .abandoned-tab-callout--single .abandoned-tab-callout__head[b-m3f01laonm] {
        grid-area: head;
        margin-bottom: 0;
    }

    /* The 10px that separated the message from the button below it is now horizontal, and column-gap owns
       it — left in place it would push the two text rows apart for no reason. */
    .abandoned-tab-callout--single .abandoned-tab-callout__body[b-m3f01laonm] {
        grid-area: body;
        margin-bottom: 0;
    }

    .abandoned-tab-callout--single .abandoned-tab-callout__actions[b-m3f01laonm] {
        grid-area: actions;
    }

    /* Phones: the drawer IS the viewport, and there is no width to put a button beside two lines of Spanish
       prose. Back to the stacked shape, which is what the rest of the footer does at this width. */
    @media (max-width: 768px) {
    .abandoned-tab-callout--single[b-m3f01laonm] {
            display: block;
        }

    .abandoned-tab-callout--single .abandoned-tab-callout__body[b-m3f01laonm] {
            margin-bottom: 10px;
        }
    }

    /* Read-only counterpart for a CLOSED abandoned tab. Mirrors the recovery callout above —
       same amber, same left-border device — because it reports the same fact after the decision
       rather than a different one. No actions row: the close already happened. Without this the
       modal said nothing at all once the tab closed, since the callout above is gated on
       Tab.IsActive && !Tab.IsPaid. */
    .abandoned-tab-closed[b-m3f01laonm] {
        background: #fef3c7;
        border-left: 4px solid #f59e0b;
        border-radius: 0;
        padding: 12px 16px;
        /* The account footer's column gap spaces it from what follows (#252). */
        margin: 0;
        font-family: 'Montserrat', sans-serif;
    }

    .abandoned-tab-closed__head[b-m3f01laonm] {
        display: flex;
        align-items: center;
        gap: 0.4rem;
        font-weight: 600;
        font-size: 0.9rem;
        color: #92400e;
    }

    .abandoned-tab-closed__body[b-m3f01laonm] {
        font-size: 0.85rem;
        color: #78350f;
        margin-top: 4px;
    }

    /* charged_to_authorized_card: the money DID arrive over the held card, so this reports the
       recovery in the positive colour instead of the amber alarm a write-off warrants. The
       heading still reads "Cuenta abandonada" — staff need to know it was a recovery charge and
       not a guest-initiated payment. */
    .abandoned-tab-closed--charged[b-m3f01laonm] {
        background: #d1fae5;
        border-left-color: #10b981;
    }

    .abandoned-tab-closed--charged .abandoned-tab-closed__head[b-m3f01laonm] {
        color: #065f46;
    }

    .abandoned-tab-closed--charged .abandoned-tab-closed__body[b-m3f01laonm] {
        color: #047857;
    }

    .abandoned-tab-btn[b-m3f01laonm] {
        min-height: 44px;
        padding: 8px 14px;
        border-radius: 0;
        font-family: 'Montserrat', sans-serif;
        font-size: 0.85rem;
        font-weight: 600;
        cursor: pointer;
    }

    .abandoned-tab-btn--mark[b-m3f01laonm] {
        background: transparent;
        color: var(--pt-navy, #000075);
        border: 1px solid var(--pt-navy, #000075);
    }

    .abandoned-tab-btn--mark:hover:not(:disabled)[b-m3f01laonm] {
        background: var(--pt-navy, #000075);
        color: #ffffff;
    }

    .abandoned-tab-btn--charge[b-m3f01laonm] {
        background: var(--pt-coral, #ec607e);
        color: var(--pt-on-coral);
        border: 1px solid var(--pt-coral, #ec607e);
    }

    .abandoned-tab-btn--charge:hover:not(:disabled)[b-m3f01laonm] { filter: brightness(0.95); }

    .abandoned-tab-btn:disabled[b-m3f01laonm] { opacity: 0.5; cursor: not-allowed; }

    @media (prefers-color-scheme: dark) {
        .abandoned-tab-callout[b-m3f01laonm] {
            background: rgba(245, 158, 11, 0.12);
        }

    .abandoned-tab-callout__head[b-m3f01laonm] { color: #fbbf24; }

    .abandoned-tab-callout__body[b-m3f01laonm] { color: #fcd34d; }

    .abandoned-tab-closed[b-m3f01laonm] { background: rgba(245, 158, 11, 0.12); }

    .abandoned-tab-closed__head[b-m3f01laonm] { color: #fbbf24; }

    .abandoned-tab-closed__body[b-m3f01laonm] { color: #fcd34d; }

    .abandoned-tab-closed--charged[b-m3f01laonm] { background: rgba(16, 185, 129, 0.12); }

    .abandoned-tab-closed--charged .abandoned-tab-closed__head[b-m3f01laonm] { color: #6ee7b7; }

    .abandoned-tab-closed--charged .abandoned-tab-closed__body[b-m3f01laonm] { color: #a7f3d0; }

    .abandoned-tab-btn--mark[b-m3f01laonm] { color: #ffffff; border-color: #ffffff; }
    }
/* /Components/Splash/SplashScreen.razor.rz.scp.css */
    .splash-screen[b-fx5dot0ubr] {
        position: fixed;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        width: 100%;
        height: 100%;
        z-index: 10000;
        overflow: hidden;
        background: var(--pt-navy, #000075);
        transition: opacity 0.5s ease-out;
    }
    
    .splash-screen.fade-out[b-fx5dot0ubr] {
        opacity: 0;
        pointer-events: none;
    }
    
    /* Grid container */
    .squares-grid[b-fx5dot0ubr] {
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        display: grid;
        grid-template-columns: repeat(var(--cols), var(--cell-size));
        grid-template-rows: repeat(var(--rows), var(--cell-size));
        width: calc(var(--cols) * var(--cell-size));
        height: calc(var(--rows) * var(--cell-size));
        gap: 0;
    }
    
    /* Individual square - all same size */
    .square[b-fx5dot0ubr] {
        position: relative;
        width: var(--cell-size);
        height: var(--cell-size);
    }
    
    .square-navy[b-fx5dot0ubr],
    .square-coral[b-fx5dot0ubr] {
        position: absolute;
        inset: -1px;
    }
    
    .square-navy[b-fx5dot0ubr] {
        background: var(--pt-navy, #000075);
    }
    
    .square-coral[b-fx5dot0ubr] {
        background: var(--pt-coral, #ec607e);
        opacity: 0;
        transition: opacity 0.8s ease-in-out;
        transition-delay: var(--delay);
    }
    
    .square.animate .square-coral[b-fx5dot0ubr] {
        opacity: 1;
    }
    
    /* Logo tile - same size as all other squares */
    .logo-tile[b-fx5dot0ubr] {
        display: flex;
        align-items: center;
        justify-content: center;
        z-index: 10;
    }
    
    .logo-bg-navy[b-fx5dot0ubr],
    .logo-bg-coral[b-fx5dot0ubr] {
        position: absolute;
        inset: -1px;
    }
    
    .logo-bg-navy[b-fx5dot0ubr] {
        background: var(--pt-navy, #000075);
    }
    
    .logo-bg-coral[b-fx5dot0ubr] {
        background: var(--pt-coral, #ec607e);
        opacity: 0;
        transition: opacity 0.8s ease-in-out;
        transition-delay: 1.2s;
    }
    
    .logo-tile.animate .logo-bg-coral[b-fx5dot0ubr] {
        opacity: 1;
    }
    
    /* iPad #1: 85% of --cell-size is what the static loading splash in
       wwwroot/index.html (.loading-logo-img) pins its widths to, so the wordmark
       does not change size the instant Blazor replaces that markup. Changing this
       percentage or --cell-size means updating those widths too. */
    .logo-img[b-fx5dot0ubr] {
        position: absolute;
        width: 85%;
        height: auto;
        max-height: 60%;
        object-fit: contain;
        z-index: 2;
        filter: drop-shadow(0 2px 8px rgba(0, 0, 0, 0.2));
    }
    
    /* Coral logo (visible initially on navy bg) */
    .logo-coral[b-fx5dot0ubr] {
        opacity: 1;
        transition: opacity 0.6s ease-in-out;
        transition-delay: 1.2s;
    }
    
    .logo-tile.animate .logo-coral[b-fx5dot0ubr] {
        opacity: 0;
    }
    
    /* Navy logo (fades in on coral bg) */
    .logo-navy[b-fx5dot0ubr] {
        opacity: 0;
        transition: opacity 0.6s ease-in-out;
        transition-delay: 1.4s;
    }
    
    .logo-tile.animate .logo-navy[b-fx5dot0ubr] {
        opacity: 1;
    }
    
    /* Mobile adjustments - smaller cells on smaller screens */
    @media (max-width: 768px) {
        .squares-grid[b-fx5dot0ubr] {
            --cell-size: 150px !important;
        }
    }
    
    @media (max-width: 480px) {
        .squares-grid[b-fx5dot0ubr] {
            --cell-size: 120px !important;
        }
    }
/* /Components/Util/AwaitingWalletReAuthPill.razor.rz.scp.css */
    /* Re-uses the .awaiting-approval-pill-* tone classes defined on
       AwaitingApprovalPill so the two pills are visually consistent.
       Only the extra amount chip needs its own rule. */
    .awaiting-approval-pill-amount[b-if6hun9015] {
        margin-left: 6px;
        padding: 2px 6px;
        background: rgba(255, 255, 255, 0.35);
        border-radius: 0;
        font-size: 12px;
        font-weight: 600;
    }
/* /Components/Util/CoursePlanPreview.razor.rz.scp.css */
    /* PayTable 2025 branding: Navy #000075 · Coral #ec607e · White
       · straight edges · touch-friendly · Montserrat body / Poppins headings. */
    .course-plan-preview[b-w82tq0630a] {
        font-family: 'Montserrat', sans-serif;
        background: rgba(0, 0, 117, 0.04);
        border-left: 4px solid var(--pt-navy, #000075);
        border-radius: 0;
        padding: 12px 16px;
        margin: 12px 0;
    }

    .course-plan-preview__header[b-w82tq0630a] {
        display: flex;
        justify-content: space-between;
        align-items: center;
        flex-wrap: wrap;
        gap: 8px;
        margin-bottom: 10px;
    }

    .course-plan-preview__title-row[b-w82tq0630a] {
        display: flex;
        align-items: center;
        gap: 8px;
        flex-wrap: wrap;
    }

    .course-plan-preview__title[b-w82tq0630a] {
        font-family: 'Poppins', 'Montserrat', sans-serif;
        font-weight: 600;
        font-size: 14px;
        color: var(--pt-navy, #000075);
    }

    .course-plan-preview__edited-tag[b-w82tq0630a] {
        font-size: 11px;
        font-weight: 600;
        padding: 3px 8px;
        border-radius: 0;
        font-family: 'Montserrat', sans-serif;
    }

    .course-plan-preview__edited-tag.auto[b-w82tq0630a] {
        background: rgba(0, 0, 117, 0.08);
        color: var(--pt-navy, #000075);
    }

    .course-plan-preview__edited-tag.edited[b-w82tq0630a] {
        background: rgba(236, 96, 126, 0.12);
        color: var(--pt-coral, #ec607e);
    }

    /* #236 — the flattened state keeps the panel's frame so the cart does not reflow
       around a disappearing block, but drops the left rule to navy-at-rest: it is a
       statement about what WILL happen, not a plan to read. */
    .course-plan-preview--flattened[b-w82tq0630a] {
        border-left-color: rgba(0, 0, 117, 0.35);
    }

    .course-plan-preview__flattened-note[b-w82tq0630a] {
        font-size: 12px;
        color: var(--ion-color-medium-shade, #4a4a52);
    }

    /* Outline-navy pill — UI plan §3.4 (no coral except for the page's
       primary CTA). Stays visible per locked decision UI-3.

       #236 — "Restaurar cursos" shares it rather than copying it. The two are the same
       control in opposite directions, and a copy is how .m-se-btn-back drifted (#235). */
    .course-plan-preview__flatten[b-w82tq0630a],
    .course-plan-preview__restore[b-w82tq0630a] {
        min-height: 44px;
        min-width: 44px;
        padding: 8px 14px;
        background: transparent;
        color: var(--pt-navy, #000075);
        border: 1px solid var(--pt-navy, #000075);
        border-radius: 0;
        font-family: 'Montserrat', sans-serif;
        font-size: 12px;
        font-weight: 600;
        cursor: pointer;
    }

    .course-plan-preview__flatten:hover:not(:disabled)[b-w82tq0630a],
    .course-plan-preview__restore:hover:not(:disabled)[b-w82tq0630a] {
        background: var(--pt-navy, #000075);
        color: #ffffff;
    }

    .course-plan-preview__course[b-w82tq0630a],
    .course-plan-preview__bar[b-w82tq0630a] {
        background: #ffffff;
        border: 1px solid rgba(0, 0, 117, 0.12);
        border-radius: 0;
        padding: 10px 12px;
        margin-bottom: 8px;
    }

    .course-plan-preview__course-header[b-w82tq0630a] {
        display: flex;
        align-items: center;
        gap: 10px;
        flex-wrap: wrap;
        margin-bottom: 6px;
    }

    .course-plan-preview__course-num[b-w82tq0630a] {
        font-weight: 600;
        font-size: 13px;
        color: var(--pt-navy, #000075);
    }

    .course-plan-preview__course-mode[b-w82tq0630a] {
        font-size: 12px;
        color: var(--ion-color-medium-shade, #4a4a52);
        flex: 1;
    }

    .course-plan-preview__edit[b-w82tq0630a] {
        min-height: 44px;
        min-width: 44px;
        padding: 6px 12px;
        background: transparent;
        color: var(--pt-navy, #000075);
        border: 1px solid var(--pt-navy, #000075);
        border-radius: 0;
        font-family: 'Montserrat', sans-serif;
        font-size: 12px;
        font-weight: 600;
        cursor: pointer;
    }

    .course-plan-preview__edit:hover:not(:disabled)[b-w82tq0630a] {
        background: var(--pt-navy, #000075);
        color: #ffffff;
    }

    @media (prefers-color-scheme: dark) {
        .course-plan-preview[b-w82tq0630a] {
            background: rgba(255, 255, 255, 0.04);
            border-left-color: var(--pt-coral, #ec607e);
        }
        .course-plan-preview__title[b-w82tq0630a] { color: #ffffff; }
        .course-plan-preview__edited-tag.auto[b-w82tq0630a] { color: #ffffff; background: rgba(255, 255, 255, 0.10); }
        .course-plan-preview__course[b-w82tq0630a],
        .course-plan-preview__bar[b-w82tq0630a] {
            background: #1f2937;
            border-color: rgba(255, 255, 255, 0.12);
        }
        .course-plan-preview__course-num[b-w82tq0630a] { color: #ffffff; }
        .course-plan-preview__course-mode[b-w82tq0630a] { color: #c8c8d0; }
        .course-plan-preview__edit[b-w82tq0630a] {
            color: #ffffff;
            border-color: #ffffff;
        }
        .course-plan-preview__flatten[b-w82tq0630a],
        .course-plan-preview__restore[b-w82tq0630a] {
            color: #ffffff;
            border-color: #ffffff;
        }
        .course-plan-preview--flattened[b-w82tq0630a] {
            border-left-color: rgba(236, 96, 126, 0.45);
        }
        .course-plan-preview__flattened-note[b-w82tq0630a] { color: #c8c8d0; }
    }
/* /Components/Util/MaxQuantitySetting.razor.rz.scp.css */
/* #612 Q2c: the setting's line under an option's fields, beside «No mostrar $0»'s. */
.max-quantity[b-rm3jn6g4dd] {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem 1rem;
    font-size: 0.8125rem;
}

.max-quantity-toggle[b-rm3jn6g4dd],
.max-quantity-max[b-rm3jn6g4dd] {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    margin: 0;
}

.max-quantity-input[b-rm3jn6g4dd] {
    width: 4.5rem;
}
/* /Components/Util/MobileWaiterCallBadge.razor.rz.scp.css */
    /* ==========================================================================
       Bell icon trigger — matches mobile header icon-button sizing.
       ========================================================================== */
    .mwc-badge[b-ieuqb2p6zb] {
        position: relative;
        width: 44px;
        height: 44px;
        padding: 4px; /* 36px visual bg inside 44px tap target — brand 44px rule */
        display: inline-flex;
        align-items: center;
        justify-content: center;
        background: rgba(255, 255, 255, 0.1);
        background-clip: content-box;
        border: none;
        color: white;
        cursor: pointer;
        transition: background 0.15s ease;
        border-radius: 0;
    }

    .mwc-badge:hover[b-ieuqb2p6zb],
    .mwc-badge:focus-visible[b-ieuqb2p6zb] {
        background: rgba(255, 255, 255, 0.2);
        outline: none;
    }

    /* ::deep -- see WaiterCallBadge.razor.css. PtIcon owns the <i>. */
    .mwc-badge[b-ieuqb2p6zb]  > i {
        font-size: 0.95rem;
    }

    .mwc-count[b-ieuqb2p6zb] {
        position: absolute;
        top: 2px;
        right: 2px;
        min-width: 16px;
        height: 16px;
        padding: 0 4px;
        background: var(--pt-coral, #ec607e);
        color: var(--pt-on-coral);
        font-size: 0.625rem;
        font-weight: 700;
        display: flex;
        align-items: center;
        justify-content: center;
        border: 2px solid var(--pt-navy, #000075);
        animation: mwcPulse-b-ieuqb2p6zb 2s ease-in-out infinite;
        font-variant-numeric: tabular-nums;
    }

    @keyframes mwcPulse-b-ieuqb2p6zb {
        0%, 100% { transform: scale(1); }
        50% { transform: scale(1.12); }
    }

    /* ==========================================================================
       Bottom-sheet overlay + panel.
       ========================================================================== */
    .mwc-overlay[b-ieuqb2p6zb] {
        position: fixed;
        inset: 0;
        background: rgba(0, 0, 0, 0.5);
        z-index: 250;
        display: flex;
        align-items: flex-end;
        animation: mwcFadeIn-b-ieuqb2p6zb 0.2s ease;
    }

    @keyframes mwcFadeIn-b-ieuqb2p6zb {
        from { opacity: 0; }
        to   { opacity: 1; }
    }

    .mwc-sheet[b-ieuqb2p6zb] {
        width: 100%;
        max-height: 80vh;
        background: white;
        display: flex;
        flex-direction: column;
        animation: mwcSlideUp-b-ieuqb2p6zb 0.25s cubic-bezier(0.25, 0.46, 0.45, 0.94);
        border-top: 3px solid var(--pt-coral, #ec607e);
    }

    @keyframes mwcSlideUp-b-ieuqb2p6zb {
        from { transform: translateY(100%); }
        to   { transform: translateY(0); }
    }

    .mwc-sheet-header[b-ieuqb2p6zb] {
        display: flex;
        align-items: center;
        justify-content: space-between;
        padding: 0.75rem 1rem;
        border-bottom: 1px solid #e5e7eb;
    }

    .mwc-sheet-header h3[b-ieuqb2p6zb] {
        margin: 0;
        font-size: 1rem;
        font-weight: 700;
        color: var(--pt-navy, #000075);
    }

    .mwc-close[b-ieuqb2p6zb] {
        width: 44px;
        height: 44px;
        padding: 6px; /* 32px icon box inside 44px tap target — brand 44px rule */
        border: none;
        background: #f3f4f6;
        color: var(--pt-navy, #000075);
        cursor: pointer;
        display: flex;
        align-items: center;
        justify-content: center;
        border-radius: 0;
        background-clip: content-box;
    }

    /* ==========================================================================
       Empty / actions / list.
       ========================================================================== */
    .mwc-empty[b-ieuqb2p6zb] {
        padding: 2rem 1rem;
        text-align: center;
        color: #6b7280;
        font-size: 0.875rem;
    }

    .mwc-empty i[b-ieuqb2p6zb] {
        color: #10b981;
        font-size: 1.5rem;
        margin-bottom: 0.5rem;
        display: block;
    }

    .mwc-actions[b-ieuqb2p6zb] {
        padding: 0.5rem 1rem;
        border-bottom: 1px solid #f3f4f6;
        display: flex;
        justify-content: flex-end;
    }

    .mwc-dismiss-all[b-ieuqb2p6zb] {
        background: none;
        border: none;
        color: var(--pt-coral, #ec607e);
        font-size: 0.75rem;
        font-weight: 600;
        cursor: pointer;
        padding: 0.25rem 0.5rem;
        text-transform: uppercase;
        letter-spacing: 0.02em;
    }

    .mwc-list[b-ieuqb2p6zb] {
        overflow-y: auto;
        max-height: 60vh;
    }

    .mwc-row[b-ieuqb2p6zb] {
        display: flex;
        align-items: center;
        gap: 0.75rem;
        padding: 0.625rem 1rem;
        border-bottom: 1px solid #f3f4f6;
        border-left: 3px solid var(--pt-coral, #ec607e);
    }

    .mwc-row:last-child[b-ieuqb2p6zb] {
        border-bottom: none;
    }

    .mwc-row-main[b-ieuqb2p6zb] {
        flex: 1;
        min-width: 0;
        display: flex;
        flex-direction: column;
        gap: 0.125rem;
    }

    .mwc-row-table[b-ieuqb2p6zb] {
        font-size: 0.875rem;
        font-weight: 700;
        color: var(--text-primary, #1f2937);
        font-variant-numeric: tabular-nums;
    }

    .mwc-row-meta[b-ieuqb2p6zb] {
        font-size: 0.75rem;
        color: var(--text-secondary, #6b7280);
    }

    .mwc-row-dot[b-ieuqb2p6zb] {
        margin: 0 0.3rem;
        color: #d1d5db;
    }

    .mwc-dismiss[b-ieuqb2p6zb] {
        width: 44px;
        height: 44px;
        padding: 6px; /* 32px icon box inside 44px tap target — brand 44px rule */
        border: none;
        background: #f3f4f6;
        color: #6b7280;
        cursor: pointer;
        display: flex;
        align-items: center;
        justify-content: center;
        border-radius: 0;
        flex-shrink: 0;
        background-clip: content-box;
    }

    .mwc-dismiss:hover[b-ieuqb2p6zb] {
        background: rgba(236, 96, 126, 0.15);
        color: var(--pt-coral, #ec607e);
    }

    /* ==========================================================================
       Dark mode.
       ========================================================================== */
    @media (prefers-color-scheme: dark) {
        .mwc-sheet[b-ieuqb2p6zb] {
            background: #1e293b;
        }

        .mwc-sheet-header[b-ieuqb2p6zb] {
            border-bottom-color: #334155;
        }

        .mwc-sheet-header h3[b-ieuqb2p6zb] {
            color: #f9fafb;
        }

        .mwc-close[b-ieuqb2p6zb] {
            background: #334155;
            color: #f9fafb;
        }

        .mwc-row[b-ieuqb2p6zb] {
            border-bottom-color: #334155;
        }

        .mwc-row-table[b-ieuqb2p6zb] {
            color: #f9fafb;
        }

        .mwc-actions[b-ieuqb2p6zb] {
            border-bottom-color: #334155;
        }

        .mwc-dismiss[b-ieuqb2p6zb] {
            background: #334155;
            color: #cbd5e1;
        }
    }

    /* Notched-phone safe area for the sheet bottom. */
    @supports (padding-bottom: env(safe-area-inset-bottom)) {
        .mwc-sheet[b-ieuqb2p6zb] {
            padding-bottom: env(safe-area-inset-bottom);
        }
    }
/* /Components/Util/OrderRowKebab.razor.rz.scp.css */
    /* Inline-positioned wrapper so the kebab sits in the per-order action
       row alongside Marcar entregado / Liberar ahora. The overlay covers the
       full viewport (outside-click closes the menu) while the menu itself
       is anchored under the trigger via the wrap's relative positioning. */
    .orow-kebab-wrap[b-bvdaoxwynm] {
        position: relative;
        display: inline-flex;
        /* #211 — the wrap is the flex item in .m-td-order-actions; stretching it is what
           lets the trigger below match the labelled buttons' height. */
        align-self: stretch;
    }

    .orow-kebab-trigger[b-bvdaoxwynm] {
        width: 44px;
        /* #211 — 44px is the FLOOR, not the height. A fixed height made this the one control
           in the row that ignored `align-items: stretch`, so it sat short beside a button
           whose label had wrapped. Square at rest, taller only if the row is. */
        min-height: 44px;
        align-self: stretch;
        padding: 10px; /* 24px visual icon area inside a 44px tap target. */
        border: 1px solid rgba(0, 0, 117, 0.15);
        background: #ffffff;
        background-clip: padding-box;
        color: var(--pt-navy, #000075);
        cursor: pointer;
        display: inline-flex;
        align-items: center;
        justify-content: center;
        border-radius: 0;
        transition: background 0.15s ease;
        flex-shrink: 0;
    }

    .orow-kebab-trigger:hover:not(:disabled)[b-bvdaoxwynm] {
        background: rgba(0, 0, 117, 0.05);
    }

    .orow-kebab-trigger:disabled[b-bvdaoxwynm] {
        opacity: 0.5;
        cursor: not-allowed;
    }

    .orow-kebab-trigger > i[b-bvdaoxwynm] {
        font-size: 0.875rem;
    }

    .orow-kebab-overlay[b-bvdaoxwynm] {
        position: fixed;
        inset: 0;
        background: transparent;
        z-index: 200;
    }

    .orow-kebab-menu[b-bvdaoxwynm] {
        position: absolute;
        /* Anchor ABOVE the trigger (bottom edge of menu = top edge of trigger
           with a 4px gap). The kebab lives in the per-order action row, which
           is at the bottom of each order block; opening downward (`top: 48px`)
           clipped the menu off the viewport when the trigger was on the last
           visible row. Opening upward keeps the menu visible regardless of
           the trigger's vertical position. */
        bottom: 48px;
        right: 0;
        min-width: 200px;
        background: #ffffff;
        border: 1px solid rgba(0, 0, 117, 0.12);
        border-bottom: 4px solid var(--pt-destructive, #ef4444);
        border-radius: 0;
        box-shadow: 0 -6px 24px rgba(0, 0, 0, 0.15);
        z-index: 210;
        display: flex;
        flex-direction: column;
    }

    .orow-kebab-item[b-bvdaoxwynm] {
        display: flex;
        align-items: center;
        gap: 0.5rem;
        min-height: 44px;
        padding: 10px 14px;
        background: transparent;
        border: none;
        border-bottom: 1px solid rgba(0, 0, 117, 0.06);
        color: var(--pt-navy, #000075);
        font-family: 'Montserrat', sans-serif;
        font-size: 0.9rem;
        font-weight: 500;
        text-align: left;
        cursor: pointer;
    }

    .orow-kebab-item:last-child[b-bvdaoxwynm] {
        border-bottom: none;
    }

    .orow-kebab-item:hover:not(:disabled)[b-bvdaoxwynm] {
        background: rgba(0, 0, 117, 0.05);
    }

    .orow-kebab-item:disabled[b-bvdaoxwynm] {
        opacity: 0.5;
        cursor: not-allowed;
    }

    .orow-kebab-item-destructive[b-bvdaoxwynm] {
        color: var(--pt-destructive-hover, #dc2626);
    }

    .orow-kebab-item-destructive:hover:not(:disabled)[b-bvdaoxwynm] {
        background: var(--pt-destructive-bg, #fee2e2);
        color: var(--pt-destructive-hover, #dc2626);
    }

    @media (prefers-color-scheme: dark) {
        .orow-kebab-trigger[b-bvdaoxwynm] {
            background: #1f2937;
            border-color: rgba(255, 255, 255, 0.12);
            color: #f9fafb;
        }
        .orow-kebab-trigger:hover:not(:disabled)[b-bvdaoxwynm] {
            background: rgba(255, 255, 255, 0.05);
        }
        .orow-kebab-menu[b-bvdaoxwynm] {
            background: #1f2937;
            border-color: rgba(255, 255, 255, 0.12);
        }
        .orow-kebab-item[b-bvdaoxwynm] {
            color: #f9fafb;
            border-bottom-color: rgba(255, 255, 255, 0.08);
        }
        .orow-kebab-item:hover:not(:disabled)[b-bvdaoxwynm] {
            background: rgba(255, 255, 255, 0.05);
        }
        .orow-kebab-item-destructive[b-bvdaoxwynm] {
            color: #f87171;
        }
        .orow-kebab-item-destructive:hover:not(:disabled)[b-bvdaoxwynm] {
            background: rgba(248, 113, 113, 0.15);
            color: #fca5a5;
        }
    }
/* /Components/Util/PtOverflowMenu.razor.rz.scp.css */
/* The ⋮ and its menu (#411). Square, like everything in this admin; 44px targets throughout. */

.pt-om[b-mmft9jatzy] {
    position: relative;
    display: inline-flex;
    flex-shrink: 0;
}

/* A BARE glyph at rest, as in Cam's tree: a boxed trigger on every Menu and Category row would be
   one more column of borders down a page that is all rows. The 44px square is the touch target,
   not a drawn box; the fill on hover and the ring on focus are what say it is a control. */
.pt-om-trigger[b-mmft9jatzy] {
    width: 44px;
    height: 44px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    border: none;
    border-radius: 0;
    background: transparent;
    color: var(--text-primary, #1f2937);
    cursor: pointer;
}

.pt-om-trigger > i[b-mmft9jatzy] {
    font-size: 1.125rem;
}

.pt-om-trigger:hover:not(:disabled)[b-mmft9jatzy],
.pt-om-trigger[aria-expanded="true"][b-mmft9jatzy] {
    background: var(--background-color, #f3f4f6);
}

.pt-om-trigger:focus-visible[b-mmft9jatzy] {
    outline: 3px solid var(--pt-coral, #ec607e);
    outline-offset: -3px;
}

.pt-om-trigger:disabled[b-mmft9jatzy] {
    opacity: 0.5;
    cursor: not-allowed;
}

/* The labelled trigger: the Menu Manager's CREAR (#411 page). Coral fill with NAVY ink. White on
   #ec607e is 3.21:1, under AA at this size; navy is 5.20:1 (--pt-on-coral in app.css, #46).

   Hover and open keep the fill and add an inset navy ring. The house hover, --pt-coral-dark, drops
   navy ink to 4.15:1, under AA for the one state the operator is looking straight at. The coral focus
   ring above would vanish on a coral button, so this one is navy and sits outside.

   #440 (Cam): "Since this is the primary action button we are displaying on the page, I think we
   should increase the width a small amount to give it more prominence." Half a rem more air on each
   side, 16px in all; the right side keeps its 2px less, since the caret carries its own. */
.pt-om-trigger--labeled[b-mmft9jatzy] {
    width: auto;
    gap: 0.5rem;
    padding: 0 1.375rem 0 1.5rem;
    background: var(--pt-coral, #ec607e);
    color: var(--pt-on-coral, #000075);
    font: inherit;
    font-size: 0.9375rem;
    font-weight: 600;
    white-space: nowrap;
}

.pt-om-trigger--labeled:hover:not(:disabled)[b-mmft9jatzy],
.pt-om-trigger--labeled[aria-expanded="true"][b-mmft9jatzy] {
    background: var(--pt-coral, #ec607e);
    box-shadow: inset 0 0 0 2px var(--pt-navy, #000075);
}

.pt-om-trigger--labeled:focus-visible[b-mmft9jatzy] {
    outline: 3px solid var(--pt-navy, #000075);
    outline-offset: 2px;
}

/* #655 (Cam's mockup) — a labelled trigger that isn't the page's primary action (Existencias' «Configuración»): outlined
   in navy over whatever it sits on, its text and glyphs navy, the same 44px and padding as «Crear». Pressed or hovered it
   takes a pale tint of it rather than the coral's ring. Inside Inventario it is Inventario's navy (--navy), which its
   dark theme lightens with its panel; elsewhere the app's. */
.pt-om-trigger--labeled.pt-om-trigger--outline[b-mmft9jatzy] {
    background: transparent;
    color: var(--navy, var(--pt-navy, #000075));
    box-shadow: inset 0 0 0 2px var(--navy, var(--pt-navy, #000075));
}

.pt-om-trigger--labeled.pt-om-trigger--outline:hover:not(:disabled)[b-mmft9jatzy],
.pt-om-trigger--labeled.pt-om-trigger--outline[aria-expanded="true"][b-mmft9jatzy] {
    background: color-mix(in srgb, var(--navy, var(--pt-navy, #000075)) 8%, transparent);
    box-shadow: inset 0 0 0 2px var(--navy, var(--pt-navy, #000075));
}

.pt-om-trigger > .pt-om-caret[b-mmft9jatzy] {
    font-size: 0.875rem;
}

.pt-om-backdrop[b-mmft9jatzy] {
    position: fixed;
    inset: 0;
    z-index: 1040;
    background: transparent;
}

/* In-flow fallback position — under the trigger, right-aligned. The script replaces it with a
   fixed top/right pair; see the note in the component. */
.pt-om-menu[b-mmft9jatzy] {
    position: absolute;
    top: calc(100% + 4px);
    right: 0;
    z-index: 1050;
    min-width: 13.5rem;
    display: flex;
    flex-direction: column;
    padding: 0.25rem 0;
    background: var(--surface-color, #ffffff);
    border: 1px solid var(--border-color, #e5e7eb);
    border-radius: 0;
    box-shadow: 0 8px 24px rgba(15, 23, 42, 0.14);
}

.pt-om-item[b-mmft9jatzy] {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    min-height: 44px;
    padding: 0 1rem;
    border: none;
    border-radius: 0;
    background: transparent;
    color: var(--text-primary, #1f2937);
    font: inherit;
    font-size: 0.9375rem;
    font-weight: 500;
    text-align: left;
    white-space: nowrap;
    cursor: pointer;
}

.pt-om-item > i[b-mmft9jatzy] {
    width: 1.25rem;
    font-size: 1.125rem;
    text-align: center;
    color: var(--text-secondary, #4b5563);
}

.pt-om-item:hover:not(:disabled)[b-mmft9jatzy],
.pt-om-item:focus-visible[b-mmft9jatzy] {
    background: var(--background-color, #f3f4f6);
    outline: none;
}

.pt-om-item:disabled[b-mmft9jatzy] {
    opacity: 0.5;
    cursor: not-allowed;
}

/* Tiled items: Crear's entries, each on its own tile. The caller's class (.action-icon-menu /
   -category / -item / -modifier in app.css) supplies the fill, square like everything else in this
   admin.

   The glyph is white unless that class says otherwise through --pt-om-tile-ink. #436 made Crear's
   Categoría the tree's light-blue tile, whose glyph is navy. A global rule can't simply set `color`
   here: this scoped rule outranks it on specificity (the class plus the scope attribute) and loads
   after app.css. A custom property is read, not fought over, so the fill's own class decides. */
.pt-om-item--tiled[b-mmft9jatzy] {
    min-height: 56px;
    gap: 0.875rem;
    padding: 0 1.25rem 0 0.75rem;
    font-size: 1rem;
    font-weight: 600;
}

.pt-om-tile[b-mmft9jatzy] {
    width: 40px;
    height: 40px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    border-radius: 0;
    color: var(--pt-om-tile-ink, #ffffff);
    font-size: 1.125rem;
}

/* #436 (Cam): "the Category icon needs to be centered vertically in the background square", and
   the Menu icon with it. Measured on the painted pixels, with the real icon font, every glyph sat 1px
   high: Bootstrap Icons seat a glyph at `vertical-align: -.125em` inside a line box, which is right
   beside words and wrong alone in a square. As a block with a 1em line, as #284 did for the icon-only
   buttons, the glyph's em box is what the flex centring centres. The tree's tiles and the Modificadores
   tab's carry the same rule, and the same contract. */
.pt-om-tile > i[b-mmft9jatzy] {
    display: block;
    line-height: 1;
}

.pt-om-tile > i[b-mmft9jatzy]::before {
    display: block;
    vertical-align: 0;
    line-height: 1;
}

/* The destructive group: red label AND red glyph, as in the mockup — the glyph alone in red would
   read as an icon choice, the label is what says "this deletes". #dc2626 is 4.8:1 on white. */
.pt-om-item--destructive[b-mmft9jatzy],
.pt-om-item--destructive > i[b-mmft9jatzy] {
    color: #dc2626;
}

.pt-om-item--destructive:hover:not(:disabled)[b-mmft9jatzy],
.pt-om-item--destructive:focus-visible[b-mmft9jatzy] {
    background: #fef2f2;
}

.pt-om-sep[b-mmft9jatzy] {
    height: 1px;
    margin: 0.25rem 0;
    background: var(--border-color, #e5e7eb);
}

@media (prefers-color-scheme: dark) {
    .pt-om-menu[b-mmft9jatzy] {
        box-shadow: 0 8px 24px rgba(0, 0, 0, 0.5);
    }

    /* #dc2626 is 3.9:1 on the dark surface; #f87171 is the red this admin's dark rules already use. */
    .pt-om-item--destructive[b-mmft9jatzy],
    .pt-om-item--destructive > i[b-mmft9jatzy] {
        color: #f87171;
    }

    .pt-om-item--destructive:hover:not(:disabled)[b-mmft9jatzy],
    .pt-om-item--destructive:focus-visible[b-mmft9jatzy] {
        background: rgba(248, 113, 113, 0.15);
    }
}
/* /Components/Util/RecentActionsMenu.razor.rz.scp.css */
/* #462 (Cam) — the Recent Actions popup, one stylesheet for every header that shows it (RecentActionsMenu.razor).

   Pedidos and Cuentas each carried a copy in a page-wide inline <style>, and the copies had drifted:
   - Cuentas' was drawn in the theme's tokens;
   - Pedidos' used fixed light colours, so its popup stayed white in dark mode;
   - only Pedidos styled the scrollbar, and only Cuentas gave cash entries their own chip.
   This is Cuentas' popup, with the scrollbar in the tokens. The time and the empty state move from --text-muted to
   --text-secondary: muted measured under AA in both themes (RecentActionsMenuContractTests). */

.updates-popup[b-qx08j6xufv] {
    position: fixed;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%) scale(0.9);
    z-index: 1050;
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    transition: all 0.3s ease;
    width: 90%;
    max-width: 800px;
    max-height: 80vh;
}

.updates-popup.show[b-qx08j6xufv] {
    opacity: 1;
    visibility: visible;
    pointer-events: auto;
    transform: translate(-50%, -50%) scale(1);
}

.popup-content[b-qx08j6xufv] {
    background: var(--surface-color);
    border-radius: 0;
    box-shadow: 0 20px 40px rgba(0, 0, 0, 0.3);
    overflow: hidden;
    display: flex;
    flex-direction: column;
    max-height: 80vh;
    border: 1px solid var(--border-color);
}

.popup-header[b-qx08j6xufv] {
    background: var(--background-color);
    padding: 1.5rem;
    display: flex;
    justify-content: space-between;
    align-items: center;
    border-bottom: 1px solid var(--border-color);
    flex-shrink: 0;
}

.popup-header h4[b-qx08j6xufv] {
    margin: 0;
    display: flex;
    align-items: center;
    gap: 0.75rem;
    font-size: 1.3rem;
    font-weight: 600;
    color: var(--text-primary);
}

.updates-list[b-qx08j6xufv] {
    flex: 1;
    overflow-y: auto;
    padding: 1rem;
    min-height: 200px;
    max-height: 60vh;
}

.updates-list[b-qx08j6xufv]::-webkit-scrollbar {
    width: 6px;
}

.updates-list[b-qx08j6xufv]::-webkit-scrollbar-track {
    background: var(--background-color);
}

.updates-list[b-qx08j6xufv]::-webkit-scrollbar-thumb {
    background: var(--text-muted);
}

.updates-list[b-qx08j6xufv]::-webkit-scrollbar-thumb:hover {
    background: var(--text-secondary);
}

/* #421 — BASELINE, not flex-start. The time and the type are chips with 0.2rem of padding and the message is bare
   text, so lining up their tops stood the message's words 4.2px above the chips' (Cam: "Fix vertical alignment of
   action text"). Baseline levels the text itself, and a message that wraps starts on the chips' line. Centring would
   level a one-line row and hang the chips halfway down a wrapped one. */
/* #502: the row wraps, so an entry's «Deshacer» that does not fit beside the words (a phone) drops to a line of its
   own instead of running out of the row. */
.update-item[b-qx08j6xufv] {
    padding: 0.75rem;
    border-bottom: 1px solid var(--border-color);
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem 1rem;
    align-items: baseline;
    transition: background-color 0.2s ease;
}

.update-item:hover[b-qx08j6xufv] {
    background-color: var(--background-color);
}

.update-item:last-child[b-qx08j6xufv] {
    border-bottom: none;
}

.timestamp[b-qx08j6xufv] {
    font-family: monospace;
    font-size: 0.875rem;
    color: var(--text-secondary);
    min-width: 70px;
    background: var(--background-color);
    padding: 0.2rem 0.5rem;
    border-radius: 0;
}

.type[b-qx08j6xufv] {
    font-weight: bold;
    min-width: 90px;
    font-size: 0.875rem;
    color: var(--text-primary);
    background: #d1ecf1;
    padding: 0.2rem 0.5rem;
    border-radius: 0;
    text-align: center;
}

.type-cash[b-qx08j6xufv] {
    background: #f8d7da;
    color: #721c24;
}

/* #502: the words keep 5rem. They break anywhere, so without a floor a «Deshacer» beside them would squeeze them to a
   few letters a line; with it the button drops to its own line first. An entry without one is unchanged down to a
   phone's width; narrower still, its words take the line under the chips rather than a sliver beside them. */
.message[b-qx08j6xufv] {
    flex: 1;
    min-width: 5rem;
    font-size: 0.875rem;
    word-break: break-word;
    color: var(--text-primary);
    line-height: 1.4;
}

/* #502 (Cam) — an entry's «Deshacer», at the row's end (on its own line too, when the row wraps). It keeps .btn's
   touch height (--pt-control-min-height) and joins the row's baseline (#421): its label reads on the line of the chips
   and the message's first words, and a message that wraps runs on below it. It needs no rule against shrinking or
   wrapping: the row wraps first, so the button always has a line wide enough for itself. */
.update-undo[b-qx08j6xufv] {
    margin-left: auto;
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
}

/* A refused undo's reason, under the entry's own words: the reopen panel's red pair, so the admin's failures read
   alike; AA in both themes (RecentActionsUndoContractTests). */
.update-undo-error[b-qx08j6xufv] {
    display: block;
    margin-top: 0.35rem;
    padding: 0.3rem 0.5rem;
    border-left: 3px solid #dc2626;
    background: #fef2f2;
    color: #991b1b;
    font-weight: 600;
}

.no-updates[b-qx08j6xufv] {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 3rem;
    color: var(--text-secondary);
    font-size: 1.1rem;
}

.no-updates i[b-qx08j6xufv] {
    font-size: 3rem;
    margin-bottom: 1rem;
    opacity: 0.5;
}

.modal-backdrop[b-qx08j6xufv] {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: rgba(0, 0, 0, 0.5);
    z-index: 1040;
}

@media (prefers-color-scheme: dark) {
    .type[b-qx08j6xufv] {
        background: #1a4d5e;
        color: #9ecfdb;
    }

    .type-cash[b-qx08j6xufv] {
        background: #5c2028;
        color: #f5c6cb;
    }

    .update-undo-error[b-qx08j6xufv] {
        background: #3a1f1f;
        color: #f87171;
    }
}

@media (prefers-reduced-motion: reduce) {
    .updates-popup[b-qx08j6xufv],
    .update-item[b-qx08j6xufv] {
        transition: none;
    }
}
/* /Components/Util/ViewToggle.razor.rz.scp.css */
/* ViewToggle — canonical two-state view switch.

   Scoped sidecar rather than app.css: nothing outside this component renders these classes, so
   there is no shared vocabulary to publish. Classes still carry the pt- prefix per the consistency
   guide ("follow the pt-/component-prefix rule for all new primitives").

   Geometry is 44x44 literal, NOT var(--touch-target-min) — that token is 40px (app.css:310),
   below the brand floor. Tabs' .lc-view-btn already hardcoded 44 for this reason; the menu's
   .mi-view-btn did too. Once .btn is repointed at --pt-control-min-height (plan step 2) this
   becomes a candidate to fold into .btn + a modifier. */

.pt-view-toggle[b-jhk6uk6txu] {
    display: inline-flex;
}

.pt-view-toggle-btn[b-jhk6uk6txu] {
    display: flex;
    align-items: center;
    justify-content: center;
    width: var(--pt-control-min-height);
    height: var(--pt-control-min-height);
    border: 2px solid var(--border-color);
    background: var(--surface-color);
    color: var(--text-muted);
    border-radius: 0;
    cursor: pointer;
    transition: all var(--transition-base, 0.2s ease);
}

/* Collapse the shared edge so the pair reads as one control, not two buttons. */
.pt-view-toggle-btn + .pt-view-toggle-btn[b-jhk6uk6txu] {
    border-left: none;
}

.pt-view-toggle-btn:hover:not(:disabled):not(.active)[b-jhk6uk6txu] {
    color: var(--text-primary);
    border-color: var(--pt-hover-border, var(--border-color));
}

.pt-view-toggle-btn.active[b-jhk6uk6txu] {
    background: var(--pt-navy, #000075);
    border-color: var(--pt-navy, #000075);
    color: #fff;
}

.pt-view-toggle-btn:disabled[b-jhk6uk6txu] {
    opacity: 0.55;
    cursor: not-allowed;
}

.pt-view-toggle-btn:focus-visible[b-jhk6uk6txu] {
    outline: 3px solid var(--pt-coral, #ec607e);
    outline-offset: -3px;
}

/* The active fill is navy in both themes; navy on a dark surface still clears contrast against
   white glyphs, and swapping it to coral here would put white-on-coral at 3.21:1 — the exact
   below-AA combination #46 is cleaning up across ~79 fills. */
@media (prefers-color-scheme: dark) {
    .pt-view-toggle-btn[b-jhk6uk6txu] {
        background: var(--surface-color);
        border-color: var(--border-color);
    }
}
/* /Components/Util/WaiterCallBadge.razor.rz.scp.css */
    /* STRETCHES to whatever holds it (#376 fourth pass). Cam: "the Bell icon highlight background
       area needs to all be clickable, currently only the icon is clickable." In the nav this box
       carries the label as well as the glyph now, so a fixed 48px would have left the label outside
       the hit area while the row's highlight ran underneath it — a control that looks wider than it
       is. Where nothing is passed it still measures 48px: the glyph box below sets the floor. */
    .waiter-badge-container[b-m0ggupwu85] {
        min-height: 48px;
        display: flex;
        align-items: center;
        justify-content: flex-start;
        flex: 1;
        min-width: 0;
        color: rgba(255, 255, 255, 0.7);
        cursor: pointer;
        transition: color 0.2s ease;
    }

    /* The glyph's own box, and the positioning context for the count. 48px keeps the bell on the
       nav's icon line — .drawer-calls starts at the 12px gutter, so the centre lands on 36, which
       is where every other nav glyph sits. */
    .waiter-badge-glyph[b-m0ggupwu85] {
        position: relative;
        width: 48px;
        height: 48px;
        display: flex;
        align-items: center;
        justify-content: center;
        flex-shrink: 0;
    }

    .waiter-badge-container:hover[b-m0ggupwu85] {
        color: #ffffff;
    }

    /* ::deep, because the <i> is PtIcon's own element and does not carry this component's scope
       attribute. Without it the rule matches nothing.

       Anchored on .waiter-badge-glyph, not on the container: the glyph moved into its own box when
       the container grew to hold the label (#376 fourth pass), so a `container > i` selector became
       a rule about a grandchild and would have quietly stopped matching — the bell would have
       dropped to the inherited size with nothing failing. */
    .waiter-badge-glyph[b-m0ggupwu85]  > i {
        font-size: 1.375rem;
    }

    /* A CIRCLE (#382). A deliberate departure from the brand's border-radius: 0, and Cam's call —
       the same exception the account avatar already carries. An alert is the one thing on this nav
       that is not part of its grid, and a round one reads as a notification rather than as another
       square in a column of squares.

       A FIXED width, not min-width, and no horizontal padding: `border-radius: 50%` on a box that
       is wider than it is tall is an ELLIPSE, and this badge's content changes width — "3" is one
       glyph and "9+" is two, so a min-width box would be a circle for most counts and an oval for
       the rest. The count is capped at "9+" by the markup, so 18px square holds every value it can
       ever show. */
    .waiter-call-count[b-m0ggupwu85] {
        position: absolute;
        top: 6px;
        right: 6px;
        width: 18px;
        height: 18px;
        background: var(--pt-coral, #ec607e);
        color: var(--pt-on-coral);
        border-radius: 50%;
        font-size: 0.625rem;
        font-weight: 600;
        display: flex;
        align-items: center;
        justify-content: center;
        border: 2px solid var(--pt-navy, #000075);
        padding: 0;
        box-sizing: border-box;
    }

    .waiter-call-count-pulse[b-m0ggupwu85] {
        animation: waiterCallCountPulse-b-m0ggupwu85 2s ease-in-out infinite;
    }

    @keyframes waiterCallCountPulse-b-m0ggupwu85 {
        0%, 100% { transform: scale(1); }
        50% { transform: scale(1.15); }
    }

    /* Dropdown */
    .waiter-call-overlay[b-m0ggupwu85] {
        position: fixed;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        z-index: 1099;
    }

    .waiter-call-dropdown[b-m0ggupwu85] {
        position: fixed;
        /* Set by the nav, which is the only thing that knows how wide it currently is — app.css
           declares --pt-call-dropdown-left on .drawer-expanded and overrides it on .active. This
           panel is a DOM descendant of that element, so the property reaches it even though
           `position: fixed` takes it out of flow. The 80px fallback is the collapsed value, and is
           what this rule used unconditionally before #376: expanded, the nav is 280 wide and the
           panel was opening on top of it. */
        left: var(--pt-call-dropdown-left, 80px);
        bottom: 120px;
        width: 320px;
        max-height: 400px;
        background: white;
        box-shadow: 0 8px 30px rgba(0, 0, 0, 0.15);
        z-index: 1100;
        display: flex;
        flex-direction: column;
        border: 2px solid var(--pt-navy, #000075);
    }

    .waiter-call-dropdown-header[b-m0ggupwu85] {
        display: flex;
        align-items: center;
        justify-content: space-between;
        padding: 0.75rem 1rem;
        border-bottom: 1px solid #e2e8f0;
        font-size: 0.8125rem;
        font-weight: 600;
        color: var(--pt-navy, #000075);
    }

    .waiter-call-dismiss-all[b-m0ggupwu85] {
        background: none;
        border: none;
        color: var(--pt-coral, #ec607e);
        font-size: 0.75rem;
        font-weight: 500;
        cursor: pointer;
        padding: 0.25rem 0.5rem;
        font-family: inherit;
    }

    .waiter-call-dismiss-all:hover[b-m0ggupwu85] {
        text-decoration: underline;
    }

    .waiter-call-empty[b-m0ggupwu85] {
        padding: 2rem 1rem;
        text-align: center;
        color: #94a3b8;
        font-size: 0.8125rem;
    }

    .waiter-call-list[b-m0ggupwu85] {
        overflow-y: auto;
        max-height: 340px;
    }

    .waiter-call-item[b-m0ggupwu85] {
        display: flex;
        align-items: center;
        justify-content: space-between;
        padding: 0.75rem 1rem;
        border-bottom: 1px solid #f1f5f9;
        transition: background 0.15s ease;
    }

    .waiter-call-item:hover[b-m0ggupwu85] {
        background: #f8fafc;
    }

    .waiter-call-info[b-m0ggupwu85] {
        display: flex;
        flex-direction: column;
        gap: 0.125rem;
    }

    .waiter-call-table[b-m0ggupwu85] {
        font-size: 0.875rem;
        font-weight: 600;
        color: #1e293b;
    }

    .waiter-call-waiter[b-m0ggupwu85] {
        font-size: 0.75rem;
        color: #64748b;
    }

    .waiter-call-time[b-m0ggupwu85] {
        font-size: 0.6875rem;
        color: #94a3b8;
    }

    .waiter-call-dismiss[b-m0ggupwu85] {
        background: none;
        border: none;
        color: #94a3b8;
        cursor: pointer;
        padding: 0.375rem;
        display: flex;
        align-items: center;
        justify-content: center;
        transition: color 0.15s ease;
    }

    .waiter-call-dismiss:hover[b-m0ggupwu85] {
        color: var(--pt-coral, #ec607e);
    }

    /* Dark mode */
    @media (prefers-color-scheme: dark) {
        .waiter-call-dropdown[b-m0ggupwu85] {
            background: #1e293b;
            border-color: #334155;
        }

        .waiter-call-dropdown-header[b-m0ggupwu85] {
            border-bottom-color: #334155;
            color: #f1f5f9;
        }

        .waiter-call-item[b-m0ggupwu85] {
            border-bottom-color: #334155;
        }

        .waiter-call-item:hover[b-m0ggupwu85] {
            background: #0f172a;
        }

        .waiter-call-table[b-m0ggupwu85] {
            color: #f1f5f9;
        }

        .waiter-call-waiter[b-m0ggupwu85] {
            color: #94a3b8;
        }
    }
/* /Layout/EmptyLayout.razor.rz.scp.css */
    .empty-layout[b-3ogeovuuf7] {
        min-height: 100vh;
        width: 100%;
        overflow-x: hidden;
    }
/* /Layout/MainLayout.razor.rz.scp.css */
/* =============================================================================
   BLAZOR CSS ISOLATION — SMOKE TEST
   =============================================================================
   This is the FIRST .razor.css in the WebApp. It exists to prove the isolation
   mechanism works end to end before any real CSS is migrated onto it:

     1. the compiler generates payTable.WebApp.styles.css with content
     2. index.html references it and it is actually served
     3. the generated scope attribute (b-xxxxxxxxxx) lands on MainLayout's own
        markup, so the rule below matches .app-layout

   DELIBERATELY VISUALLY INERT. It sets one custom property that nothing reads,
   so a failure at any step above changes nothing on screen — it just makes the
   probe below return empty. Nothing about the app's appearance depends on it.

   To verify on a deployed environment, in the browser console:

       getComputedStyle(document.querySelector('.app-layout'))
         .getPropertyValue('--pt-isolation-smoke')

   Expected: " ok". Empty string means isolation is NOT working — either the
   bundle was not generated, or index.html is not loading it, or the scope
   attribute did not match.

   Also worth checking in the same session:
       document.querySelector('.app-layout').attributes    -> expect a b-* attribute
       [...document.styleSheets].map(s => s.href)          -> expect the bundle

   REMOVE THIS FILE once real component CSS has migrated and the mechanism is
   proven — it has no purpose beyond the pilot. See #52.
   ============================================================================= */

.app-layout[b-htylljkzxu] {
    --pt-isolation-smoke: ok;
}

/* ---- migrated from the component's inline <style> ---- */
    /* App Layout with Sidebar */
    .app-layout[b-htylljkzxu] {
        display: flex;
        min-height: 100vh;
        background: var(--background-color);
    }
    
    /* Main Content Area */
    .main-content[b-htylljkzxu] {
        flex: 1;
        margin-left: 72px;
        padding: 1.5rem;
        padding-bottom: 2rem;
        height: 100vh;
        overflow-y: auto;
        overflow-x: hidden;
        display: flex;
        flex-direction: column;
        box-sizing: border-box;
    }
    
    /* Public Layout (Login, Register, etc.) */
    .public-layout[b-htylljkzxu] {
        min-height: 100vh;
    }
    
    /* Responsive adjustments */
    @media (max-width: 768px) {
        .main-content[b-htylljkzxu] {
            padding: 1rem;
        }
    }
/* /Pages/Cfd/CfdIdle.razor.rz.scp.css */
    .cfd-idle[b-8hkdb9x670] {
        width: 100%;
        height: 100%;
        display: flex;
        align-items: center;
        justify-content: center;
        position: relative;
        overflow: hidden;
    }

    .cfd-idle-content[b-8hkdb9x670] {
        display: flex;
        flex-direction: column;
        align-items: center;
        gap: 2rem;
        position: relative;
        z-index: 1;
    }

    /* ── Restaurant name ── */
    .idle-restaurant-name[b-8hkdb9x670] {
        font-size: 2.2rem;
        font-weight: 700;
        letter-spacing: 0.06em;
        color: var(--cfd-text-primary);
        text-align: center;
        max-width: 80%;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
        animation: cfd-fade-in-b-8hkdb9x670 2s ease-out;
    }

    /* ── Ambient glow ── */
    .idle-glow[b-8hkdb9x670] {
        position: absolute;
        width: 500px;
        height: 500px;
        border-radius: 50%;
        background: radial-gradient(circle, rgba(236, 96, 126, 0.08) 0%, transparent 70%);
        animation: cfd-glow-pulse-b-8hkdb9x670 6s ease-in-out infinite;
        pointer-events: none;
    }

    @keyframes cfd-glow-pulse-b-8hkdb9x670 {
        0%, 100% { transform: scale(1); opacity: 0.6; }
        50% { transform: scale(1.15); opacity: 1; }
    }

    /* ── Logo ── */
    .idle-logo[b-8hkdb9x670] {
        animation: cfd-logo-breathe-b-8hkdb9x670 8s ease-in-out infinite;
    }

    .idle-logo img[b-8hkdb9x670] {
        width: 320px;
        height: auto;
        filter: drop-shadow(0 0 40px rgba(236, 96, 126, 0.15));
    }

    /* Restaurant logo: larger, constrained to fit various aspect ratios */
    .idle-restaurant-logo img[b-8hkdb9x670] {
        width: auto;
        max-width: 400px;
        max-height: 240px;
        object-fit: contain;
        filter: drop-shadow(0 4px 20px rgba(0, 0, 0, 0.2));
    }

    @keyframes cfd-logo-breathe-b-8hkdb9x670 {
        0%, 100% { transform: scale(1); }
        50% { transform: scale(1.02); }
    }

    /* ── Welcome text ── */
    .idle-welcome[b-8hkdb9x670] {
        display: flex;
        align-items: center;
        gap: 1rem;
        animation: cfd-fade-in-b-8hkdb9x670 2s ease-out;
    }

    .welcome-text[b-8hkdb9x670] {
        font-size: 1.5rem;
        font-weight: 300;
        letter-spacing: 0.15em;
        text-transform: uppercase;
        color: var(--cfd-text-secondary);
    }

    .welcome-divider[b-8hkdb9x670] {
        font-size: 1.5rem;
        color: var(--cfd-accent);
        opacity: 0.6;
    }

    @keyframes cfd-fade-in-b-8hkdb9x670 {
        from { opacity: 0; transform: translateY(10px); }
        to { opacity: 1; transform: translateY(0); }
    }

    /* ── Animated line ── */
    .idle-line[b-8hkdb9x670] {
        width: 200px;
        height: 2px;
        background: var(--cfd-border);
        border-radius: 0;
        overflow: hidden;
    }

    .idle-line-fill[b-8hkdb9x670] {
        width: 60px;
        height: 100%;
        background: linear-gradient(90deg, transparent, var(--cfd-accent), transparent);
        animation: cfd-line-sweep-b-8hkdb9x670 4s ease-in-out infinite;
    }

    @keyframes cfd-line-sweep-b-8hkdb9x670 {
        0% { transform: translateX(-60px); }
        100% { transform: translateX(200px); }
    }

    /* ── Powered by footer ── */
    .idle-powered-by[b-8hkdb9x670] {
        position: absolute;
        bottom: 2rem;
        left: 50%;
        transform: translateX(-50%);
        font-size: 0.8rem;
        font-weight: 300;
        letter-spacing: 0.04em;
        color: var(--cfd-text-muted);
        opacity: 0.5;
    }

    .idle-powered-by strong[b-8hkdb9x670] {
        font-weight: 600;
        color: var(--cfd-accent);
        opacity: 1;
    }

    /* ── Clock ── */
    .idle-clock[b-8hkdb9x670] {
        position: absolute;
        bottom: 2rem;
        right: 2.5rem;
        font-size: 1.1rem;
        font-weight: 300;
        letter-spacing: 0.05em;
        color: var(--cfd-text-muted);
    }
/* /Pages/GroupViews.razor.rz.scp.css */
/* Chain Catalog P5.4 — «Vistas del grupo». Scoped, on the app.css tokens, so light and dark read alike (PG5d-7): the guide's
   data table is Inventario's and never darkens, so these tables are the page's own. The 44px and straight edges of its
   buttons are app.css's (.btn); the drill-down's count buttons, which are not .btn, take --pt-control-min-height here.
   Blocked has no app token pair (#379 kept Cancelado's red untokenised), so it is the page's: Bootstrap's danger pairs,
   7:1 in light and in dark. Each health's rule on the left is the page's too: the status inks are pale on a dark card, so
   the rules there are saturated, every one above 3:1 on the card. */
.gv[b-ktb1189j0r] {
    --gv-blocked-bg: #f8d7da;
    --gv-blocked-fg: #842029;
    --gv-blocked-border: #f1aeb5;
    --gv-blocked-rule: #842029;
    --gv-attention-rule: #856404;
    --gv-ok-rule: #155724;
    display: flex;
    flex-direction: column;
    gap: 1rem;
    max-width: 72rem;
}
@media (prefers-color-scheme: dark) {
    .gv[b-ktb1189j0r] {
        --gv-blocked-bg: #2c0b0e;
        --gv-blocked-fg: #ea868f;
        --gv-blocked-border: #842029;
        --gv-blocked-rule: #ea868f;
        --gv-attention-rule: #d4a017;
        --gv-ok-rule: #3fb37f;
    }
}

.gv-head[b-ktb1189j0r] {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
}
.gv-title[b-ktb1189j0r] {
    margin: 0;
    font-family: var(--pt-font-heading);
    color: var(--pt-navy-fg, #000075);
}
.gv-catalog[b-ktb1189j0r] {
    font-size: 1.0625rem;
    font-weight: 600;
    color: var(--text-primary, #1e293b);
}

.gv-state[b-ktb1189j0r] {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 0.75rem;
    padding: 1rem;
    background: var(--surface-color, #ffffff);
    color: var(--text-primary, #1e293b);
    border: 1px solid var(--pt-card-border, #cbd5e1);
}
.gv-state-text[b-ktb1189j0r] {
    margin: 0;
}
.gv-failed[b-ktb1189j0r] {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.75rem;
    padding: 0.75rem 1rem;
    background: var(--surface-color, #ffffff);
    color: var(--pt-field-invalid-text, #b91c1c);
    border: 1px solid var(--pt-card-border, #cbd5e1);
    border-left: 3px solid var(--pt-field-invalid, #ef4444);
    font-size: 0.875rem;
}
.gv-banner[b-ktb1189j0r] {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.75rem;
    padding: 0.75rem 1rem;
    background: var(--pt-status-pending-bg, #fff3cd);
    color: var(--pt-status-pending-fg, #856404);
    border: 1px solid var(--pt-status-pending-border, #ffe69c);
    font-size: 0.875rem;
}
.gv-banner-text[b-ktb1189j0r] {
    flex: 1 1 16rem;
}

.gv-consistency[b-ktb1189j0r] {
    display: flex;
    flex-direction: column;
    gap: 1rem;
}
.gv-section-title[b-ktb1189j0r] {
    margin: 0;
    font-size: 1.125rem;
    font-weight: 600;
    color: var(--pt-navy-fg, #000075);
}
.gv-note[b-ktb1189j0r] {
    margin: 0;
    font-size: 0.875rem;
    color: var(--text-secondary, #64748b);
}
.gv-muted[b-ktb1189j0r] {
    font-size: 0.875rem;
    color: var(--text-secondary, #64748b);
}

/* The three counts. Each health is a rule on the left in its own ink, and the words say it: colour never alone. */
.gv-summary[b-ktb1189j0r] {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 0.75rem;
}
.gv-tile[b-ktb1189j0r] {
    display: flex;
    flex-direction: column;
    gap: 0.125rem;
    padding: 0.75rem 1rem;
    background: var(--surface-color, #ffffff);
    border: 1px solid var(--pt-card-border, #cbd5e1);
    border-left-width: 4px;
}
.gv-tile-n[b-ktb1189j0r] {
    font-size: 1.5rem;
    font-weight: 700;
    line-height: 1.2;
    color: var(--text-primary, #1e293b);
}
.gv-tile-label[b-ktb1189j0r] {
    font-size: 0.8125rem;
    color: var(--text-secondary, #64748b);
}
.gv-tile.gv-blocked[b-ktb1189j0r],
.gv-member.gv-blocked[b-ktb1189j0r] {
    border-left-color: var(--gv-blocked-rule);
}
.gv-tile.gv-attention[b-ktb1189j0r],
.gv-member.gv-attention[b-ktb1189j0r] {
    border-left-color: var(--gv-attention-rule);
}
.gv-tile.gv-ok[b-ktb1189j0r],
.gv-member.gv-ok[b-ktb1189j0r] {
    border-left-color: var(--gv-ok-rule);
}

/* A member: a card, its health in a chip and on its left rule. */
.gv-member[b-ktb1189j0r] {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
    padding: 1rem;
    background: var(--surface-color, #ffffff);
    color: var(--text-primary, #1e293b);
    border: 1px solid var(--pt-card-border, #cbd5e1);
    border-left-width: 4px;
}
.gv-member-head[b-ktb1189j0r] {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
}
.gv-member-name[b-ktb1189j0r] {
    margin: 0;
    font-size: 1.0625rem;
    font-weight: 600;
    color: var(--pt-navy-fg, #000075);
}
.gv-chips[b-ktb1189j0r] {
    display: flex;
    flex-wrap: wrap;
    gap: 0.375rem;
}
.gv-chip[b-ktb1189j0r] {
    font-size: 0.75rem;
    font-weight: 600;
    padding: 0.125rem 0.5rem;
    border: 1px solid;
    white-space: nowrap;
}
.gv-chip-muted[b-ktb1189j0r],
.gv-unknown .gv-chip-health[b-ktb1189j0r] {
    background: var(--pt-status-done-bg, #e9ecef);
    color: var(--pt-status-done-fg, #41464b);
    border-color: var(--pt-status-done-border, #ced4da);
}
.gv-blocked .gv-chip-health[b-ktb1189j0r] {
    background: var(--gv-blocked-bg);
    color: var(--gv-blocked-fg);
    border-color: var(--gv-blocked-border);
}
.gv-attention .gv-chip-health[b-ktb1189j0r] {
    background: var(--pt-status-pending-bg, #fff3cd);
    color: var(--pt-status-pending-fg, #856404);
    border-color: var(--pt-status-pending-border, #ffe69c);
}
.gv-ok .gv-chip-health[b-ktb1189j0r] {
    background: var(--pt-status-ready-bg, #d4edda);
    color: var(--pt-status-ready-fg, #155724);
    border-color: var(--pt-status-ready-border, #b7e0c6);
}

.gv-reasons[b-ktb1189j0r],
.gv-list[b-ktb1189j0r] {
    margin: 0;
    padding-left: 1.25rem;
    font-size: 0.875rem;
    color: var(--text-primary, #1e293b);
}
.gv-blocking[b-ktb1189j0r] {
    font-weight: 600;
}

.gv-facts[b-ktb1189j0r] {
    margin: 0;
    display: flex;
    flex-wrap: wrap;
    gap: 0.25rem 1.5rem;
    font-size: 0.875rem;
}
.gv-fact[b-ktb1189j0r] {
    display: flex;
    flex-wrap: wrap;
    gap: 0.375rem;
}
.gv-fact-wide[b-ktb1189j0r] {
    flex: 1 1 100%;
}
.gv-fact dt[b-ktb1189j0r] {
    font-weight: 600;
    color: var(--text-secondary, #64748b);
}
.gv-fact dd[b-ktb1189j0r] {
    margin: 0;
    color: var(--text-primary, #1e293b);
    overflow-wrap: anywhere;
}

.gv-part[b-ktb1189j0r] {
    display: flex;
    flex-direction: column;
    gap: 0.375rem;
}
.gv-part-title[b-ktb1189j0r] {
    margin: 0;
    font-size: 0.875rem;
    font-weight: 600;
    color: var(--text-secondary, #64748b);
}

/* The counts and the drill-down: small tables in their own scroll box, so a phone scrolls them and never the page. */
.gv-tablewrap[b-ktb1189j0r] {
    max-width: 100%;
    overflow-x: auto;
    border: 1px solid var(--pt-card-border, #cbd5e1);
}
.gv-table[b-ktb1189j0r] {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.875rem;
    color: var(--text-primary, #1e293b);
}
.gv-table th[b-ktb1189j0r],
.gv-table td[b-ktb1189j0r] {
    padding: 0.375rem 0.75rem;
    text-align: left;
    vertical-align: middle;
    border-bottom: 1px solid var(--pt-card-border, #cbd5e1);
}
.gv-table thead th[b-ktb1189j0r] {
    background: var(--pt-subhead-bg, #fafbfd);
    font-weight: 600;
    white-space: nowrap;
}
.gv-table tbody th[b-ktb1189j0r] {
    font-weight: 600;
    white-space: nowrap;
}
.gv-table .gv-num[b-ktb1189j0r] {
    text-align: right;
}
.gv-count[b-ktb1189j0r] {
    min-width: var(--pt-control-min-height, 44px);
    min-height: var(--pt-control-min-height, 44px);
    padding: 0 0.5rem;
    background: transparent;
    color: var(--pt-navy-fg, #000075);
    border: 1px solid var(--pt-navy-fg, #000075);
    border-radius: 0;
    font-weight: 600;
}
.gv-count:hover[b-ktb1189j0r],
.gv-count:focus-visible[b-ktb1189j0r] {
    background: var(--pt-navy-fg, #000075);
    color: var(--surface-color, #ffffff);
}
.gv-zero[b-ktb1189j0r] {
    color: var(--text-secondary, #64748b);
}
.gv-drill[b-ktb1189j0r] {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 0.5rem;
    padding: 0.75rem;
    border: 1px solid var(--pt-card-border, #cbd5e1);
    border-left: 3px solid var(--pt-navy-fg, #000075);
}
.gv-drill > .gv-tablewrap[b-ktb1189j0r] {
    align-self: stretch;
}
.gv-drill-head[b-ktb1189j0r] {
    align-self: stretch;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
}
.gv-drill-title[b-ktb1189j0r] {
    font-weight: 600;
    color: var(--pt-navy-fg, #000075);
}

.gv-actions[b-ktb1189j0r] {
    display: flex;
    flex-wrap: wrap;
    gap: 0.75rem;
}

/* A phone: the actions stack at the same full width; a long location name wraps inside its button, icon on the first line. */
@media (max-width: 576px) {
    .gv-actions .gv-action[b-ktb1189j0r] {
        display: block;
        flex: 1 1 100%;
        text-align: center;
        white-space: normal;
    }
}

/* P5.6: the two views' tab bar (PG5d-9). Straight edges, 44px, the active tab underlined in navy. */
.gv-tabs[b-ktb1189j0r] {
    display: flex;
    gap: 0.25rem;
    border-bottom: 1px solid var(--pt-card-border, #cbd5e1);
    overflow-x: auto;
}
.gv-tab[b-ktb1189j0r] {
    min-height: var(--pt-control-min-height, 44px);
    padding: 0.5rem 1rem;
    border: 0;
    border-bottom: 3px solid transparent;
    border-radius: 0;
    background: transparent;
    color: var(--text-secondary, #64748b);
    font-weight: 600;
    white-space: nowrap;
}
.gv-tab-active[b-ktb1189j0r] {
    color: var(--pt-navy-fg, #000075);
    border-bottom-color: var(--pt-navy-fg, #000075);
}
/* /Pages/Menu.razor.rz.scp.css */
/* The Menu Manager page (Menu.razor). Moved here from the page's inline <style> by #461 (Igor, 2026-09-19: an inline
   <style> never stays; component-specific CSS is isolated). The rules are unchanged except where #461 says otherwise.

   Isolation: the header, the banner and the panel's place are this page's own markup and take its scope. The tabs, their
   strip and the panel's look are app.css's shared folder tabs (#611 B), so nothing here reaches into PtTabbar. */

.menu-page[b-tabw812ali] {
    display: flex;
    flex-direction: column;
    height: 100%;
}

.menu-page .header[b-tabw812ali] {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 1rem 1.5rem;
    background: var(--surface-color);
    border-radius: 0;
    margin-bottom: 1rem;
    box-shadow: var(--shadow-sm);
    border: 1px solid var(--border-color);
    border-bottom: 3px solid var(--pt-coral, #ec607e);
}

.menu-page .header h3[b-tabw812ali] {
    margin: 0;
    font-size: 1.5rem;
    font-weight: 700;
    color: var(--text-primary);
    display: flex;
    align-items: center;
    gap: 0.75rem;
}

.menu-page .header h3 i[b-tabw812ali] {
    color: var(--pt-navy-fg);
}

/* #611 B — the tabs and the panel are the admin's folder tabs (app.css .pt-folder-tabs / .pt-folder-tab / .pt-folder-panel),
   shared with Mesas. This page had the skin first; it lived here until #611 lifted it, values unchanged. menu-tab and
   menu-content stay on the markup as hooks (tests select on them), with no look of their own. */

.menu-content[b-tabw812ali] {
    flex: 1;
}

.no-active-menu-banner[b-tabw812ali] {
    display: flex;
    align-items: center;
    gap: 1rem;
    padding: 1rem 1.5rem;
    background: #dc3545;
    color: white;
    border-radius: 0;
    margin-bottom: 1rem;
    box-shadow: var(--shadow-sm);
}

.no-active-menu-banner i[b-tabw812ali] {
    font-size: 1.75rem;
    flex-shrink: 0;
}

.no-active-menu-banner .banner-text[b-tabw812ali] {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
}

.no-active-menu-banner .banner-text strong[b-tabw812ali] {
    font-size: 1.1rem;
}

.no-active-menu-banner .banner-text span[b-tabw812ali] {
    font-size: 0.9rem;
    opacity: 0.95;
}

/* #461 — the "Responsive" block went: below 768px it stacked the tabs into a column (flex-direction: column, a full
   border on each, the active tab's merge hidden), which is what Cam's card replaces with the scrolling row. Its last
   rule, .menu-content's border-radius: 0, repeated the base rule above. */

/* Chain Catalog P3.2 - the group menu could not be opened. Text on --text-primary (12.0:1 light on the red-100
   fill, 11.3:1 dark); the red is the 4px edge only, since --pt-destructive-fg on that fill is 3.95:1, under 4.5:1
   for text. */
.gm-failed[b-tabw812ali] {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    margin-bottom: 1rem;
    padding: 0.75rem 1rem;
    background: var(--pt-destructive-bg, #fee2e2);
    border-left: 4px solid var(--pt-destructive-fg, #dc2626);
    color: var(--text-primary, #1e293b);
}
