/* ===========================================================================
   LUCANTA — TOKENS CENTRALIZADOS (Checkpoint 1)
   ===========================================================================

   Se carga DESPUÉS de lucanta-app.css y sobrescribe solo lo que debe cambiar.
   Aditivo a propósito: quitar una línea del layout revierte el checkpoint entero,
   sin tocar las hojas existentes.

   PRINCIPIO
   ---------
   Lucanta es una herramienta de trabajo, no una vitrina. Legibilidad y velocidad
   por encima de cualquier efecto. La identidad azul marino + turquesa se conserva
   intacta: aquí no se cambia ningún color de marca, solo los grises que no eran
   legibles y los tamaños que no lo permitían.

   REGLA DURA
   ----------
   Ningún token de TEXTO por debajo de 4.5:1 sobre el fondo más claro donde puede
   aparecer (--bg #f8f8f8). Si un gris no llega, no es un token de texto: es
   decorativo y no puede llevar información.
   =========================================================================== */

:root {
    /* -------------------------------------------------------------- COLOR ---
       Medido antes:  --text-3 #7c7c7c = 3.95:1   ✗
                      --text-4 #999999 = 2.85:1   ✗  ← el menú lateral entero
                      --border-3 #c7c7c7 = 1.69:1 ✗  (1.4.11 exige 3.0 en bordes)

       Los grises nuevos están calculados contra #f8f8f8, no contra blanco: es el
       fondo real de la aplicación y el caso peor. Sobre blanco sobra margen.      */

    --text-3: #666666;      /* 5.41:1 sobre --bg · 5.17 sobre --surface-3 · secundario */
    --text-4: #6f6f6f;      /* 4.73:1 sobre --bg · 4.53 sobre --surface-3 · terciario  */

    /* El borde de un control no es decoración: delimita dónde se puede escribir.
       Calculado sobre --surface-3 #ededed, que es el fondo más claro donde puede
       aparecer un input; sobre blanco sobra margen (3.54). */
    --border-input: #888888;   /* 3.03:1 sobre --surface-3 · WCAG 1.4.11 */
    --border-3:     #888888;   /* 3.03:1 · separadores con significado */

    /* Foco. Un solo tratamiento en toda la aplicación, con contraste suficiente
       sobre superficie clara y sobre la marca. */
    /* Enlace. Medido: --brand-link #006eff = 4.49:1 sobre blanco — a un pelo del
       mínimo, y 3.85:1 sobre el fondo activo del menú. Mismo tono, más profundo:
       5.84 sobre blanco y 5.00 sobre --brand-soft. La identidad no se mueve. */
    --brand-link:   #0060d1;

    --focus:        #0060d1;
    --focus-ring:   0 0 0 2px #ffffff, 0 0 0 4px var(--focus);
    --focus-width:  2px;
    --focus-offset: 2px;

    /* ---------------------------------------------------------- TIPOGRAFÍA ---
       Medido antes: el menú lateral usaba 10.5px. Por debajo de 12px el texto
       operativo deja de ser legible con luz de mostrador, y es justo donde se
       concentraban los fallos de contraste.                                      */

    --fs-caption: 12px;   /* PISO ABSOLUTO para texto informativo */
    --fs-body-sm: 13px;
    --fs-body:    14px;
    --fs-h3:      16px;
    --fs-h2:      20px;
    --fs-display: 28px;

    --lh-tight:  1.25;
    --lh-normal: 1.5;

    --fw-regular: 400;
    --fw-medium:  500;
    --fw-semi:    650;
    --fw-bold:    700;

    /* -------------------------------------------------------------- ESPACIO ---
       Escala de 4. Sin valores intermedios inventados por pantalla.              */

    --sp-1:  4px;  --sp-2:  8px;  --sp-3: 12px;  --sp-4: 16px;
    --sp-6: 24px;  --sp-8: 32px;  --sp-12: 48px; --sp-16: 64px;

    /* --------------------------------------------------------------- TAMAÑO ---
       WCAG 2.2 AA (2.5.8) exige 24px. 44px es lo que funciona con el pulgar en
       un mostrador. Medido antes: Reportes 11 objetivos por debajo, Inicio 5.     */

    --control-h:        40px;   /* escritorio */
    --control-h-touch:  44px;   /* móvil y tablet */
    --target-min:       24px;   /* mínimo absoluto, nunca por debajo */

    /* --------------------------------------------------------------- CAPAS ---
       Declaradas de una vez para que ningún componente invente su z-index.        */

    --z-sticky:   10;
    --z-sidebar:  100;
    --z-dropdown: 500;
    --z-drawer:   800;
    --z-modal:    900;
    --z-toast:    950;
    --z-offline:  9999;

    /* ---------------------------------------------------- ELEVACIÓN Y RADIO ---
       Cuatro niveles y ninguno decorativo. Al mismo nivel de interacción se
       separa con BORDE; la sombra indica profundidad real.                        */

    --elev-0: none;
    --elev-1: var(--shadow-1);
    --elev-2: var(--shadow-2);
    --elev-3: var(--shadow-3);

    /* ----------------------------------------------------- BREAKPOINTS ---
       ONE set of cuts for the whole app (E9). Before this there were 10 in the
       theme and 15 more inside the SFCs: nothing lined up, so a screen could be
       "mobile" for its table and "desktop" for its toolbar at the same width.

         --bp-narrow 380px   ONLY content that stops fitting on one row on the
                             narrowest phones (the word «Crear» next to five other
                             header controls). Never layout.
         --bp-phone  600px   phone
         --bp-tablet 900px   tablet and below (also: mobile shell)
         --bp-table 1080px   ONLY the dense-table reflow (.tbl--cards):
                             a 7-column table needs to stack before the layout does

       Two of the four are the layout ladder (600/900); the other two are named,
       single-purpose tiers. That is the whole list — the test refuses any other value.

       --bp-wide (1280px) was retired in F8: it was declared «reserved for wide
       dashboards» and in a year nothing ever reserved it. A token no rule uses is a
       fifth answer to «which cut do I take?» that costs a reader a lookup and gives
       them nothing. If a wide tier is ever needed, it comes back with the rule that
       needs it — 1280 is still an allowed value in the responsive contract.

       CSS cannot read a custom property inside a media/container query, so the
       queries repeat the literal value. These tokens are the single source of
       truth for JS (sweeps, tests) and the contract that
       tests/js/responsive-contract.test.js enforces: no other value is allowed. */
    --bp-narrow: 380px;
    --bp-phone:  600px;
    --bp-tablet: 900px;
    --bp-table:  1080px;
}

