/* ═══════════════════════════════════════════════════════════════
   Sapphire custom CSS — overrides and missing Metronic utilities
   Loaded AFTER styles.css so these rules take effect correctly.
   ═══════════════════════════════════════════════════════════════ */

/* ── Success semantic color (not in Metronic bundle) ─────────── */
:root {
    --success: var(--color-green-500);
    --success-foreground: #fff;
}

/* ── Missing kt-btn variants ──────────────────────────────────── */
.kt-btn-success {
    background-color: var(--color-green-500);
    color: #fff;
}
.kt-btn-success:hover {
    background-color: var(--color-green-600);
}
.kt-btn-success:disabled {
    opacity: 0.6;
    cursor: not-allowed;
}

.kt-btn-light {
    background-color: var(--muted);
    color: var(--muted-foreground);
}
.kt-btn-light:hover {
    color: var(--foreground);
}

/* ── Missing Tailwind success utilities ───────────────────────── */
.bg-success         { background-color: var(--color-green-500); }
.text-success       { color: var(--color-green-500); }
.text-success-dark  { color: var(--color-green-800); }
.border-success     { border-color: var(--color-green-500); }

.bg-success\/5  { background-color: color-mix(in oklab, var(--color-green-500)  5%, transparent); }
.bg-success\/10 { background-color: color-mix(in oklab, var(--color-green-500) 10%, transparent); }
.bg-success\/15 { background-color: color-mix(in oklab, var(--color-green-500) 15%, transparent); }

.border-success\/30 { border-color: color-mix(in oklab, var(--color-green-500) 30%, transparent); }
.border-success\/50 { border-color: color-mix(in oklab, var(--color-green-500) 50%, transparent); }
.border-success\/60 { border-color: color-mix(in oklab, var(--color-green-500) 60%, transparent); }

.hover\:border-success\/60:hover { border-color: color-mix(in oklab, var(--color-green-500) 60%, transparent); }

/* ── Missing Tailwind warning utilities ───────────────────────── */
/* Same case as `success` above: the precompiled Metronic bundle ships NO `warning` variant at
   all (0 rules for text-/bg-/border-warning, measured), so the 40 usages across 19 views render
   with no colour and no background, silently. Defined here once instead of rewriting the views.
   Found via: in `Sales/Detail` the date of an EXPIRED quote is highlighted with `text-warning`
   and was not highlighted, and the editable-invoice banner in `Sales/Form` had neither
   background nor border. `--color-amber-500` does not exist in the bundle; `--color-yellow-500`
   does. Governing: AgDR-234-3. */
.text-warning       { color: var(--color-yellow-500); }
.bg-warning\/10     { background-color: color-mix(in oklab, var(--color-yellow-500) 10%, transparent); }
.border-warning\/20 { border-color: color-mix(in oklab, var(--color-yellow-500) 20%, transparent); }
.border-warning\/30 { border-color: color-mix(in oklab, var(--color-yellow-500) 30%, transparent); }

/* ── Missing destructive hover utility ────────────────────────── */
/* #433: the bundle ships no `danger` variant at all, so the views now use `destructive`, which it does
   ship (text-, bg-/5, border-/10, kt-btn-, kt-badge-, kt-alert-). The one it lacks is the hover text
   colour, used by the ghost "x" of the branch selector (Shared/Components/ScopeSelector). */
.hover\:text-destructive:hover { color: var(--destructive); }

/* ── kt-form-message: show it whenever it has something to show (#377) ─────────────── */
/* The bundle hides `.kt-form-message` (display:none) and only reveals it under
   `.kt-form-item:has([aria-invalid='true'])`, which `_ValidationScriptsPartial` sets for jQuery
   Validate. Screens with their own JS validation (CashShifts/Close, CashWithdrawals/Register) toggle
   `hidden` on the inner span and never set aria-invalid, and several views put permanent hints in
   this class: both stayed invisible. One rule instead of fixing view by view: the container shows
   when it holds a child that is neither empty nor `.hidden`. An empty `asp-validation-for` span keeps
   it hidden, so standard forms get no extra gap (measured: 0 px on 6 forms). Hints keep their own
   colour class; the container's destructive colour only reaches bare error text.
   Also covers a validation message placed outside any `.kt-form-item` (Sales/Form LinesJson:
   "add at least one line"), which the bundle rule can never reach. */
