/* =============================================================================
   OASYS ERP — Capa de componentes del Sistema de Diseno
   Portado de docs/design/oasys-design-system.dc.html (hifi: valores exactos).
   Consume los tokens de static/css/shadcn/theme.css (:root = claro, .dark = oscuro).
   Se carga DESPUES de tailwind.css para que estas clases ganen a las utilities
   de igual especificidad.
   ============================================================================= */

/* ============== UTILIDADES DE TEXTO ============== */
.mono { font-family: 'JetBrains Mono', monospace; font-variant-numeric: tabular-nums; }
.muted { color: var(--tx2); }
.faint { color: var(--tx3); }
.tnum { font-variant-numeric: tabular-nums; }
.trunc { max-width: 260px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pos { color: var(--ok); font-weight: 600; }
.neg { color: var(--dg); font-weight: 600; }
.mono.pos { color: var(--ok); }
.mono.neg { color: var(--dg); }
.eyebrow { font-size: 11px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; color: var(--brand-txt); }

/* ============== PULIDO GLOBAL: scrollbar, seleccion, focus, motion ============== */
::-webkit-scrollbar { width: 11px; height: 11px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: rgba(133, 133, 140, .38); border-radius: 99px; border: 3px solid transparent; background-clip: content-box; }
::-webkit-scrollbar-thumb:hover { background: rgba(133, 133, 140, .62); background-clip: content-box; }
::-webkit-scrollbar-corner { background: transparent; }
html { scrollbar-width: thin; scrollbar-color: rgba(133, 133, 140, .38) transparent; }

::selection { background: var(--brand-sub-bd); color: var(--tx); }

code { font-family: 'JetBrains Mono', monospace; font-size: .86em; background: var(--hover); padding: 1.5px 6px; border-radius: 6px; color: var(--brand-txt); border: 1px solid var(--bd); }

:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; border-radius: 6px; }
:focus:not(:focus-visible) { outline: none; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
}

/* ============== KEYFRAMES ============== */
@keyframes fade { from { opacity: 0; } }
@keyframes pop { from { opacity: 0; transform: scale(.96) translateY(6px); } }
@keyframes slide { from { transform: translateX(24px); opacity: .4; } }
@keyframes toastin { from { opacity: 0; transform: translateX(24px) scale(.97); } }
@keyframes shim { 0% { background-position: 100% 0; } 100% { background-position: -100% 0; } }
@keyframes spin { to { transform: rotate(360deg); } }
@keyframes isospin { to { transform: rotate(360deg); } }
@keyframes dotp { 0%, 60%, 100% { opacity: .25; transform: translateY(0); } 30% { opacity: 1; transform: translateY(-4px); } }

/* ============== TARJETA BASE ============== */
.card { background: var(--card); border: 1px solid var(--bd); border-radius: 12px; box-shadow: var(--sh-sm); }

/* ============== BOTONES ============== */
.btn { display: inline-flex; align-items: center; justify-content: center; gap: 7px; height: 36px; padding: 0 14px; border-radius: 8px; font: inherit; font-weight: 600; font-size: 13px; border: 1px solid transparent; cursor: pointer; transition: .15s; white-space: nowrap; line-height: 1; }
.btn svg { width: 15px; height: 15px; }
/* El `border-box` del shorthand NO es decorativo: `.btn` lleva un borde de 1px
   transparente (para que todos los botones midan igual con o sin borde visible).
   Sobre un degradado se cruzan tres defaults de CSS -- background-origin
   padding-box, background-clip border-box y background-repeat repeat -- y ese
   anillo de 1px termina mostrando el mosaico repetido, o sea el color del
   extremo opuesto (el teal) filtrado por todo el perimetro. Con `border-box` el
   degradado se dimensiona al borde y el anillo desaparece. */