/* =========================================================================
   RESPONSIVE SYSTEM (E9) — width utilities
   =========================================================================
   These replace the loose `style="width:NNNpx"` that lived in 80 components. A
   pixel width in the markup cannot yield on a phone: the cell still measures
   150px on a 360px screen and pushes the table out of the viewport. Here the
   width is a layout HINT on the desktop and it disappears on the phone.

   Scale (4 steps, no in-between values invented per screen):
     .w-xs   44px   checkboxes, row icons, action columns
     .w-sm   90px   short quantities
     .w-md  120px   dates, amounts, statuses
     .w-lg  200px   names, descriptions, toolbar pickers

   The values are the MODES of the measured distribution (36 cells used 120px,
   21 used 44px…), so the sweep moved most columns by a few pixels and none of
   them changed role.

   TWO SEMANTICS, ON PURPOSE
   -------------------------
   · Everywhere: a `min-width` FLOOR. A control that shares a flex toolbar row
     must be able to grow — three call sites (Transfers, InventoryAdjustment,
     CashReceipts) were written as `min-width` before the sweep and a fixed
     `width` was a downgrade.
   · On <th>/<td> only: also a fixed `width`, because a table column wants the
     hint, not just the floor.

   THE DOUBLED CLASS IS DELIBERATE
   -------------------------------
   `html.lucanta input.lc-input { width: 100% }` (lucanta-forms.css) is (0,2,2).
   A bare `.w-lg` is (0,1,0) and loses regardless of load order — which is why
   ten `class="lc-input w-lg"` were doing nothing at all. `.w-lg.w-lg` inside
   `html.lucanta` is (0,3,1), and the <th> variant (0,3,2): they win where they
   must, and any rule that genuinely needs to override them still can — which is
   exactly what `!important` would have taken away.
   tests/js/responsive-contract.test.js computes both specificities and fails if
   the utility ever stops winning. */
