/* ════════════════════════════════════════════════════════════════
 * layouts.css · SGI Contenedores Patagonia
 * ─────────────────────────────────────────────────────────────────
 * UN SOLO ARCHIVO con todas las reglas responsive del sistema.
 * Reemplaza:
 *   - layout-mobile.css   (≤639.98px)
 *   - layout-tablet.css   (640-1023.98px)
 *   - layout-desktop.css  (≥1024px + sub-rangos 1280/1200/1400)
 *
 * Cargado SIEMPRE (sin media="" en el <link>). Cada bloque @media
 * adentro decide si aplica o no según el viewport. Esto simplifica
 * el HTML (3 link tags totales) y mantiene la performance — el browser
 * solo APLICA las reglas que matcheen el viewport actual.
 *
 * Estructura (orden topdown, cada bloque autónomo):
 *
 *   1. Mobile        @media (max-width: 639.98px)
 *   2. Tablet        @media (min-width: 640px) and (max-width: 1023.98px)
 *   3. Desktop       @media (min-width: 1024px)
 *      3a. Sub-rango pequeño   (1024-1280)
 *      3b. Sub-rango intermedio (1024-1200)
 *      3c. Sub-rango grande    (1024-1400)
 *
 * NO hay @media anidados. Cada regla vive en exactamente una sección.
 * Si una regla aplica a múltiples breakpoints, aparece en cada bloque.
 *
 * Cargar DESPUÉS de tokens.css y components.css en index.html.
 * ──────────────────────────────────────────────────────────────── */

/* ════════════════════════════════════════════════════════════════
   1. MOBILE · @media (max-width: 639.98px)
   ════════════════════════════════════════════════════════════════ */

