/* Design System & CSS Variables — AcopioUCV brand tokens (ver marca/marca.md) */
:root {
    --bg: #F7F5F2;
    --surface: #FFFFFF;
    --s2: #F2F0ED;
    --sidebar: #111827;
    --side2: #0D1520;

    /* Brand accent */
    --amber: #F59E0B;
    --amber-d: #D97706;
    --amber-bg: #FEF3C7;

    /* Semantic colors */
    --red: #EF4444;
    --red-bg: #FEF2F2;
    --green: #10B981;
    --grn-bg: #ECFDF5;
    --blue: #6366F1;
    --blu-bg: #EEF2FF;

    /* Text */
    --t1: #111827;
    --t2: #374151;
    --t3: #6B7280;
    --t4: #9CA3AF;

    --bdr: #E5E7EB;

    --sh: 0 1px 3px rgba(0,0,0,.05), 0 1px 2px rgba(0,0,0,.04);
    --sh-md: 0 4px 12px rgba(0,0,0,.08);
    --sh-lg: 0 16px 40px rgba(0,0,0,.12);

    --r: 12px;
    --r-sm: 8px;
    --r-xs: 6px;
    --r-xl: 18px;

    --transition-smooth: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
}

/* Base resets */
* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

body {
    background-color: var(--bg);
    color: var(--t1);
    font-family: 'Inter', sans-serif;
    overflow-x: hidden;
    min-height: 100vh;
}

h1, h2, h3, h4, h5, h6 {
    font-family: 'Space Grotesk', sans-serif;
}

/* App Container */
.app-container {
    max-width: 1440px;
    margin: 0 auto;
    padding: 24px;
    display: flex;
    flex-direction: column;
    gap: 24px;
}

/* App Header / Topnav */
.app-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 14px 24px;
    background: var(--sidebar);
    border-top: 3px solid var(--amber);
    border-radius: var(--r);
    box-shadow: var(--sh-md);
}

.logo-area {
    display: flex;
    align-items: center;
    gap: 14px;
}

.logo-icon {
    width: 38px;
    height: 38px;
    color: var(--amber);
    background: rgba(245, 158, 11, 0.12);
    border: 1px solid rgba(245, 158, 11, 0.25);
    padding: 6px;
    border-radius: var(--r-sm);
}

.logo-text h1 {
    font-size: 22px;
    font-weight: 700;
    letter-spacing: -0.5px;
    line-height: 1;
    color: #fff;
}

.logo-text h1 span {
    color: var(--amber);
}

.logo-text p {
    font-size: 10px;
    color: rgba(255, 255, 255, 0.45);
    font-weight: 700;
    letter-spacing: 1.8px;
    text-transform: uppercase;
    margin-top: 4px;
}

.system-status {
    display: flex;
    align-items: center;
    gap: 10px;
    background: rgba(255, 255, 255, 0.05);
    padding: 8px 14px;
    border-radius: 50px;
    border: 1px solid rgba(255, 255, 255, 0.08);
}

/* Radar / pulse motif (marca.md §7) */
.radar-dot {
    position: relative;
    width: 10px;
    height: 10px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

.radar-core {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--amber);
    box-shadow: 0 0 6px var(--amber);
}

.radar-ring {
    position: absolute;
    inset: 0;
    border-radius: 50%;
    border: 1.5px solid var(--amber);
    animation: radar-expand 2.2s ease-out infinite;
    opacity: 0.55;
}

.radar-ring-2 {
    animation-delay: 1.1s;
}

@keyframes radar-expand {
    0% { transform: scale(1); opacity: 0.55; }
    100% { transform: scale(3.2); opacity: 0; }
}

.status-label {
    font-family: 'Space Grotesk', sans-serif;
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.3px;
    color: #fff;
}

/* Layout: barra lateral de Carga Rápida + contenido principal */
.app-body {
    display: flex;
    align-items: flex-start;
    gap: 24px;
}

.main-content-area {
    flex: 1;
    min-width: 0;
}

.quick-sidebar {
    width: 300px;
    flex-shrink: 0;
    background: var(--sidebar);
    border-radius: var(--r);
    box-shadow: var(--sh-md);
    padding: 20px;
    display: flex;
    flex-direction: column;
    gap: 14px;
    position: sticky;
    top: 24px;
}

.quick-sidebar-header {
    display: flex;
    align-items: center;
    gap: 12px;
}

.quick-sidebar-icon {
    width: 36px;
    height: 36px;
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--amber);
    color: var(--sidebar);
    border-radius: var(--r-sm);
}

.quick-sidebar-header h3 {
    color: #fff;
    font-size: 15px;
    font-weight: 700;
}

.quick-sidebar-header p {
    color: rgba(255, 255, 255, 0.45);
    font-size: 11px;
    margin-top: 2px;
}

/* Botón de cerrar y FAB de Carga Rápida: solo existen visualmente en móvil
   (ver @media 900px más abajo) — display:none acá para que nunca aparezcan
   en desktop, donde #quick-sidebar ya está siempre visible como barra
   lateral. */
.quick-sidebar-close {
    display: none;
    margin-left: auto;
    flex-shrink: 0;
}

.quick-fab {
    display: none;
    position: fixed;
    right: 18px;
    z-index: 85;
    width: 56px;
    height: 56px;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    border: none;
    background: var(--amber);
    color: #fff;
    box-shadow: 0 8px 20px rgba(245, 158, 11, 0.4);
    cursor: pointer;
    transition: var(--transition-smooth);
}
.quick-fab:hover { background: var(--amber-d); }
.quick-fab .lucide { width: 26px; height: 26px; }

.quick-form { display: flex; flex-direction: column; gap: 10px; }

.quick-sidebar .form-group label { color: rgba(255, 255, 255, 0.55); }
.quick-sidebar .form-group input,
.quick-sidebar .form-group select {
    background: rgba(255, 255, 255, 0.05);
    border-color: rgba(255, 255, 255, 0.14);
    color: #fff;
}
.quick-sidebar .form-group input::placeholder { color: rgba(255, 255, 255, 0.35); }
.quick-sidebar .form-group select option { color: var(--t1); }

.select-with-button {
    display: flex;
    gap: 8px;
    align-items: center;
}
.select-with-button select { flex: 1; min-width: 0; }
.select-with-button .btn-icon { width: 36px; height: 36px; flex-shrink: 0; }

/* Buscador de personas (voluntarios) — Carga Manual y Carga Rápida, mismo
   patrón visual que el buscador de items (.item-search-*). */
.person-search-wrap { position: relative; flex: 1; min-width: 0; }
.person-search-wrap .person-search-input { width: 100%; }
.person-search-results {
    display: none;
    position: absolute;
    top: calc(100% + 4px);
    left: 0;
    right: 0;
    background: var(--surface);
    border: 1px solid var(--bdr);
    border-radius: var(--r-sm);
    box-shadow: var(--sh-lg);
    max-height: 220px;
    overflow-y: auto;
    z-index: 50;
}
.person-search-option {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: 8px 10px;
    cursor: pointer;
    font-size: 13px;
}
.person-search-option:hover { background: var(--s2); }
.person-search-sub { color: var(--t4); font-size: 11px; }
.person-search-empty {
    padding: 8px 10px;
    font-size: 13px;
    color: var(--t4);
}