html.lucanta .w-xs.w-xs { min-width: 44px; }
html.lucanta .w-sm.w-sm { min-width: 90px; }
html.lucanta .w-md.w-md { min-width: 120px; }
html.lucanta .w-lg.w-lg { min-width: 200px; }

html.lucanta th.w-xs.w-xs, html.lucanta td.w-xs.w-xs { width: 44px; }
html.lucanta th.w-sm.w-sm, html.lucanta td.w-sm.w-sm { width: 90px; }
html.lucanta th.w-md.w-md, html.lucanta td.w-md.w-md { width: 120px; }
html.lucanta th.w-lg.w-lg, html.lucanta td.w-lg.w-lg { width: 200px; }

/* On the phone the fixed width disappears: the control takes whatever there is. */
@container app (max-width: 600px) {
    html.lucanta .w-xs.w-xs, html.lucanta .w-sm.w-sm,
    html.lucanta .w-md.w-md, html.lucanta .w-lg.w-lg { min-width: 0; max-width: 100%; }
    html.lucanta th.w-xs.w-xs, html.lucanta td.w-xs.w-xs,
    html.lucanta th.w-sm.w-sm, html.lucanta td.w-sm.w-sm,
    html.lucanta th.w-md.w-md, html.lucanta td.w-md.w-md,
    html.lucanta th.w-lg.w-lg, html.lucanta td.w-lg.w-lg { width: auto; }
}
@media (max-width: 600px) {
    /* container-twin: generated from the @container rule above by scripts/postcss-container-twins.js */
    html.lucanta .w-xs.w-xs, html.lucanta .w-sm.w-sm,
    html.lucanta .w-md.w-md, html.lucanta .w-lg.w-lg { min-width: 0; max-width: 100%; }
    html.lucanta th.w-xs.w-xs, html.lucanta td.w-xs.w-xs,
    html.lucanta th.w-sm.w-sm, html.lucanta td.w-sm.w-sm,
    html.lucanta th.w-md.w-md, html.lucanta td.w-md.w-md,
    html.lucanta th.w-lg.w-lg, html.lucanta td.w-lg.w-lg { width: auto; }
}

/* ------------------------------------------------------------------ FOCO ---
   Un solo tratamiento, y solo con teclado: :focus-visible evita el anillo al
   hacer clic con el ratón, que es lo que empuja a la gente a quitarlo. */
html.lucanta :focus-visible {
    outline: var(--focus-width) solid var(--focus);
    outline-offset: var(--focus-offset);
}
/* Los componentes nuevos no deben quitar el outline. Si una hoja antigua lo hace,
   se corrige en su módulo: un !important global aquí escondería el problema. */

/* ------------------------------------------------ PISO TIPOGRÁFICO REAL ---
   El menú lateral usaba 10.5px. Se sube al piso de 12px SIN tocar su estructura:
   solo tamaño, interlineado y color heredado del token corregido. */
html.lucanta .lc-nav-section,
html.lucanta .lc-side-section,
html.lucanta .nav-section-title,
html.lucanta .lc-app [class*="section-title"],
html.lucanta .lc-app [class*="nav-label"] {
    font-size: var(--fs-caption);
    line-height: var(--lh-normal);
    letter-spacing: .02em;
}

/* NOTA: no se aplica un piso global de tamaño con un selector universal. Se probó
   y reseteaba toda la jerarquía tipográfica. Los casos sueltos por debajo de 12px
   se corrigen por módulo, con medición previa, en los checkpoints 7-11. */

