/* =============================================================================
   SISTEMA VISUAL DEL PANEL — ESTRUCTURA COMPARTIDA (plataforma DIADOLOS)
   -----------------------------------------------------------------------------
   Una sola hoja para TODO el panel. No hay CSS de identidad repetido pantalla por
   pantalla: las vistas usan estas clases y, como mucho, agregan reglas de
   composición propias de esa pantalla (una grilla, un ancho de columna).

   ESTA HOJA NO ES DE NINGÚN CLIENTE (Bloque 11)

   Hasta el Bloque 11 se declaraba acá la identidad del primer comercio —su azul y
   su amarillo—, así que ésa era la identidad por omisión de TODOS: un cliente nuevo
   entraba a su panel y veía la marca de otro. Ahora cada comercio tiene su propio
   archivo en css/tenants/, y acá quedan dos cosas: la ESTRUCTURA (espaciado,
   tipografía, formas, componentes) y, como valor por omisión, la identidad NEUTRA
   de la plataforma.

   LAS DOS CAPAS SIGUEN SIENDO DOS, y es lo que hace que un tema sea un puñado de
   valores y no una hoja entera:

     --panel-principal    QUE color es          (identidad: la pone el tema)
     --color-primary      PARA QUE se usa       (rol: lo mapea esta hoja)

   Los nombres de la capa de identidad ya no nombran a un cliente ni a un color
   concreto (el viejo nombre decía "azul" y el de un cliente): el color principal de un
   comercio puede ser rojo. Es el mismo renombre que login.css hizo en el Bloque 9,
   por el mismo motivo, y no cambia ningún valor computado.

   ORDEN DE CARGA: site.css, después login.css en las pantallas públicas, y al final
   css/tenants/<tema>.css, que gana sobre las dos. Un comercio sin tema propio se
   queda con lo neutro de acá, nunca con la identidad de otro.

   RELACION CON EL LOGIN: login.css es autónomo —no referencia ningún --color-* de
   acá— y se carga DESPUES de esta hoja. El único riesgo real sería agregar acá
   reglas sobre selectores de elemento desnudos que el acceso no sobreescriba; por
   eso casi todo cuelga de clases.

   TEMA OSCURO: sigue existiendo (ver theme.js, con test). La identidad se mantiene
   en los dos temas; lo que cambia es el fondo y la superficie.
   ========================================================================== */