.quick-sidebar .person-search-results {
    background: var(--side2);
    border-color: rgba(255, 255, 255, 0.14);
}
.quick-sidebar .person-search-option:hover { background: rgba(255, 255, 255, 0.08); }
.quick-sidebar .person-search-name { color: #fff; }
.quick-sidebar .person-search-sub { color: rgba(255, 255, 255, 0.45); }
.quick-sidebar .person-search-empty { color: rgba(255, 255, 255, 0.45); }

.quick-sidebar .item-row {
    background: var(--side2);
    border-color: rgba(255, 255, 255, 0.08);
    grid-template-columns: 1fr 64px 30px;
}
.quick-sidebar .item-row:hover {
    background: rgba(255, 255, 255, 0.04);
    border-color: rgba(255, 255, 255, 0.2);
}
.quick-sidebar .item-row input {
    background: rgba(255, 255, 255, 0.05);
    border-color: rgba(255, 255, 255, 0.14);
    color: #fff;
}
.quick-sidebar .item-row input::placeholder {
    color: rgba(255, 255, 255, 0.35);
}
.quick-sidebar .item-search-results {
    background: var(--side2);
    border-color: rgba(255, 255, 255, 0.14);
}
.quick-sidebar .item-search-option:hover { background: rgba(255, 255, 255, 0.08); }
.quick-sidebar .item-search-name { color: #fff; }
.quick-sidebar .item-search-empty { color: rgba(255, 255, 255, 0.45); }
.quick-sidebar .btn-delete-row { color: rgba(255, 255, 255, 0.4); }
.quick-sidebar .btn-delete-row:hover { color: var(--red); }

@media (max-width: 900px) {
    .app-body { flex-direction: column; }
    .quick-sidebar { width: 100%; position: static; }
    /* align-items:flex-start de .app-body no estira los hijos en el eje
       cruzado — en flex-direction:column ese eje es el ancho, así que sin
       esto .main-content-area se dimensiona por fit-content en vez de
       ocupar el ancho disponible. */
    .main-content-area { width: 100%; }
}

/* Stats Panel Grid */
.stats-container {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
    gap: 16px;
}

.stat-card {
    background: var(--surface);
    border: 1px solid var(--bdr);
    border-radius: var(--r);
    padding: 16px;
    display: flex;
    justify-content: space-between;
    align-items: center;
    cursor: pointer;
    box-shadow: var(--sh);
    transition: var(--transition-smooth);
}

.stat-card:hover {
    border-color: var(--amber);
    transform: translateY(-2px);
    box-shadow: var(--sh-md);
}

.stat-info {
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.stat-title {
    font-family: 'Space Grotesk', sans-serif;
    font-size: 10px;
    color: var(--t3);
    font-weight: 700;
    letter-spacing: 1px;
    text-transform: uppercase;
}

.stat-value {
    font-family: 'JetBrains Mono', monospace;
    font-size: 26px;
    font-weight: 600;
    letter-spacing: -1px;
    color: var(--t1);
}

.stat-icon-wrapper {
    width: 40px;
    height: 40px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: var(--r-sm);
    background: var(--s2);
    border: 1px solid var(--bdr);
}

.stat-icon-wrapper.all { color: var(--t2); }
.stat-icon-wrapper.pending { color: var(--blue); background: var(--blu-bg); border-color: transparent; }
.stat-icon-wrapper.processing { color: var(--blue); background: var(--blu-bg); border-color: transparent; }
.stat-icon-wrapper.extracted { color: var(--amber-d); background: var(--amber-bg); border-color: transparent; }
.stat-icon-wrapper.verified { color: var(--green); background: var(--grn-bg); border-color: transparent; }
.stat-icon-wrapper.error { color: var(--red); background: var(--red-bg); border-color: transparent; }

/* Main Workspace Grid */
.main-content {
    display: grid;
    grid-template-columns: 350px 1fr;
    gap: 24px;
    align-items: start;
}

@media (max-width: 1024px) {
    .main-content {
        grid-template-columns: 1fr;
    }
}

/* Cards & Panels */
.card {
    background: var(--surface);
    border: 1px solid var(--bdr);
    border-radius: var(--r);
    padding: 24px;
    box-shadow: var(--sh);
}

.card-header {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-bottom: 20px;
}

.card-header i {
    color: var(--amber);
    width: 22px;
    height: 22px;
}

.card-header h2 {
    font-family: 'Space Grotesk', sans-serif;
    font-size: 16px;
    font-weight: 700;
    color: var(--t1);
}

/* Model Selector (OCR test toggle) */
.model-selector {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    flex-wrap: wrap;
    margin-bottom: 16px;
    padding: 10px 12px;
    background: var(--s2);
    border: 1px solid var(--bdr);
    border-radius: var(--r-sm);
}

.model-selector-label {
    font-size: 12px;
    color: var(--t3);
    white-space: nowrap;
}

.model-selector-options {
    display: flex;
    gap: 4px;
    background: var(--surface);
    border: 1px solid var(--bdr);
    border-radius: var(--r-sm);
    padding: 3px;
}

.model-option {
    border: none;
    background: transparent;
    color: var(--t3);
    font-family: 'Space Grotesk', sans-serif;
    font-size: 12px;
    font-weight: 700;
    padding: 5px 12px;
    border-radius: 99px;
    cursor: pointer;
    transition: var(--transition-smooth);
}

.model-option:hover {
    color: var(--t1);
}

.model-option.active {
    background: var(--amber);
    color: #fff;
    box-shadow: 0 2px 8px rgba(245, 158, 11, 0.35);
}

.model-badge {
    font-family: 'Space Grotesk', sans-serif;
    font-size: 11px;
    font-weight: 700;
    color: var(--amber-d);
    background: var(--amber-bg);
    padding: 3px 10px;
    border-radius: 999px;
    white-space: nowrap;
}

.reprocess-model-hint {
    font-size: 10px;
    font-weight: 500;
    opacity: 0.8;
    margin-left: 4px;
}

/* Upload Panel Styles */
.upload-zone {
    border: 2px dashed var(--bdr);
    border-radius: var(--r-sm);
    padding: 40px 20px;
    text-align: center;
    cursor: pointer;
    transition: var(--transition-smooth);
    background: var(--s2);
}

.upload-zone:hover, .upload-zone.dragover {
    border-color: var(--amber);
    background: var(--amber-bg);
}

.file-input-hidden {
    display: none;
}

.upload-prompt {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 12px;
}

.upload-main-icon {
    width: 48px;
    height: 48px;
    color: var(--t4);
    transition: var(--transition-smooth);
}

.upload-zone:hover .upload-main-icon {
    color: var(--amber-d);
    transform: translateY(-4px);
}

.upload-prompt h3 {
    font-size: 16px;
    font-weight: 600;
    color: var(--t1);
}

.upload-prompt p {
    font-size: 13px;
    color: var(--t3);
}

.file-types-hint {
    font-size: 11px;
    color: var(--t3);
    background: var(--surface);
    padding: 4px 8px;
    border-radius: 4px;
    border: 1px solid var(--bdr);
}

.upload-progress-container {
    margin-top: 20px;
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.progress-info {
    display: flex;
    justify-content: space-between;
    font-size: 12px;
    font-weight: 500;
    color: var(--t2);
}

.progress-bar-wrapper {
    background: var(--s2);
    height: 6px;
    border-radius: 3px;
    overflow: hidden;
}

.progress-bar {
    background: var(--amber);
    width: 0%;
    height: 100%;
    border-radius: 3px;
    transition: width 0.2s ease-out;
}

/* Dashboard Panel / Table Controls */
.dashboard-panel {
    display: flex;
    flex-direction: column;
    gap: 20px;
    min-height: 520px;
}

.dashboard-controls {
    display: flex;
    gap: 16px;
    align-items: center;
    flex-wrap: wrap;
}

/* Filtro de categoría de la pestaña Personas — pills tipo tab, igual
   patrón visual que los stat-card clicables de Confirmar Comandas. */
.voluntarios-filter-bar {
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
    margin-top: 12px;
}
.voluntarios-filter-bar .btn.active {
    background: var(--t1);
    border-color: var(--t1);
    color: #fff;
}

.voluntarios-filter-bar select {
    background: var(--surface);
    border: 1.5px solid var(--bdr);
    color: var(--t1);
    padding: 6px 10px;
    border-radius: var(--r-sm);
    font-family: inherit;
    font-size: 13px;
}

/* Selector de nivel de precisión (Entrega Personal / Comanda Completa) en
   "Registrar Comanda" — mismo patrón visual que .voluntarios-filter-bar,
   deliberadamente NO .tab-bar/.tab-btn (esas se vuelven position:fixed en
   móvil, ver @media max-width:900px más abajo). */
.manual-subtab-bar {
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
    margin: 16px 0 20px;
}
.manual-subtab-bar .btn.active {
    background: var(--t1);
    border-color: var(--t1);
    color: #fff;
}

.search-box {
    position: relative;
    flex: 1;
    min-width: 250px;
}

.search-box i {
    position: absolute;
    left: 14px;
    top: 50%;
    transform: translateY(-50%);
    width: 18px;
    height: 18px;
    color: var(--t4);
}

.search-box input {
    width: 100%;
    background: var(--surface);
    border: 1.5px solid var(--bdr);
    color: var(--t1);
    padding: 10px 14px 10px 42px;
    border-radius: var(--r-sm);
    font-family: inherit;
    font-size: 14px;
    transition: var(--transition-smooth);
}

.search-box input:focus {
    outline: none;
    border-color: var(--amber);
    box-shadow: 0 0 0 3px rgba(245, 158, 11, 0.12);
}

.filter-controls {
    display: flex;
    align-items: center;
    gap: 10px;
}

.filter-controls label {
    font-size: 13px;
    color: var(--t3);
}

.filter-controls select {
    background: var(--surface);
    border: 1.5px solid var(--bdr);
    color: var(--t1);
    padding: 10px 14px;
    border-radius: var(--r-sm);
    font-family: inherit;
    font-size: 14px;
    outline: none;
    cursor: pointer;
    transition: var(--transition-smooth);
}

.filter-controls select:focus {
    border-color: var(--amber);
    box-shadow: 0 0 0 3px rgba(245, 158, 11, 0.12);
}

/* Buttons (marca.md §6.1) */
.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    padding: 9px 18px;
    border-radius: 99px;
    font-family: 'Space Grotesk', sans-serif;
    font-size: 13px;
    font-weight: 700;
    cursor: pointer;
    transition: var(--transition-smooth);
    border: 1px solid transparent;
}

.btn-icon {
    width: 36px;
    height: 36px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: var(--surface);
    border: 1px solid var(--bdr);
    color: var(--t2);
    border-radius: var(--r-sm);
    cursor: pointer;
    transition: var(--transition-smooth);
}
.btn-icon:hover {
    background: var(--amber-bg);
    color: var(--amber-d);
    border-color: var(--amber);
}

.btn-refresh {
    background: var(--surface);
    border: 1px solid var(--bdr);
    color: var(--t2);
}
.btn-refresh:hover {
    background: var(--s2);
}

.btn-secondary {
    background: transparent;
    border: 1px solid var(--bdr);
    color: var(--t2);
}
.btn-secondary:hover {
    background: var(--s2);
}

.btn-primary {
    background: var(--amber);
    color: #fff;
    box-shadow: 0 4px 15px rgba(245, 158, 11, 0.25);
}
.btn-primary:hover {
    background: var(--amber-d);
    transform: translateY(-1px);
}

.btn-success {
    background: var(--green);
    color: #fff;
    box-shadow: 0 4px 12px rgba(16, 185, 129, 0.25);
}
.btn-success:hover {
    background: #0ea271;
    transform: translateY(-1px);
}

.btn-danger {
    background: var(--red-bg);
    border: 1px solid rgba(239, 68, 68, 0.3);
    color: var(--red);
}
.btn-danger:hover {
    background: var(--red);
    border-color: var(--red);
    color: #fff;
}

.btn-warning {
    background: transparent;
    border: 1px solid rgba(217, 119, 6, 0.35);
    color: var(--amber-d);
}
.btn-warning:hover {
    background: var(--amber-bg);
    border-color: var(--amber-d);
}

.btn-sm {
    padding: 6px 12px;
    font-size: 12px;
}

/* Comandas Table */
.table-container {
    overflow-x: auto;
    width: 100%;
}

.comandas-table {
    width: 100%;
    border-collapse: collapse;
    text-align: left;
    font-size: 14px;
}

.comandas-table th {
    background: var(--s2);
    border-bottom: 2px solid var(--bdr);
    padding: 12px 16px;
    font-weight: 700;
    color: var(--t4);
    font-family: 'Space Grotesk', sans-serif;
    font-size: 10px;
    text-transform: uppercase;
    letter-spacing: 0.8px;
}

.comandas-table td {
    padding: 14px 16px;
    border-bottom: 1px solid var(--bdr);
    color: var(--t2);
}

/* Solo el color de fondo cambia en :hover — transition:all (var(--transition-smooth))
   en un <tr> de una tabla border-collapse:collapse, dentro de un
   .table-container con scroll horizontal, promueve la fila a su propia capa
   de composición en cada repintado y en algunos navegadores móviles (visto
   en Personas UCV) corrompe visualmente el render de esa fila con bandas de
   ruido horizontal ("rayas"). Acotar la transition a background-color evita
   la promoción de capa innecesaria. */
.comandas-table tbody tr {
    transition: background-color 0.2s ease;
}

.comandas-table tbody tr:hover {
    background: #FAFAF8;
}

.loading-placeholder {
    text-align: center;
    padding: 40px !important;
    color: var(--t3);
}

.pagination-controls {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 16px;
    padding-top: 4px;
}

.pagination-controls span {
    color: var(--t3);
    font-size: 13px;
    font-weight: 600;
}

/* Status Badges (marca.md §6.5, semántica §8) */
.status-badge {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 4px 10px;
    border-radius: 50px;
    font-family: 'Space Grotesk', sans-serif;
    font-size: 11px;
    font-weight: 700;
    text-transform: uppercase;
}

.status-badge.pending { color: var(--blue); background: var(--blu-bg); }
.status-badge.processing { color: var(--blue); background: var(--blu-bg); }
.status-badge.extracted { color: var(--amber-d); background: var(--amber-bg); }
.status-badge.verified { color: var(--green); background: var(--grn-bg); }
.status-badge.exported { color: var(--green); background: var(--grn-bg); }
.status-badge.error { color: var(--red); background: var(--red-bg); }
.status-badge.por_completar { color: var(--amber-d); background: var(--amber-bg); }
.status-badge.completada { color: var(--green); background: var(--grn-bg); }
.status-badge.fallida { color: var(--red); background: var(--red-bg); }

/* Animation Utility classes */
.spin {
    animation: anime-spin 1.5s linear infinite;
}
@keyframes anime-spin {
    0% { transform: rotate(0deg); }
    100% { transform: rotate(360deg); }
}

/* Modal Styling. Los 9 .modal-overlay de la app quedan montados en el DOM
   con display:flex incluso cerrados (solo opacity:0 los oculta, ver
   CLAUDE.md) — así que backdrop-filter en la regla base significaba 9 capas
   de blur a viewport completo (100vw/100vh) siempre activas y siempre
   resampleando el contenido de abajo, aunque ningún modal estuviera abierto.
   En Android Chrome eso es una carga de composición GPU altísima y
   constante durante cualquier scroll de la app, y backdrop-filter tiene
   bugs de corrupción visual bien documentados en ese motor bajo esa carga
   (visto como "rayas"/estática al hacer scroll en listas largas). Mover el
   blur a .open (solo activo mientras el modal realmente se ve) lo evita. */
.modal-overlay {
    position: fixed;
    top: 0;
    left: 0;
    width: 100vw;
    height: 100vh;
    background: rgba(10, 15, 30, 0.45);
    z-index: 100;
    display: flex;
    align-items: center;
    justify-content: center;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.3s ease;
}

.modal-overlay.open {
    opacity: 1;
    pointer-events: auto;
    backdrop-filter: blur(4px);
}

.modal-card {
    background: var(--surface);
    border-radius: var(--r-xl);
    width: 92%;
    max-width: 1200px;
    height: 88vh;
    display: flex;
    flex-direction: column;
    box-shadow: var(--sh-lg);
    overflow: hidden;
    transform: scale(0.95);
    transition: transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
    /* .modal-overlay es flex (row) y TODO modal queda montado en el DOM con
       display:flex incluso cerrado (solo opacity:0 lo oculta, ver
       .modal-overlay más arriba) — sin min-width:0, el valor por defecto
       min-width:auto de un flex item impide que .modal-card encoja por
       debajo del ancho mínimo de su contenido. En un teléfono angosto eso
       fuerza a .modal-card (y por lo tanto a TODA la página, incluso con
       el modal cerrado) a ensancharse más allá del viewport, aunque nadie
       esté viendo ese modal en ese momento. */
    min-width: 0;
}

.modal-overlay.open .modal-card {
    transform: scale(1);
}

.modal-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 18px 24px;
    border-bottom: 1px solid var(--bdr);
    background: var(--surface);
}

.modal-title-area {
    display: flex;
    align-items: center;
    gap: 12px;
}

.modal-title-area i {
    color: var(--amber-d);
}

.modal-title-area h2 {
    font-family: 'Space Grotesk', sans-serif;
    font-size: 18px;
    font-weight: 700;
    color: var(--t1);
}

.btn-close {
    background: transparent;
    border: none;
    color: var(--t3);
    cursor: pointer;
    transition: var(--transition-smooth);
    padding: 6px;
    border-radius: 50%;
}
.btn-close:hover {
    background: var(--red-bg);
    color: var(--red);
}

.modal-body-split {
    display: grid;
    grid-template-columns: 1fr 1.2fr;
    flex: 1;
    overflow: hidden;
}

@media (max-width: 800px) {
    .modal-body-split {
        grid-template-columns: 1fr;
        /* Sin esto, las 2 filas implícitas quedan en "auto" (tamaño por
           contenido): la imagen, sin altura acotada, crece a su tamaño
           natural y empuja el formulario fuera del modal (recortado por el
           overflow:hidden de este contenedor, e inalcanzable). Con una fila
           fija para la imagen y 1fr para el resto, cada mitad scrollea
           dentro de sí misma (.image-scroll-wrapper / .details-form-container
           ya tienen su propio overflow) en vez de desbordar el modal. */
        grid-template-rows: 34vh 1fr;
    }
    .image-viewer-container,
    .details-form-container {
        min-height: 0;
    }
}

/* Modal Left: Image Viewer — se mantiene oscuro (variante dashboard del manual §6.7) */
.image-viewer-container {
    background: var(--sidebar);
    position: relative;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

/* Mismo motivo que .modal-overlay.open arriba: este bloque vive dentro del
   modal de detalle de comanda, montado siempre en el DOM — sin acotar el
   blur a cuando el modal está realmente abierto, es otra capa de blur
   siempre activa de más. */
.viewer-controls {
    position: absolute;
    top: 14px;
    right: 14px;
    display: flex;
    gap: 8px;
    z-index: 10;
    background: rgba(255, 255, 255, 0.08);
    padding: 6px;
    border-radius: var(--r-sm);
    border: 1px solid rgba(255, 255, 255, 0.1);
}

.modal-overlay.open .viewer-controls {
    backdrop-filter: blur(6px);
}

.viewer-controls .btn-icon {
    background: transparent;
    border: none;
    color: rgba(255, 255, 255, 0.8);
}
.viewer-controls .btn-icon:hover {
    background: rgba(245, 158, 11, 0.15);
    color: var(--amber);
}

.image-scroll-wrapper {
    flex: 1;
    overflow: auto;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 20px;
    cursor: grab;
}
.image-scroll-wrapper:active {
    cursor: grabbing;
}

.zoomable-image {
    max-width: 100%;
    max-height: 100%;
    object-fit: contain;
    border-radius: var(--r-sm);
    box-shadow: 0 4px 20px rgba(0,0,0,0.4);
    transform-origin: center;
    transition: transform 0.2s ease-out;
}

/* Tira de miniaturas para elegir entre las varias imágenes de una comanda
   (foto OCR original + foto de entrega, que ahora conviven). flex-shrink:0
   para que .image-scroll-wrapper (flex:1) sea quien ceda espacio, nunca esta
   tira; overflow-x:auto para que en móvil (320-375px) las miniaturas
   scrolleen horizontalmente en vez de romper el layout del modal. */
.image-thumbnails {
    flex-shrink: 0;
    display: flex;
    gap: 8px;
    padding: 10px 14px;
    overflow-x: auto;
    background: rgba(0, 0, 0, 0.2);
}

.image-thumbnail {
    flex-shrink: 0;
    min-width: 0;
    width: 64px;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
    background: transparent;
    border: 2px solid transparent;
    border-radius: var(--r-sm);
    padding: 3px;
    cursor: pointer;
}

.image-thumbnail img {
    width: 100%;
    height: 48px;
    object-fit: cover;
    border-radius: 4px;
    display: block;
}

.image-thumbnail-label {
    font-size: 10px;
    color: rgba(255, 255, 255, 0.7);
    text-align: center;
    white-space: nowrap;
}

.image-thumbnail.active {
    border-color: var(--amber);
}
.image-thumbnail.active .image-thumbnail-label {
    color: var(--amber);
}

/* Modal Right: Details Form & Items */
.details-form-container {
    padding: 24px;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    gap: 24px;
    background: var(--surface);
}

.form-section {
    background: var(--s2);
    border: 1px solid var(--bdr);
    border-radius: var(--r-sm);
    padding: 20px;
}

.form-section h3 {
    font-family: 'Space Grotesk', sans-serif;
    font-size: 13px;
    font-weight: 700;
    color: var(--amber-d);
    margin-bottom: 16px;
    text-transform: uppercase;
    letter-spacing: 0.8px;
}

.section-title-action {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 16px;
}
.section-title-action h3 {
    margin-bottom: 0;
}

.form-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 16px;
}

.form-group {
    display: flex;
    flex-direction: column;
    gap: 6px;
    /* .form-group es a la vez ítem de grid (.form-grid) y, en filas como el
       teléfono partido, contenedor de un flex anidado (.phone-field-row). Sin
       min-width:0 un ítem de grid/flex no encoge por debajo del ancho
       "preferido" de su contenido (aquí ~317px, por el <select> de prefijo +
       el <input> de 7 dígitos) — en un teléfono angosto eso infla la pista
       del grid completo (todos los .form-group de esa fila, no solo el del
       teléfono) más allá del viewport, arrastrando a toda la página con él. */
    min-width: 0;
}

.form-grid .full-width {
    grid-column: span 2;
}

/* Grid de fotos de una ubicación (modales Editar y Confirmar). Columnas
   responsivas con auto-fill en vez de un número fijo, para que en 320-375px
   quepan 2 columnas angostas sin desbordar el .form-group full-width que ya
   hereda min-width:0. */
.ubic-imagenes-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(90px, 1fr));
    gap: 8px;
    margin-top: 8px;
}