/* ----------------------------------------------------- OBJETIVOS TÁCTILES ---
   WCAG 2.2 AA (2.5.8) exige 24x24. Se aplica a BOTONES, no a enlaces: un enlace
   dentro de un párrafo no debe engordar la línea.

   Se probó primero ampliando el área con un pseudo-elemento para no engordar el
   diseño; se descartó porque tapaba a los controles vecinos. Un mínimo real es
   más honesto y más predecible. */
html.lucanta .lc-app button,
html.lucanta .lc-app [role="button"] {
    min-height: var(--target-min);
    min-width: var(--target-min);
}
/* En móvil y tablet el objetivo cómodo no es el mínimo legal. */
@container app (max-width: 900px) {
    html.lucanta .lc-app button,
    html.lucanta .lc-app [role="button"] { min-height: var(--control-h-touch); }
}
@media (max-width: 900px) {
    /* container-twin: generated from the @container rule above by scripts/postcss-container-twins.js */
    html.lucanta .lc-app button,
    html.lucanta .lc-app [role="button"] { min-height: var(--control-h-touch); }
}

/* --------------------------------------------------- MOVIMIENTO REDUCIDO ---
   No es un extra: para quien tiene sensibilidad vestibular es una barrera. */
@media (prefers-reduced-motion: reduce) {
    html.lucanta *, html.lucanta *::before, html.lucanta *::after {
        animation-duration: .01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: .01ms !important;
        scroll-behavior: auto !important;
    }
}

/* ----------------------------------------------------- SOLO PARA LECTORES ---
   Texto que existe para el lector de pantalla y no ocupa espacio visual. */
.lc-sr-only {
    position: absolute !important;
    width: 1px; height: 1px;
    padding: 0; margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}
/* Salvo cuando recibe el foco: los enlaces de salto deben verse al tabular. */
.lc-sr-only.lc-focusable:focus,
.lc-sr-only.lc-focusable:focus-visible {
    position: static !important;
    width: auto; height: auto;
    clip: auto; margin: 0;
    padding: var(--sp-2) var(--sp-3);
}

/* ==========================================================================
   CORRECCIONES PUNTUALES MEDIDAS
   ==========================================================================
   No son colores nuevos: son el token que YA EXISTE en el tema y sí cumple,
   puesto donde se estaba usando uno que no. La identidad no cambia.
   ========================================================================== */

/* Etiqueta de sección del menú lateral.
   Medido: 10.5px con --text-4 (#999) = 2.85:1. Dos infracciones a la vez.
   El color ya lo corrige el token; aquí solo se sube al piso de 12px. */
html.lucanta .sb-group {
    font-size: var(--fs-caption);
    line-height: var(--lh-normal);
}

/* Delta de los indicadores («Por pagar», «Abierta»).
   Medido: --green #30a66d = 3.09:1. El tema ya tiene --green-text #16794c = 5.42:1,
   pensado precisamente para texto. Se usa ese. */
html.lucanta .k-delta.k-up   { color: var(--green-text); }
html.lucanta .k-delta.k-down { color: var(--red); }        /* #cc2929 = 5.36:1 ✓ */

/* Elemento activo del menú.
   Medido: --brand-link #006eff sobre #d1f3ff = 3.85:1. Sobre ese mismo fondo,
   --brand #00438B da 8.26:1 y es más coherente con la identidad. */
html.lucanta .sb-item.active .txt,
html.lucanta .sb-item.active { color: var(--brand); }

/* Bordes de control: el token corregido tiene que llegar al input, no quedarse
   declarado. Solo donde el borde delimita una zona de escritura. */
/* Default borders must not override the component's focused border. */
html.lucanta .lc-app :where(input:not([type=checkbox]):not([type=radio]), select, textarea):not(:focus) {
    border-color: var(--border-input);
}

/* An invalid control keeps its red border, including while focused. */
html.lucanta .lc-app input[aria-invalid="true"]:not([type=checkbox]):not([type=radio]),
html.lucanta .lc-app select[aria-invalid="true"],
html.lucanta .lc-app textarea[aria-invalid="true"],
html.lucanta .lc-app input.is-error:not([type=checkbox]):not([type=radio]),
html.lucanta .lc-app select.is-error,
html.lucanta .lc-app textarea.is-error,
html.lucanta .lc-app .is-invalid input:not([type=checkbox]):not([type=radio]),
html.lucanta .lc-app .is-invalid select,
html.lucanta .lc-app .is-invalid textarea,
html.lucanta .lc-app select.is-invalid {
    border-color: var(--red-fill);
}