:root {
    /* -- Identidad NEUTRA de la plataforma: QUE color es -----------------
       Es la de DIADOLOS, deliberadamente distinta de la de cualquier cliente, y
       la pisa el tema del comercio cuando tiene uno. */
    --panel-profundo: #1d2235;
    --panel-oscuro: #2b3353;
    --panel-principal: #3f4a73;
    --panel-claro: #6b7aa8;
    --panel-acento: #c7ccd8;
    --panel-acento-nav: #dfe3ec;
    --panel-suave: #eef0f5;
    --panel-texto: #1d2235;
    --panel-texto-suave: #5a6172;

    /* Colores de los cuadrados de icono de las tarjetas de inicio. Cada tarjeta
       tiene el suyo y no se derivan de los roles de abajo: son parte de la
       composición, no del sistema de acciones, así que cada tema trae los suyos. */
    --panel-tile-1: #4a5680;
    --panel-tile-2: #6b7aa8;
    --panel-tile-3: #8d9ac2;

    /* -- Roles: PARA QUE se usa ------------------------------------------ */
    --color-bg: #f3f4f7;
    --color-surface: #ffffff;
    --color-surface-alt: var(--panel-suave);
    --color-border: #dfe1e8;
    --color-border-strong: #c6cad5;
    --color-text: var(--panel-texto);
    --color-text-muted: var(--panel-texto-suave);

    --color-primary: var(--panel-principal);
    --color-primary-dark: var(--panel-oscuro);
    --color-primary-soft: rgba(63, 74, 115, 0.08);
    --color-on-primary: #ffffff;

    --color-accent: var(--panel-acento);
    --color-accent-strong: #b3b9c8;
    --color-on-accent: var(--panel-profundo);

    /* La cabecera es la única superficie oscura del panel en tema claro, así que
       tiene sus propios tokens: el resto del sistema no debe tener que saber que
       existe una zona invertida. El amarillo del texto de navegación es MÁS claro
       que el de la pastilla activa: sobre el tono profundo, el de la pastilla se apaga. */
    --color-header-bg: var(--panel-profundo);
    --color-header-text: var(--panel-acento-nav);
    --color-header-hover: rgba(255, 255, 255, 0.1);
    --color-header-divider: rgba(255, 255, 255, 0.22);

    --color-danger: #c0392b;

    --color-row-alt: rgba(29, 34, 53, 0.025);
    --color-success-bg: #e4f4ea;
    --color-success-border: #b5e0c4;
    --color-success-text: #155c31;
    --color-warning-bg: #fdf3d6;
    --color-warning-border: #f0dca0;
    --color-warning-text: #7a5600;
    --color-danger-bg: #fbe4e1;
    --color-danger-border: #f2b8b0;
    --color-danger-text: #7a231a;
    --color-muted-bg: #eceef3;
    --color-info-bg: var(--panel-suave);
    --color-info-border: #ccd2e2;
    --color-info-text: #394166;

    /* -- Espaciado: escala de 4px ---------------------------------------- */
    --space-1: 0.25rem;
    --space-2: 0.5rem;
    --space-3: 0.75rem;
    --space-4: 1rem;
    --space-5: 1.5rem;
    --space-6: 2rem;
    --space-7: 3rem;

    /* -- Tipografía ------------------------------------------------------- */
    --text-xs: 0.75rem;
    --text-sm: 0.875rem;
    --text-base: 1rem;
    --text-lg: 1.125rem;
    --text-xl: 1.375rem;
    --text-2xl: 1.75rem;

    --weight-medium: 500;
    --weight-semibold: 600;
    --weight-bold: 700;

    --leading-tight: 1.2;
    --leading-normal: 1.55;

    /* -- Forma y profundidad ---------------------------------------------- */
    --radius-sm: 8px;
    --radius: 12px;
    --radius-lg: 20px;
    --radius-pill: 999px;

    /* Sombras MUY sutiles: la jerarquía la da el borde y el fondo, no el drama.
       --shadow-card es la de las tarjetas del inicio del mockup: difusa, amplia y
       sin borde, que es lo que les da el aire de estar apoyadas sobre el fondo. */
    --shadow-sm: 0 1px 2px rgba(20, 22, 30, 0.05);
    --shadow-md: 0 4px 14px rgba(20, 22, 30, 0.07);
    --shadow-lg: 0 16px 40px rgba(20, 22, 30, 0.16);
    --shadow-card: 0 10px 30px rgba(20, 22, 30, 0.08);

    --focus-ring: 0 0 0 3px rgba(63, 74, 115, 0.3);
    --transition: 150ms ease;

    /* Altura mínima de cualquier control táctil. 44px es el piso de las guías de
       accesibilidad y el valor que se verificó a 375px. */
    --tap-target: 44px;

    font-family: "Segoe UI", system-ui, -apple-system, BlinkMacSystemFont, Roboto, Helvetica, Arial, sans-serif;
}

:root[data-theme="dark"] {
    --color-bg: #12141a;
    --color-surface: #1a1d26;
    --color-surface-alt: #222632;
    --color-border: #2e323d;
    --color-border-strong: #414653;
    --color-text: #e8ecf3;
    --color-text-muted: #9aa8bd;

    /* El azul institucional no tiene contraste suficiente sobre fondo oscuro:
       en tema oscuro el rol "primary" lo toma el azul claro de la identidad. */
    --color-primary: var(--panel-claro);
    --color-primary-dark: #8d9ac2;
    --color-primary-soft: rgba(107, 122, 168, 0.16);
    --color-on-primary: #0e1018;

    --color-header-bg: #14161d;
    --color-header-divider: rgba(255, 255, 255, 0.16);

    --color-danger: #e0574a;

    --color-row-alt: rgba(255, 255, 255, 0.03);
    --color-success-bg: #1a3626;
    --color-success-border: #2d6440;
    --color-success-text: #9fe0af;
    --color-warning-bg: #352c19;
    --color-warning-border: #65552b;
    --color-warning-text: #f0cd7a;
    --color-danger-bg: #36211e;
    --color-danger-border: #67372f;
    --color-danger-text: #f0a89f;
    --color-muted-bg: #262a34;
    --color-info-bg: #1e2230;
    --color-info-border: #343a4c;
    --color-info-text: #c2c8da;

    --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.4);
    --shadow-md: 0 4px 14px rgba(0, 0, 0, 0.45);
    --shadow-lg: 0 16px 40px rgba(0, 0, 0, 0.6);
    --shadow-card: 0 10px 30px rgba(0, 0, 0, 0.42);
    --focus-ring: 0 0 0 3px rgba(107, 122, 168, 0.45);
}