.kt-form-message:has(> :not(.hidden):not(:empty)) { display: block; }

/* ── Missing translate utilities (toggle component) ──────────── */
.translate-x-1 { translate: calc(var(--spacing, 0.25rem) * 1) 0; }
.translate-x-6 { translate: calc(var(--spacing, 0.25rem) * 6) 0; }

/* ── Missing transition-transform utility ─────────────────────── */
.transition-transform {
    transition-property: translate, transform;
    transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
    transition-duration: 150ms;
}

/* ── jQuery Validation Unobtrusive compatibility ──────────────── */
/* Required so bare <span asp-validation-for> stays hidden when valid */
.field-validation-valid  { display: none; }
.field-validation-error  { color: var(--destructive); font-size: var(--text-xs); line-height: var(--text-xs--line-height); }
/* Hide the summary block when all fields are valid */
.validation-summary-valid { display: none; }
.validation-summary-errors { color: var(--destructive); font-size: var(--text-sm); }

/* ── Wizard stepper (_Stepper.cshtml) ─────────────────────────── */
/* The Metronic bundle ships KTStepper JS but no stepper CSS, so the indicator
   styling lives here (Metronic look: numbered circles, connector lines, active
   primary / completed green). States are toggled by the host JS via
   .is-active / .is-completed on [data-stepper-item]. The step-body show/hide is
   driven by inline style in the host JS — NOT by this file — so a stale cached
   site.css can never leave the wizard showing all steps at once. */

/* Indicator circle */
.sap-stepper-circle {
    border-width: 2px;
    background-color: var(--background);
    color: var(--secondary-foreground);
    transition: background-color 150ms ease, border-color 150ms ease, color 150ms ease, box-shadow 150ms ease;
}
.sap-stepper-item.is-active .sap-stepper-circle {
    background-color: var(--primary);
    border-color: var(--primary);
    color: var(--primary-foreground);
    box-shadow: 0 0 0 4px color-mix(in oklab, var(--primary) 18%, transparent);
}
.sap-stepper-item.is-active .sap-stepper-title { color: var(--primary); }
.sap-stepper-item.is-completed .sap-stepper-circle {
    background-color: var(--color-green-500);
    border-color: var(--color-green-500);
    color: #fff;
}
.sap-stepper-item.is-completed .sap-stepper-number { display: none; }
.sap-stepper-item.is-completed .sap-stepper-check  { display: inline-block; }
.sap-stepper-item { transition: opacity 150ms ease; }
.sap-stepper-item:not(.is-active):not(.is-completed) { opacity: .65; }

/* Connector line turns primary once the steps around it are done/active */
.sap-stepper-line { transition: background-color 150ms ease; }
.sap-stepper-item.is-completed + .sap-stepper-line { background-color: var(--primary); }

/* The partial holds indicator + nav, but they must wrap the host step bodies
   (indicator on top, bodies in the middle, nav at the bottom). display:contents
   lifts the partial's children into the host flex container so `order` can place
   them around the bodies. Purely cosmetic ordering — never controls visibility. */
.sap-stepper { display: contents; }
.sap-stepper-nav     { order: 0; }   /* indicator on top */
.wizard-step         { order: 10; }  /* step bodies in the middle */
.sap-stepper-actions { order: 20; }  /* Back / Next at the bottom */

/* ── Reposición sugerida: columna "Depósitos" solo en pantallas ≥768px (issue #111) ─
   md:table-cell NO existe en el bundle (el template original nunca lo usó — mismo gotcha
   que md:col-span-N arriba). Oculta en mobile por default; en el resto vuelve al display
   nativo de <td>/<th> (table-cell), no "block" (rompería el layout de la tabla). */