/* ------------------------------------------------- ACCIONES DE FILA (CP5) ---
   En Cuentas por cobrar la fila entera era el botón: `@click` sobre un <tr>, que
   no recibe foco ni responde al teclado, y cuya única pista era un `title` de
   ratón. La acción principal de la pantalla —registrar un pago— era inalcanzable
   sin ratón. Ahora el NOMBRE DEL CLIENTE es el control: se ve igual y se comporta
   como botón. */
html.lucanta .rec-open {
    all: unset;
    cursor: pointer;
    font: inherit;
    color: inherit;
    font-weight: 700;
}
html.lucanta .rec-open:focus-visible {
    outline: var(--focus-width) solid var(--focus);
    outline-offset: 2px;
    border-radius: 4px;
}

/* Insignia usada como enlace (catálogo de Reportes). Medida: 23 px de alto, a un
   píxel del mínimo de WCAG 2.5.8. No es texto en línea —es un control suelto—,
   así que no le aplica la excepción de línea. */
html.lucanta a.bdg {
    min-height: var(--target-min);
    display: inline-flex;
    align-items: center;
}

/* ------------------------------------ ENLACES DE ACCIÓN SUELTOS (CP5) ---
   En el Checkpoint 1 el mínimo de 24 px se aplicó SOLO a botones, porque engordar
   un enlace dentro de un párrafo rompe la línea de texto (excepción de línea de
   WCAG 2.5.8). Medido ahora, estos NO están dentro de una frase: son acciones
   sueltas al pie de una tarjeta y en la miga de pan, y a 17-21 px de alto se
   quedan por debajo del mínimo sin que la excepción les ampare. */
html.lucanta a.lnk,
html.lucanta .ph-crumb a {
    min-height: var(--target-min);
    display: inline-flex;
    align-items: center;
}

/* --------------------------------------------------- SALTAR AL CONTENIDO ---
   Invisible hasta que recibe el foco. Cuando aparece tiene que verse SOBRE todo
   lo demás y leerse: si sale medio tapado por la barra superior no sirve. */
html.lucanta .lc-skip.lc-focusable:focus,
html.lucanta .lc-skip.lc-focusable:focus-visible {
    position: fixed !important;
    top: var(--sp-2);
    left: var(--sp-2);
    z-index: var(--z-offline);
    background: var(--brand);
    color: #fff;
    border-radius: var(--r-sm, 8px);
    font-size: var(--fs-body);
    font-weight: var(--fw-semi);
    text-decoration: none;
    min-height: var(--control-h-touch);
    display: inline-flex;
    align-items: center;
}
/* El destino del salto no debe dibujar un anillo: no es un control. */
html.lucanta #lc-contenido:focus { outline: none; }

/* ------------------------------------------- MODO FISCAL: ESTADO SIN COLOR ---
   Una opción bloqueada se distinguía por estar atenuada. El atenuado es color, y
   quien no lo percibe —o usa lector— no tiene manera de saber cuál puede elegir.
   La etiqueta lo dice con palabras. */
html.lucanta .lc-mode-tag {
    display: inline-flex;
    align-items: center;
    margin-left: var(--sp-2);
    padding: 0 var(--sp-2);
    min-height: var(--target-min);
    border: 1px solid var(--border-3);
    border-radius: 999px;
    font-size: var(--fs-caption);
    font-weight: var(--fw-semi);
    color: var(--text-3);
}
html.lucanta .lc-mode-tag-ok { border-color: var(--green-text); color: var(--green-text); }
/* El enunciado de la confirmación recibe el foco: no debe dibujar un anillo de
   control, pero sí ser alcanzable por código. */
html.lucanta .lc-confirm-focus:focus { outline: none; }