* {
    box-sizing: border-box;
}

/* Lo único que vale para TODAS las pantallas, públicas incluidas. Son los dos
   valores que el acceso aprobado ya tenía en producción, así que mantenerlos
   globales no lo cambia. */
body {
    margin: 0;
    line-height: var(--leading-normal);
}

/* EL ÁMBITO VA CON :where() Y NO CON .app-shell A SECAS.
   `:where(.app-shell) h1` pesa lo mismo que `h1` a secas: (0,0,1). Así acotar el
   panel NO le sube la especificidad a ninguna regla, y los estilos propios de cada
   pantalla (una clase, (0,1,0)) siguen ganando como antes. Con `.app-shell h1`
   —(0,1,1)— pasaba lo contrario: el saludo del inicio quedaba en 28px porque la
   regla genérica del panel le ganaba a su propia clase.

   Fondo, color de texto y suavizado son del PANEL y no pueden alcanzar al acceso:
   el panel derecho del acceso es transparente, así que el fondo del <body> ES lo
   que se ve detrás de la tarjeta de ingreso. Cuando esto estaba suelto en `body`,
   repintar --color-bg le cambió ese fondo al acceso; y el antialiased, que en el
   panel es cosmético, en macOS afina toda la tipografía del acceso. */
body.app-shell {
    background: var(--color-bg);
    color: var(--color-text);
    -webkit-font-smoothing: antialiased;
    /* La composición de marca del inicio sangra hasta el borde de la ventana saliendo
       del contenedor centrado (ver .home-art). `clip` recorta ese desborde sin crear
       un contenedor de scroll — por eso NO es `hidden`, que rompería la cabecera fija. */
    overflow-x: clip;
}

:where(.app-shell) a {
    color: var(--color-primary);
}

/* =========================================================================
   TIPOGRAFIA
   ========================================================================= */

:where(.app-shell) h1 {
    font-size: var(--text-2xl);
    font-weight: var(--weight-bold);
    line-height: var(--leading-tight);
    letter-spacing: -0.015em;
    margin: 0 0 var(--space-2);
}

:where(.app-shell) h2 {
    font-size: var(--text-xl);
    font-weight: var(--weight-semibold);
    line-height: var(--leading-tight);
    margin: var(--space-6) 0 var(--space-3);
}

:where(.app-shell) h3 {
    font-size: var(--text-lg);
    font-weight: var(--weight-semibold);
    margin: var(--space-5) 0 var(--space-2);
}

:where(.app-shell) h4 {
    font-size: var(--text-base);
    font-weight: var(--weight-semibold);
    margin: 0 0 var(--space-2);
}

:where(.app-shell) p {
    margin: 0 0 var(--space-3);
}

/* =========================================================================
   CABECERA GLOBAL
   -------------------------------------------------------------------------
   Reproduce el mockup aprobado: una sola fila sobre azul profundo, logo real y
   marca en dos líneas a la izquierda, los diez destinos al medio con el ICONO
   ARRIBA del nombre, y a la derecha el nombre del usuario con su avatar.

   El icono arriba del nombre es lo que hace que los diez entren en una fila a
   1280px: medido, con icono y nombre en línea sumaban ~1010px y el último destino
   quedaba tapado por el avatar; apilados suman ~800px.

   No hay botón de menú en ningún ancho (decisión explícita). En pantallas angostas
   la fila de destinos se desplaza en horizontal DENTRO de la barra; la página nunca
   scrollea de costado.
   ========================================================================= */

.app-header {
    position: sticky;
    top: 0;
    z-index: 50;
    background: var(--color-header-bg);
    box-shadow: var(--shadow-md);
}

/* Las medidas van con clamp() contra el ancho de la ventana, no fijas: así la barra
   reproduce EXACTAMENTE el mockup a su tamaño nativo (1672px: alto 112, logo 72,
   icono 26, nombre 15px) y baja de forma proporcionada en pantallas más chicas
   (1280px: alto 86, logo 55, icono 20, nombre 11,5px). */
.app-header__inner {
    max-width: 1700px;
    margin: 0 auto;
    padding: 0 clamp(var(--space-3), 1.9vw, var(--space-6));
    display: flex;
    align-items: stretch;
    gap: clamp(var(--space-3), 1.4vw, var(--space-5));
    min-height: clamp(76px, 6.7vw, 112px);
}

/* -- Marca ------------------------------------------------------------- */