.ubic-imagen-thumb {
    position: relative;
    aspect-ratio: 1;
    border-radius: var(--r-sm);
    overflow: hidden;
    border: 1.5px solid var(--bdr);
}

.ubic-imagen-thumb img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

.ubic-imagen-delete {
    position: absolute;
    top: 4px;
    right: 4px;
    background: rgba(0, 0, 0, 0.55);
    color: #fff;
    border: none;
    border-radius: var(--r-sm);
    padding: 4px;
    cursor: pointer;
}
.ubic-imagen-delete:hover {
    background: var(--danger, #dc2626);
}

/* Grupo de checkboxes tipo "pill" (días/horarios/zonas de un conductor).
   flex-wrap en vez de una grilla de columnas fijas: en un viewport angosto
   las opciones simplemente pasan a la siguiente línea en vez de desbordar
   horizontalmente (mismo criterio anti-overflow móvil de CLAUDE.md, sin
   necesitar min-width:0 porque no hay ningún hijo de ancho intrínseco fijo). */
.checkbox-pill-group {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

.checkbox-pill-group label {
    display: flex;
    align-items: center;
    gap: 5px;
    font-size: 12.5px;
    font-weight: 500;
    color: var(--t2);
    background: var(--surface);
    border: 1.5px solid var(--bdr);
    border-radius: var(--r-sm);
    padding: 5px 10px;
    cursor: pointer;
}

.checkbox-pill-group input[type="checkbox"] {
    width: auto;
    margin: 0;
}

.form-grid-subheader {
    margin-top: 10px;
    padding-bottom: 4px;
    border-bottom: 1px solid var(--bdr);
    color: var(--amber-d);
    font-family: 'Space Grotesk', sans-serif;
    font-size: 12px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.6px;
}

.form-group label {
    font-size: 12px;
    font-weight: 500;
    color: var(--t3);
}

.form-group input, .form-group textarea, .form-group select {
    background: var(--surface);
    border: 1.5px solid var(--bdr);
    color: var(--t1);
    padding: 8px 12px;
    border-radius: var(--r-sm);
    font-family: inherit;
    font-size: 14px;
    transition: var(--transition-smooth);
}

.form-group input:focus, .form-group textarea:focus, .form-group select:focus {
    outline: none;
    border-color: var(--amber);
    box-shadow: 0 0 0 3px rgba(245, 158, 11, 0.12);
}

/* Campo bloqueado (ej. Nombre/Apellido/Teléfono del modal de alta de
   Conductor cuando la cédula ya pertenece a una Person existente, ver
   _pqaSetIdentityFieldsLocked en app.js) — el disabled nativo del navegador
   por sí solo no se nota lo suficiente, así que se oscurece a propósito
   contra el fondo blanco de .form-group input. */
.form-group input:disabled, .form-group textarea:disabled, .form-group select:disabled {
    background: var(--bdr);
    color: var(--t3);
    cursor: not-allowed;
}

/* Campo de teléfono partido: <select> de prefijo + <input> de 7 dígitos.
   min-width:0 porque este bloque también se usa como ítem flex directo de
   `.contacto-row` (filas dinámicas del modal Confirmar Ubicación) sin un
   `.form-group` de por medio que ya lo aportara — sin esto, al ser a la vez
   ítem flex y contenedor flex con un <select> de ancho fijo, no encoge por
   debajo de su ancho preferido en un teléfono angosto (mismo bug de
   min-width:0 documentado en CLAUDE.md, reaparecido en un contexto sin
   `.form-group`). */
.phone-field-row {
    display: flex;
    gap: 8px;
    min-width: 0;
}

.phone-field-row select {
    flex: 0 0 92px;
}

.phone-field-row input {
    flex: 1;
    min-width: 0;
}

/* OCR Alert Box */
.ocr-error-alert {
    background: var(--red-bg);
    border: 1px solid rgba(239, 68, 68, 0.25);
    color: var(--red);
    border-radius: var(--r-sm);
    padding: 12px;
    margin-bottom: 20px;
    display: flex;
    gap: 12px;
    align-items: flex-start;
}
.ocr-error-alert i {
    flex-shrink: 0;
    width: 20px;
    height: 20px;
}
.ocr-error-alert p {
    font-size: 13px;
    margin-top: 4px;
    color: var(--t2);
}

/* Items List Component */
.items-table-header {
    display: grid;
    grid-template-columns: 1fr 80px 50px;
    gap: 10px;
    padding: 8px 12px;
    background: var(--s2);
    border-radius: var(--r-sm);
    font-family: 'Space Grotesk', sans-serif;
    font-size: 10px;
    font-weight: 700;
    color: var(--t4);
    text-transform: uppercase;
    letter-spacing: 0.8px;
    margin-bottom: 10px;
}

.items-list-container {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.item-row {
    display: grid;
    grid-template-columns: 1fr 80px 50px;
    gap: 10px;
    align-items: center;
    background: var(--surface);
    border: 1px solid var(--bdr);
    border-left: 3px solid transparent;
    padding: 6px 8px;
    border-radius: var(--r-sm);
    transition: var(--transition-smooth);
}
.item-row:hover {
    border-color: var(--t4);
    background: var(--s2);
}
.item-row.conf-media { border-left-color: var(--amber); }
.item-row.conf-baja { border-left-color: var(--red); }
.item-row.conf-media, .item-row.conf-baja { cursor: help; }

/* Celda del nombre: contenedor relativo para colgar el badge de % de confianza
   o el dropdown del buscador de items */
.item-name-cell { position: relative; display: block; }
.item-name-cell .item-name,
.item-name-cell .item-name-search { width: 100%; }
.item-name-cell.has-conf .item-name { padding-right: 48px; }

/* Buscador de items (catálogo products/inventory) — carga manual y edición de
   comandas manuales */
.item-search-results {
    display: none;
    position: absolute;
    top: calc(100% + 4px);
    left: 0;
    right: 0;
    background: var(--surface);
    border: 1px solid var(--bdr);
    border-radius: var(--r-sm);
    box-shadow: var(--sh-lg);
    max-height: 220px;
    overflow-y: auto;
    z-index: 50;
}
.item-search-option {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 10px;
    padding: 8px 10px;
    cursor: pointer;
    font-size: 13px;
}
.item-search-option:hover { background: var(--s2); }
.item-search-measure { color: var(--t4); font-size: 12px; }
.item-search-disp {
    font-family: 'JetBrains Mono', monospace;
    font-size: 11px;
    color: var(--green);
    white-space: nowrap;
}
.item-search-disp.sin-stock, td.sin-stock { color: var(--red); }
.item-search-empty {
    padding: 8px 10px;
    font-size: 13px;
    color: var(--t4);
}

/* Badge numérico de confianza del OCR (ítems y cabecera) */
.conf-chip,
.field-conf {
    font-family: 'JetBrains Mono', monospace;
    font-size: 10px;
    font-weight: 600;
    line-height: 1;
    padding: 3px 6px;
    border-radius: 99px;
    white-space: nowrap;
}
.conf-chip {
    position: absolute;
    right: 6px;
    top: 50%;
    transform: translateY(-50%);
    pointer-events: none;
}
.field-conf {
    display: inline-block;
    margin-left: 8px;
    vertical-align: middle;
}
.conf-chip.conf-alta,
.field-conf.conf-alta { background: var(--grn-bg); color: var(--green); }
.conf-chip.conf-media,
.field-conf.conf-media { background: var(--amber-bg); color: var(--amber-d); }
.conf-chip.conf-baja,
.field-conf.conf-baja { background: var(--red-bg); color: var(--red); }

.item-row input {
    background: var(--surface);
    border: 1px solid var(--bdr);
    color: var(--t1);
    padding: 6px 10px;
    border-radius: var(--r-xs);
    font-family: inherit;
    font-size: 13px;
}
.item-row .item-qty {
    font-family: 'JetBrains Mono', monospace;
}
.item-row input:focus {
    outline: none;
    border-color: var(--amber);
}

.btn-delete-row {
    background: transparent;
    border: none;
    color: var(--t4);
    cursor: pointer;
    transition: var(--transition-smooth);
    display: flex;
    justify-content: center;
    align-items: center;
}
.btn-delete-row:hover {
    color: var(--red);
}

/* Filas dinámicas de contacto (modal Confirmar Ubicación) — mismo espíritu
   que .item-row pero con 3 campos (nombre/teléfono partido/rol) en vez de 2. */
.contacto-row {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    align-items: center;
    background: var(--surface);
    border: 1px solid var(--bdr);
    padding: 8px;
    border-radius: var(--r-sm);
}
.contacto-row .contacto-nombre { flex: 1 1 160px; }
.contacto-row .phone-field-row { flex: 1 1 180px; }
.contacto-row .contacto-rol { flex: 1 1 120px; }
.contacto-row input, .contacto-row select {
    background: var(--surface);
    border: 1.5px solid var(--bdr);
    color: var(--t1);
    padding: 8px 12px;
    border-radius: var(--r-sm);
    font-family: inherit;
    font-size: 14px;
}

/* Modal Footer */
.modal-footer {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 16px 24px;
    border-top: 1px solid var(--bdr);
    background: var(--surface);
    flex-shrink: 0;
}

/* <form class="manual-form"> es hijo directo de .modal-card en todos los
   modales de alta/edición — sin este selector es un <form> de bloque
   normal (sin flex propio), así que el flex:1/overflow-y:auto de
   .modal-form-body no tenía ningún efecto: el form entero (body + footer)
   crecía a su altura de contenido y se salía del modal, dejando el footer
   (con los botones de guardar/cancelar) recortado por el overflow:hidden
   de .modal-card e inalcanzable. Acotado a ".modal-card >" para no tocar
   el mismo <form class="manual-form"> cuando se usa fuera de un modal
   (Carga Manual, Registrar Ubicación). */
.modal-card > .manual-form {
    display: flex;
    flex-direction: column;
    flex: 1;
    min-height: 0;
    overflow: hidden;
}

.footer-left-actions, .footer-right-actions {
    display: flex;
    gap: 12px;
}

/* Toasts / Notifications (marca.md §6.8) */
.toast-container {
    position: fixed;
    /* env() es 0 en dispositivos sin barra de navegación por gestos, así que
       esto no cambia nada fuera de móvil. */
    bottom: calc(24px + env(safe-area-inset-bottom));
    right: 24px;
    display: flex;
    flex-direction: column;
    gap: 10px;
    z-index: 1000;
}

.toast {
    background: var(--t1);
    border-left: 4px solid var(--blue);
    color: #fff;
    padding: 14px 20px;
    border-radius: var(--r-sm);
    box-shadow: var(--sh-lg);
    display: flex;
    align-items: center;
    gap: 12px;
    font-size: 14px;
    min-width: 300px;
    transform: translateY(20px);
    opacity: 0;
    transition: all 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275);
}

.toast.show {
    transform: translateY(0);
    opacity: 1;
}

.toast.success { border-left-color: var(--green); }
.toast.info { border-left-color: var(--blue); }
.toast.warning { border-left-color: var(--amber); }
.toast.error { border-left-color: var(--red); }

/* Mobile Enhancements */
@media (max-width: 600px) {
    .modal-card {
        width: 100%;
        height: 100vh;
        height: 100dvh; /* excluye barras de navegación/URL dinámicas del móvil */
        border-radius: 0;
        max-width: 100vw;
    }
    .form-grid {
        grid-template-columns: 1fr;
    }
    .form-grid .full-width {
        grid-column: span 1;
    }
    .items-table-header {
        display: none;
    }
    .item-row {
        grid-template-columns: 1fr auto;
        grid-template-areas: 'name del' 'qty del';
        gap: 6px;
    }
    .item-name-cell { grid-area: name; }
    .item-name { grid-area: name; }
    .item-qty { grid-area: qty; }
    .btn-delete-row {
        grid-area: del;
        height: 100%;
        display: flex;
        align-items: center;
        justify-content: center;
    }
    .mobile-upload-actions {
        flex-direction: column;
    }
    .modal-footer {
        flex-direction: column;
        gap: 12px;
        padding: 16px;
        /* Empuja los botones por encima de las barras de navegación por
           gestos/botones del sistema, que de otro modo los tapan y los
           dejan inalcanzables (env() es 0 si el dispositivo no la usa). */
        padding-bottom: calc(16px + env(safe-area-inset-bottom));
        flex-shrink: 0;
    }
    .footer-left-actions, .footer-right-actions {
        width: 100%;
        justify-content: center;
        gap: 8px;
    }
    .footer-left-actions button, .footer-right-actions button {
        flex: 1;
        padding: 10px 8px;
        font-size: 12px;
    }
    .modal-title-area {
        flex-wrap: wrap;
    }
}

/* ============================================================================
   Rediseño en 3 pestañas (Carga Manual / Tomar Fotos / Confirmar)
   ============================================================================ */

/* Barra de pestañas */
.tab-bar {
    display: flex;
    gap: 8px;
    padding: 6px;
    margin: 0 0 22px;
    background: var(--surface);
    border: 1px solid var(--bdr);
    border-radius: 99px;
    box-shadow: var(--sh);
    flex-wrap: wrap;
}
.tab-btn {
    flex: 1;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    padding: 10px 16px;
    border: none;
    background: transparent;
    color: var(--t3);
    font-family: 'Space Grotesk', sans-serif;
    font-weight: 700;
    font-size: 13px;
    border-radius: 99px;
    cursor: pointer;
    transition: var(--transition-smooth);
    white-space: nowrap;
}
.tab-btn:hover { color: var(--t1); background: var(--s2); }
.tab-btn.active { color: #fff; background: var(--amber); }
.tab-btn.active:hover { background: var(--amber-d); }
.tab-btn .lucide { width: 16px; height: 16px; }
.tab-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 20px;
    height: 20px;
    padding: 0 6px;
    border-radius: 99px;
    background: var(--red);
    color: #fff;
    font-family: 'JetBrains Mono', monospace;
    font-size: 11px;
    font-weight: 600;
}
.tab-btn.active .tab-badge { background: rgba(0,0,0,.25); }

/* Páginas */
.tab-page { display: none; animation: pg-in 0.2s ease; }
.tab-page.active { display: block; }
@keyframes pg-in { from { opacity: 0; transform: translateY(5px); } to { opacity: 1; transform: none; } }

/* Layout de la carga manual */
.manual-layout { display: flex; flex-direction: column; gap: 22px; max-width: 900px; margin: 0 auto; }
.manual-form .form-grid { margin-bottom: 18px; }
.manual-submit-row { display: flex; justify-content: flex-end; margin-top: 20px; }

/* Chip de usuario logueado + botón de logout (header) */
.user-chip {
    display: flex; align-items: center; gap: 8px; margin-left: 16px;
    padding: 6px 10px; border-radius: 99px; background: var(--s2);
    color: var(--t2); font-size: 13px;
}
.user-chip .lucide { width: 16px; height: 16px; color: var(--amber); flex-shrink: 0; }
.user-chip .btn-icon { width: 24px; height: 24px; padding: 0; flex-shrink: 0; }
.user-chip span {
    max-width: 160px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Envoltorio de los 4 botones de acción del header (perfil/OCR/ubicaciones/
   logout). display:contents en desktop = sin efecto alguno, sus hijos siguen
   siendo ítems flex directos de .user-chip exactamente como antes de este
   wrapper existir. Solo se activa como fila propia en el header fijo de
   móvil, ver @media 900px más abajo. */
.header-actions { display: contents; }

/* ============================================================================
   Rediseño de navegación móvil (header fijo + tab-bar inferior + FAB)
   ============================================================================
   A partir de 900px (el mismo corte donde .app-body ya pasa a columna, ver
   @media 900px arriba) la navegación de escritorio deja de tener sentido: el
   header ya no entra en una fila y la barra lateral de Carga Rápida termina
   ocupando toda la pantalla como un bloque más al principio. Este bloque la
   reemplaza por un patrón de app móvil: header fijo arriba (nombre del
   sistema + nombre de usuario + los 4 botones, grandes), tab-bar fija abajo
   (solo iconos, para que las 4 opciones quepan en una sola línea) y un botón
   flotante "+" que abre Carga Rápida a pantalla completa en vez de tenerla
   siempre expandida. Ambas barras fijas restan su alto + env(safe-area-*)
   correspondiente del contenido para no taparlo, y consideran la barra de
   gestos/botones de navegación del sistema (env(safe-area-inset-bottom)) en
   vez de asumir que el viewport termina en el borde físico de la pantalla. */
:root {
    --mobile-header-h: 108px;
    --mobile-tabbar-h: 58px;
}

@media (max-width: 900px) {
    /* --- Header fijo -------------------------------------------------------
       .logo-area/.system-status/.user-chip pasan a display:contents para que
       sus hijos (nombre del sistema, nombre de usuario, .header-actions) se
       vuelvan ítems directos del grid de .app-header y cada uno se pueda
       ubicar en su propia área — fila 1: nombre (izquierda) + usuario
       (derecha); fila 2: los 4 botones, ocupando todo el ancho. */
    .app-header {
        position: fixed;
        top: 0; left: 0; right: 0;
        z-index: 90;
        display: grid;
        grid-template-columns: auto 1fr;
        grid-template-areas:
            "name    user"
            "actions actions";
        align-items: center;
        row-gap: 10px;
        border-radius: 0;
        padding: 10px 14px;
        padding-top: calc(10px + env(safe-area-inset-top));
    }
    .logo-area, .system-status, .user-chip { display: contents; }
    .logo-icon { display: none; }
    .logo-text { grid-area: name; }
    .logo-text p { display: none; } /* "Gestión de Comandas": se sacrifica por espacio */
    .radar-dot, .status-label { display: none; } /* "Sistema Conectado": reemplazado por este header compacto */
    .user-chip > .lucide { display: none; }
    #user-chip-name {
        grid-area: user;
        justify-self: end;
        max-width: none;
        color: #fff;
        font-weight: 700;
        font-size: 14px;
    }
    .header-actions {
        grid-area: actions;
        display: flex;
        gap: 8px;
    }
    .header-actions .btn-icon {
        flex: 1;
        width: auto;
        height: 48px;
        border-radius: var(--r-sm);
        background: rgba(255, 255, 255, 0.06);
        border: 1px solid rgba(255, 255, 255, 0.12);
        color: rgba(255, 255, 255, 0.85);
    }
    .header-actions .btn-icon:hover {
        background: rgba(245, 158, 11, 0.18);
        color: var(--amber);
        border-color: var(--amber);
    }
    .header-actions .btn-icon .lucide { width: 20px; height: 20px; }

    /* Despeja el header fijo para el resto del contenido. */
    .app-container {
        padding-top: calc(var(--mobile-header-h) + env(safe-area-inset-top));
    }

    /* --- Tab-bar inferior fija, solo iconos ---------------------------------
       Las 3 barras de pestañas de la app (#tab-bar, #ocr-tab-bar,
       #ubicaciones-tab-bar) comparten la clase .tab-bar — un solo cambio
       cubre las tres. Cada .view-container muestra únicamente la suya (las
       otras dos quedan en display:none), así que nunca hay dos fijas a la
       vez pisándose. */
    .tab-bar {
        position: fixed;
        left: 0; right: 0; bottom: 0;
        z-index: 90;
        margin: 0;
        border-radius: 0;
        border: none;
        border-top: 1px solid var(--bdr);
        box-shadow: 0 -6px 20px rgba(0, 0, 0, .08);
        flex-wrap: nowrap;
        padding: 6px 6px calc(6px + env(safe-area-inset-bottom));
    }
    .tab-btn { padding: 8px 2px; gap: 2px; }
    .tab-btn .tab-label { display: none; }
    .tab-btn .lucide { width: 22px; height: 22px; }

    /* Deja ver el final de cada vista por encima de la tab-bar fija. */
    .view-container {
        padding-bottom: calc(var(--mobile-tabbar-h) + env(safe-area-inset-bottom));
    }

    /* --- FAB de Carga Rápida ------------------------------------------------ */
    .quick-fab {
        bottom: calc(var(--mobile-tabbar-h) + env(safe-area-inset-bottom) + 16px);
    }
    .quick-fab:not(.fab-hidden) { display: flex; }

    /* --- Carga Rápida como panel de pantalla completa -----------------------
       Reemplaza el stack "barra lateral arriba de todo el contenido" que
       tenía antes (.app-body en columna, ver @media 900px arriba): oculta
       por defecto (transform fuera de pantalla), el FAB la abre agregando
       .open. */
    .quick-sidebar {
        position: fixed;
        inset: 0;
        z-index: 95;
        width: 100%;
        max-width: 100%;
        border-radius: 0;
        transform: translateY(100%);
        transition: transform 0.25s ease;
        overflow-y: auto;
        padding-bottom: calc(20px + env(safe-area-inset-bottom));
    }
    .quick-sidebar.open { transform: translateY(0); }
    .quick-sidebar-close { display: flex; color: rgba(255, 255, 255, 0.7); }
    .quick-sidebar-close:hover { background: rgba(255, 255, 255, 0.1); color: #fff; }
}

/* Overlay de login */
.login-card { max-width: 380px; width: 92%; }
.voluntario-card { max-width: 520px; width: 92%; }
/* height:auto (diálogo compacto, centrado) solo en desktop — en móvil
   height:auto pisaba el height:100dvh + scroll interno que .modal-card ya
   trae en el bloque de 600px de más abajo (mismo selector .modal-card,
   pero .login-card/.voluntario-card definidos después "ganaban" el
   height sin importar el viewport). Con un formulario largo (ej. Nueva
   Persona con "¿Es ucevista?" marcado, que agrega el campo Carrera) la
   tarjeta crecía más alta que la pantalla y el footer (Guardar/Cancelar)
   quedaba inalcanzable. */
@media (min-width: 601px) {
    .login-card, .voluntario-card { height: auto; }
}
.login-form { padding: 20px 24px 24px; display: flex; flex-direction: column; gap: 14px; }

/* Cuerpo del formulario dentro de un modal chico (ej. Nueva Persona): mismo
   padding que .details-form-container, para que los campos no queden pegados
   a los bordes del modal. flex+overflow-y para que, si el contenido no cabe
   en los 88vh de .modal-card, este cuerpo scrollee solo — el header y el
   footer (con los botones de guardar/cancelar) quedan siempre visibles. */
.modal-form-body { padding: 24px; flex: 1; min-height: 0; overflow-y: auto; }
.login-error {
    color: var(--red); font-size: 13px; background: var(--red-bg);
    border-radius: var(--r-xs); padding: 8px 10px;
}

.aprobado-form-header { display: flex; justify-content: space-between; align-items: center; gap: 10px; margin-bottom: 12px; }
.aprobado-select-row { display: flex; gap: 10px; align-items: center; }
.aprobado-select-row select {
    flex: 1;
    background: var(--surface);
    border: 1.5px solid var(--bdr);
    color: var(--t1);
    padding: 8px 12px;
    border-radius: var(--r-sm);
    font-family: inherit;
    font-size: 14px;
    transition: var(--transition-smooth);
}
.aprobado-select-row select:focus {
    outline: none;
    border-color: var(--amber);
    box-shadow: 0 0 0 3px rgba(245, 158, 11, 0.12);
}

/* Botón ghost (marca) */
.btn-ghost {
    background: transparent; border: 1px solid var(--bdr); color: var(--t2);
}
.btn-ghost:hover { background: var(--s2); }

/* Pequeños helpers de tabla */
.items-count-badge {
    display: inline-block; padding: 3px 8px; border-radius: 99px;
    background: var(--s2); color: var(--t2);
    font-family: 'JetBrains Mono', monospace; font-size: 11px;
}
.text-muted { color: var(--t4); }
.tag-amber {
    display: inline-flex; align-items: center; gap: 5px;
    padding: 4px 10px; border-radius: 99px;
    background: var(--amber-bg); color: var(--amber-d);
    font-family: 'Space Grotesk', sans-serif; font-size: 11px; font-weight: 700;
}
.lock-tag { white-space: nowrap; }

/* Pestaña 2: captura */
.capture-card { max-width: 640px; margin: 0 auto; }

/* Cropper modal */
.cropper-card { max-width: 720px; width: 92%; }
.cropper-body {
    padding: 16px; background: var(--s2);
    max-height: 62vh; display: flex; align-items: center; justify-content: center;
}
.cropper-body #cropper-image { max-width: 100%; display: block; }

/* Mensaje "sin imagen" en el modal de detalle */
.no-image-msg {
    flex-direction: column; align-items: center; justify-content: center;
    gap: 10px; color: var(--t4); text-align: center; padding: 30px;
    height: 100%;
}
.no-image-msg .lucide { width: 40px; height: 40px; }

/* Distintivo de versión fijo en la esquina (para confirmar el despliegue). */
.version-badge {
    position: fixed;
    bottom: calc(8px + env(safe-area-inset-bottom));
    right: 10px;
    z-index: 9999;
    font-family: 'JetBrains Mono', monospace;
    font-size: 11px;
    color: var(--t4);
    opacity: 0.65;
    pointer-events: none;
    user-select: none;
}

/* Botón "Agregar Fila" al final de la lista de ítems (creación y edición). */
.btn-add-row {
    margin-top: 12px;
    width: 100%;
    justify-content: center;
    border-style: dashed;
}

/* ============================================================================
   Ajustes de móvil (fuera del bloque "Mobile Enhancements" original para que
   sobrescriba, en cascada, las reglas base de la sección de arriba: mismo
   selector + misma especificidad, pero definido después, gana).
   ============================================================================ */
@media (max-width: 600px) {
    /* Contenedor general: menos aire para aprovechar el ancho en móvil.
       padding-top NO se toca acá (a propósito, no es un olvido): lo fija el
       bloque de 900px de más abajo para despejar el header fijo, y como ese
       bloque también aplica a <=600px, un padding:14px shorthand acá lo
       resetearía a 14px y el header taparía el principio de cada pestaña. */
    .app-container {
        padding-left: 14px;
        padding-right: 14px;
        padding-bottom: 14px;
        gap: 16px;
    }

    /* Header y tab-bar de móvil: ver el bloque dedicado
       "Rediseño de navegación móvil (header fijo + tab-bar inferior + FAB)"
       más abajo — reemplazó por completo el stack vertical que había acá. */

    .card {
        padding: 16px;
    }

    .manual-submit-row {
        justify-content: stretch;
    }

    .manual-submit-row .btn {
        width: 100%;
    }

    .dashboard-controls {
        flex-direction: column;
        align-items: stretch;
    }

    .dashboard-controls h2 {
        text-align: center;
    }

    .filter-controls {
        width: 100%;
    }

    .filter-controls select {
        flex: 1;
    }

    .btn-refresh {
        justify-content: center;
    }

    /* Anterior/Siguiente + label de página no entran en una sola fila en
       teléfonos angostos (comandas-table, inventario, log, ubicaciones). */
    .pagination-controls {
        flex-wrap: wrap;
        row-gap: 8px;
    }

    /* El padding-bottom que despeja la tab-bar inferior fija (y la barra de
       gestos/botones del sistema) vive en el bloque de 900px de más abajo —
       ese fijado ya cubre este caso, no hace falta repetirlo acá. */

    /* min-width:300px del toast se sale de un teléfono angosto (ej. 320px,
       con right:24px ya no queda espacio) — en móvil ocupa el ancho
       disponible en vez de un ancho mínimo fijo. */
    .toast-container {
        left: 14px;
        right: 14px;
    }
    .toast {
        min-width: 0;
        width: 100%;
    }
}