.sap-replenishment-col-md { display: none; }
@media (width >= 48rem) {
  .sap-replenishment-col-md { display: table-cell; }
}

/* ── Mínimos y stock deseado: divisor entre grupos de depósito (issue #111 retoque UX) ─
   Cada depósito es un th colspan=3 (Actual/Mínimo/Deseable); el borde marca dónde empieza
   el próximo grupo sin agregar una columna real. kt-table-border ya da el resto de los bordes. */
.sap-thresholds-group,
.sap-thresholds-sub {
  border-left: 1px solid var(--border);
}

/* ── jsTree overrides (SPEC-UI-42 §6, A1 — exception to DEC-T005) ─
   Blend jsTree node styles into the Metronic Tailwind palette.
   themes: { icons: false, dots: false } limits the CSS surface area.  */
.jstree-default .jstree-wholerow-hovered { background: var(--muted); }
.jstree-default .jstree-wholerow-clicked { background: color-mix(in oklab, var(--primary) 12%, transparent); }
.jstree-default .jstree-anchor          { color: var(--foreground); font-size: 0.875rem; line-height: 1.5rem; }
.jstree-default .jstree-anchor:hover    { color: var(--primary); text-decoration: none; }
.jstree-default.jstree-focused > .jstree-container-ul .jstree-clicked { background: color-mix(in oklab, var(--primary) 15%, transparent); }
/* Expand/collapse toggle — use Metronic muted tone */
.jstree-default .jstree-icon.jstree-ocl { color: var(--muted-foreground); }
.jstree-default .jstree-icon           { font-family: inherit; }

/* DataTables serverSide: el indicador "procesando" como OVERLAY, no en el flujo.
   Sin esto ocupa ~56px (alto de una fila) y la grilla "salta" al paginar/cambiar tamaño
   (el contenedor crece y vuelve). Solo el POSICIONAMIENTO: la apariencia (fondo/padding/radio)
   la da Metronic con mayor especificidad. Governing: SPEC-UI-230 §6 · conventions.md (grilla). */
.dt-container { position: relative; }
.dt-processing {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    z-index: 10;
    pointer-events: none;
}

/* DataTables con scrollX: la celda del layout que contiene la tabla tiene que poder achicarse al ancho de la
   tarjeta. Con el min-width automático de los ítems flex crece hasta la suma de los anchos de columna y el área que
   se desplaza queda afuera de la tarjeta; la integración de DataTables de Metronic no trae esta regla. Sin
   scrollX no cambia nada: la tabla ya ocupa el 100% del contenedor. Governing: #379. */
.dt-layout-table > .dt-layout-cell { min-width: 0; }

/* Con los anchos de columna fijos (table-layout: fixed de Metronic), un texto sin espacios más largo que su columna
   —un correo, un código fuera de lo común— se desborda sobre la columna vecina. Así parte línea dentro de su celda,
   y sólo cuando no entra. Governing: #379. */
table.dataTable > tbody > tr > td { overflow-wrap: anywhere; }

/* Fotos del producto (#389): el recuadro de tamaño fijo donde va la miniatura, con el ícono de "sin foto"
   detrás y la foto encima. Va acá y no con clases de Tailwind porque el bundle está precompilado y los
   tamaños que hacen falta (48×64 en la grilla, 70×90 en la ficha) no están entre las clases que el template
   usó: se ignorarían en silencio y la miniatura quedaría sin alto. Governing: diseno.md §3 · plan de #389. */
.foto-producto {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
    flex-shrink: 0;
}
.foto-producto--grilla { width: 64px; height: 48px; }
.foto-producto--ficha  { width: 90px; height: 70px; }
/* La foto llena el recuadro entero manteniendo la proporción: se escala hasta cubrirlo y lo que sobra de
   un lado queda recortado (object-fit: cover). Con "contain" entraba completa pero dejaba franjas grises a
   los costados, y una tira de miniaturas de distintas proporciones se veía despareja. */