.app-brand {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: var(--space-3);
    flex: 0 0 auto;
    padding-right: clamp(var(--space-3), 1.4vw, var(--space-5));
    text-decoration: none;
    color: #ffffff;
}

/* Los dos separadores verticales NO llegan de borde a borde de la barra: en el mockup
   son dos líneas cortas centradas, que es lo que los hace ordenar en vez de parecer
   mal alineados. Por eso van en pseudo-elementos y no como border del elemento, que
   con align-items:stretch tomaba toda la altura. */
.app-brand::after,
.app-user::before {
    content: "";
    position: absolute;
    top: 22%;
    bottom: 22%;
    width: 1px;
    background: var(--color-header-divider);
}

.app-brand::after { right: 0; }
.app-user::before { left: 0; }

.app-brand__logo {
    width: clamp(44px, 4.3vw, 72px);
    height: clamp(44px, 4.3vw, 72px);
    border-radius: var(--radius-pill);
    background: #ffffff;
    object-fit: contain;
    flex: 0 0 auto;
}

/* "TODO" sobre "POLLO": dos líneas, mayúsculas, muy compacto y en AMARILLO, como en
   el mockup. (Estaba en blanco: era la diferencia más visible contra la referencia.) */
.app-brand__name {
    color: var(--color-header-text);
    display: flex;
    flex-direction: column;
    font-size: clamp(1.05rem, 2.05vw, 2.14rem);
    font-weight: 800;
    line-height: 0.92;
    letter-spacing: -0.01em;
    text-transform: uppercase;
    white-space: nowrap;
}

/* -- Navegación -------------------------------------------------------- */

.app-nav {
    display: flex;
    align-items: center;
    gap: 2px;
    flex: 1 1 auto;
    min-width: 0;
    /* Sin botón de menú: cuando no entran, los destinos se desplazan acá adentro.
       La barra de desplazamiento se oculta porque el gesto es táctil y en
       escritorio no hace falta — el contenido entra. */
    overflow-x: auto;
    scrollbar-width: none;
}

.app-nav::-webkit-scrollbar {
    display: none;
}

.nav-link {
    display: inline-flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 5px;
    flex: 0 0 auto;
    padding: var(--space-2) var(--space-3);
    border-radius: var(--radius-sm);
    text-decoration: none;
    white-space: nowrap;
    color: var(--color-header-text);
    transition: background var(--transition), color var(--transition);
}

.nav-link__icon {
    width: clamp(19px, 1.55vw, 26px);
    height: clamp(19px, 1.55vw, 26px);
    flex: 0 0 auto;
}

.nav-link__label {
    font-size: clamp(0.7rem, 0.9vw, 0.94rem);
    font-weight: 600;
    letter-spacing: -0.005em;
}

.nav-link:hover {
    background: var(--color-header-hover);
    color: #ffffff;
}

/* Activo: pastilla amarilla llena con icono y texto azules. El estado cuelga de
   aria-current="page", el atributo que ya usaba el layout, así que lo que ve el
   lector de pantalla y lo que se ve en pantalla no pueden desincronizarse. */
.nav-link[aria-current="page"] {
    background: var(--color-accent);
    color: var(--color-on-accent);
}

.nav-link[aria-current="page"]:hover {
    background: var(--color-accent-strong);
    color: var(--color-on-accent);
}

/* -- Usuario ----------------------------------------------------------- */

.app-user {
    position: relative;
    display: flex;
    align-items: center;
    flex: 0 0 auto;
    padding-left: clamp(var(--space-3), 1.6vw, var(--space-6));
}

.app-user__trigger {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-1) var(--space-1) var(--space-1) var(--space-2);
    border: none;
    border-radius: var(--radius-pill);
    background: transparent;
    color: #ffffff;
    font: inherit;
    cursor: pointer;
}

.app-user__trigger:hover {
    background: var(--color-header-hover);
}