.btn-brand { background: var(--grad-btn) border-box; color: #fff; box-shadow: 0 2px 12px -3px var(--acc-glow); }
.btn-brand:hover { filter: brightness(1.08); transform: translateY(-1px); }
.btn-primary { background: var(--primary-grad) border-box; color: #fff; }
.btn-primary:hover { filter: brightness(1.08); transform: translateY(-1px); }
.btn-secondary { background: var(--card); color: var(--tx); border-color: var(--bd-2); }
.btn-secondary:hover { background: var(--hover); border-color: var(--tx3); }
.btn-ghost { background: transparent; color: var(--tx2); }
.btn-ghost:hover { background: var(--hover); color: var(--tx); }
.btn-danger { background: var(--dg); color: #fff; }
.btn-danger:hover { filter: brightness(1.06); }
.btn-warn { background: var(--warn); color: #fff; } /* accion de advertencia (ej. NC/ND, revertir) */
.btn-warn:hover { filter: brightness(1.06); }
.btn-ok { background: var(--ok); color: #fff; } /* accion de confirmacion positiva (ej. aprobar, marcar pagado) */
.btn-ok:hover { filter: brightness(1.06); }
.btn-sm { height: 30px; padding: 0 10px; font-size: 12px; border-radius: 7px; }
.btn-lg { height: 42px; padding: 0 19px; font-size: 14.5px; }
.btn:disabled { opacity: .45; cursor: not-allowed; }

/* Boton de icono */
.icon-btn { width: 32px; height: 32px; display: inline-flex; align-items: center; justify-content: center; border: 1px solid var(--bd-2); background: var(--card); border-radius: 8px; color: var(--tx2); cursor: pointer; transition: .15s; }
.icon-btn:hover { background: var(--hover); color: var(--tx); }
.icon-btn svg { width: 16px; height: 16px; }

/* ============== INPUTS Y FORMULARIOS ============== */
.field { display: flex; flex-direction: column; gap: 6px; }
.label { font-size: 12px; font-weight: 600; color: var(--tx2); }
.input { height: 36px; padding: 0 12px; border-radius: 8px; border: 1px solid var(--bd-2); background: var(--card); color: var(--tx); font: inherit; font-size: 13px; width: 100%; transition: .15s; }
.input:focus { outline: none; border-color: var(--brand); box-shadow: 0 0 0 3px var(--ring); }
.input::placeholder { color: var(--tx3); }

/* Input con icono */
.iw { position: relative; display: flex; align-items: center; }
.iw > svg { position: absolute; left: 11px; width: 15px; height: 15px; color: var(--tx3); pointer-events: none; }
.iw .input { padding-left: 33px; }

/* Select estilizado con caret SVG */
select.input { cursor: pointer; -webkit-appearance: none; appearance: none; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%235b6373' stroke-width='2.4'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E"); background-repeat: no-repeat; background-position: right 11px center; padding-right: 30px; }

/* Switch */
.switch { width: 38px; height: 22px; border-radius: 999px; background: var(--bd-2); position: relative; cursor: pointer; transition: .18s; border: 0; flex: none; }
.switch::after { content: ""; position: absolute; top: 2px; left: 2px; width: 18px; height: 18px; border-radius: 50%; background: #fff; transition: .18s; box-shadow: 0 1px 3px rgba(0, 0, 0, .4); }
.switch.on { background: var(--brand-solid); }
.switch.on::after { left: 18px; }

/* Checkbox */
.check { width: 18px; height: 18px; border-radius: 5px; border: 1.5px solid var(--bd-2); display: inline-flex; align-items: center; justify-content: center; background: var(--card); }
.check.on { background: var(--brand-solid); border-color: var(--brand-solid); color: #fff; }
.ck-grp, .radio-grp { display: flex; flex-direction: column; gap: 9px; }
.ck-row { display: flex; align-items: center; gap: 10px; cursor: pointer; font-size: 13.5px; font-weight: 500; }

/* Radio */
.radio { display: flex; align-items: center; gap: 10px; cursor: pointer; font-size: 13.5px; font-weight: 500; }
.radio-o { width: 19px; height: 19px; border-radius: 50%; border: 1.5px solid var(--bd-2); flex: none; display: flex; align-items: center; justify-content: center; transition: .14s; }
.radio.on .radio-o { border-color: var(--brand); }
.radio-o::after { content: ""; width: 9px; height: 9px; border-radius: 50%; background: var(--brand); transform: scale(0); transition: .16s; }
.radio.on .radio-o::after { transform: scale(1); }

/* Validacion */
.form-g { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 20px; }
.req { color: var(--dg); margin-left: 2px; }
.input.err { border-color: var(--dg); box-shadow: 0 0 0 3px var(--dg-sub); }
.hint { font-size: 11.5px; color: var(--tx3); display: flex; align-items: center; gap: 5px; }
.hint.bad { color: var(--dg); }
.hint svg { width: 13px; height: 13px; flex: none; }
.counter { font-size: 11.5px; color: var(--tx3); text-align: right; font-variant-numeric: tabular-nums; }

/* Dropzone */
.drop { border: 1.5px dashed var(--bd-2); border-radius: 12px; padding: 26px; display: flex; flex-direction: column; align-items: center; gap: 7px; text-align: center; cursor: pointer; transition: .16s; background: var(--card); }
.drop:hover { border-color: var(--brand); background: var(--brand-sub); }
.drop-ic { width: 38px; height: 38px; border-radius: 10px; background: var(--brand-sub); color: var(--brand-txt); display: flex; align-items: center; justify-content: center; }
.drop-ic svg { width: 19px; height: 19px; }
.drop-t { font-size: 13px; font-weight: 600; }
.drop-s { font-size: 11.5px; color: var(--tx3); }

/* ============== BADGES / PILLS ============== */
.badge { display: inline-flex; align-items: center; gap: 5px; height: 22px; padding: 0 9px; border-radius: 6px; font-size: 11.5px; font-weight: 600; line-height: 1; white-space: nowrap; border: 1px solid transparent; }
.b-brand { background: var(--brand-sub); color: var(--brand-txt); border-color: var(--brand-sub-bd); }
.b-ok { background: var(--ok-sub); color: var(--ok); }
.b-warn { background: var(--warn-sub); color: var(--warn); }
.b-dg { background: var(--dg-sub); color: var(--dg); }
.b-neutral { background: var(--hover); color: var(--tx2); border-color: var(--bd); }
.dot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; flex: none; }

/* ============== TABS / CHIPS / SEGMENTED ============== */
.tabs { display: flex; gap: 0; border-bottom: 1px solid var(--bd); width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; scrollbar-width: none; }
.tabs::-webkit-scrollbar { display: none; } /* oculta scrollbar: los tabs scrollean horizontal en movil sin barra visible */
.tab { padding: 9px 2px; margin-right: 20px; border: 0; background: 0; font: inherit; font-weight: 600; font-size: 13.5px; color: var(--tx2); cursor: pointer; border-bottom: 2px solid transparent; margin-bottom: -1px; transition: .12s; white-space: nowrap; flex-shrink: 0; }
.tab:hover { color: var(--tx); }
.tab.on { color: var(--brand-txt); border-color: var(--brand); }

.chip { display: inline-flex; align-items: center; gap: 6px; height: 30px; padding: 0 12px; border-radius: 999px; border: 1px solid var(--bd-2); background: var(--card); font-size: 12px; font-weight: 600; color: var(--tx2); cursor: pointer; transition: .14s; }
.chip:hover { border-color: var(--brand); color: var(--brand-txt); }
.chip.on { background: var(--brand); border-color: var(--brand); color: #fff; }

.seg { display: inline-flex; padding: 3px; gap: 2px; background: var(--panel); border-radius: 9px; border: 1px solid var(--bd); }
.seg-btn { height: 28px; padding: 0 13px; border: 0; background: transparent; color: var(--tx2); font: inherit; font-weight: 600; font-size: 12.5px; border-radius: 6px; cursor: pointer; transition: .15s; }
.seg-btn:hover { color: var(--tx); }
.seg-btn.on { background: var(--card); color: var(--tx); box-shadow: var(--sh-sm); }

/* ============== KPI / STAT ============== */
.stat { padding: 17px 18px; display: flex; flex-direction: column; gap: 11px; position: relative; overflow: hidden; transition: .18s; }
.stat:hover { border-color: var(--bd-acc); transform: translateY(-2px); }
.stat::before { content: ""; position: absolute; top: 0; left: 0; right: 0; height: 2px; background: var(--grad); opacity: 0; transition: opacity .18s; }
.stat:hover::before { opacity: 1; }
.stat-top { display: flex; align-items: center; justify-content: space-between; }
.stat-l { font-size: 12px; color: var(--tx2); font-weight: 600; }
.stat-i { width: 30px; height: 30px; border-radius: 8px; background: var(--brand-sub); color: var(--brand-txt); display: flex; align-items: center; justify-content: center; }
.stat-i svg { width: 16px; height: 16px; }
.stat-v { font-size: 25px; font-weight: 800; letter-spacing: -.03em; font-variant-numeric: tabular-nums; }
.stat-foot { display: flex; align-items: flex-end; justify-content: space-between; gap: 8px; margin-top: 2px; }
.delta { display: inline-flex; align-items: center; gap: 3px; font-size: 12px; font-weight: 700; }
.delta.up { color: var(--ok); }
.delta.down { color: var(--dg); }

/* ============== TABLA ============== */
.tbl-wrap { border: 1px solid var(--bd); border-radius: 12px; overflow: hidden; background: var(--card); }
.tbl { width: 100%; border-collapse: collapse; font-size: 13px; }
.tbl th { text-align: left; font-size: 11px; text-transform: uppercase; letter-spacing: .05em; color: var(--tx3); font-weight: 700; padding: 10px 15px; background: var(--panel); border-bottom: 1px solid var(--bd); }
.tbl td { padding: 11px 15px; border-bottom: 1px solid var(--bd); color: var(--tx); vertical-align: middle; }
.tbl tbody tr:last-child td { border-bottom: 0; }
.tbl tbody tr { transition: .1s; }
.tbl tbody tr:hover { background: var(--hover); }

/* Estados de datos: tabla larga con cabecera pegajosa */
.tbl-scroll { max-height: 300px; overflow: auto; }
.tbl.sticky thead th { position: sticky; top: 0; z-index: 2; }

/* ============== TABLAS EN MOVIL: cada fila es una tarjeta ==============
   En < 640px una tabla obliga a scroll lateral y a esconder columnas: hoy hay
   ~388 celdas marcadas `hidden … table-cell` que en el telefono directamente no
   existen. Debajo de ese ancho la fila se convierte en una tarjeta etiqueta:valor
   y se muestran TODAS las columnas.

   La etiqueta sale de `data-label`, que js/base/tabla-responsive.js copia desde
   el <th> correspondiente — por eso esto no obliga a tocar ningun template.

   Excepcion: `.tbl-num` (contabilidad y tesoreria). Ahi las columnas numericas se
   leen comparandolas entre si, y apilarlas rompe la lectura: esas conservan la
   tabla con scroll lateral y primera columna fija. */
@media (max-width: 639px) {
  .tbl:not(.tbl-num) thead { display: none; }
  .tbl:not(.tbl-num),
  .tbl:not(.tbl-num) tbody,
  .tbl:not(.tbl-num) tr,
  .tbl:not(.tbl-num) td { display: block; width: auto; }

  .tbl:not(.tbl-num) tbody tr {
    position: relative;
    border: 1px solid var(--bd);
    border-radius: 12px;
    background: var(--card);
    padding: 4px 0;
    margin-bottom: 10px;
  }
  .tbl:not(.tbl-num) tbody tr:last-child { margin-bottom: 0; }

  /* Mas especifico que `.hidden` de Tailwind: las columnas que el desktop oculta
     por falta de ancho aca si tienen lugar. */
  .tbl:not(.tbl-num) tbody td {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    text-align: left !important;
    padding: 6px 13px;
    border-bottom: 0;
  }
  .tbl:not(.tbl-num) tbody td::before {
    content: attr(data-label);
    flex: none;
    font-size: 10.5px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .05em;
    color: var(--tx3);
  }
  /* Celda sin cabecera (checkbox, acciones) o etiqueta vacia: sin etiqueta. */
  .tbl:not(.tbl-num) tbody td:not([data-label])::before,
  .tbl:not(.tbl-num) tbody td[data-label=""]::before { content: none; }

  /* La primera celda es el identificador de la fila: titulo de la tarjeta. */
  .tbl:not(.tbl-num) tbody td:first-child {
    display: block;
    padding: 9px 13px 7px;
    font-weight: 600;
    border-bottom: 1px solid var(--bd);
    margin-bottom: 4px;
    padding-right: 46px;   /* deja lugar al menu de acciones */
  }
  .tbl:not(.tbl-num) tbody td:first-child::before { content: none; }

  /* El menu "..." va a la esquina de la tarjeta, no a una fila propia. */
  .tbl:not(.tbl-num) tbody td[data-row-actions] {
    position: absolute;
    top: 7px;
    right: 8px;
    width: auto;
    padding: 0;
    border: 0;
  }
  .tbl:not(.tbl-num) tbody td[data-row-actions]::before { content: none; }

  /* Filas de agrupacion y estados vacios (una sola celda con colspan): no son
     tarjetas. Las marca el mismo script. */
  .tbl:not(.tbl-num) tbody tr.tbl-fila-plana {
    border: 0;
    background: none;
    padding: 0;
    margin: 0;
  }
  .tbl:not(.tbl-num) tbody tr.tbl-fila-plana td { padding: 10px 2px; }
  .tbl:not(.tbl-num) tbody tr.tbl-fila-plana td:first-child {
    border-bottom: 0;
    margin-bottom: 0;
    padding-right: 2px;
  }

  /* Contabilidad y tesoreria: tabla intacta, con la columna de concepto fija
     para no perder la referencia al scrollear los importes. El min-width es lo
     que hace posible ese scroll: sin el, la tabla se comprime hasta caber y los
     importes se parten en dos lineas en vez de desbordar. */
  .tbl-num { min-width: 620px; }
  .tbl-num th,
  .tbl-num td { white-space: nowrap; }
  .tbl-num th:first-child,
  .tbl-num td:first-child {
    position: sticky;
    left: 0;
    z-index: 1;
    background: var(--card);
  }
  .tbl-num thead th:first-child { z-index: 3; background: var(--panel); }
}

/* Celda cliente: avatar + nombre */
.cli { display: flex; align-items: center; gap: 9px; font-weight: 500; }
.av { width: 28px; height: 28px; border-radius: 8px; background: var(--grad); color: #fff; display: flex; align-items: center; justify-content: center; font-size: 11px; font-weight: 700; flex: none; }

/* ============== TABLA AVANZADA: orden, seleccion, lote, paginacion ============== */
.th-ck, .td-ck { width: 42px; text-align: center !important; padding-left: 16px !important; }
.th-s { cursor: pointer; user-select: none; white-space: nowrap; }
.th-s:hover { color: var(--tx2); }
.th-s .car { display: inline-flex; vertical-align: middle; margin-left: 4px; opacity: 0; transition: .14s; }
.th-s.act .car { opacity: 1; color: var(--brand-txt); }
.th-s.act { color: var(--brand-txt); }
.car svg { width: 12px; height: 12px; transition: transform .18s; }
.car.desc svg { transform: rotate(180deg); }
.tr-sel { background: var(--brand-sub) !important; }
.tr-sel:hover { background: var(--brand-sub) !important; }
.bulk { display: flex; align-items: center; gap: 14px; padding: 10px 16px; background: var(--brand-sub); border-bottom: 1px solid var(--brand-sub-bd); }
.bulk-n { font-size: 13px; font-weight: 700; color: var(--brand-txt); }
.bulk-sp { flex: 1; }
.pager { display: flex; align-items: center; justify-content: space-between; padding: 12px 16px; border-top: 1px solid var(--bd); font-size: 12.5px; color: var(--tx3); }
.pager-nav { display: flex; gap: 5px; align-items: center; }
.pg-b { min-width: 30px; height: 30px; padding: 0 9px; border-radius: 8px; border: 1px solid var(--bd); background: var(--card); color: var(--tx2); font: inherit; font-size: 12.5px; font-weight: 600; cursor: pointer; transition: .14s; display: flex; align-items: center; justify-content: center; }
.pg-b:hover { background: var(--hover); color: var(--tx); }
.pg-b.on { background: var(--brand); border-color: var(--brand); color: #fff; }
.pg-b:disabled { opacity: .4; cursor: not-allowed; }
.pg-b svg { width: 14px; height: 14px; }

/* ============== FEEDBACK: TOASTS ============== */
.toast-wrap { position: fixed; right: 20px; bottom: 20px; z-index: 80; display: flex; flex-direction: column; gap: 10px; width: 340px; max-width: calc(100vw - 40px); }
/* Movil: subir los toasts por encima del FAB (bottom:24px right:24px, 56px) para que no se tapen */
@media (max-width: 639px) {
  .toast-wrap {
    bottom: calc(24px + 56px + 12px + env(safe-area-inset-bottom));
    right: max(16px, env(safe-area-inset-right));
  }
}
.toast { display: flex; align-items: flex-start; gap: 11px; padding: 13px 14px; background: var(--card); border: 1px solid var(--bd); border-radius: 12px; box-shadow: var(--sh-lg); position: relative; overflow: hidden; animation: toastin var(--dur-med) var(--ease-out); }
.toast::before { content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 3px; }
.toast-ic { width: 20px; height: 20px; flex: none; border-radius: 50%; display: flex; align-items: center; justify-content: center; margin-top: 1px; }
.toast-ic svg { width: 13px; height: 13px; stroke-width: 3; }
.toast-b { flex: 1; min-width: 0; }
.toast-t { font-size: 13px; font-weight: 700; }
.toast-m { font-size: 12px; color: var(--tx2); margin-top: 2px; line-height: 1.4; }
.toast-x { background: 0; border: 0; color: var(--tx3); cursor: pointer; padding: 2px; border-radius: 5px; transition: .14s; flex: none; }
.toast-x:hover { background: var(--hover); color: var(--tx); }
.toast-x svg { width: 14px; height: 14px; }
.toast.ok::before { background: var(--ok); }
.toast.ok .toast-ic { background: var(--ok-sub); color: var(--ok); }
.toast.warn::before { background: var(--warn); }
.toast.warn .toast-ic { background: var(--warn-sub); color: var(--warn); }
.toast.dg::before { background: var(--dg); }
.toast.dg .toast-ic { background: var(--dg-sub); color: var(--dg); }
.toast.info::before { background: var(--brand); }
.toast.info .toast-ic { background: var(--brand-sub); color: var(--brand-txt); }

/* ============== FEEDBACK: ALERTAS CONTEXTUALES ============== */
.alert { display: flex; align-items: flex-start; gap: 12px; padding: 13px 15px; border-radius: 12px; border: 1px solid var(--bd); background: var(--card); }
.alert-ic { width: 22px; height: 22px; flex: none; display: flex; align-items: center; justify-content: center; margin-top: 1px; }
.alert-ic svg { width: 18px; height: 18px; }
.alert-t { font-size: 13.5px; font-weight: 700; }
.alert-m { font-size: 12.5px; color: var(--tx2); margin-top: 2px; line-height: 1.45; }
.alert.a-ok { background: var(--ok-sub); border-color: transparent; }
.alert.a-ok .alert-ic { color: var(--ok); }
.alert.a-ok .alert-t { color: var(--ok); }
.alert.a-warn { background: var(--warn-sub); border-color: transparent; }
.alert.a-warn .alert-ic { color: var(--warn); }
.alert.a-warn .alert-t { color: var(--warn); }
.alert.a-dg { background: var(--dg-sub); border-color: transparent; }
.alert.a-dg .alert-ic { color: var(--dg); }
.alert.a-dg .alert-t { color: var(--dg); }
.alert.a-info { background: var(--brand-sub); border-color: transparent; }
.alert.a-info .alert-ic { color: var(--brand-txt); }
.alert.a-info .alert-t { color: var(--brand-txt); }

/* ============== FEEDBACK: SKELETON / LOADERS / ESTADOS ============== */
.sk { background: linear-gradient(90deg, var(--hover) 25%, var(--bd) 37%, var(--hover) 63%); background-size: 400% 100%; animation: shim 1.4s ease infinite; border-radius: 7px; }

.spin { width: 22px; height: 22px; border-radius: 50%; border: 2.5px solid var(--bd-2); border-top-color: var(--brand); animation: spin .7s linear infinite; flex: none; }
.spin.lg { width: 34px; height: 34px; border-width: 3px; }
.spin.sm { width: 15px; height: 15px; border-width: 2px; }
/* Dentro de un boton el spin hereda el color del texto (brand sobre brand seria invisible) */
.btn .spin { border-color: color-mix(in srgb, currentColor 35%, transparent); border-top-color: currentColor; }
/* Loader de marca: isotipo OASYS girando. El PNG es blanco: en claro se tinta a oscuro */
.iso-load { width: 40px; height: 40px; object-fit: contain; animation: isospin 1.5s cubic-bezier(.65,.15,.35,.85) infinite; filter: brightness(0) opacity(.82); }
.dark .iso-load { filter: none; opacity: .92; }
/* .iso-load y .spin quedan con giro: son animacion esencial de estado (indican carga);
   congelarlos parece UI colgada (visto en Windows con "Efectos de animacion" apagado).
   Bajo reduced-motion el spin solo baja el ritmo; .sk y .dots (decorativos) si se apagan */
@media (prefers-reduced-motion: reduce) {
  .spin { animation-duration: 2s; }
  .sk, .dots span { animation: none; }
  .emp-chev, .emp-bar-fill { transition: none; }
}
.dots { display: inline-flex; gap: 5px; align-items: center; }
.dots span { width: 7px; height: 7px; border-radius: 50%; background: var(--brand); animation: dotp 1s ease infinite; }
.dots span:nth-child(2) { animation-delay: .15s; }
.dots span:nth-child(3) { animation-delay: .3s; }
.load-lbl { font-size: 12.5px; color: var(--tx2); font-weight: 500; }

/* Estados vacio / error */
.state { display: flex; flex-direction: column; align-items: center; text-align: center; padding: 42px 24px; gap: 5px; }
.state-ic { width: 56px; height: 56px; border-radius: 16px; display: flex; align-items: center; justify-content: center; background: var(--brand-sub); color: var(--brand-txt); margin-bottom: 11px; }
.state-ic svg { width: 26px; height: 26px; }
.state.err .state-ic { background: var(--dg-sub); color: var(--dg); }
.state-t { font-size: 15px; font-weight: 700; }
.state-d { font-size: 13px; color: var(--tx2); max-width: 320px; line-height: 1.5; margin-bottom: 8px; }

/* ============== OVERLAY / MODAL / DRAWER ============== */
.overlay { position: fixed; inset: 0; z-index: 60; background: rgba(6, 8, 14, .55); backdrop-filter: blur(4px); display: flex; align-items: center; justify-content: center; padding: 24px; animation: fade var(--dur-med) var(--ease-out); }
.modal { width: 450px; max-width: 100%; background: var(--card); border: 1px solid var(--bd-2); border-radius: 16px; box-shadow: var(--sh-lg); overflow: hidden; animation: pop var(--dur-med) var(--ease-out); }
.modal-h { padding: 22px 24px 0; }
.modal-b { padding: 14px 24px 20px; }
.modal-f { padding: 15px 24px; background: var(--panel); border-top: 1px solid var(--bd); display: flex; justify-content: flex-end; gap: 9px; }
.drawer-wrap { position: fixed; inset: 0; z-index: 60; display: flex; justify-content: flex-end; background: rgba(6, 8, 14, .5); backdrop-filter: blur(4px); animation: fade var(--dur-med) var(--ease-out); }
.drawer { width: 396px; max-width: 100%; height: 100%; background: var(--card); border-left: 1px solid var(--bd-2); box-shadow: var(--sh-lg); animation: slide var(--dur-med) var(--ease-out); overflow-y: auto; }
.drawer-h { padding: 19px 22px; border-bottom: 1px solid var(--bd); display: flex; align-items: center; justify-content: space-between; }

/* ============== KBD / ATAJOS ============== */
.kbd { display: inline-flex; align-items: center; justify-content: center; min-width: 18px; height: 18px; padding: 0 5px; border-radius: 5px; background: var(--panel); border: 1px solid var(--bd-2); border-bottom-width: 2px; font-family: 'JetBrains Mono', monospace; font-size: 10.5px; font-weight: 600; color: var(--tx2); }
.kbd-btn { display: inline-flex; align-items: center; gap: 7px; height: 34px; padding: 0 12px; border-radius: 9px; border: 1px solid var(--bd-2); background: var(--card); color: var(--tx2); font: inherit; font-size: 13px; font-weight: 500; cursor: pointer; transition: .14s; }
.kbd-btn:hover { background: var(--hover); color: var(--tx); }

/* ============== COMMAND PALETTE (Ctrl/Cmd+K) ============== */
.cmdk-ov { position: fixed; inset: 0; z-index: 90; background: rgba(8, 10, 16, .55); backdrop-filter: blur(6px); display: flex; justify-content: center; align-items: flex-start; padding-top: 12vh; animation: fade var(--dur-med) var(--ease-out); }
.cmdk { width: 580px; max-width: calc(100vw - 32px); background: var(--card); border: 1px solid var(--bd-2); border-radius: 16px; box-shadow: var(--sh-lg); overflow: hidden; animation: pop var(--dur-med) var(--ease-out); }
.cmdk-top { display: flex; align-items: center; gap: 11px; padding: 15px 17px; border-bottom: 1px solid var(--bd); }
.cmdk-top > svg { width: 19px; height: 19px; color: var(--tx3); flex: none; }
.cmdk-in { flex: 1; border: 0; background: 0; font: inherit; font-size: 15.5px; color: var(--tx); outline: none; }
.cmdk-in::placeholder { color: var(--tx3); }
.cmdk-list { max-height: 340px; overflow-y: auto; padding: 8px; }
.cmdk-grp { font-size: 10.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .07em; color: var(--tx3); padding: 10px 10px 5px; }
.cmdk-i { display: flex; align-items: center; gap: 12px; padding: 10px 11px; border-radius: 10px; cursor: pointer; transition: .1s; }
.cmdk-i.on { background: var(--brand-sub); }
.cmdk-i-ic { width: 30px; height: 30px; border-radius: 8px; background: var(--panel); color: var(--tx2); display: flex; align-items: center; justify-content: center; flex: none; }
.cmdk-i.on .cmdk-i-ic { background: var(--brand); color: #fff; }
.cmdk-i-ic svg { width: 16px; height: 16px; }
.cmdk-i-t { flex: 1; font-size: 13.5px; font-weight: 600; }
.cmdk-i-s { font-size: 11.5px; color: var(--tx3); }
.cmdk-foot { display: flex; align-items: center; gap: 16px; padding: 9px 15px; border-top: 1px solid var(--bd); font-size: 11px; color: var(--tx3); }
.cmdk-foot span { display: flex; align-items: center; gap: 5px; }
.cmdk-empty { padding: 34px; text-align: center; font-size: 13px; color: var(--tx3); }

/* Command palette REAL (#oasys-cmd, command-palette.js togglea .hidden): entrada
   unificada con el resto de overlays. Backdrop = fade, panel = pop (scale-in);
   ambos --dur-med + --ease-out. Se re-disparan porque .hidden = display:none.
   El panel esta centrado con -translate-x-1/2 (translateX(-50%)); por eso usa un
   keyframe que PRESERVA ese eje X (si no, saltaria a la derecha durante la animacion). */
@keyframes popcx {
  from { opacity: 0; transform: translateX(-50%) scale(.96) translateY(6px); }
  to   { opacity: 1; transform: translateX(-50%) scale(1) translateY(0); }
}
#oasys-cmd:not(.hidden) > #cmd-backdrop { animation: fade var(--dur-med) var(--ease-out); }
#oasys-cmd:not(.hidden) > #cmd-backdrop + div { animation: popcx var(--dur-med) var(--ease-out); }

/* ============== MENU DE USUARIO (topbar) ============== */
.usr { position: relative; }
.usr-btn { display: flex; align-items: center; gap: 9px; height: 38px; padding: 3px 9px 3px 4px; border-radius: 10px; border: 1px solid var(--bd); background: var(--card); cursor: pointer; transition: .15s; }
.usr-btn:hover { background: var(--hover); }
.usr-av { width: 30px; height: 30px; border-radius: 8px; background: var(--grad); color: #fff; display: flex; align-items: center; justify-content: center; font-size: 11.5px; font-weight: 700; flex: none; }
.usr-av.lg { width: 38px; height: 38px; border-radius: 10px; font-size: 14px; }
.usr-meta { display: flex; flex-direction: column; line-height: 1.15; text-align: left; }
.usr-name { font-size: 12.5px; font-weight: 600; color: var(--tx); white-space: nowrap; }
.usr-role { font-size: 10.5px; color: var(--tx3); white-space: nowrap; }
.usr-cr { width: 14px; height: 14px; color: var(--tx3); }
.usr-scrim { position: fixed; inset: 0; z-index: 55; }
.usr-pop { position: absolute; top: 47px; right: 0; width: 238px; background: var(--card); border: 1px solid var(--bd); border-radius: 13px; box-shadow: var(--sh-lg); padding: 6px; z-index: 56; animation: pop var(--dur-med) var(--ease-out); }
.usr-pop-h { display: flex; align-items: center; gap: 11px; padding: 9px 8px 11px; }
.usr-pn { font-size: 13.5px; font-weight: 700; color: var(--tx); }
.usr-pe { font-size: 11.5px; color: var(--tx3); margin-top: 1px; }
.um-i { display: flex; align-items: center; gap: 11px; padding: 9px 10px; border-radius: 8px; font-size: 13px; font-weight: 500; color: var(--tx2); cursor: pointer; transition: .12s; }
.um-i:hover { background: var(--hover); color: var(--tx); }
.um-i svg { width: 16px; height: 16px; flex: none; }
.um-i.danger { color: var(--dg); }
.um-i.danger:hover { background: var(--dg-sub); }
.um-div { height: 1px; background: var(--bd); margin: 5px 6px; }
@media (max-width: 820px) { .usr-meta { display: none; } }

/* ============== LAYOUT DE PAGINA ============== */
.page-h { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; margin-bottom: 20px; flex-wrap: wrap; }
.page-t { font-size: 21px; font-weight: 800; letter-spacing: -.025em; }
.page-s { font-size: 13px; color: var(--tx2); margin-top: 2px; }
.search { position: relative; display: flex; align-items: center; }
.search svg { position: absolute; left: 11px; width: 14px; height: 14px; color: var(--tx3); }
.search .input { padding-left: 32px; height: 34px; width: 230px; }
.kpis { display: grid; grid-template-columns: repeat(4, 1fr); gap: 14px; margin-bottom: 18px; }
.panels { display: grid; grid-template-columns: 1.6fr 1fr; gap: 14px; margin-bottom: 18px; }
.panel-h { display: flex; align-items: center; justify-content: space-between; padding: 14px 17px; border-bottom: 1px solid var(--bd); }
.panel-t { font-size: 14px; font-weight: 700; }
.sec-lbl { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .07em; color: var(--tx3); margin: 22px 0 11px; }

/* ============== ACCESOS RAPIDOS Y TARJETAS DE MODULO ============== */
.qa-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px; }
.qa { display: flex; align-items: center; gap: 12px; padding: 14px 15px; background: var(--card); border: 1px solid var(--bd); border-radius: 12px; cursor: pointer; transition: .16s; box-shadow: var(--sh-sm); }
.qa:hover { border-color: var(--bd-acc); transform: translateY(-2px); }
.qa-i { width: 38px; height: 38px; border-radius: 10px; background: var(--brand-sub); color: var(--brand-txt); display: flex; align-items: center; justify-content: center; flex: none; }
.qa-i svg { width: 19px; height: 19px; }
.qa-t { font-size: 13.5px; font-weight: 600; }
.qa-s { font-size: 11.5px; color: var(--tx3); margin-top: 1px; }
.mod-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px; }
.mod { display: flex; flex-direction: column; gap: 9px; padding: 15px; background: var(--card); border: 1px solid var(--bd); border-radius: 12px; cursor: pointer; transition: .16s; box-shadow: var(--sh-sm); }
.mod:hover { border-color: var(--bd-acc); transform: translateY(-2px); }
.mod-i { width: 34px; height: 34px; border-radius: 9px; background: var(--brand-sub); color: var(--brand-txt); display: flex; align-items: center; justify-content: center; }
.mod-i svg { width: 17px; height: 17px; }
.mod-n { font-size: 13.5px; font-weight: 600; }
.mod-m { font-size: 11.5px; color: var(--tx3); }

/* ============== RESPONSIVE ============== */
@media (max-width: 1024px) and (min-width: 821px) {
  .kpis { grid-template-columns: repeat(2, 1fr); }
  .panels { grid-template-columns: 1fr; }
}
@media (max-width: 820px) {
  .kpis { grid-template-columns: repeat(2, 1fr); }
  .panels { grid-template-columns: 1fr; }
  .qa-grid, .mod-grid { grid-template-columns: repeat(2, 1fr) !important; }
}

/* ============== PROSA DEL KB (modulo Conocimiento) ==============
   El contenido de un articulo llega como HTML ya sanitizado (Markdown
   renderizado al guardar), sin clases: no se le puede poner utilities de
   Tailwind. Estos estilos son de ALCANCE ACOTADO a `.kb-prose` y usan solo
   tokens del DS — no introducen color ni tipografia nueva. */
.kb-prose { font-size: 14.5px; line-height: 1.7; color: var(--tx); }
.kb-prose > :first-child { margin-top: 0; }
.kb-prose > :last-child { margin-bottom: 0; }
.kb-prose h1, .kb-prose h2, .kb-prose h3, .kb-prose h4 { font-weight: 700; letter-spacing: -.02em; margin: 26px 0 10px; }
.kb-prose h1 { font-size: 21px; }
.kb-prose h2 { font-size: 17px; padding-bottom: 6px; border-bottom: 1px solid var(--bd); }
.kb-prose h3 { font-size: 15px; }
.kb-prose h4 { font-size: 14px; color: var(--tx2); }
.kb-prose p { margin: 0 0 13px; }
.kb-prose ul, .kb-prose ol { margin: 0 0 13px; padding-left: 22px; }
.kb-prose ul { list-style: disc; }
.kb-prose ol { list-style: decimal; }
.kb-prose li { margin-bottom: 5px; }
.kb-prose li > ul, .kb-prose li > ol { margin: 5px 0 0; }
.kb-prose a { color: var(--brand-txt); text-decoration: underline; text-underline-offset: 2px; }
.kb-prose a:hover { filter: brightness(1.15); }
.kb-prose blockquote { margin: 0 0 13px; padding: 2px 0 2px 14px; border-left: 3px solid var(--brand-sub-bd); color: var(--tx2); }
.kb-prose pre { margin: 0 0 13px; padding: 13px 15px; background: var(--panel); border: 1px solid var(--bd); border-radius: 10px; overflow-x: auto; }
.kb-prose pre code { background: none; border: 0; padding: 0; font-size: 12.5px; color: var(--tx); }
.kb-prose hr { border: 0; border-top: 1px solid var(--bd); margin: 22px 0; }
.kb-prose img { max-width: 100%; height: auto; border-radius: 10px; }
.kb-prose table { width: 100%; border-collapse: collapse; font-size: 13px; margin: 0 0 13px; display: block; overflow-x: auto; }
.kb-prose th { text-align: left; font-size: 11px; text-transform: uppercase; letter-spacing: .05em; color: var(--tx3); font-weight: 700; padding: 9px 13px; background: var(--panel); border-bottom: 1px solid var(--bd); }
.kb-prose td { padding: 9px 13px; border-bottom: 1px solid var(--bd); vertical-align: top; }
.kb-prose mark { background: var(--brand-sub); color: var(--brand-txt); padding: 0 2px; border-radius: 3px; }

/* ============== TACTIL (touch / puntero grueso) ============== */
/* En dispositivos sin hover el patron `opacity-40 group-hover:opacity-100` de las
   acciones de fila quedaria invisible. Forzamos visibilidad de esas utilities. */
@media (hover: none) {
  .group:hover .group-hover\:opacity-100,
  [class*="group-hover:opacity-100"] { opacity: 1 !important; }
}
/* Puntero grueso (dedo): sube los botones de fila de 28/32px a 36px (target Fitts >=44 con padding). */
@media (pointer: coarse) {
  table .w-7[class*="h-7"],
  table .w-8[class*="h-8"] { width: 2.25rem; height: 2.25rem; }
}

/* ============== PROGRESO DEL EQUIPO (dashboard) ==============
   Cada miembro es un <details>: la fila resume y al desplegarse lista su
   trabajo abierto. Sin JS, y el teclado lo maneja el propio <summary>.

   Vive aca y no como utilities en el template porque Tailwind compila local
   (`npm run build:css`) y el tailwind.css commiteado es el que se despliega:
   utilities no compiladas dejan la fila sin padding. Un componente con nombre
   ademas se lee mejor que ocho valores arbitrarios. */

.emp-item { position: relative; }
.emp-item > details { position: relative; }
/* min-height fija: asi el boton "Asignar" se centra con un top calculado y no
   baila segun cuantos badges traiga la fila. */
.emp-row { display: flex; align-items: center; gap: 12px; min-height: 68px; padding: 12px 124px 12px 17px; }

summary.emp-row { cursor: pointer; list-style: none; transition: background-color .12s; }
summary.emp-row::-webkit-details-marker { display: none; }
summary.emp-row:hover { background: var(--hover); }

/* Desplegado: fondo suave + barra de marca a la izquierda. Es una senal de
   estado tranquila; antes el unico indicio era el anillo de foco, que en una
   fila a todo el ancho se lee como un recuadro azul duro alrededor de todo. */
details[open] > summary.emp-row { background: var(--hover); }
details[open]::before {
  content: ""; position: absolute; left: 0; top: 0; bottom: 0;
  width: 2px; background: var(--brand);
}
/* El <ul> contenedor lleva overflow-hidden + rounded-b-xl en el template: sin
   eso la barra sobresale de la esquina redondeada de la tarjeta. */

/* El anillo de foco NO va en el summary: ocupa el ancho completo de la tarjeta
   y Chrome lo dispara tambien al hacer click, no solo con teclado. Se mueve al
   nombre, que identifica la fila igual y es un objetivo del tamano correcto.
   El indicador sigue existiendo (WCAG 2.2): esto NO es `outline: none` pelado
   (trampa T6), es el mismo anillo sobre otro elemento. */
summary.emp-row:focus-visible { outline: none; }
summary.emp-row:focus-visible .emp-nombre {
  outline: 2px solid var(--brand); outline-offset: 3px; border-radius: 6px;
}

.emp-nombre { font-size: 13px; font-weight: 500; color: var(--tx); }
.emp-meta { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; margin-top: 5px; }
.emp-toggle { display: inline-flex; align-items: center; gap: 5px; font-size: 11.5px; color: var(--tx3); white-space: nowrap; }
.emp-chev { transition: transform .15s; }
details[open] > summary .emp-chev { transform: rotate(180deg); }

/* Lista desplegada. La linea vertical baja desde el centro del avatar y ata
   visualmente los pendientes a su persona; sin ella el bloque flota suelto. */
.emp-pend {
  position: relative; list-style: none; margin: 0;
  padding: 4px 17px 14px 62px; display: flex; flex-direction: column;
}
.emp-pend > li { display: flex; align-items: flex-start; gap: 16px; padding: 7px 0; }
.emp-pend > li + li { border-top: 1px solid var(--bd); }
.emp-pend-main { min-width: 0; flex: 1; }
/* La fecha va a la derecha: el contenido ocupaba solo el tercio izquierdo y
   dejaba la fila desbalanceada, y en columna se comparan de un vistazo. */
.emp-pend-side { flex: none; margin-left: auto; padding-top: 1px; }
.emp-pend-fecha { font-size: 11.5px; color: var(--tx3); white-space: nowrap; }
/* Baja desde el centro del avatar y ata los pendientes a su persona; sin ella
   el bloque flota suelto. --bd-2 y no --bd: con --bd no se veia. */
.emp-pend::before {
  content: ""; position: absolute; left: 33px; top: 0; bottom: 16px;
  width: 1px; background: var(--bd-2);
}
.emp-pend-t { font-size: 13px; color: var(--tx); }
.emp-pend-t a { color: inherit; text-decoration: none; }
.emp-pend-t a:hover { color: var(--brand-txt); text-decoration: underline; text-underline-offset: 2px; }
.emp-pend-m { display: flex; align-items: center; flex-wrap: wrap; gap: 7px; margin-top: 3px; font-size: 11.5px; color: var(--tx3); }
.emp-pend-sep { color: var(--bd-2); }
.emp-pend-mas { font-size: 11.5px; color: var(--tx3); }

/* (68 - 36) / 2 = 16. El .btn del DS trae su propia transicion; no se pisa. */
.emp-asignar { position: absolute; right: 17px; top: 16px; }
@media (pointer: coarse) {
  /* Piso de 44px de target tactil (GUIDELINES/Rules/10-diseno.md). (68-44)/2 = 12. */
  .emp-asignar { height: 44px; top: 12px; }
}

@media (max-width: 640px) {
  /* Sin la etiqueta "Asignar" el boton es solo icono: se recupera el ancho. */
  .emp-row { padding-right: 68px; }
  .emp-pend { padding-left: 44px; }
  .emp-pend::before { left: 24px; }
}

/* Barra de progreso del panel de equipo. Relleno unico --brand: los tokens
   semanticos estan calibrados para TEXTO sobre fondo claro (--warn = #946012)
   y como relleno se ven turbios; las variantes vivas del tema oscuro caen a
   ~1.5:1 contra el riel, bajo el minimo de 3:1 de grafico no textual.
   --brand da 5.34:1 en claro y 3.25:1 en oscuro. */
.emp-bar { flex: 1; max-width: 120px; height: 6px; border-radius: 999px; background: var(--bd-2); overflow: hidden; }
.emp-bar-fill { height: 100%; border-radius: 999px; background: var(--brand); transition: width .5s; }

/* ============== HUB (indices de navegacion) ==============
   Tarjetas de un indice que agrupa pantallas afines bajo una sola entrada del
   menu. Va en oasys.css y no como utilities porque Tailwind compila local y el
   tailwind.css commiteado es el que se despliega. */
.hub-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(288px, 1fr)); gap: 10px; }

.hub-card {
  display: flex; align-items: flex-start; gap: 12px; padding: 14px 15px;
  background: var(--card); border: 1px solid var(--bd); border-radius: 12px;
  box-shadow: var(--sh-sm); text-decoration: none; transition: .15s;
}
.hub-card:hover { border-color: var(--bd-2); box-shadow: var(--sh-md, var(--sh-sm)); transform: translateY(-1px); }
.hub-card:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }

.hub-card-i {
  flex: none; width: 34px; height: 34px; border-radius: 9px;
  background: var(--brand-sub); color: var(--brand-txt);
  display: flex; align-items: center; justify-content: center;
}
.hub-card-t { display: block; font-size: 13.5px; font-weight: 600; color: var(--tx); }
.hub-card-d { display: block; font-size: 11.5px; line-height: 1.45; color: var(--tx3); margin-top: 2px; }

/* La flecha aparece al enfocar o pasar por encima: en reposo son 25 flechas que
   no dicen nada, y todas las tarjetas son enlaces igual. */
.hub-card-cr { flex: none; margin-left: auto; align-self: center; color: var(--tx3); opacity: 0; transition: opacity .15s; }
.hub-card:hover .hub-card-cr, .hub-card:focus-visible .hub-card-cr { opacity: .7; }

@media (prefers-reduced-motion: reduce) {
  .hub-card, .hub-card-cr { transition: none; }
  .hub-card:hover { transform: none; }
}