@media (max-width: 639.98px) {
  /* ══════════════════════════════════════════════════════════════
   TAP RESET · sistema universal anti-sticky
   ══════════════════════════════════════════════════════════════
   Bug clásico mobile: al hacer tap en un botón, el browser muestra
   un highlight gris/azul que persiste si el JS bloquea el thread
   (re-render, navegación). Visualmente: el botón "queda pegado".

   Fix universal:
   - tap-highlight-color transparent (saca el destello del sistema)
   - user-select none (evita selección accidental en hold)
   - touch-callout none (saca el menú contextual del long-press)
   - outline none en :focus, ring solo en :focus-visible (a11y intacto
     para teclado, invisible para tap)
   - transform de :active con transition de salida 80ms — vuelve suave */
  .btab-item,
  .gx-quick-btn,
  .alm-pill,
  .oa-pill,
  .gx-segctl-tab,
  .gx-collapsible-toggle,
  .topbar .tact .gx-btn,
  .topbar .tact .gx-btn-sm,
  #NOTIF_BELL_CONTAINER button,
  .mhbtn,
  .alm-card-actions .gx-btn,
  .oa-mcard-actions .gx-btn {
    -webkit-tap-highlight-color: transparent;
    -webkit-touch-callout: none;
    user-select: none;
    outline: none;
  }
  .btab-item:focus,
  .gx-quick-btn:focus,
  .alm-pill:focus,
  .oa-pill:focus,
  .gx-segctl-tab:focus,
  .gx-collapsible-toggle:focus,
  .topbar .tact .gx-btn:focus,
  .mhbtn:focus {
    outline: none;
  }

  /* A11y intacto: ring de focus solo en navegación con teclado */
  .btab-item:focus-visible,
  .gx-quick-btn:focus-visible,
  .alm-pill:focus-visible,
  .oa-pill:focus-visible,
  .gx-segctl-tab:focus-visible {
    outline: 2px solid var(--info-500, #3b82f6);
    outline-offset: 2px;
  }

  /* ══════════════════════════════════════════════════════════════
   SHELL · Sidebar drawer overlay + main full width (CRÍTICO)
   ══════════════════════════════════════════════════════════════
   Override del .sb sticky de main.css (desktop): en mobile el
   sidebar es un DRAWER que se desliza desde la izquierda y se
   superpone sobre el contenido, NO lo empuja. Por default está
   fuera de pantalla (translateX -100%); cuando body.sb-open
   está activo, slide-in. El overlay .sb-ov cubre el contenido
   y permite cerrar al tocarlo. */
  .shell {
    display: block;
  }

  .sb {
    position: fixed;
    top: 0;
    left: 0;
    bottom: 0;
    width: 85vw;
    max-width: 320px;
    height: 100vh;
    z-index: 500;
    transform: translateX(-100%);
    transition: transform 0.26s cubic-bezier(0.4, 0, 0.2, 1);
    box-shadow: 4px 0 24px rgba(0, 0, 0, 0.25);
  }
  body.sb-open .sb {
    transform: translateX(0);
  }

  .sb-ov {
    display: none;
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.5);
    z-index: 499;
    -webkit-tap-highlight-color: transparent;
  }
  body.sb-open .sb-ov {
    display: block;
  }

  /* Main ocupa todo el ancho del viewport — sin compartir con sidebar */
  .main {
    width: 100%;
    margin: 0;
    flex: none;
    display: flex;
    flex-direction: column;
  }

  /* Botón hamburguesa visible y táctil en topbar */
  .mhbtn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    background: transparent;
    border: 1px solid var(--border);
    border-radius: 8px;
    cursor: pointer;
    color: var(--text-primary);
    flex-shrink: 0;
  }
  .mhbtn svg {
    width: 20px;
    height: 20px;
    stroke-width: 2;
  }

  /* Botón cerrar drawer dentro del header del sidebar */
  .sb-hd .sb-close {
    display: inline-flex;
  }

  /* Migrado desde main.css L356-360 (era @media(max-width:640px)) */
  .alertc {
    flex-wrap: wrap;
  }
  .alertc-cta {
    width: 100%;
    align-self: stretch;
  }
  .alertc-cta .btn {
    width: 100%;
  }

  /* Migrado desde main.css L762-779 (era @media (max-width:480px)) */
  /* Phone — modal a bottom sheet (más natural en mobile) */
  .mbg {
    align-items: flex-end;
    padding: 0;
  }
  .mbox {
    width: 100%;
    max-width: 100%;
    border-radius: var(--radius-2xl) var(--radius-2xl) 0 0;
    max-height: 92vh;
    padding: 20px 18px 24px;
    animation: slideUp var(--duration-slow) var(--ease-out);
  }
  .mbox-lg {
    width: 100%;
    max-width: 100%;
  }
  /* Toast con margen inferior para no chocar con safe-area */
  .twrap {
    bottom: max(20px, env(safe-area-inset-bottom));
  }

  /* ════════════════════════════════════════════════════════════════
   SISTEMA DE DISEÑO · TOPBAR MOBILE (TDM)
   ────────────────────────────────────────────────────────────────
   Reglas duras (no negociables):

   1. UNA SOLA FILA de 56px alto — sin wrap
   2. Slots fijos:
        [≡ ham] · [título / subtítulo (ellipsis)] · [🔔 bell] · [● primary]
   3. SOLO botones .gx-btn-primary son visibles en mobile (CSS filter)
        → si una page tiene 3 botones (CSV, PDF, Nueva OC), solo se ve el primary
        → las otras acciones se acceden desde el body de la página o desktop
   4. Selects, separadores <span>, <input> NUNCA en topbar mobile
        → si una page tiene <select> de período, se mueve al body
   5. El botón primary se renderiza ICON-ONLY (texto oculto vía font-size:0)
        → 36x36 cuadrado, SVG centrado, mismo look para todos
   6. Bell de notificaciones (#NOTIF_BELL_CONTAINER) siempre visible 36x36
   7. Sync indicator (.sync-topbar) NO en topbar — fixed top-right del viewport

   Esto cubre el 90% de las 62 pages sin tocar JS. Las pages pueden seguir
   pasando su HTML completo a setTop(); CSS lo simplifica automáticamente.
   ──────────────────────────────────────────────────────────────── */

  .topbar {
    padding: 10px 12px;
    gap: 8px;
    flex-wrap: nowrap;
    align-items: center;
    min-height: 56px;
  }
  .mhbtn {
    order: 0;
    flex-shrink: 0;
  }

  /* Slot 2: título+subtítulo · ocupa el espacio disponible · ellipsis si trunca */
  .topbar > div:nth-child(2) {
    order: 1;
    min-width: 0;
    flex: 1 1 auto;
  }

  /* Slot 3: wrapper de actions (sync + bell + tact) · tamaño natural */
  .topbar > div:nth-child(3) {
    order: 2;
    flex: 0 0 auto;
    flex-shrink: 0;
    display: flex;
    align-items: center;
    gap: 6px;
  }

  /* Tipografía título + subtítulo · 1 línea estricta cada uno */
  .ptit {
    font-size: 16px;
    line-height: 1.2;
    font-weight: 700;
    letter-spacing: -0.01em;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .psub {
    font-size: 11px;
    line-height: 1.3;
    color: var(--text-muted);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 100%;
  }

  /* ── REGLA CLAVE · filtro automático de acciones en topbar mobile ──
   Todo lo que NO sea .gx-btn-primary queda oculto. Esto cubre:
   - .gx-btn-secondary (CSV, PDF, Configurar avisos, Volver, etc.)
   - <select> de período/empresa/área
   - <span> separadores
   - <input> de búsqueda
   - cualquier otro botón ghost o link
*/
  .topbar .tact {
    display: flex;
    align-items: center;
    gap: 6px;
  }
  .topbar .tact > *:not(.gx-btn-primary) {
    display: none !important;
  }

  /* El botón primary visible · 36x36 cuadrado icon-only */
  .topbar .tact .gx-btn-primary {
    width: 36px;
    height: 36px;
    min-height: 36px;
    padding: 0;
    font-size: 0; /* oculta texto literal */
    border-radius: 8px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
  }
  .topbar .tact .gx-btn-primary svg {
    width: 18px;
    height: 18px;
    font-size: initial; /* SVG mantiene su tamaño propio */
    display: block;
  }
  .topbar .tact .gx-btn-primary i {
    font-size: 18px; /* fallback si ic() no se hidrató */
  }

  /* Bell de notificaciones (#NOTIF_BELL) · siempre visible 36x36 */
  #NOTIF_BELL_CONTAINER button {
    width: 36px !important;
    height: 36px !important;
    padding: 0 !important;
    border-radius: 8px !important;
    display: inline-flex !important;
    align-items: center;
    justify-content: center;
  }
  #NOTIF_BELL_CONTAINER button svg {
    width: 18px !important;
    height: 18px !important;
  }

  /* SYNC indicator en mobile: solo el dot fijo en esquina superior derecha
   del viewport. Sin texto. El inline style del HTML fue removido en
   index.html, así que la regla de main.css aplica por default y acá la
   sobreescribimos sin necesidad de !important. */
  .sync-topbar {
    position: fixed;
    top: 14px;
    right: 14px;
    z-index: 200;
    font-size: 0; /* oculta los text nodes "Sync: ..." */
    line-height: 0;
    pointer-events: none; /* no bloquea taps en el topbar de abajo */
    white-space: nowrap;
  }
  .sync-topbar > span:first-child {
    font-size: 16px; /* solo el dot ● visible y prominente */
    line-height: 1;
    filter: drop-shadow(0 0 3px rgba(255, 255, 255, 0.9));
  }
  .sync-topbar > span:not(:first-child),
  .sync-topbar > br {
    display: none; /* oculta "(Activo)" y el line break */
  }

  /* Filtros en columna en phone */
  .fbar {
    padding: 10px 12px;
    gap: 8px;
    border-radius: var(--radius-lg);
  }

  /* Auto-colapso de grids multi-columna a 2x en mobile.
   Cubre las variantes inline más comunes en el codebase:
   - repeat(N, minmax(0, 1fr)) con/sin espacios
   - repeat(N, 1fr) sin minmax
   - patrones custom específicos (hero gerencia 1.6fr 1fr 1fr 1fr)
   Las cards a mitad-y-mitad aprovechan mejor el ancho del viewport. */
  div[style*="grid-template-columns:repeat(4,minmax(0,1fr))"],
  div[style*="grid-template-columns:repeat(5,minmax(0,1fr))"],
  div[style*="grid-template-columns:repeat(3,minmax(0,1fr))"],
  div[style*="grid-template-columns:repeat(4, minmax(0, 1fr))"],
  div[style*="grid-template-columns:repeat(5, minmax(0, 1fr))"],
  div[style*="grid-template-columns:repeat(3, minmax(0, 1fr))"],
  div[style*="grid-template-columns:repeat(4,1fr)"],
  div[style*="grid-template-columns:repeat(5,1fr)"],
  div[style*="grid-template-columns:repeat(3,1fr)"],
  div[style*="grid-template-columns:repeat(4, 1fr)"],
  div[style*="grid-template-columns:repeat(5, 1fr)"],
  div[style*="grid-template-columns:repeat(3, 1fr)"],
  div[style*="grid-template-columns:1.6fr 1fr 1fr 1fr"],
  div[style*="grid-template-columns: 1.6fr 1fr 1fr 1fr"] {
    grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
    gap: 8px !important;
  }

  /* Auto-colapso de tablas 7+ columnas (M06 Área del jefe) — cuando el
   container es padre directo de #CT, ya está cubierto por la conversión
   genérica de tablas a cards. Para tablas dentro de cards más complejas,
   forzamos overflow-x:auto para que sean scrollables horizontalmente
   en lugar de pisarse contra el ancho del viewport. */
  .content table:not(.rptb):not(.gx-table-keep) {
    font-size: 11px;
  }
  .content .gx-card > div[style*="overflow-x:auto"],
  .content .gx-card > .tw {
    -webkit-overflow-scrolling: touch;
  }
  /* Stats inline del greeting: en mobile horizontal compacto */
  .gx-greeting-stats {
    gap: 14px;
  }

  /* Migrado desde main.css L1047-1058 (era @media (max-width:640px)) */
  /* KPI rail cards: en mobile reducir tamaño del valor para que quepa */
  div[style*="position:relative"][style*="border-radius:var(--radius-lg)"] > span.gx-tabular[style*="font-size:24px"],
  div[style*="position:relative"][style*="border-radius:var(--radius-lg)"] > span.gx-tabular[style*="font-size:26px"],
  div[style*="position:relative"][style*="border-radius:var(--radius-lg)"] > span.gx-tabular[style*="font-size:30px"],
  div[style*="position:relative"][style*="border-radius:var(--radius-lg)"] > span.gx-tabular[style*="font-size:32px"] {
    font-size: 22px !important;
  }

  /* Migrado desde main.css L1070-1077 (era @media (max-width:640px)) */
  /* Tabla con avatares y muchas columnas — densidad reducida en mobile */
  .gx-table thead th,
  .gx-table tbody td {
    padding: 8px 10px !important;
    font-size: 11px;
  }
  /* Avatar en tabla mobile · 10px = .t-overline (canonical) */
  .gx-table .gx-avatar {
    width: 18px !important;
    height: 18px !important;
    font-size: 10px !important;
  }

  /* Migrado desde main.css L1100-1104 (era @media (max-width:640px)) */
  /* App-shell en mobile: hero greeting más compacto */
  .gx-greeting {
    padding: 12px !important;
    flex-wrap: wrap;
  }
  .gx-greeting > div:nth-child(2) {
    flex: 1 1 100%;
    min-width: 0;
  }
  .gx-greeting > div:nth-child(2) > div:first-child {
    font-size: 16px !important;
  }

  /* Migrado desde main.css L1110-1112 (era @media (max-width:480px)) */
  .gx-table {
    min-width: 100%;
    font-size: 11px;
  }

  /* Migrado desde main.css L1222-1248 (era @media (max-width:640px)) */
  [style*="grid-template-columns:repeat(4"],
  [style*="grid-template-columns:repeat(5"],
  [style*="grid-template-columns:repeat(6"],
  [style*="grid-template-columns: repeat(4"],
  [style*="grid-template-columns: repeat(5"],
  [style*="grid-template-columns: repeat(6"] {
    grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
  }
  .gx-kpi-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
  }

  /* Greeting card en mobile: stats van debajo, no al costado */
  .gx-greeting-stats {
    flex: 1 1 100%;
    margin-top: 8px;
    display: grid !important;
    grid-template-columns: repeat(3, 1fr) !important;
    gap: 8px;
  }
  /* Stats inline · 10px overline + 18px h2-mobile (canonical) */
  .gx-stat-label {
    font-size: 10px !important;
  }
  .gx-stat-value {
    font-size: 18px !important;
  }

  /* Stock crítico alert: el botón pasa abajo full-width, evita wrapping feo */
  .gx-critical {
    flex-wrap: wrap;
  }
  .gx-critical > div:last-child {
    flex: 1 1 100%;
  }
  .gx-critical .gx-btn {
    width: 100%;
    justify-content: center;
  }

  /* Migrado desde main.css L1253-1271 (era @media (max-width:640px)) */
  /* Filter bars (.gx-search, .gx-select, etc) adentro del bar
   gris claro: stacking vertical para no apretar. */
  div[style*="display:flex"][style*="flex-wrap:wrap"] > .gx-search {
    flex: 1 1 100% !important;
    width: 100% !important;
    min-width: 0 !important;
  }

  /* (Reglas .topbar .tact .gx-btn ya definidas arriba en sección topbar — no duplicar) */

  /* gx-card padding reducido */
  .gx-card {
    padding: 12px;
  }

  /* Section headers más compactos */
  .gx-panel-head {
    padding: 10px 12px !important;
    flex-wrap: wrap;
    gap: 8px !important;
  }

  /* ── HERO NAVY MÓVIL (specs exactos M1 Grovex DS) ──
   Background: var(--navy-900) sólido (cleanup: era #0F2E5C hardcoded)
   Padding: 16px (más compacto que antes)
   Border-radius: 0 en bordes superiores · 16px abajo (full bleed top) */
  .gx-greeting {
    background: var(--navy-900) !important;
    color: #fff !important;
    padding: 16px 18px !important;
    border-radius: 14px !important;
    border: none !important;
    box-shadow: 0 4px 14px rgba(15, 46, 92, 0.18) !important;
    margin: 0 0 14px !important;
    flex-wrap: wrap !important;
    align-items: flex-start !important;
    gap: 12px !important;
  }

  /* Avatar 40px (M1 spec), ring blanco translúcido */
  .gx-greeting .gx-avatar,
  .gx-greeting .gx-avatar-lg {
    width: 40px !important;
    height: 40px !important;
    background: rgba(255, 255, 255, 0.15) !important;
    color: #fff !important;
    font-size: 13px !important;
    font-weight: 700 !important;
    border: 2px solid rgba(255, 255, 255, 0.25) !important;
    flex-shrink: 0;
  }

  /* Saludo nombre — M1 spec: 20px fontWeight 700 letterSpacing -.02em */
  .gx-greeting > div:nth-child(2) > div:first-child {
    color: #fff !important;
    font-size: 20px !important;
    font-weight: 700 !important;
    letter-spacing: -0.02em !important;
    line-height: 1.2 !important;
  }

  /* Subtítulo descripción — M1 spec: 11px opacity 0.65 */
  .gx-greeting > div:nth-child(2) > div:nth-child(2) {
    color: rgba(255, 255, 255, 0.65) !important;
    font-size: 11px !important;
    margin-top: 4px !important;
    line-height: 1.45 !important;
  }
  .gx-greeting > div:nth-child(2) > div:nth-child(2) strong {
    color: rgba(255, 255, 255, 0.92) !important;
    font-weight: 700 !important;
  }

  /* Stats inline (HOY/SEM/BODEGA) — M1 spec: glass cards translúcidos */
  .gx-greeting-stats {
    flex: 1 1 100% !important;
    margin-top: 14px !important;
    padding-top: 0 !important;
    border-top: none !important;
    display: grid !important;
    grid-template-columns: repeat(3, 1fr) !important;
    gap: 8px !important;
  }
  .gx-greeting-stats > div {
    padding: 10px 12px !important;
    background: rgba(255, 255, 255, 0.08) !important;
    border: 1px solid rgba(255, 255, 255, 0.1) !important;
    border-radius: 10px !important;
    text-align: left !important;
  }
  .gx-greeting-stats > div:first-child {
    padding-left: 12px !important;
  }
  .gx-greeting-stats > div:last-child {
    padding-right: 12px !important;
  }

  .gx-greeting-stats .gx-stat-label {
    /* = .t-overline · 10px / 700 / .1em uppercase */
    color: rgba(255, 255, 255, 0.7) !important;
    font-size: 10px !important;
    font-weight: 700 !important;
    text-transform: uppercase !important;
    letter-spacing: 0.1em !important;
    margin-bottom: 4px !important;
  }
  .gx-greeting-stats .gx-stat-value {
    color: #fff !important;
    font-size: 22px !important;
    font-weight: 700 !important;
    line-height: 1 !important;
    letter-spacing: -0.02em !important;
  }
  /* "OCs" pequeño junto al número grande */
  .gx-greeting-stats .gx-stat-value span {
    color: rgba(255, 255, 255, 0.6) !important;
    font-size: 10px !important;
  }

  /* Tablas inline (no .gx-table-cards) — al menos achicar font para
   que entren mejor en pantalla cuando tienen scroll horizontal. */
  table:not(.gx-table-cards) {
    font-size: 11px;
  }

  /* Tabs scroll horizontal (gx-tabs y similares) */
  .gx-tabs {
    overflow-x: auto;
    scrollbar-width: thin;
  }
  .gx-tabs::-webkit-scrollbar {
    height: 0;
  }
  .gx-tab {
    white-space: nowrap;
    flex-shrink: 0;
  }

  /* gx-card padding más ajustado en cards apretadas */
  .gx-card {
    border-radius: 12px;
  }

  /* Banner crítico (.gx-critical) — M01 spec: overlap con hero navy
   margin negativo arriba para que se monte sobre el hero. */
  .gx-critical {
    border-radius: 12px !important;
    box-shadow: 0 4px 12px rgba(215, 0, 21, 0.12) !important;
    margin-top: -10px !important;
    position: relative;
    z-index: 1;
  }

  /* Migrado desde main.css L1397-1493 (era @media (max-width:640px)) */
  /* OC ABIERTAS · CARDS MOBILE NATIVAS (estilo M3 Grovex DS) */
  /* Mostrar las cards mobile, ocultar la tabla desktop */
  .oa-mlist {
    display: block;
    margin-bottom: 12px;
  }
  .oa-desktop-table {
    display: none !important;
  }

  /* Filter bar pesado (search + 5 selects) oculto en mobile.
   Las pills .oa-pills cubren el filtrado por estado, que es lo más usado. */
  .oa-filter-bar {
    display: none !important;
  }

  /* ── PILLS DE FILTRO M03 (mobile-only · sticky al tope) ── */
  .oa-pills {
    display: flex;
    gap: 6px;
    margin-bottom: 12px;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    padding: 8px 14px 6px;
    scrollbar-width: none;
    position: sticky;
    top: 0;
    z-index: 10;
    background: var(--bg, var(--slate-50));
    margin-left: -14px;
    margin-right: -14px;
  }
  .oa-pills::-webkit-scrollbar {
    display: none;
  }
  .oa-pill {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 8px 12px;
    background: #fff;
    border: 1px solid var(--border);
    border-radius: 999px;
    font-size: 12px;
    font-weight: 600;
    color: var(--text-secondary);
    cursor: pointer;
    font-family: inherit;
    white-space: nowrap;
    transition: all 0.15s;
  }
  .oa-pill:active {
    transform: scale(0.97);
  }
  .oa-pill.is-active {
    background: var(--navy-900);
    color: #fff;
    border-color: var(--navy-900);
  }
  .oa-pill.is-active.tone-danger {
    background: var(--danger-50);
    color: var(--danger-700);
    border-color: var(--danger-200);
  }
  .oa-pill.is-active.tone-warning {
    background: var(--warning-50);
    color: var(--warning-700);
    border-color: var(--warning-200);
  }
  .oa-pill-count {
    font-size: 10px;
    font-weight: 700;
    padding: 1px 6px;
    border-radius: 999px;
    background: var(--slate-100);
    color: var(--text-muted);
    font-variant-numeric: tabular-nums;
  }
  .oa-pill.is-active .oa-pill-count {
    background: rgba(255, 255, 255, 0.2);
    color: inherit;
  }
  .oa-pill.is-active.tone-danger .oa-pill-count,
  .oa-pill.is-active.tone-warning .oa-pill-count {
    background: rgba(0, 0, 0, 0.06);
    color: inherit;
  }

  .oa-mcard {
    background: #fff;
    border: 1px solid var(--border);
    border-left: 3px solid var(--slate-300);
    border-radius: 10px;
    padding: 12px 14px;
    margin-bottom: 8px;
    box-shadow: var(--shadow-xs);
    position: relative;
    transition:
      box-shadow 0.15s,
      border-left-color 0.15s;
  }
  .oa-mcard:active {
    box-shadow: var(--shadow-sm);
  }

  /* Borde lateral por estado (badge interno detectado vía :has()) */
  .oa-mcard:has(.gx-badge-danger) {
    border-left-color: var(--red);
  }
  .oa-mcard:has(.gx-badge-warning) {
    border-left-color: #c45200;
  }
  .oa-mcard:has(.gx-badge-success) {
    border-left-color: var(--green);
  }
  .oa-mcard:has(.gx-badge-info) {
    border-left-color: var(--blue);
  }

  /* Header: OC # · SOL # + badge top-right */
  .oa-mcard-head {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 8px;
  }
  .oa-mcard-id {
    font-family: ui-monospace, Menlo, monospace;
    font-size: 13px;
    font-weight: var(--weight-semibold);
    color: var(--navy-700);
    letter-spacing: -0.01em;
  }
  .oa-mcard-sol {
    font-family: ui-monospace, Menlo, monospace;
    font-size: 11px;
    color: var(--text-muted);
  }
  .oa-mcard-badge {
    margin-left: auto;
  }
  .oa-mcard-badge .gx-badge {
    font-size: 10px;
    padding: 2px 8px;
  }

  /* Proveedor uppercase prominente */
  .oa-mcard-prov {
    font-size: 14px;
    font-weight: var(--weight-semibold);
    color: var(--text-primary);
    text-transform: uppercase;
    letter-spacing: 0.01em;
    line-height: 1.3;
    margin-bottom: 6px;
  }

  /* Meta line: TIPO · vence dd/mm + monto a la derecha */
  .oa-mcard-meta {
    display: flex;
    align-items: center;
    gap: 0;
    font-size: 11px;
    color: var(--text-muted);
    flex-wrap: wrap;
  }
  .oa-mcard-tipo {
    font-weight: var(--weight-semibold);
    color: var(--text-secondary);
    letter-spacing: 0.04em;
  }
  .oa-mcard-monto {
    margin-left: auto;
    font-family: ui-monospace, Menlo, monospace;
    font-variant-numeric: tabular-nums;
    font-size: 14px;
    font-weight: var(--weight-semibold);
    color: var(--text-primary);
    letter-spacing: -0.01em;
  }

  /* Action bar — botones grandes táctiles abajo */
  .oa-mcard-actions {
    display: flex;
    gap: 6px;
    margin-top: 10px;
    padding-top: 10px;
    border-top: 1px solid var(--border-subtle);
    flex-wrap: wrap;
  }
  .oa-mcard-actions .gx-btn {
    flex: 1;
    min-height: 36px;
    justify-content: center;
    font-size: 12px;
  }

  /* Migrado desde main.css L1502-1588 (era @media (max-width:640px)) */
  /* TABLAS → CARDS EN MOBILE (responsive cleanly) */
  /* TODAS las tablas dentro de #CT se convierten en cards apiladas,
   excepto .rptb (reportes imprimibles) y .gx-table-keep (opt-out).
   Selector: #CT table:not(.rptb):not(.gx-table-keep) */
  #CT table:not(.rptb):not(.gx-table-keep) thead {
    display: none;
  }
  #CT table:not(.rptb):not(.gx-table-keep) {
    min-width: 100% !important;
    border-collapse: separate;
    width: 100% !important;
  }
  #CT table:not(.rptb):not(.gx-table-keep) tbody,
  #CT table:not(.rptb):not(.gx-table-keep) tr {
    display: block;
  }
  #CT table:not(.rptb):not(.gx-table-keep) tr {
    background: #fff;
    border: 1px solid var(--border);
    border-left: 3px solid #e6e9ef; /* rail lateral default (gris) */
    border-radius: 10px;
    padding: 12px 14px 10px;
    margin-bottom: 8px;
    box-shadow: var(--shadow-xs);
    position: relative;
    transition:
      border-left-color 0.15s,
      box-shadow 0.15s;
  }
  #CT table:not(.rptb):not(.gx-table-keep) tr:active {
    box-shadow: var(--shadow-sm);
  }
  /* Borde lateral por estado, detectado vía :has() del badge interno */
  #CT table:not(.rptb):not(.gx-table-keep) tr:has(.gx-badge-danger),
  #CT table:not(.rptb):not(.gx-table-keep) tr:has(.gx-badge-solid-danger),
  #CT table:not(.rptb):not(.gx-table-keep) tr:has(.bdg.br) {
    border-left-color: var(--red);
  }
  #CT table:not(.rptb):not(.gx-table-keep) tr:has(.gx-badge-warning),
  #CT table:not(.rptb):not(.gx-table-keep) tr:has(.gx-badge-solid-warning),
  #CT table:not(.rptb):not(.gx-table-keep) tr:has(.bdg.bor) {
    border-left-color: #c45200;
  }
  #CT table:not(.rptb):not(.gx-table-keep) tr:has(.gx-badge-success),
  #CT table:not(.rptb):not(.gx-table-keep) tr:has(.gx-badge-solid-success),
  #CT table:not(.rptb):not(.gx-table-keep) tr:has(.bdg.bg) {
    border-left-color: var(--green);
  }
  #CT table:not(.rptb):not(.gx-table-keep) tr:has(.gx-badge-info),
  #CT table:not(.rptb):not(.gx-table-keep) tr:has(.bdg.bb) {
    border-left-color: var(--blue);
  }

  #CT table:not(.rptb):not(.gx-table-keep) td {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 4px 0;
    border: none !important;
    text-align: right;
    gap: 12px;
    font-size: 12px;
    width: 100% !important;
    min-width: 0 !important;
  }
  #CT table:not(.rptb):not(.gx-table-keep) td::before {
    content: attr(data-label);
    font-size: 10px;
    font-weight: var(--weight-semibold);
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    text-align: left;
    flex-shrink: 0;
  }
  /* Primera celda (típicamente título / ID): full-width, prominente */
  #CT table:not(.rptb):not(.gx-table-keep) td:first-child {
    border-bottom: 1px solid var(--border) !important;
    padding-bottom: 10px;
    margin-bottom: 8px;
    font-size: 14px;
    font-weight: var(--weight-semibold);
    color: var(--text-primary);
    text-align: left;
    justify-content: flex-start;
  }
  #CT table:not(.rptb):not(.gx-table-keep) td:first-child::before {
    display: none;
  }

  /* Badges dentro de cards: layout más amigable */
  #CT table:not(.rptb):not(.gx-table-keep) td .gx-badge,
  #CT table:not(.rptb):not(.gx-table-keep) td .bdg {
    flex-shrink: 0;
    margin-left: auto;
  }

  /* Celdas vacías: ocultarlas para no dejar líneas con solo el label */
  #CT table:not(.rptb):not(.gx-table-keep) td:empty {
    display: none;
  }

  /* tw wrapper (overflow-x:auto) inútil cuando son cards: quitar overflow */
  #CT .tw {
    overflow: visible !important;
  }

  /* Migrado desde main.css L1599-1650 (era @media (max-width:640px)) */
  /* ACCIONES RÁPIDAS MÓVIL (estilo M1 Grovex DS) */
  .gx-quick-actions {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 8px; /* M01 spec: 8px */
    margin-bottom: 16px;
  }
  .gx-quick-btn {
    display: flex;
    align-items: center;
    gap: 10px; /* M01 spec: 10px */
    padding: 12px 14px; /* M01 spec: 12 14 */
    background: #fff;
    border: 1px solid var(--border);
    border-radius: 10px; /* M01 spec: 10px */
    color: var(--text-primary);
    font-size: 13px;
    font-weight: var(--weight-semibold);
    cursor: pointer;
    transition: all 0.15s;
    text-align: left;
    box-shadow: var(--shadow-xs);
    font-family: inherit;
    min-height: 52px;
  }
  .gx-quick-btn:active {
    transform: scale(0.97);
    box-shadow: none;
  }
  .gx-quick-btn .gx-quick-ico {
    width: 28px; /* M01 spec: 28px */
    height: 28px; /* M01 spec: 28px */
    border-radius: 8px;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    background: var(--info-50);
    color: var(--info-700);
    font-size: 14px;
    font-weight: 700;
  }
  .gx-quick-btn .gx-quick-ico svg {
    width: 16px;
    height: 16px;
  }
  .gx-quick-btn.tone-danger .gx-quick-ico {
    background: var(--danger-50);
    color: var(--danger-700);
  }
  .gx-quick-btn.tone-success .gx-quick-ico {
    background: var(--success-50);
    color: var(--success-700);
  }
  .gx-quick-btn.tone-warning .gx-quick-ico {
    background: var(--warning-50);
    color: var(--warning-700);
  }
  .gx-quick-btn .gx-quick-count {
    margin-left: auto;
    background: var(--red);
    color: #fff;
    font-size: 11px;
    font-weight: 700;
    padding: 2px 7px;
    border-radius: 10px;
    flex-shrink: 0;
  }

  /* Migrado desde main.css L856-938 (era @media (max-width:768px))
   BOTTOM TABS móvil — componente solo visible en mobile.
   Vive en layout-mobile.css porque es exclusivo de phone (<640px).
   Tablet ya oculta .btab vía layout-tablet.css. */
  .btab {
    display: flex;
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    height: 64px;
    padding: 6px 4px calc(6px + env(safe-area-inset-bottom));
    background: #fff;
    border-top: 1px solid var(--border);
    box-shadow: 0 -2px 12px rgba(1, 45, 85, 0.06);
    z-index: 90;
    align-items: stretch;
    justify-content: space-around;
  }
  .btab-item {
    flex: 1 1 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 2px;
    padding: 4px 2px;
    background: none;
    border: none;
    cursor: pointer;
    color: var(--text-muted);
    font-family: inherit;
    font-size: 10px;
    font-weight: var(--weight-medium);
    text-decoration: none;
    /* Transition de salida para que :active vuelva suave a scale(1) — sin esto
     el browser puede mantener el transform si pierde el touchend (sticky tap). */
    transition:
      color var(--duration-fast) var(--ease-standard),
      transform 100ms ease-out;
    position: relative;
    min-width: 0;
    transform: scale(1); /* estado base explícito · ayuda al reset post-tap */
  }
  .btab-item .btab-ico {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 24px;
    height: 24px;
  }
  .btab-item .btab-ico svg {
    width: 22px;
    height: 22px;
    stroke-width: 2;
  }
  .btab-item .btab-lbl {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    max-width: 100%;
    line-height: 1.1;
  }
  .btab-item.is-active {
    color: var(--red);
  }
  .btab-item.is-active .btab-ico svg {
    stroke: var(--red);
  }
  .btab-item:active {
    transform: scale(0.95);
  }

  .btab-badge {
    position: absolute;
    top: 2px;
    right: calc(50% - 16px);
    min-width: 16px;
    height: 16px;
    padding: 0 4px;
    background: var(--red);
    color: #fff;
    font-size: 10px;
    font-weight: var(--weight-semibold);
    line-height: 16px;
    text-align: center;
    border-radius: 8px;
    border: 2px solid #fff;
    font-variant-numeric: tabular-nums;
  }

  /* Padding inferior del content para que el último elemento no quede
   tapado por los bottom tabs fijos */
  .content {
    padding-bottom: 80px;
  }

  /* ════════════════════════════════════════════════════════════════
   DASHBOARD · KPI cards compactas estilo M1 (Grovex DS)
   ────────────────────────────────────────────────────────────────
   Las KPI cards de Volumen/Performance del dashboard (.gx-kpi-card)
   tienen el HTML siguiente:
     <div class="gx-card gx-kpi-card">
       <div>label + delta arriba</div>
       <div>VALOR GRANDE</div>
       <div>subtext (opcional)</div>
       <div>sparkline</div>
     </div>

   En mobile las hacemos más compactas:
   - Padding 12px 14px (era 18px 20px)
   - Valor 24px (era 30px)
   - Sparkline 80x24 (era 160x32)
   - Border-radius 12px
   ──────────────────────────────────────────────────────────────── */

  .gx-kpi-card {
    padding: 12px 14px !important;
    gap: 6px !important;
    border-radius: 12px !important;
    border: 1px solid var(--border) !important;
    background: #fff !important;
  }

  /* Row 1: label + delta inline */
  .gx-kpi-card > div:first-child {
    align-items: center !important;
    gap: 6px !important;
  }
  .gx-kpi-card > div:first-child > div:first-child {
    /* = .t-overline · 10px / 700 / .1em uppercase (canonical) */
    font-size: 10px !important;
    letter-spacing: 0.1em !important;
    font-weight: 700 !important;
  }
  .gx-kpi-card > div:first-child > span {
    font-size: 10px !important;
  }

  /* Row 2: valor grande — M01 spec: 22px (no 26) */
  .gx-kpi-card > div:nth-child(2) {
    font-size: 22px !important;
    line-height: 1 !important;
    letter-spacing: -0.02em !important;
    margin-top: 4px;
  }

  /* Subtext: lo ocultamos en mobile (la card es más compacta) */
  .gx-kpi-card > div:nth-child(3):not([style*="margin-top:auto"]) {
    display: none !important;
  }

  /* Sparkline más pequeño — M01 spec exacto: 48x14 */
  .gx-kpi-card svg {
    width: 48px !important;
    height: 14px !important;
    max-width: 100%;
  }
  .gx-kpi-card > div:last-child {
    margin-top: 0 !important;
  }

  /* ════════════════════════════════════════════════════════════════
   DASHBOARD · Cards compactas para .gx-alert-table
   ────────────────────────────────────────────────────────────────
   Override de la conversión genérica de tabla→cards. En vez de
   apilar cada celda en una fila propia (resultado: 6 filas/card,
   muy alto), usamos CSS Grid para layout compacto:

     ┌─────────────────────────────────────┐
     │ #9936  ●Comercial Vásquez   $1.8M  │  ← fila 1: OC + proveedor + monto
     │ Paulina · 1 d atraso                │  ← fila 2: comprador + atraso
     └─────────────────────────────────────┘

   Cada card pasa de ~250px de alto a ~70px. Acción "Gestionar"
   se oculta en mobile (la card entera funciona como tap target
   al detalle).
   ──────────────────────────────────────────────────────────────── */

  /* Stack-card pattern (M01 spec): UNA sola card con N rows separadas por
   border-top — más denso que cards individuales con gap. */
  #CT .gx-alert-table {
    border: none;
    background: #fff;
    border-radius: 12px;
    overflow: hidden;
    border: 1px solid var(--border);
    box-shadow: var(--shadow-xs);
  }
  #CT .gx-alert-table tbody {
    display: flex;
    flex-direction: column;
    gap: 0;
  }
  #CT .gx-alert-table tr {
    display: grid !important;
    grid-template-columns: auto 1fr auto;
    grid-template-areas:
      "oc      prov     monto"
      "comp    atraso   action";
    align-items: center;
    gap: 4px 10px;
    padding: 11px 14px !important;
    background: transparent;
    border: none;
    border-top: 1px solid var(--border-subtle, #f1f5f9);
    border-radius: 0;
    box-shadow: none;
    margin: 0 !important;
  }
  #CT .gx-alert-table tr:first-child {
    border-top: none;
  }

  /* Reset de la conversión genérica heredada (#CT table:not(.rptb)) */
  #CT .gx-alert-table td {
    display: block !important;
    border: none !important;
    padding: 0 !important;
    text-align: left !important;
    background: transparent !important;
    margin: 0 !important;
  }
  #CT .gx-alert-table td::before {
    content: none !important;
  }

  /* Asignar áreas del grid a cada td (orden del HTML) */
  #CT .gx-alert-table td:nth-child(1) {
    grid-area: oc;
  } /* #9936  */
  #CT .gx-alert-table td:nth-child(2) {
    grid-area: prov; /* Proveedor */
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  #CT .gx-alert-table td:nth-child(3) {
    grid-area: comp;
  } /* Comprador */
  #CT .gx-alert-table td:nth-child(4) {
    grid-area: atraso;
  } /* "1 d atraso" */
  #CT .gx-alert-table td:nth-child(5) {
    grid-area: monto; /* $X */
    text-align: right !important;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    font-size: 13px;
  }
  #CT .gx-alert-table td:nth-child(6) {
    grid-area: action;
    text-align: right !important;
  }
  #CT .gx-alert-table td:nth-child(6) .gx-btn {
    padding: 4px 10px !important;
    font-size: 11px !important;
    min-height: auto !important;
    border-radius: 6px !important;
  }

  /* Tipografías compactas dentro de la card */
  #CT .gx-alert-table td:nth-child(1) span {
    font-size: 11px !important;
    font-weight: 700 !important;
    color: var(--text-muted) !important;
    letter-spacing: 0.02em;
  }
  #CT .gx-alert-table td:nth-child(2) span {
    font-size: 13px !important;
    font-weight: 600 !important;
    color: var(--text-primary) !important;
    text-transform: none !important;
    letter-spacing: -0.01em !important;
  }
  #CT .gx-alert-table td:nth-child(3) {
    font-size: 11px;
    color: var(--text-muted);
  }
  #CT .gx-alert-table td:nth-child(3) .gx-avatar {
    /* Avatar 18px · 10px text (canonical t-overline) */
    width: 18px !important;
    height: 18px !important;
    font-size: 10px !important;
    margin-right: 4px;
  }
  #CT .gx-alert-table td:nth-child(4) span {
    font-size: 11px !important;
    font-weight: 700;
  }

  /* Tap visual sutil en cards de alertas */
  #CT .gx-alert-table tr {
    transition: box-shadow 0.15s;
  }
  #CT .gx-alert-table tr:active {
    box-shadow: var(--shadow-sm);
  }

  /* ════════════════════════════════════════════════════════════════
   PÁGINA ALERTAS · diseño M2 Grovex DS (mobile-only)
   ────────────────────────────────────────────────────────────────
   Banner crítico + pills filtrables + cards verticales con borde
   lateral semántico + acciones grandes táctiles. Reemplaza por
   completo el layout desktop (tabla) en mobile.
   ──────────────────────────────────────────────────────────────── */

  /* En mobile mostramos solo el layout móvil de alertas.
   !important necesario porque los <div class="alm-desktop-only"> tienen
   inline style="display:grid|flex" que tiene mayor specificity que una
   clase CSS normal. Sin !important el desktop layout seguía visible. */
  .alm-desktop-only {
    display: none !important;
  }
  .alm-mobile-only {
    display: block;
  }

  /* ── BANNER CRÍTICO M2 (specs exactos Grovex DS) ── */
  .alm-banner-critical {
    background: linear-gradient(135deg, #fef2f2, #fee2e2); /* M2 spec: gradient */
    border: 1px solid #fca5a5;
    border-radius: 12px; /* M2 spec: 12px no 16 */
    padding: 14px; /* M2 spec: 14px */
    margin-bottom: 14px;
    display: flex;
    flex-wrap: wrap;
    gap: 10px; /* M2 spec: 10px */
    align-items: flex-start;
  }
  .alm-banner-icon {
    width: 36px; /* M2 spec: 36px no 44 */
    height: 36px;
    border-radius: 10px;
    background: #ef4444; /* M2 spec: rojo claro */
    color: #fff;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
  }
  .alm-banner-icon svg {
    width: 20px;
    height: 20px;
  }
  .alm-banner-body {
    flex: 1 1 200px;
    min-width: 0;
  }
  .alm-banner-pre {
    font-size: 11px;
    font-weight: 700;
    color: #b91c1c; /* M2 spec: #B91C1C */
    text-transform: uppercase;
    letter-spacing: 0.08em;
  }
  .alm-banner-title {
    font-size: 15px; /* M2 spec: 15px no 18 */
    font-weight: 700;
    color: var(--danger-900, #7f1d1d); /* M2 spec: rojo oscuro */
    margin-top: 4px;
    line-height: 1.25;
    letter-spacing: -0.01em;
  }
  .alm-banner-meta {
    font-size: 12px;
    color: var(--danger-700);
    margin-top: 4px;
  }
  .alm-banner-cta {
    flex: 1 1 100%;
    display: flex;
    gap: 6px; /* M2 spec: 6px */
    margin-top: 12px;
  }
  .alm-banner-cta .gx-btn {
    flex: 1;
    min-height: 38px; /* M2 spec: más compacto */
    font-size: 13px;
    font-weight: 600;
    justify-content: center;
  }
  .alm-banner-cta-primary {
    background: var(--danger-500) !important;
    color: #fff !important;
    border-color: var(--danger-500) !important;
  }
  .alm-banner-cta-secondary {
    background: #fff !important;
    color: var(--danger-700) !important;
    border-color: var(--danger-200) !important;
  }

  /* ── PILLS DE FILTRO M2 (specs exactos Grovex DS) ── */
  /* Sticky en mobile: las pills quedan ancladas al tope al scrollear,
   siempre visibles para cambiar de tab rápido sin volver arriba. */
  .alm-pills {
    display: flex;
    gap: 6px; /* M2 spec: 6px */
    margin-bottom: 12px;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    padding: 8px 0 6px;
    scrollbar-width: none;
    position: sticky;
    top: 0;
    z-index: 10;
    background: var(--bg, var(--slate-50));
    margin-left: -14px;
    margin-right: -14px;
    padding-left: 14px;
    padding-right: 14px;
  }
  .alm-pills::-webkit-scrollbar {
    display: none;
  }
  .alm-pill {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    gap: 6px; /* M2 spec: 6px */
    padding: 8px 12px; /* M2 spec: 8 12 no 9 16 */
    background: #fff;
    border: 1px solid var(--border);
    border-radius: 999px;
    font-size: 12px; /* M2 spec: 12px */
    font-weight: 600;
    color: var(--text-secondary);
    cursor: pointer;
    font-family: inherit;
    white-space: nowrap;
    transition: all 0.15s;
  }
  .alm-pill:active {
    transform: scale(0.97);
  }
  .alm-pill-count {
    background: var(--slate-100);
    color: var(--text-muted);
    font-size: 10px; /* M2 spec: 10px */
    font-weight: 700;
    padding: 1px 6px;
    border-radius: 999px;
    font-variant-numeric: tabular-nums;
  }
  /* Estado activo M2: background tonal sólido, sin border outline grueso.
   Cleanup: tokens semánticos en lugar de hex hardcoded. */
  .alm-pill.is-active.tone-danger {
    background: var(--danger-50);
    border-color: var(--danger-200);
    color: var(--danger-700);
  }
  .alm-pill.is-active.tone-danger .alm-pill-count {
    background: rgba(0, 0, 0, 0.06);
    color: var(--danger-700);
  }
  .alm-pill.is-active.tone-warning {
    background: var(--warning-50);
    border-color: var(--warning-200);
    color: var(--warning-700);
  }
  .alm-pill.is-active.tone-warning .alm-pill-count {
    background: rgba(0, 0, 0, 0.06);
    color: var(--warning-700);
  }
  .alm-pill.is-active.tone-info {
    background: var(--info-50);
    border-color: var(--info-200);
    color: var(--info-700);
  }
  .alm-pill.is-active.tone-info .alm-pill-count {
    background: rgba(0, 0, 0, 0.06);
    color: var(--info-700);
  }

  /* ── CARDS DE ALERTA M2 (specs exactos Grovex DS) ── */
  .alm-cards {
    display: flex;
    flex-direction: column;
    gap: 8px;
  } /* M2 spec: 8px */

  .alm-card {
    background: #fff;
    border: 1px solid var(--border);
    border-left: 3px solid #94a3b8; /* M2 spec: 3px no 4 · default slate */
    border-radius: 10px; /* M2 spec: 10px no 14 */
    padding: 12px 14px; /* M2 spec: 12px 14px */
    box-shadow: var(--shadow-xs);
    transition:
      box-shadow 0.15s,
      border-left-color 0.15s;
  }
  .alm-card:active {
    box-shadow: var(--shadow-sm);
  }
  .alm-card-danger {
    border-left-color: #ef4444;
  } /* M2 spec: red-500 */
  .alm-card-warning {
    border-left-color: #f59e0b;
  } /* M2 spec: amber */
  .alm-card-info {
    border-left-color: #3b82f6;
  } /* M2 spec: blue-500 */

  .alm-card-head {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 0;
  }
  .alm-card-id {
    /* = .t-overline mono · 11px / 700 / .02em uppercase muted */
    font-family: var(--font-mono);
    font-size: 11px;
    font-weight: 700;
    color: var(--text-muted);
    letter-spacing: 0.02em;
    text-transform: uppercase;
  }
  .alm-card-badge {
    /* badge tonal · 11px / 700 con tone variants */
    font-size: 11px;
    font-weight: 700;
    padding: 2px 8px;
    border-radius: 999px;
    border: 1px solid transparent;
  }
  .alm-card-badge-danger {
    background: var(--danger-50);
    color: var(--danger-700);
    border-color: var(--danger-200);
  }
  .alm-card-badge-warning {
    background: var(--warning-50);
    color: var(--warning-700);
    border-color: var(--warning-200);
  }
  .alm-card-badge-info {
    background: var(--info-50);
    color: var(--info-700);
    border-color: var(--info-200);
  }

  .alm-card-prov {
    font-size: 14px; /* M2 spec: 14px no 16 */
    font-weight: 600; /* M2 spec: 600 no 700 */
    color: var(--text-primary);
    margin-top: 4px;
    line-height: 1.3;
    letter-spacing: -0.01em;
    word-break: break-word;
  }
  .alm-card-meta {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-top: 4px;
    margin-bottom: 12px;
  }
  .alm-card-hace {
    font-size: 11px; /* M2 spec: 11px */
    color: var(--text-muted);
  }
  .alm-card-monto {
    font-size: 14px; /* M2 spec: 14px no 16 */
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    color: var(--text-primary);
  }

  /* Acciones — M2 spec: botones más compactos */
  .alm-card-actions {
    display: flex;
    gap: 6px;
  }
  .alm-card-actions .gx-btn {
    flex: 1;
    min-height: 36px; /* M2 spec: 36px */
    font-size: 12px;
    font-weight: 600;
    border-radius: 8px;
    justify-content: center;
  }
  .alm-card-actions .alm-card-more {
    flex: 0 0 40px;
    font-size: 16px;
    letter-spacing: 1px;
    color: var(--text-muted);
  }

  /* ── EMPTY STATE ── */
  .alm-empty {
    background: #fff;
    border: 1px solid var(--border);
    border-radius: 14px;
    padding: 50px 20px;
    text-align: center;
    color: var(--text-muted);
    font-size: 14px;
  }
  .alm-empty-icon {
    margin-bottom: 12px;
    color: var(--success-500);
    font-size: 32px;
    display: flex;
    justify-content: center;
  }
  .alm-empty-icon svg {
    width: 32px;
    height: 32px;
  }
  .alm-empty-sub {
    font-size: 12px;
    margin-top: 4px;
    color: var(--text-muted);
  }

  /* ════════════════════════════════════════════════════════════════
   UTILITY CLASSES Grovex Mobile DS (M03-M13)
   ────────────────────────────────────────────────────────────────
   Componentes reutilizables extraídos de las pantallas M03-M13.
   Cada clase es atómica — usar a discreción en pages/.
   No rompen nada existente.
   ──────────────────────────────────────────────────────────────── */

  /* ── Segmented Control iOS-style (M04, M11) ──
   Tabs con pill-bg-slate sliding tab. */
  .gx-segctl {
    display: flex;
    background: var(--slate-100);
    border-radius: 10px;
    padding: 3px;
    gap: 0;
    margin-bottom: 12px;
  }
  .gx-segctl-tab {
    flex: 1;
    padding: 8px 4px;
    border-radius: 8px;
    font-size: 12px;
    font-weight: 600;
    cursor: pointer;
    border: none;
    background: transparent;
    color: var(--text-secondary);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 5px;
    font-family: inherit;
    transition: all 0.15s;
  }
  .gx-segctl-tab.is-active {
    background: #fff;
    color: var(--text-primary);
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.06);
  }
  .gx-segctl-tab .gx-segctl-count {
    font-size: 10px;
    font-weight: 700;
    padding: 1px 6px;
    border-radius: 999px;
    background: rgba(0, 0, 0, 0.05);
    color: var(--text-muted);
    font-variant-numeric: tabular-nums;
  }
  .gx-segctl-tab.is-active .gx-segctl-count {
    background: var(--slate-100);
  }

  /* ── Hero Card Gradient Navy (M05, M06, M11) ──
   Card con linear-gradient navy reutilizable. */
  .gx-hero-grad {
    background: linear-gradient(135deg, #0f2e5c, #1b3a6b);
    color: #fff;
    border-radius: 12px;
    padding: 14px;
  }
  .gx-hero-grad-lg {
    padding: 16px 18px;
  }
  .gx-hero-grad-label {
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    opacity: 0.7;
  }
  .gx-hero-grad-title {
    font-size: 14px;
    font-weight: 700;
    margin-top: 4px;
    letter-spacing: -0.01em;
  }
  .gx-hero-grad-metric {
    font-size: 36px;
    font-weight: 700;
    letter-spacing: -0.03em;
    line-height: 1;
    margin-top: 4px;
    font-variant-numeric: tabular-nums;
    font-family: var(--font-mono, ui-monospace, Menlo, monospace);
  }
  .gx-hero-grad-sub {
    font-size: 11px;
    opacity: 0.7;
    margin-top: 3px;
  }
  .gx-hero-grad-bar {
    height: 5px;
    background: rgba(255, 255, 255, 0.15);
    border-radius: 999px;
    margin-top: 12px;
    overflow: hidden;
  }
  .gx-hero-grad-bar > span {
    display: block;
    height: 100%;
    background: linear-gradient(90deg, #34d399, #10b981);
    border-radius: 999px;
  }
  .gx-hero-grad-cta {
    margin-top: 10px;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 11px;
    font-weight: 600;
    padding: 7px 12px;
    border-radius: 8px;
    border: 1px solid rgba(255, 255, 255, 0.2);
    background: rgba(255, 255, 255, 0.1);
    color: #fff;
    cursor: pointer;
    font-family: inherit;
  }

  /* ── Section Header con dot indicator (M11, M12) ──
   "● Listos para retiro · 4 disponibles" pattern */
  .gx-section-hdr {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin: 16px 0 8px;
    padding-left: 4px;
  }
  .gx-section-hdr-l {
    display: inline-flex;
    align-items: center;
    gap: 6px;
  }
  .gx-section-hdr-dot {
    width: 6px;
    height: 6px;
    border-radius: 999px;
    background: var(--success-500);
    flex-shrink: 0;
  }
  .gx-section-hdr-dot.tone-warning {
    background: var(--warning-500);
  }
  .gx-section-hdr-dot.tone-danger {
    background: var(--danger-500);
  }
  .gx-section-hdr-dot.tone-info {
    background: var(--info-500);
  }
  .gx-section-hdr-title {
    font-size: 11px;
    font-weight: 700;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 0.1em;
  }
  .gx-section-hdr-count {
    font-size: 11px;
    color: var(--text-muted);
  }
  .gx-section-hdr-link {
    font-size: 11px;
    font-weight: 600;
    color: var(--red-600, var(--red, #c8102e));
    text-decoration: none;
  }

  /* ── Stack Card · rows en una sola card (M01 "Por vencer") ──
   En lugar de N cards individuales, una card con N rows internas
   separadas por border-top. Más denso y funcional para listas. */
  .gx-stack-card {
    background: #fff;
    border: 1px solid var(--border);
    border-radius: 12px;
    overflow: hidden;
  }
  .gx-stack-row {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 11px 14px;
    border-top: 1px solid var(--border-subtle, #f1f5f9);
  }
  .gx-stack-row:first-child {
    border-top: none;
  }
  .gx-stack-row-id {
    font-size: 11px;
    font-weight: 700;
    color: var(--text-muted);
    min-width: 42px;
    font-variant-numeric: tabular-nums;
    font-family: var(--font-mono, ui-monospace, Menlo, monospace);
  }
  .gx-stack-row-body {
    flex: 1;
    min-width: 0;
  }
  .gx-stack-row-title {
    font-size: 13px;
    font-weight: 600;
    color: var(--text-primary);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .gx-stack-row-sub {
    font-size: 11px;
    color: var(--text-muted);
    margin-top: 1px;
    font-variant-numeric: tabular-nums;
    font-family: var(--font-mono, ui-monospace, Menlo, monospace);
  }
  .gx-stack-row-tag {
    font-size: 11px;
    font-weight: 700;
    padding: 3px 8px;
    border-radius: 999px;
    background: var(--warning-50);
    color: var(--warning-700);
    border: 1px solid var(--warning-100);
    flex-shrink: 0;
  }
  .gx-stack-row-tag.tone-danger {
    background: var(--danger-50);
    color: var(--danger-700);
    border-color: var(--danger-100);
  }
  .gx-stack-row-tag.tone-success {
    background: var(--success-50);
    color: var(--success-700);
    border-color: var(--success-100);
  }
  .gx-stack-row-tag.tone-info {
    background: var(--info-50);
    color: var(--info-700);
    border-color: var(--info-100);
  }

  /* ════════════════════════════════════════════════════════════════
   M04 · Informes hub · mini-hero mobile-only
   ────────────────────────────────────────────────────────────────
   El breadcrumb desktop es muy delgado para mobile; el hero gradient
   da contexto y "mood" navy consistente con M01/M11. */
  .hub-hero-m {
    display: block;
    margin-bottom: 14px;
  }
  .hub-bc {
    display: none !important;
  }

  /* ════════════════════════════════════════════════════════════════
   .gx-tabs → estilo segmented control automático en mobile
   ────────────────────────────────────────────────────────────────
   El componente .gx-tabs (tabs con borderbottom) se transforma a
   segmented control iOS-style en mobile. Cubre tabs en: dashboard
   alerts, OC abiertas, área del jefe, asistente_detalle, etc.
   No toca la lógica JS (sigue funcionando data-action="alertsTab").
   ──────────────────────────────────────────────────────────────── */
  .gx-tabs {
    display: flex !important;
    background: var(--slate-100) !important;
    border-radius: 10px !important;
    padding: 3px !important;
    gap: 0 !important;
    border: none !important;
    height: auto !important;
    margin-bottom: 12px !important;
    overflow-x: auto;
  }
  .gx-tab {
    flex: 1 !important;
    padding: 8px 4px !important;
    border-radius: 8px !important;
    font-size: 12px !important;
    font-weight: 600 !important;
    cursor: pointer !important;
    border: none !important;
    background: transparent !important;
    color: var(--text-secondary) !important;
    display: inline-flex !important;
    align-items: center !important;
    justify-content: center !important;
    gap: 5px !important;
    font-family: inherit !important;
    white-space: nowrap !important;
    margin-bottom: 0 !important;
    transition:
      background 0.15s,
      color 0.15s;
  }
  .gx-tab.is-active {
    background: #fff !important;
    color: var(--text-primary) !important;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.06) !important;
    border-bottom: none !important;
  }
  .gx-tab-count {
    font-size: 10px !important;
    font-weight: 700 !important;
    padding: 1px 6px !important;
    border-radius: 999px !important;
    background: rgba(0, 0, 0, 0.05) !important;
    color: var(--text-muted) !important;
    font-variant-numeric: tabular-nums;
  }
  .gx-tab.is-active .gx-tab-count {
    background: var(--slate-100) !important;
  }

  /* ════════════════════════════════════════════════════════════════
   COMPONENTES PILOTADOS · alineación con sistema tipográfico
   ────────────────────────────────────────────────────────────────
   Las clases legacy mantienen su nombre pero ahora reflejan los
   tamaños canónicos del sistema. Comentarios indican equivalencia
   con .t-* para futura migración. */

  /* (Estos overrides no cambian el render — solo documentan equivalencia) */

  /* ════════════════════════════════════════════════════════════════
   UNIFICAR · .kpi (legacy bodega) → look de .gx-kpi-card (Grovex)
   ────────────────────────────────────────────────────────────────
   El módulo Bodega usa `.kpi` como contenedor de KPI. El módulo
   Adquisiciones usa `.gx-kpi-card`. Para que ambos compartan el
   mismo lenguaje visual en mobile, hacemos que `.kpi` adopte los
   specs de `.gx-kpi-card` (M01 spec).

   Solo afecta mobile <640px — desktop sigue con el look original.
   ──────────────────────────────────────────────────────────────── */
  .kpi {
    padding: 12px 14px !important;
    border-radius: 10px !important;
    border: 1px solid var(--border) !important;
    background: #fff !important;
    box-shadow: var(--shadow-xs) !important;
    transition: none !important; /* sin hover lift en mobile */
  }
  .kpi:hover {
    transform: none !important;
  }
  .kl {
    /* = .t-overline · 10px / 700 / .1em uppercase muted */
    font-size: 10px !important;
    font-weight: 700 !important;
    letter-spacing: 0.1em !important;
    margin-bottom: 4px !important;
    color: var(--text-muted) !important;
  }
  .kv {
    /* = .t-h1 mobile · 22px / 700 / -.02em tabular */
    font-size: 22px !important;
    font-weight: 700 !important;
    letter-spacing: -0.02em !important;
    line-height: 1.05 !important;
  }
  .ks {
    /* = .t-caption · 11px / muted */
    font-size: 11px !important;
    color: var(--text-muted) !important;
    margin-top: 4px !important;
    font-weight: 500 !important;
  }

  /* ════════════════════════════════════════════════════════════════
   UNIFICAR · banners legacy bodega (.orangeb / .blueb / .redb / .greenb)
   ────────────────────────────────────────────────────────────────
   Bodega usa banners propios. Los alineamos al estilo Grovex
   (border-left tone + bg tonal sutil + radius consistente).
   ──────────────────────────────────────────────────────────────── */
  .orangeb,
  .blueb,
  .redb,
  .greenb,
  .corp-red {
    border-radius: 10px !important;
    padding: 12px 14px !important;
    border-left-width: 3px !important;
    border-left-style: solid !important;
  }
  .orangeb {
    background: var(--warning-50) !important;
    border-left-color: var(--warning-500) !important;
    color: var(--warning-700) !important;
  }
  .blueb {
    background: var(--info-50) !important;
    border-left-color: var(--info-500) !important;
    color: var(--info-700) !important;
  }
  .redb,
  .corp-red {
    background: var(--danger-50) !important;
    border-left-color: var(--danger-500) !important;
    color: var(--danger-700) !important;
  }
  .greenb {
    background: var(--success-50) !important;
    border-left-color: var(--success-500) !important;
    color: var(--success-700) !important;
  }

  /* ════════════════════════════════════════════════════════════════
   UNIFICAR · badges de estado bodega (.estadoBadge / .areaBadge / .tipoBadge)
   ────────────────────────────────────────────────────────────────
   Mismo aspecto que .gx-badge / alm-card-badge: pill 11px / 700
   con tone semántico.
   ──────────────────────────────────────────────────────────────── */
  .estadoBadge,
  .areaBadge,
  .tipoBadge {
    font-size: 10px !important;
    font-weight: 700 !important;
    padding: 2px 8px !important;
    border-radius: 999px !important;
    border: 1px solid transparent !important;
    display: inline-flex !important;
    align-items: center !important;
    gap: 4px !important;
  }

  /* ── Collapsible section · default colapsado en mobile (M01) ──
   Para secciones que en desktop son siempre visibles pero en mobile
   ocupan demasiado scroll — ej. ranking de compradores. */
  .gx-collapsible {
    position: relative;
  }
  .gx-collapsible[data-collapsed="true"] > .gx-collapsible-content {
    display: none;
  }
  .gx-collapsible-toggle {
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    padding: 12px 14px;
    background: #fff;
    border: 1px solid var(--border);
    border-radius: 10px;
    color: var(--text-secondary);
    font-size: 13px;
    font-weight: 600;
    font-family: inherit;
    cursor: pointer;
    margin-bottom: 12px;
    transition: all 0.15s;
  }
  .gx-collapsible-toggle:active {
    transform: scale(0.98);
  }
  .gx-collapsible-toggle::after {
    content: "▾";
    font-size: 11px;
    color: var(--text-muted);
    transition: transform 0.2s;
  }
  .gx-collapsible[data-collapsed="true"] .gx-collapsible-toggle::after {
    transform: rotate(-90deg);
  }

  /* (gx-greeting-bell eliminado · duplicaba el bell del topbar #NOTIF_BELL) */
}

/* ════════════════════════════════════════════════════════════════
   2. TABLET · @media (min-width: 640px) and (max-width: 1023.98px)
   ════════════════════════════════════════════════════════════════ */

@media (min-width: 640px) and (max-width: 1023.98px) {
  /* ══════════════════════════════════════════════════════════════
   1. SHELL · Sidebar drawer + topbar + content
   ══════════════════════════════════════════════════════════════ */

  /* Sidebar como drawer (oculto por default, slide-in con .sb-open) */
  .sb {
    position: fixed;
    top: 0;
    left: 0;
    bottom: 0;
    z-index: 100;
    transform: translateX(-100%);
    transition: transform var(--duration-base) var(--ease-out);
    width: 280px;
    box-shadow: 0 0 24px rgba(0, 0, 0, 0.08);
  }
  body.sb-open .sb {
    transform: translateX(0);
  }

  /* Overlay del drawer */
  .sb-ov {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.4);
    z-index: 99;
    opacity: 0;
    visibility: hidden;
    transition:
      opacity var(--duration-base) var(--ease-out),
      visibility 0s linear var(--duration-base);
  }
  body.sb-open .sb-ov {
    opacity: 1;
    visibility: visible;
    transition:
      opacity var(--duration-base) var(--ease-out),
      visibility 0s;
  }

  /* Botón cerrar drawer visible solo cuando está abierto */
  .sb-hd .sb-close {
    display: inline-flex;
  }

  /* Main toma todo el ancho (no hay sidebar fijo restando espacio) */
  .main {
    margin-left: 0;
  }

  /* Botón hamburguesa visible en topbar */
  .mhbtn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    background: transparent;
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    cursor: pointer;
    color: var(--text-primary);
  }
  .mhbtn:hover {
    background: var(--slate-50);
  }
  .mhbtn svg {
    width: 20px;
    height: 20px;
  }

  /* ── TOPBAR tablet — fila horizontal con prioridad de ancho ──
   Layout: hamburger | título+subtítulo flex (con ellipsis) | acciones
   Sin wrap a columna — siempre en una sola fila. Si las acciones son
   muchas, el último div hace flex-wrap interno hacia abajo. */
  .topbar {
    padding: 14px 20px;
    gap: 14px;
    flex-wrap: nowrap;
    align-items: center;
  }
  .topbar > div:nth-child(2) {
    min-width: 0;
    flex: 1 1 0;
  }
  .topbar > div:nth-child(3) {
    flex: 0 1 auto;
    flex-wrap: wrap;
    justify-content: flex-end;
    min-width: 0;
  }
  .ptit {
    font-size: 20px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .psub {
    font-size: 12px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 100%;
  }

  /* Content padding intermedio */
  .content {
    padding: 20px;
  }

  /* Bottom tabs ocultos en tablet — el drawer es suficiente */
  .btab {
    display: none;
  }

  /* ══════════════════════════════════════════════════════════════
   2. KPI GRIDS · 2 columnas en tablet (vs 4 desktop, 1 mobile)
   ══════════════════════════════════════════════════════════════ */

  /* Grids inline-style con 4/5/6 columnas → 2 columnas en tablet */
  [style*="grid-template-columns:repeat(4"],
  [style*="grid-template-columns:repeat(5"],
  [style*="grid-template-columns:repeat(6"],
  [style*="grid-template-columns: repeat(4"],
  [style*="grid-template-columns: repeat(5"],
  [style*="grid-template-columns: repeat(6"] {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  /* Grids de 3 columnas se mantienen en 3 (hay espacio) */

  .gx-kpi-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  /* ══════════════════════════════════════════════════════════════
   3. TABLAS · scroll horizontal cómodo (NO convertir a cards)
   ══════════════════════════════════════════════════════════════ */

  /* Tabla con scroll horizontal — cabe más info que en mobile */
  .gx-table {
    min-width: 700px;
    font-size: 12px;
  }
  .gx-table thead th {
    padding: 10px 12px;
    font-size: 11px;
  }
  .gx-table tbody td {
    padding: 10px 12px;
  }

  /* Avatares en tablas — tamaño normal */
  .gx-table .gx-avatar {
    width: 22px;
    height: 22px;
    font-size: 10px;
  }

  /* ══════════════════════════════════════════════════════════════
   4. CARDS · espaciado intermedio
   ══════════════════════════════════════════════════════════════ */

  .gx-card {
    padding: 16px;
    border-radius: 12px;
  }

  /* ── Greeting card en tablet ──
   Layout en 2 filas: avatar+título (fila 1) | stats inline (fila 2)
   Esto evita que las stats consuman ancho y rompan el título en
   columna palabra-por-palabra. */
  .gx-greeting {
    padding: 18px 22px;
    border-radius: 14px;
    flex-wrap: wrap;
    align-items: center;
    gap: 14px;
  }
  /* Container título+descripción: prioridad de ancho en fila 1 */
  .gx-greeting > div:nth-child(2) {
    flex: 1 1 200px;
    min-width: 0;
  }
  .gx-greeting > div:nth-child(2) > div:first-child {
    font-size: 18px;
    line-height: 1.3;
  }
  .gx-greeting > div:nth-child(2) > div:nth-child(2) {
    font-size: 13px;
    line-height: 1.5;
  }

  /* Stats SIEMPRE van en fila 2, ocupando todo el ancho */
  .gx-greeting-stats {
    flex: 1 1 100%;
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 12px;
    padding-top: 12px;
    margin-top: 4px;
    border-top: 1px solid var(--border);
  }
  .gx-greeting-stats > div {
    padding: 0;
    text-align: left;
  }

  /* ══════════════════════════════════════════════════════════════
   5. FILTER BARS · más compactos pero horizontales
   ══════════════════════════════════════════════════════════════ */

  .fbar {
    padding: 10px 14px;
    gap: 10px;
    flex-wrap: wrap;
  }

  /* Search box ocupa toda la primera fila si los filtros se wrappean */
  .fbar .gx-search {
    min-width: 220px;
    flex: 1 1 220px;
  }

  /* ══════════════════════════════════════════════════════════════
   6. MODALES · 92vw máximo (zona táctil cómoda)
   ══════════════════════════════════════════════════════════════ */

  .mbox {
    width: 92vw;
    max-width: 720px;
    border-radius: 14px;
    padding: 24px 22px;
  }
  .mbox-lg {
    width: 96vw;
    max-width: 920px;
  }

  /* ══════════════════════════════════════════════════════════════
   7. PÁGINAS ESPECÍFICAS · ajustes puntuales
   ══════════════════════════════════════════════════════════════ */

  /* Dashboard quick actions: ocultas en tablet — el drawer + sidebar tiene
   acceso completo a las páginas. Las quick actions son atajos UX para
   mobile donde la nav es más limitada. */
  .gx-quick-actions {
    display: none;
  }

  /* OC Abiertas: la tabla se mantiene, ocultar las cards mobile */
  .oa-mlist {
    display: none;
  }
  .oa-desktop-table {
    display: block;
  }

  /* Acción row en OC Abiertas — botones más cómodos */
  .oa-mcard-actions {
    display: none;
  }

  /* Alertas: ocultar layout mobile (banner + pills + cards M2).
   No necesitamos forzar .alm-desktop-only — sus inline styles
   (display:grid/flex) ya lo muestran correctamente. */
  .alm-mobile-only {
    display: none;
  }

  /* ══════════════════════════════════════════════════════════════
   8. SECTION HEADERS · padding intermedio
   ══════════════════════════════════════════════════════════════ */

  .gx-panel-head {
    padding: 12px 16px;
    gap: 12px;
  }

  .gx-panel-title {
    font-size: 14px;
  }

  /* ══════════════════════════════════════════════════════════════
   9. ADICIONALES (ex-migradas desde main.css)
   ══════════════════════════════════════════════════════════════
   Reglas adicionales que NO duplican lo definido arriba (1-8).
   Cubren: grids inline-style, touch targets WCAG, tablas responsive,
   tabs scroll, banners stack. SIN duplicados, SIN !important
   innecesarios. Las reglas de .topbar/.ptit/.psub/.mbox ya viven
   en sus secciones canónicas arriba.
   ══════════════════════════════════════════════════════════════ */

  /* g-area legacy → 1 columna */
  .g-area {
    grid-template-columns: 1fr;
  }

  /* Alert columns y k4/g2/k3 → adaptados a tablet */
  .alert-cols {
    grid-template-columns: 1fr;
  }
  .k4 {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
  .k3 {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
  .g2 {
    grid-template-columns: 1fr;
  }

  /* KPI grids inline-style → 2 columnas (más coherente con tablet portrait) */
  .content [style*="repeat(4,1fr)"] {
    grid-template-columns: repeat(2, 1fr);
  }
  .content [style*="repeat(5,1fr)"] {
    grid-template-columns: repeat(2, 1fr);
  }
  .content [style*="repeat(3,1fr)"] {
    grid-template-columns: repeat(2, 1fr);
  }

  /* Auto-fit grids con minmax grandes (ej. ranking + gasto en Rendimiento) → 1 col */
  div[style*="grid-template-columns:repeat(auto-fit,minmax(420px,1fr))"] {
    grid-template-columns: 1fr;
  }

  /* ── Touch targets WCAG 2.5.5 (mínimo 44×44px) ──
   En tablet los usuarios suelen tocar con dedo, los botones legacy
   .btn deben tener tamaño cómodo. */
  .btn {
    min-height: var(--tap-min);
    padding: 10px 18px;
    font-size: var(--text-md);
  }
  .btn.bsm {
    min-height: 38px;
    padding: 8px 14px;
    font-size: var(--text-sm);
  }
  .btn.bic {
    min-height: var(--tap-min);
    min-width: var(--tap-min);
    padding: 10px;
  }
  .ni {
    min-height: var(--tap-min);
    padding: 11px 12px;
  }
  .tgb {
    min-height: 38px;
    padding: 8px 18px;
  }

  /* Inputs con font-size legible (evita zoom auto en iOS al focusear) */
  .inp {
    padding: 12px 14px;
    border-radius: var(--radius-lg);
  }
  input[type="date"] {
    height: var(--tap-min);
    padding: 10px 14px;
  }

  /* Sidebar items con tap cómodo */
  .sb-nav {
    padding: 10px;
  }
  .nsec {
    padding: 14px 12px 6px;
  }

  /* ── Tablas .tw con scroll horizontal cómodo en tablet ──
   En vez de truncar, dejamos scroll para ver toda la info. */
  .tw table {
    min-width: 560px;
  }
  .tw thead th,
  .tw tbody td {
    padding: 8px 10px;
    font-size: 11px;
  }

  /* ── Tablas .tbl-responsive (opt-in card view) ──
   Para tablas que opten al card-view en tablet portrait pequeño.
   En desktop y >tablet se mantienen como tabla normal. */
  table.tbl-responsive,
  table.tbl-responsive thead,
  table.tbl-responsive tbody,
  table.tbl-responsive th,
  table.tbl-responsive td,
  table.tbl-responsive tr {
    display: block;
  }
  table.tbl-responsive thead {
    border: 0;
    clip: rect(0 0 0 0);
    height: 1px;
    margin: -1px;
    overflow: hidden;
    padding: 0;
    position: absolute;
    width: 1px;
  }
  table.tbl-responsive tr {
    margin-bottom: var(--space-3);
    background: var(--s0);
    border: 1px solid var(--b0);
    border-radius: var(--radius-lg);
    padding: var(--space-3);
    box-shadow: var(--shadow-xs);
  }
  table.tbl-responsive td {
    padding: var(--space-1) 0;
    border: 0;
    text-align: left;
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: var(--space-3);
  }
  table.tbl-responsive td::before {
    content: attr(data-label);
    font-size: var(--text-xs);
    font-weight: var(--font-weight-semibold);
    color: var(--t3);
    text-transform: uppercase;
    letter-spacing: 0.4px;
    flex-shrink: 0;
  }
  table.tbl-responsive td:not([data-label]) {
    justify-content: flex-start;
  }
  table.tbl-responsive td:not([data-label])::before {
    content: none;
  }
  .tw:has(table.tbl-responsive) {
    overflow-x: visible;
  }

  /* ── Tabs horizontales con scroll en tablet pequeño ── */
  div[style*="border-bottom:1px solid var(--border)"][style*="background:var(--slate-50)"][style*="height:38px"] {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    flex-wrap: nowrap;
  }

  /* ── Banner critical / alert: stack vertical si no entra ── */
  .gx-critical {
    flex-wrap: wrap;
  }
  .gx-critical-icon,
  .gx-critical > div:first-of-type {
    flex-shrink: 0;
  }

  /* ── Greeting avatar tamaño tablet (40px) ──
   Stats inline ya están definidos en sección "4. CARDS" arriba — no duplicar */
  .gx-greeting > .gx-avatar {
    width: 40px;
    height: 40px;
    font-size: var(--text-md);
  }

  /* ── Filter bars: select dentro de filter row toma 100% si wrap ── */
  div[style*="background:#fff"][style*="border-radius:var(--radius-md)"][style*="flex-wrap:wrap"] > .gx-select {
    flex: 1 1 100%;
    min-width: 0;
  }

  /* ══════════════════════════════════════════════════════════════
   10. PRINT · respetar layout normal cuando se imprime desde tablet
   ══════════════════════════════════════════════════════════════ */

  @media print {
    /* Las reglas print viven en main.css — solo overrides puntuales */
    .sb,
    .sb-ov,
    .mhbtn,
    .btab {
      display: none;
    }
    .main {
      margin: 0;
    }
    .content {
      padding: 0;
    }
  }

  /* ── Collapsible: en tablet también always-expanded (es exclusivo mobile). ── */
  .gx-collapsible-toggle {
    display: none !important;
  }
  .gx-collapsible[data-collapsed="true"] > .gx-collapsible-content {
    display: block !important;
  }

  /* ══════════════════════════════════════════════════════════════
   11. PRO REFINEMENTS · pulido nivel "production-grade" para tablet
   ══════════════════════════════════════════════════════════════
   Lo siguiente lleva el tablet design del estándar "funcional"
   al nivel "pro". Specs derivadas de scaling proporcional entre
   M01-M13 (mobile, 390px) y desktop (1440px+).
   ══════════════════════════════════════════════════════════════ */

  /* ── HERO greeting con stats al costado (3 col grid) ──
   En mobile el hero es compacto (avatar+greeting arriba, stats abajo).
   En desktop hay más espacio (stats al costado).
   Tablet: aprovechar el ancho con stats al costado pero más compactas. */
  .gx-greeting {
    display: grid;
    grid-template-columns: auto 1fr auto;
    gap: 14px;
    align-items: center;
    flex-wrap: nowrap;
  }
  .gx-greeting > div:nth-child(2) {
    min-width: 0;
  }
  .gx-greeting-stats {
    flex: 0 0 auto;
    display: grid;
    grid-template-columns: repeat(3, auto);
    gap: 16px;
    padding-top: 0;
    padding-left: 16px;
    margin-top: 0;
    border-top: none;
    border-left: 1px solid var(--border);
  }
  .gx-greeting-stats > div {
    padding: 0 4px;
    text-align: left;
  }

  /* ── KPI grids · 3 col en tablet (intermedio entre mobile 2-col y desktop 4-col) ──
   Aprovecha el ancho 768-1023px sin apretar las cards. */
  [style*="grid-template-columns:repeat(4"],
  [style*="grid-template-columns:repeat(5"],
  [style*="grid-template-columns: repeat(4"],
  [style*="grid-template-columns: repeat(5"] {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }

  /* ── KPI cards · padding intermedio (entre mobile 12x14 y desktop 18x20) ── */
  .gx-kpi-card,
  .kpi {
    padding: 14px 16px;
  }
  .gx-kpi-card > div:nth-child(2),
  .kv {
    font-size: 24px; /* desktop 28-30, mobile 22 — tablet 24 intermedio */
  }

  /* ── Cards padding intermedio · pulido pro ── */
  .gx-card,
  .card {
    padding: 18px;
    border-radius: 14px; /* sutil más redondeado que mobile (10), menos que desktop (16) */
  }

  /* ── Section heads · espaciado tablet ── */
  .gx-section-head {
    margin-top: 8px;
    margin-bottom: 12px;
  }

  /* ── Topbar · título destacado · más espacio ── */
  .ptit {
    font-size: 22px; /* mobile 16, tablet 22, desktop 24 */
    font-weight: 700;
    letter-spacing: -0.02em;
  }
  .psub {
    font-size: 13px; /* +1px vs mobile */
    margin-top: 2px;
  }

  /* ── Filter bars · search expandido (no flex 1 1 100% mobile-style) ── */
  .gx-search {
    flex: 1 1 320px !important;
    min-width: 240px;
    max-width: 480px;
  }

  /* ── Buttons en topbar tablet · permitir texto (no icon-only como mobile) ── */
  .topbar .tact .gx-btn,
  .topbar .tact .gx-btn-sm {
    padding: 0 12px;
    font-size: 12px;
    width: auto;
    height: 32px;
    font-size: 12px;
  }
  .topbar .tact .gx-btn:has(> svg:only-child),
  .topbar .tact .gx-btn-sm:has(> svg:only-child) {
    width: 32px;
    padding: 0;
  }
  .topbar .tact > *:not(.gx-btn-primary) {
    display: inline-flex !important; /* en tablet sí se ven todos los botones */
  }

  /* ── Modales · width óptima tablet ── */
  .mbox {
    width: 88vw;
    max-width: 600px;
    border-radius: 16px;
    padding: 24px;
  }

  /* ── Animaciones más sutiles para tablet (entre mobile y desktop) ── */
  .gx-card,
  .kpi,
  .card {
    transition:
      border-color var(--duration-fast) var(--ease-out),
      box-shadow var(--duration-fast) var(--ease-out);
  }
  .gx-card:hover,
  .card:hover {
    border-color: var(--border-strong);
    box-shadow: var(--shadow-sm);
  }

  /* ── Pills de OC abiertas (M03) — mobile-only ── */
  .oa-pills {
    display: none !important;
  }

  /* ── Hub Informes mini-hero (M04) — mobile-only · breadcrumb tablet ── */
  .hub-hero-m {
    display: none !important;
  }
  .hub-bc {
    display: flex !important;
  }
}

/* ════════════════════════════════════════════════════════════════
   3. DESKTOP · @media (min-width: 1024px)
   ════════════════════════════════════════════════════════════════
   Nota: los sub-rangos internos del archivo desktop original eran
   @media nested. Acá los aplanamos a queries compuestos (min+max)
   al nivel top para máxima compatibilidad.
   ════════════════════════════════════════════════════════════════ */

@media (min-width: 1024px) {
  /* Componentes mobile-only · ocultos en desktop */
  .btab {
    display: none;
  }
  .gx-quick-actions {
    display: none;
  }
  .oa-mlist {
    display: none;
  }
  .alm-mobile-only {
    display: none;
  }

  /* Collapsible: en desktop el toggle siempre oculto, content siempre visible */
  .gx-collapsible-toggle {
    display: none !important;
  }
  .gx-collapsible[data-collapsed="true"] > .gx-collapsible-content {
    display: block !important;
  }

  /* Pills de OC abiertas (M03) — mobile-only */
  .oa-pills {
    display: none !important;
  }

  /* Hub Informes mini-hero (M04) — mobile-only · breadcrumb desktop */
  .hub-hero-m {
    display: none !important;
  }
  .hub-bc {
    display: flex !important;
  }
}

/* ════════════════════════════════════════════════════════════════
   3a. DESKTOP PEQUEÑO · 1024-1280px (drawer + densidad reducida)
   ════════════════════════════════════════════════════════════════
   Tablet K11 landscape (~1280) y portátiles 1024-1280: sidebar como
   drawer (no fijo). KPI grids 4col → 2-3col. Tablas con scroll
   horizontal en lugar de truncar.
   ════════════════════════════════════════════════════════════════ */

@media (min-width: 1024px) and (max-width: 1280px) {
  /* Sidebar drawer */
  .mhbtn {
    display: inline-flex;
  }
  .sb {
    position: fixed;
    top: 0;
    left: 0;
    bottom: 0;
    width: 240px;
    height: 100vh;
    z-index: 500;
    transform: translateX(-100%);
    transition: transform 0.26s ease;
    box-shadow: 4px 0 24px rgba(0, 0, 0, 0.35);
  }
  .sb-hd {
    min-height: 60px;
    justify-content: flex-start;
    padding: 12px 14px;
  }
  .sb-hd img {
    width: 140px;
  }
  .sb-hd .sb-close {
    display: inline-flex;
  }
  .ni {
    padding: 9px 10px;
    font-size: 12px;
    gap: 9px;
  }
  .nsec {
    padding: 14px 12px 6px;
    font-size: 10px;
  }
  body.sb-open .sb {
    transform: translateX(0);
  }
  .main {
    width: 100%;
  }

  /* Topbar + content compactos */
  .topbar {
    padding: 12px 14px 0;
    align-items: center;
  }
  .content {
    padding: 12px 14px 22px;
  }
  .ptit {
    font-size: 19px;
  }

  /* KPI grids reducidos */
  .k4 {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
  .k3 {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
  .g2 {
    grid-template-columns: 1fr;
  }
  .rpkr {
    grid-template-columns: repeat(2, 1fr);
  }
  .rpk:nth-child(2n) {
    border-right: none;
  }

  /* Tablas con scroll horizontal */
  .tw {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
  }
  .tw::-webkit-scrollbar {
    height: 8px;
  }
  .tw::-webkit-scrollbar-thumb {
    background: rgba(1, 45, 85, 0.35);
  }
  table:not(.rptb) {
    table-layout: auto;
  }
  .tw table {
    width: auto;
    min-width: 100%;
  }
  thead th,
  tbody td {
    padding: 8px 10px;
    font-size: 11px;
    white-space: nowrap;
    overflow: visible;
    text-overflow: clip;
  }
  thead th[style*="width"] {
    width: auto !important;
    min-width: auto;
  }
  tbody td .btn.bsm {
    padding: 4px 9px;
    font-size: 10px;
  }
  tbody td .btn.bic {
    padding: 5px;
  }
  [style*="overflow-x:auto"]::-webkit-scrollbar {
    height: 8px;
  }
  [style*="overflow-x:auto"]::-webkit-scrollbar-thumb {
    background: rgba(1, 45, 85, 0.35);
  }
  .mbox .tw {
    max-width: 100%;
  }
  .mbox table {
    min-width: auto;
  }

  /* KPI strips Grovex 5col → 3col */
  div[style*="grid-template-columns:repeat(5,minmax(0,1fr))"],
  div[style*="grid-template-columns:repeat(5, minmax(0, 1fr))"] {
    grid-template-columns: repeat(3, minmax(0, 1fr)) !important;
  }

  /* Filter bar Grovex stack en pantalla mediana */
  div[style*="background:#fff"][style*="border-radius:var(--radius-md)"][style*="flex-wrap:wrap"] > .gx-search {
    width: 100% !important;
  }
}

/* ════════════════════════════════════════════════════════════════
   3b. DESKTOP INTERMEDIO · 1024-1200px (sidebar más angosto)
   ════════════════════════════════════════════════════════════════ */

@media (min-width: 1024px) and (max-width: 1200px) {
  :root {
    --sb: 200px;
  }
  .sb-hd img {
    width: 130px;
  }
  .content {
    padding: 12px 16px 24px;
  }
  .k4 {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  /* Grids inline-style adaptados */
  .content [style*="repeat(4,1fr)"] {
    grid-template-columns: repeat(2, 1fr) !important;
  }
  .content [style*="repeat(5,1fr)"] {
    grid-template-columns: repeat(3, 1fr) !important;
  }
}

/* ════════════════════════════════════════════════════════════════
   3c. DESKTOP GRANDE · 1024-1400px (padding ajustado + alert cols)
   ════════════════════════════════════════════════════════════════ */

@media (min-width: 1024px) and (max-width: 1400px) {
  .content {
    padding: 14px 20px 28px;
  }
  .alert-cols {
    grid-template-columns: repeat(2, 1fr) !important;
  }
}