.app-user__name {
    font-size: var(--text-sm);
    font-weight: var(--weight-semibold);
    max-width: 16ch;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.app-user__caret {
    width: 16px;
    height: 16px;
    flex: 0 0 auto;
    opacity: 0.8;
    transition: transform var(--transition);
}

.app-user__trigger[aria-expanded="true"] .app-user__caret {
    transform: rotate(180deg);
}

/* Círculo con iniciales: contorno claro sobre el azul, como en el mockup. */
.app-user__avatar {
    width: clamp(38px, 2.9vw, 48px);
    height: clamp(38px, 2.9vw, 48px);
    flex: 0 0 auto;
    border-radius: var(--radius-pill);
    border: 2px solid rgba(255, 255, 255, 0.55);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: var(--text-sm);
    font-weight: var(--weight-bold);
    letter-spacing: 0.02em;
}

/* Lo que no es una sección —apariencia y salir— cuelga del nombre, igual que la
   flecha del mockup sugiere. Nada se esconde: sólo deja de competir por espacio. */
.app-user__menu {
    position: absolute;
    top: calc(100% - var(--space-2));
    right: 0;
    z-index: 10;
    min-width: 220px;
    padding: var(--space-2);
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    box-shadow: var(--shadow-lg);
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.app-user__menu[hidden] {
    display: none;
}

.app-user__item {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    width: 100%;
    min-height: var(--tap-target);
    padding: 0 var(--space-3);
    border: none;
    border-radius: var(--radius-sm);
    background: transparent;
    color: var(--color-text);
    font: inherit;
    font-size: var(--text-sm);
    font-weight: var(--weight-medium);
    text-align: left;
    cursor: pointer;
}

.app-user__item:hover {
    background: var(--color-primary-soft);
    color: var(--color-primary);
}

.app-user__item-icon {
    width: 18px;
    height: 18px;
    flex: 0 0 auto;
}

/* =========================================================================
   CONTENIDO
   ========================================================================= */

.app-main {
    max-width: 1180px;
    margin: 0 auto;
    padding: var(--space-6) var(--space-4) var(--space-7);
}

/* El inicio usa todo el ancho de la barra, sin el margen de lectura: su composición
   llega hasta el borde. Va DESPUES de .app-main: misma especificidad, gana el orden.
   Ver ViewData["MainModifier"] en _Layout.

   SIN ancho máximo, a propósito. Con un tope (estaba en 1700px) la composición dejaba
   de llegar al borde derecho en pantallas más anchas, y como el dibujo está pintado
   hasta su propio borde, ahí aparecía una línea vertical dura. El inicio es una
   composición a sangre: o llega al borde, o se le ve el corte. */
.app-main--wide {
    max-width: none;
    padding: 0;
}

.page-head {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    justify-content: space-between;
    gap: var(--space-3);
    margin-bottom: var(--space-5);
}

.page-head__text {
    min-width: 0;
}

.page-head__sub {
    margin: 0;
    color: var(--color-text-muted);
    font-size: var(--text-sm);
}

.page-head__actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
}

/* =========================================================================
   BOTONES
   ========================================================================= */

/* Los dos botones de la CABECERA (el nombre del usuario y las opciones de su menú)
   quedan afuera: no son acciones del contenido y tienen su propio aspecto más
   arriba. Se excluyen acá, en el selector, y no con una regla posterior que pelee
   por especificidad. */
:where(.app-shell) button:not(.app-user__trigger):not(.app-user__item),
:where(.app-shell) .btn,
:where(.app-shell) .btn-secondary,
:where(.app-shell) .btn-danger,
:where(.app-shell) .btn-ghost {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    min-height: var(--tap-target);
    padding: 0 var(--space-4);
    border: 1px solid transparent;
    border-radius: var(--radius-sm);
    background: var(--color-primary);
    color: var(--color-on-primary);
    font: inherit;
    font-size: var(--text-sm);
    font-weight: var(--weight-semibold);
    line-height: 1;
    text-decoration: none;
    cursor: pointer;
    transition: background var(--transition), border-color var(--transition), color var(--transition);
}

:where(.app-shell) .btn:hover,
:where(.app-shell) button:not(.btn-secondary):not(.btn-danger):not(.btn-ghost):not(.link-button):not(.app-user__trigger):not(.app-user__item):hover {
    background: var(--color-primary-dark);
}

.btn-secondary {
    background: var(--color-surface);
    color: var(--color-primary);
    border-color: var(--color-border-strong);
}

.btn-secondary:hover {
    background: var(--color-primary-soft);
    border-color: var(--color-primary);
}

.btn-danger {
    background: var(--color-danger);
    color: #ffffff;
}

.btn-danger:hover {
    background: #9d2e22;
}

.btn-ghost {
    background: transparent;
    color: var(--color-text-muted);
    border-color: transparent;
    padding: 0 var(--space-3);
}

.btn-ghost:hover {
    background: var(--color-muted-bg);
    color: var(--color-text);
}

:where(.app-shell) .btn:disabled,
:where(.app-shell) .btn-secondary:disabled,
:where(.app-shell) .btn-danger:disabled,
:where(.app-shell) button:disabled {
    opacity: 0.55;
    cursor: not-allowed;
}

/* Foco visible y consistente en TODO lo interactivo. Nunca se quita el outline
   sin reemplazarlo: navegar con teclado tiene que ser posible. */
:where(.app-shell) a:focus-visible,
:where(.app-shell) button:focus-visible,
:where(.app-shell) .btn:focus-visible,
:where(.app-shell) .btn-secondary:focus-visible,
:where(.app-shell) .btn-danger:focus-visible,
:where(.app-shell) .btn-ghost:focus-visible,
:where(.app-shell) .nav-link:focus-visible,
:where(.app-shell) input:focus-visible,
:where(.app-shell) select:focus-visible,
:where(.app-shell) textarea:focus-visible,
:where(.app-shell) summary:focus-visible {
    outline: 2px solid transparent;
    box-shadow: var(--focus-ring);
    border-radius: var(--radius-sm);
}

/* Sobre el azul de la cabecera el anillo azul no se vería: ahí el foco es amarillo. */
.app-header a:focus-visible,
.app-header button:focus-visible {
    box-shadow: 0 0 0 3px rgba(255, 198, 22, 0.65);
}

.link-button {
    background: none;
    border: none;
    min-height: 0;
    padding: 0;
    font: inherit;
    color: var(--color-text-muted);
    cursor: pointer;
    text-decoration: underline;
}

/* El selector de apariencia vive dentro del menú del usuario y toma su aspecto de
   .app-user__item; acá sólo se asegura que no herede el relleno azul de los
   botones de acción. */
.theme-toggle {
    background: transparent;
}

/* =========================================================================
   SUPERFICIES
   ========================================================================= */

.card {
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    padding: var(--space-5);
    margin-bottom: var(--space-4);
    box-shadow: var(--shadow-sm);
}

.card--danger {
    border-color: var(--color-danger-border);
}

.toolbar {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-3);
    align-items: center;
    margin-bottom: var(--space-4);
}