.foto-producto > img {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

/* Fila de carga de línea de la orden de venta (#396): Producto, Cantidad, Depósito, Precio unitario y Agregar en
   UNA fila desde 768px (el breakpoint md de Metronic), apilados uno por fila en pantallas más angostas. Va acá y
   no con clases de Tailwind porque el bundle precompilado no tiene md:grid-cols-12, md:col-span-N ni md:w-*:
   se ignoraban en silencio y cada campo ocupaba una fila entera. Los ítems se alinean arriba (etiqueta con
   etiqueta) para que la ayuda debajo del depósito no desalinee los inputs. Governing: diseno.md §3. */
.ov-linea {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
}
@media (min-width: 768px) {
    .ov-linea { flex-direction: row; align-items: flex-start; }
    /* #582: campo "Código" (carga por código exacto), antes del buscador; ancho fijo como cantidad/precio. */
    .ov-linea-codigo   { width: 10rem; flex-shrink: 0; }
    .ov-linea-producto { flex: 1 1 0; min-width: 0; }
    .ov-linea-cantidad { width: 7rem; flex-shrink: 0; }
    .ov-linea-deposito { width: 13rem; flex-shrink: 0; }
    /* #806: 9rem (era 11rem) para darle ese ancho al producto; un precio como $1.250.000,00 sigue entrando. */
    .ov-linea-precio   { width: 9rem; flex-shrink: 0; }
    .ov-linea-agregar  { flex-shrink: 0; }
}

/* #582: el código interno se guarda en mayúsculas; el campo lo muestra así mientras se escribe, sin lógica
   (la normalización real la hace el servidor). */
#lineCode { text-transform: uppercase; }

/* Aviso de precio desactualizado (#397): vive debajo del input de precio unitario, que es una columna angosta
   de la fila de carga (.ov-linea-precio). El badge de Metronic no parte líneas y desbordaba sobre la ayuda del
   depósito; acá se lo deja partir en varias líneas dentro de su columna. El :not(.hidden) es para que el
   display:block no le gane a la clase hidden con la que arranca oculto. Governing: diseno.md §3. */
.ov-linea-precio #staleMsg:not(.hidden) {
    display: block;
    white-space: normal;
    height: auto;
    line-height: 1.3;
    margin-top: 0.25rem;
}

/* #407: modal "Simular cuotas" del form de venta. Ancho para la tabla de 7 columnas y alto con scroll; las
   utilidades max-w-[…]/max-h-[…] no están en el bundle precompilado (diseno §3). */
#installmentsModal .kt-modal-content { width: calc(100% - 2rem); max-width: 60rem; margin-top: 6vh; }
#installmentsModal .kt-modal-body { max-height: 75vh; }

/* Filas que el importador del listado de precios rechazó (#350), como lista debajo del resumen. Va acá porque
   list-disc no está en el bundle precompilado: se ignoraría en silencio y la lista saldría sin viñetas.
   Governing: diseno.md §3 · ficha de #350. */
.filas-rechazadas {
    list-style: disc;
    padding-inline-start: 1.25rem;
    margin-top: 0.25rem;
}

/* Grilla de líneas de la OC: las celdas se alinean arriba. `.kt-table tbody td` centra en vertical, y una celda con un
   aviso debajo del campo ("Sin precio del proveedor", el del código de proveedor) centraba el bloque campo + aviso:
   el campo subía y quedaba desalineado del resto de la línea. Alineadas arriba, los campos comparten la línea y el
   aviso cuelga debajo del suyo. El template no trae tablas con un campo y un texto en la misma celda, y `align-top` no
   está en el CSS precompilado. El subtotal y los botones, que no son campos, se centran en el alto de un campo
   (spacing × 8.5, el de `.kt-input`) para quedar a la altura del texto de los campos. Va por una clase propia
   y no por `#linesTable`, porque ese id lo repiten la orden de venta y la factura de compra. Governing: #440. */