.toolbar--between {
    justify-content: space-between;
}

.toolbar--tight {
    gap: var(--space-2);
    margin-bottom: 0;
}

.empty-state {
    background: var(--color-surface);
    border: 1px dashed var(--color-border-strong);
    border-radius: var(--radius);
    padding: var(--space-7) var(--space-5);
    text-align: center;
}

.empty-state__icon {
    font-size: 2rem;
    line-height: 1;
    margin-bottom: var(--space-3);
}

.empty-state__title {
    font-size: var(--text-lg);
    font-weight: var(--weight-semibold);
    margin: 0 0 var(--space-2);
}

.empty-state__text {
    color: var(--color-text-muted);
    font-size: var(--text-sm);
    max-width: 48ch;
    margin: 0 auto var(--space-4);
}

/* =========================================================================
   FORMULARIOS
   ========================================================================= */

:where(.app-shell) label {
    display: block;
    font-size: var(--text-sm);
    font-weight: var(--weight-medium);
    margin-bottom: var(--space-1);
}

.field {
    margin-bottom: var(--space-4);
}

:where(.app-shell) input[type="text"],
:where(.app-shell) input[type="email"],
:where(.app-shell) input[type="password"],
:where(.app-shell) input[type="search"],
:where(.app-shell) input[type="number"],
:where(.app-shell) input[type="date"],
:where(.app-shell) input[type="tel"],
:where(.app-shell) select,
:where(.app-shell) textarea {
    width: 100%;
    min-height: var(--tap-target);
    padding: 0 var(--space-3);
    border: 1px solid var(--color-border-strong);
    border-radius: var(--radius-sm);
    background: var(--color-surface);
    color: var(--color-text);
    font: inherit;
    font-size: var(--text-sm);
}

:where(.app-shell) textarea {
    padding: var(--space-3);
    min-height: 6rem;
    line-height: var(--leading-normal);
}

:where(.app-shell) input:focus,
:where(.app-shell) select:focus,
:where(.app-shell) textarea:focus {
    border-color: var(--color-primary);
    outline: none;
}

.search-input {
    max-width: 340px;
}

.form-actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-3);
    align-items: center;
    margin-top: var(--space-5);
}

/* =========================================================================
   TABLAS
   ========================================================================= */

.table-responsive {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    background: var(--color-surface);
}

/* El ancho mínimo que evita que los encabezados se superpongan cuando la tabla
   se comprime. Verificado a 375px: por debajo de esto, "Transferencia" se monta
   sobre la columna vecina. La tabla scrollea DENTRO de su contenedor; la página
   nunca scrollea en horizontal. */