.oc-lines-table > tbody > tr:not(.surcharge-row) > td { vertical-align: top; }
.oc-lines-table > tbody > tr:not(.surcharge-row) > td[id^="lineSubtotal_"],
.oc-lines-table > tbody > tr:not(.surcharge-row) > td:last-child { line-height: calc(var(--spacing) * 8.5); }
.oc-lines-table > tbody > tr:not(.surcharge-row) > td:last-child > .kt-btn { vertical-align: middle; }

/* Reportes › Ventas › Total de ventas (#750): el tablero del mockup de la tarea. Las barras y el avatar con iniciales
   usan los componentes del template (kt-progress, kt-avatar / kt-avatar-fallback). Lo que va acá es lo que el bundle
   precompilado no trae: las grillas de 4 / 2 / 1 columnas (lg:grid-cols-4, sm:grid-cols-2 no existen), los números de
   los cuadros y el renglón de ranking. Colores con las variables del tema para que anden en claro y oscuro.
   Governing: plan #750 · mockup.html de la tarea. */
.rep-grid { display: grid; gap: 1.25rem; grid-template-columns: repeat(4, minmax(0, 1fr)); }
.rep-grid-2 { display: grid; gap: 1.25rem; grid-template-columns: repeat(2, minmax(0, 1fr)); }
.rep-charts { display: grid; gap: 1.25rem; grid-template-columns: 2fr 1fr; }
@media (max-width: 1100px) { .rep-charts { grid-template-columns: 1fr; } }
@media (max-width: 1100px) { .rep-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 900px) { .rep-grid-2 { grid-template-columns: 1fr; } }
@media (max-width: 600px) { .rep-grid { grid-template-columns: 1fr; } }
.rep-kpi { padding: 1.1rem 1.25rem; display: grid; gap: 0.4rem; }
.rep-kpi-value { font-size: 1.6rem; font-weight: 600; font-variant-numeric: tabular-nums; letter-spacing: -0.01em; }
.rep-kpi-main { background: var(--primary); color: var(--primary-foreground); border-color: transparent; }
.rep-kpi-main .rep-kpi-value { font-size: 2rem; }
.rep-kpi-main .rep-muted { color: var(--primary-foreground); opacity: 0.85; }
.rep-muted { font-size: 0.75rem; color: var(--muted-foreground); }
.rep-rank { display: grid; gap: 0.9rem; align-content: start; }
.rep-rank-row { display: grid; gap: 0.3rem; }
.rep-rank-top { display: flex; justify-content: space-between; gap: 0.6rem; font-size: 0.8125rem; }
.rep-rank-name { display: flex; gap: 0.5rem; align-items: center; min-width: 0; }
.rep-rank-name > span:last-child { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rep-pos { width: 1.25rem; height: 1.25rem; border-radius: 999px; background: var(--muted); font-size: 0.6875rem; font-weight: 600;
    display: inline-flex; align-items: center; justify-content: center; flex: none; }
.rep-pos-first { background: var(--primary); color: var(--primary-foreground); }
.rep-amount { font-variant-numeric: tabular-nums; font-weight: 600; white-space: nowrap; }
.rep-num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.rep-plan > td:first-child { padding-inline-start: 2rem; color: var(--muted-foreground); }
.rep-surcharge { color: var(--color-orange-700, #c2410c); }
.rep-discount { color: var(--color-green-700, #15803d); }
.rep-pct-input { width: 6rem; text-align: right; }
.rep-sim-total { display: flex; flex-wrap: wrap; gap: 0.75rem 1.75rem; padding: 0.9rem 1rem; border-radius: 0.5rem; background: var(--muted); font-size: 0.8125rem; }
.rep-sim-total b { display: block; font-size: 1.125rem; font-variant-numeric: tabular-nums; }