.table-responsive > table {
    min-width: 520px;
    margin: 0;
    border: none;
}

:where(.app-shell) table {
    width: 100%;
    border-collapse: collapse;
    font-size: var(--text-sm);
}

:where(.app-shell) th,
:where(.app-shell) td {
    padding: var(--space-3);
    text-align: left;
    border-bottom: 1px solid var(--color-border);
    vertical-align: middle;
}

:where(.app-shell) th {
    background: var(--color-surface-alt);
    color: var(--color-text-muted);
    font-size: var(--text-xs);
    font-weight: var(--weight-semibold);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    white-space: nowrap;
}

:where(.app-shell) tbody tr:last-child td {
    border-bottom: none;
}

:where(.app-shell) tbody tr:nth-child(even) {
    background: var(--color-row-alt);
}

/* =========================================================================
   INDICADORES
   ========================================================================= */

.badge {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    padding: 0.15rem var(--space-2);
    border-radius: var(--radius-pill);
    font-size: var(--text-xs);
    font-weight: var(--weight-semibold);
    white-space: nowrap;
}

.badge-success { background: var(--color-success-bg); color: var(--color-success-text); }
.badge-warning { background: var(--color-warning-bg); color: var(--color-warning-text); }
.badge-muted   { background: var(--color-muted-bg);   color: var(--color-text-muted); }
.badge-danger  { background: var(--color-danger-bg);  color: var(--color-danger-text); }

.alert {
    padding: var(--space-3) var(--space-4);
    border-radius: var(--radius-sm);
    margin-bottom: var(--space-4);
    font-size: var(--text-sm);
}

.alert-danger  { background: var(--color-danger-bg);  color: var(--color-danger-text);  border: 1px solid var(--color-danger-border); }
.alert-success { background: var(--color-success-bg); color: var(--color-success-text); border: 1px solid var(--color-success-border); }
.alert-warning { background: var(--color-warning-bg); color: var(--color-warning-text); border: 1px solid var(--color-warning-border); }
.alert-info    { background: var(--color-info-bg);    color: var(--color-info-text);    border: 1px solid var(--color-info-border); }

/* Estado de ocupado al enviar un formulario (ver site.js). */
.is-busy {
    position: relative;
    pointer-events: none;
    opacity: 0.8;
}

.is-busy::after {
    content: "";
    width: 0.9em;
    height: 0.9em;
    margin-left: var(--space-2);
    border: 2px solid currentColor;
    border-right-color: transparent;
    border-radius: var(--radius-pill);
    animation: tp-spin 650ms linear infinite;
}

@keyframes tp-spin {
    to { transform: rotate(360deg); }
}

@media (prefers-reduced-motion: reduce) {
    .is-busy::after { animation: none; }
    * { transition: none !important; }
}

/* =========================================================================
   LISTADO DE CATALOGO (Productos)
   ========================================================================= */

.product-group {
    padding: 0;
    overflow: hidden;
}

.product-group > summary {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    min-height: var(--tap-target);
    padding: var(--space-3) var(--space-5);
    background: var(--color-surface-alt);
    border-bottom: 1px solid var(--color-border);
    font-size: var(--text-base);
    font-weight: var(--weight-semibold);
    cursor: pointer;
    list-style: none;
    user-select: none;
}

.product-group > summary::-webkit-details-marker {
    display: none;
}

/* Flecha propia: la nativa cambia de forma entre navegadores y no se puede
   alinear con el texto. Rota al abrir. */
.product-group > summary::before {
    content: "";
    width: 0;
    height: 0;
    flex: 0 0 auto;
    border-left: 6px solid currentColor;
    border-top: 4.5px solid transparent;
    border-bottom: 4.5px solid transparent;
    transition: transform var(--transition);
}

.product-group[open] > summary::before {
    transform: rotate(90deg);
}

.product-group__count {
    margin-left: auto;
    font-size: var(--text-xs);
    font-weight: var(--weight-medium);
    color: var(--color-text-muted);
}

.product-row {
    padding: var(--space-4) var(--space-5);
    border-top: 1px solid var(--color-border);
}

.product-row:first-of-type {
    border-top: none;
}

.product-row--inactive {
    background: var(--color-muted-bg);
}

.product-row--inactive .product-row__name {
    color: var(--color-text-muted);
}

.product-row__name {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    margin: 0 0 var(--space-3);
    font-size: var(--text-base);
}

/* Precios: alineados a la derecha, tabulares y con algo más de peso que el
   resto de la fila. Comparar una columna de precios es lo que más se hace en
   esta pantalla, y con cifras proporcionales los dígitos no quedan en columna. */
.price {
    display: block;
    text-align: right;
    font-variant-numeric: tabular-nums;
    font-feature-settings: "tnum" 1;
    font-size: var(--text-base);
    font-weight: var(--weight-semibold);
    letter-spacing: -0.01em;
    white-space: nowrap;
}

.price--transfer {
    color: var(--color-text-muted);
    font-weight: var(--weight-medium);
}

/* =========================================================================
   UTILIDADES
   ========================================================================= */

.stack > * + * { margin-top: var(--space-4); }
.stack-sm > * + * { margin-top: var(--space-2); }
.text-sm { font-size: var(--text-sm); }
.text-xs { font-size: var(--text-xs); }
.text-muted { color: var(--color-text-muted); }
.text-right { text-align: right; }
.nowrap { white-space: nowrap; }
.w-full { width: 100%; }
.mt-0 { margin-top: 0; }
.m-0 { margin: 0; }
.mt-3 { margin-top: var(--space-3); }

/* Visible sólo para lectores de pantalla: texto que explica un control cuyo
   significado en pantalla lo da la forma o el color. */
.sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* =========================================================================
   RESPONSIVE
   -------------------------------------------------------------------------
   NO HAY BOTON DE MENU en ningún ancho: es una decisión explícita del diseño.
   Cuando los diez destinos no entran, la fila se desplaza en horizontal DENTRO de
   la barra (patrón de pestañas deslizables), con los destinos conservando su
   objetivo táctil. La PAGINA nunca scrollea de costado — eso está verificado.

   Por debajo de 1100px la marca escrita y el nombre del usuario ceden el lugar a
   la navegación, que es lo que se usa; quedan el logo real y el avatar.
   ========================================================================= */

@media (max-width: 1099px) {
    .app-header__inner {
        gap: var(--space-3);
        padding: 0 var(--space-3);
        min-height: 76px;
    }

    .app-brand {
        padding-right: var(--space-3);
    }

    .app-brand__name {
        display: none;
    }

    .app-user {
        padding-left: var(--space-3);
    }

    .app-user__name {
        display: none;
    }

    /* Deslizable: se le da inercia táctil y se encaja cada destino al soltar, para
       que no queden medios iconos a la vista.

       El degradado del borde derecho es el único indicio de que la fila sigue: sin
       él, a 375px se ven cuatro destinos y nada sugiere que haya seis más. Es una
       máscara, no un elemento: no ocupa lugar, no se puede tocar y desaparece sola
       cuando la fila llega al final. */
    .app-nav {
        -webkit-overflow-scrolling: touch;
        scroll-snap-type: x proximity;
        -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 28px), transparent 100%);
        mask-image: linear-gradient(to right, #000 calc(100% - 28px), transparent 100%);
    }

    .nav-link {
        scroll-snap-align: start;
        min-width: 68px;
    }
}

@media (max-width: 640px) {
    .app-main {
        padding: var(--space-4) var(--space-3) var(--space-6);
    }

    /* A 375px la barra se queda con lo esencial: el logo real a la izquierda, la
       fila de destinos deslizable al medio y el avatar a la derecha. El nombre
       escrito de la marca no se pierde: la propia imagen del logo dice
       "TODO POLLO". La flecha del usuario también se va; el avatar sigue abriendo
       el menú. */
    .app-user__caret {
        display: none;
    }

    .app-shell h1 {
        font-size: var(--text-xl);
    }

    .card {
        padding: var(--space-4);
    }

    /* .product-group ES una .card, pero sin relleno propio: el encabezado de
       categoría y las filas llegan hasta el borde. Hay que repetirlo acá porque
       la regla de arriba tiene la misma especificidad y va después: sin esto, en
       teléfono la categoría quedaba con 16px de aire a los lados y el acordeón
       perdía el borde a borde que tiene en escritorio. */
    .product-group {
        padding: 0;
    }

    .page-head {
        align-items: flex-start;
    }

    .page-head__actions,
    .page-head__actions > * {
        width: 100%;
    }

    .toolbar > .btn,
    .toolbar > .btn-secondary,
    .toolbar > .btn-danger {
        flex: 1 1 auto;
    }

    .search-input {
        max-width: none;
        flex: 1 1 100%;
    }

    .form-actions > * {
        width: 100%;
    }
}
