/* ===== Premium UI — Animations & Enhanced Components ===== */

/* ===== Keyframes ===== */
@keyframes fadeInUp {
  from { opacity: 0; transform: translateY(12px); }
  to   { opacity: 1; transform: translateY(0); }
}

@keyframes fadeIn {
  from { opacity: 0; }
  to   { opacity: 1; }
}

@keyframes slideInRight {
  from { transform: translateX(100%); }
  to   { transform: translateX(0); }
}

@keyframes slideOutRight {
  from { transform: translateX(0); }
  to   { transform: translateX(100%); }
}

@keyframes shimmer {
  0%   { background-position: -200% 0; }
  100% { background-position: 200% 0; }
}

@keyframes scaleIn {
  from { opacity: 0; transform: scale(.95); }
  to   { opacity: 1; transform: scale(1); }
}

@keyframes toastSlideIn {
  from { opacity: 0; transform: translateX(20px) scale(.95); }
  to   { opacity: 1; transform: translateX(0) scale(1); }
}

@keyframes toastSlideOut {
  from { opacity: 1; transform: translateX(0) scale(1); }
  to   { opacity: 0; transform: translateX(20px) scale(.9); }
}

@keyframes float {
  0%   { transform: translateY(0) scale(1); }
  100% { transform: translateY(-30px) scale(1.1); }
}

@keyframes pulse {
  0%, 100% { opacity: 1; }
  50%      { opacity: .5; }
}

@keyframes checkBounce {
  0%   { transform: scale(0); }
  50%  { transform: scale(1.2); }
  100% { transform: scale(1); }
}

/* ===== Page Entry Animation ===== */
.content-area > *:not(.slide-panel):not(.slide-panel-backdrop):not(.cmd-palette):not(.cmd-palette-backdrop):not(script):not(style) {
  /* fill-mode `backwards` (no `both`): mantiene el estado inicial durante el
     delay escalonado pero NO deja un transform residual al terminar. Con `both`,
     el translateY(0) final persistía y convertía cada hijo de .content-area en
     un stacking context permanente; el row de gráficas (hermano posterior)
     pintaba encima del panel de los combos multi-select que desborda sobre él,
     y ningún z-index lo rescataba (el panel queda atrapado en el contexto de su
     fila). Validado headless 19 Jul 2026. */
  animation: fadeInUp .4s cubic-bezier(.4,0,.2,1) backwards;
}
.content-area > *:nth-child(2):not(.slide-panel):not(.slide-panel-backdrop) { animation-delay: .05s; }
.content-area > *:nth-child(3):not(.slide-panel):not(.slide-panel-backdrop) { animation-delay: .1s; }
.content-area > *:nth-child(4):not(.slide-panel):not(.slide-panel-backdrop) { animation-delay: .15s; }
.content-area > *:nth-child(5):not(.slide-panel):not(.slide-panel-backdrop) { animation-delay: .2s; }
.content-area > *:nth-child(6):not(.slide-panel):not(.slide-panel-backdrop) { animation-delay: .25s; }

/* Forzar que slide panels no tengan animacion de entrada y mantengan su transform */
.content-area > .slide-panel,
.content-area > .slide-panel-backdrop {
  animation: none !important;
}

/* ===== Page Header (Concept C — Minimal lightweight) ===== */
.page-header {
  display: flex;
  align-items: center;
  gap: .9rem;
  margin-bottom: 1.75rem;
  padding: 0;
  background: none;
  border-radius: 0;
  box-shadow: none;
  border-left: none;
}

.page-header-icon {
  width: 36px;
  height: 36px;
  border-radius: 9px;
  background: color-mix(in srgb, var(--accent-primary) 10%, transparent);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--accent-primary);
  font-size: 1rem;
  flex-shrink: 0;
  box-shadow: none;
}

.page-header-text h4 {
  font-size: 1.4rem;
  font-weight: 300;
  margin: 0;
  color: var(--text-primary);
  line-height: 1.2;
  letter-spacing: -.3px;
}

.page-header-text small {
  color: var(--text-muted);
  font-size: .78rem;
  margin-top: 2px;
  display: block;
  font-weight: 400;
}

.page-header-actions {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: .5rem;
  flex-shrink: 0;
}

/* ===== Card Enhancements (Concept C — minimal) ===== */
.card {
  transition: box-shadow .15s ease;
}
.card:hover {
  box-shadow: var(--card-shadow-hover);
}

.card-filter {
  border: 1px solid var(--border-color) !important;
  background: var(--card-bg) !important;
}

.card-header {
  font-weight: 500;
  font-size: .85rem;
}

/* ===== Dropdown Themed ===== */
.dropdown-menu {
  background: var(--card-bg);
  border: 1px solid var(--border-color);
  border-radius: 10px;
  box-shadow: 0 8px 24px rgba(0,0,0,.12);
  padding: 6px;
}

.dropdown-item {
  color: var(--text-primary);
  border-radius: 6px;
  padding: .5rem .75rem;
  font-size: .85rem;
  transition: background .15s ease;
}

.dropdown-item:hover,
.dropdown-item:focus {
  background: var(--page-bg);
  color: var(--text-primary);
}

.dropdown-item.text-danger {
  color: var(--badge-danger-text) !important;
}
.dropdown-item.text-danger:hover {
  background: var(--badge-danger-bg);
}

.dropdown-divider {
  border-color: var(--border-color-light);
  margin: 4px 0;
}

/* ===== Table Enhancements (Concept C — clean) ===== */
.table > tbody > tr {
  transition: background .12s ease;
}
.table > tbody > tr:hover {
  background: var(--page-bg) !important;
}
.table > tbody > tr:hover > td {
  color: var(--text-primary);
}

.row-actions {
  opacity: .3;
  transition: opacity .2s ease;
  display: inline-flex;
  align-items: center;
  gap: .25rem;
  white-space: nowrap;
}
tr:hover .row-actions {
  opacity: 1;
}
.row-actions .btn {
  white-space: nowrap;
}

/* Row stagger animation */
.row-entering {
  animation: fadeInUp .3s cubic-bezier(.4,0,.2,1) both;
  animation-delay: calc(var(--i, 0) * 30ms);
}

/* Sticky thead */
.table-responsive .table thead th {
  position: sticky;
  top: 0;
  z-index: 1;
}

/* Table card wrapper */
.card .table-responsive {
  border-radius: 0 0 var(--radius-md, 14px) var(--radius-md, 14px);
  overflow: hidden;
}

/* Card footer counter */
.card-footer {
  font-size: .8rem;
  font-weight: 500;
}

/* ===== Slide Panel ===== */
.slide-panel-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(0,0,0,.35);
  z-index: 1040;
  opacity: 0;
  transition: opacity .3s ease;
  pointer-events: none;
}
.slide-panel-backdrop.active {
  opacity: 1;
  pointer-events: auto;
}

.slide-panel {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  width: 480px;
  max-width: 90vw;
  background: var(--card-bg);
  border-left: 1px solid var(--border-color);
  box-shadow: var(--shadow-elevation-3, 0 12px 36px rgba(0,0,0,.1));
  z-index: 1050;
  transform: translateX(100%);
  transition: transform .35s cubic-bezier(.4,0,.2,1);
  display: flex;
  flex-direction: column;
}
.slide-panel.active {
  transform: translateX(0);
}

.slide-panel-header {
  padding: 1.25rem 1.5rem;
  border-bottom: 1px solid var(--border-color-light);
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.slide-panel-header h5 {
  margin: 0;
  font-weight: 700;
  font-size: 1.1rem;
  color: var(--text-primary);
}
.slide-panel-close {
  background: none;
  border: none;
  color: var(--text-muted);
  font-size: 1.25rem;
  cursor: pointer;
  padding: 4px;
  border-radius: 6px;
  transition: all .15s ease;
}
.slide-panel-close:hover {
  background: var(--sidebar-hover-bg);
  color: var(--text-primary);
}

.slide-panel-body {
  flex: 1;
  overflow-y: auto;
  padding: 1.5rem;
}

.slide-panel-footer {
  padding: 1rem 1.5rem;
  border-top: 1px solid var(--border-color-light);
  display: flex;
  gap: .5rem;
  justify-content: flex-end;
}

/* ===== Toast System ===== */
.toast-container-custom {
  position: fixed;
  bottom: 1.5rem;
  right: 1.5rem;
  z-index: 1100;
  display: flex;
  flex-direction: column-reverse;
  gap: .5rem;
  pointer-events: none;
}

.toast-custom {
  pointer-events: auto;
  padding: .75rem 1rem;
  border-radius: var(--radius-sm, 10px);
  background: var(--card-bg);
  border: 1px solid var(--border-color-light);
  box-shadow: var(--shadow-elevation-2, 0 4px 12px rgba(0,0,0,.08));
  display: flex;
  align-items: center;
  gap: .75rem;
  min-width: 280px;
  max-width: 400px;
  animation: toastSlideIn .4s cubic-bezier(.175,.885,.32,1.275);
}

.toast-custom.removing {
  animation: toastSlideOut .25s ease forwards;
}

.toast-custom-icon {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: .8rem;
  flex-shrink: 0;
}
.toast-custom.toast-success .toast-custom-icon {
  background: var(--badge-success-bg);
  color: var(--badge-success-text);
}
.toast-custom.toast-danger .toast-custom-icon {
  background: var(--badge-danger-bg);
  color: var(--badge-danger-text);
}
.toast-custom.toast-warning .toast-custom-icon {
  background: var(--badge-warning-bg);
  color: var(--badge-warning-text);
}

.toast-custom-text {
  flex: 1;
  font-size: .85rem;
  color: var(--text-primary);
  font-weight: 500;
}

.toast-custom-close {
  background: none;
  border: none;
  color: var(--text-muted);
  cursor: pointer;
  padding: 2px;
  font-size: .75rem;
  opacity: .5;
  transition: opacity .15s;
}
.toast-custom-close:hover { opacity: 1; }

/* ===== Empty States ===== */
.empty-state {
  padding: 3rem 1.5rem;
  text-align: center;
  animation: fadeIn .5s ease;
}

.empty-state-icon {
  width: 64px;
  height: 64px;
  border-radius: 50%;
  background: color-mix(in srgb, var(--accent-primary) 8%, transparent);
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 0 auto 1rem;
  font-size: 1.5rem;
  color: var(--accent-primary);
}

.empty-state h6 {
  font-weight: 600;
  margin-bottom: .25rem;
  color: var(--text-primary);
}

.empty-state p {
  color: var(--text-muted);
  font-size: .85rem;
  max-width: 280px;
  margin: 0 auto;
}

.empty-state .btn {
  margin-top: 1rem;
}

/* ===== Skeleton Loaders ===== */
.skeleton {
  background: linear-gradient(90deg, var(--skeleton-base, var(--border-color-light)) 25%, var(--skeleton-shine, var(--card-bg)) 50%, var(--skeleton-base, var(--border-color-light)) 75%);
  background-size: 200% 100%;
  animation: shimmer 1.5s infinite;
  border-radius: 4px;
}
.skeleton-text { height: 12px; margin-bottom: 8px; }
.skeleton-text-sm { height: 10px; margin-bottom: 6px; }
.skeleton-row { height: 40px; margin-bottom: 4px; border-radius: 6px; }

/* ===== Navbar Breadcrumb ===== */
.navbar-breadcrumb {
  display: flex;
  align-items: center;
  gap: 6px;
  color: var(--text-muted);
  font-size: .8rem;
}
.navbar-breadcrumb .bi { font-size: .55rem; }
.navbar-breadcrumb span { color: var(--text-secondary); }

/* Navbar user button */
.navbar-user-btn {
  border-radius: var(--radius-sm, 10px) !important;
  padding: .35rem .65rem !important;
  transition: all .15s ease !important;
}
.navbar-user-btn:hover {
  background: var(--sidebar-hover-bg) !important;
}

/* ===== Export Dropdown ===== */
.export-dropdown .dropdown-item i {
  width: 18px;
  text-align: center;
}

/* ===== Navbar rediseñado (Concept C) — OMITIDO en este puerto (M1.5) =====
   El donante (actividades_personal) rediseña .top-navbar/.cmd-trigger para
   su propio navbar de marca. presupuestos-gastos ya tiene un topbar propio
   (M1.4, shell.css: nav.top-navbar bg-primary + botón .cmd-trigger
   deshabilitado "próximamente") con las MISMAS clases. Con la misma
   especificidad de selector, estas reglas del donante ganarían la cascada
   por cargar después de shell.css y dejarían el botón sin fondo/borde
   (usa var(--page-bg)/var(--border-color)/var(--accent-primary), que no
   son las variables de este proyecto — ver puente v1→v2 en theme-base.css)
   — rompiendo un control ya en producción. Se omite hasta que una tarea
   futura rediseñe el trigger del command palette real y adapte el markup
   de topbar.ejs a juego con estas clases.
   ====================================================================== */

/* ===== Command Palette Overlay ===== */
.cmd-palette-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(8,9,10,.45);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
  z-index: 1060;
  opacity: 0;
  pointer-events: none;
  transition: opacity .2s ease;
}
.cmd-palette-backdrop.active {
  opacity: 1;
  pointer-events: auto;
}

.cmd-palette {
  position: fixed;
  top: 15vh;
  left: 50%;
  transform: translateX(-50%) scale(.96);
  width: 90%;
  max-width: 600px;
  background: var(--card-bg);
  border-radius: 14px;
  box-shadow: 0 20px 60px rgba(0,0,0,.25), 0 0 0 1px var(--border-color-light);
  z-index: 1070;
  opacity: 0;
  pointer-events: none;
  transition: all .2s cubic-bezier(.4,0,.2,1);
  overflow: hidden;
  display: flex;
  flex-direction: column;
  max-height: 70vh;
}
.cmd-palette.active {
  opacity: 1;
  pointer-events: auto;
  transform: translateX(-50%) scale(1);
}

.cmd-palette-input-wrap {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 16px 20px;
  border-bottom: 1px solid var(--border-color-light);
}
.cmd-palette-input-wrap i {
  color: var(--text-muted);
  font-size: 16px;
}
.cmd-palette-input {
  flex: 1;
  border: none;
  outline: none;
  background: none;
  font-size: 15px;
  color: var(--text-primary);
  font-family: inherit;
}
.cmd-palette-input::placeholder {
  color: var(--text-muted);
}
.cmd-palette-esc {
  background: var(--page-bg);
  border: 1px solid var(--border-color);
  border-radius: 5px;
  padding: 2px 6px;
  font-size: 10px;
  color: var(--text-muted);
  font-family: inherit;
}

.cmd-palette-results {
  flex: 1;
  overflow-y: auto;
  padding: 8px;
}

.cmd-palette-section {
  font-size: 10px;
  font-weight: 700;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: .8px;
  padding: 8px 12px 4px;
}

.cmd-item {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 8px 12px;
  border-radius: 8px;
  cursor: pointer;
  transition: background .1s ease;
  user-select: none;
}
.cmd-item:hover,
.cmd-item.selected {
  background: color-mix(in srgb, var(--accent-primary) 8%, transparent);
}

.cmd-item-icon {
  width: 32px;
  height: 32px;
  border-radius: 8px;
  background: var(--page-bg);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 14px;
  color: var(--accent-primary);
  flex-shrink: 0;
}

.cmd-item-content {
  flex: 1;
  min-width: 0;
}
.cmd-item-title {
  font-size: 13px;
  font-weight: 500;
  color: var(--text-primary);
  margin-bottom: 1px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.cmd-item-subtitle {
  font-size: 11px;
  color: var(--text-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.cmd-item-hint {
  font-size: 10px;
  color: var(--text-muted);
  display: flex;
  align-items: center;
  gap: 4px;
  flex-shrink: 0;
}

.cmd-palette-empty {
  padding: 40px 20px;
  text-align: center;
  color: var(--text-muted);
  font-size: 13px;
}

.cmd-palette-footer {
  padding: 8px 16px;
  border-top: 1px solid var(--border-color-light);
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-size: 11px;
  color: var(--text-muted);
  background: var(--page-bg);
}
.cmd-palette-footer-hints {
  display: flex;
  gap: 16px;
}
.cmd-palette-footer-hint {
  display: flex;
  align-items: center;
  gap: 4px;
}
.cmd-palette-footer-hint kbd {
  background: var(--card-bg);
  border: 1px solid var(--border-color);
  border-radius: 3px;
  padding: 0 4px;
  font-size: 9px;
  font-family: inherit;
  color: var(--text-secondary);
}

/* Hide the breadcrumb we don't need anymore */
.navbar-breadcrumb { display: none !important; }

/* ===== Nivel de agrupación de reportes (Área / Centro) ===== */
.rpt-group-head td {
  background: var(--ln-surface-2);
  color: var(--ln-fg);
  font-weight: 600;
  cursor: pointer;
  border-top: 1px solid var(--ln-border-strong);
  user-select: none;
}
.rpt-group-head:hover td { background: var(--ln-hover-bg); }
.rpt-group-head:focus-visible { outline: 2px solid var(--ln-accent); outline-offset: -2px; }
.rpt-group-head .rpt-caret {
  display: inline-block;
  width: 1em;
  color: var(--ln-fg-muted);
  transition: transform var(--ln-dur-fast, .15s) var(--ln-ease, ease);
}
.rpt-group-count { color: var(--ln-fg-muted); font-weight: 400; font-size: .85em; }
.rpt-group-sub td {
  background: var(--ln-surface-3);
  font-weight: 600;
  border-top: 1px solid var(--ln-border);
}
.rpt-leaf td:first-child { padding-left: 1.4rem; }

/* ===== Reduced Motion ===== */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

.dist-chip { background: var(--ln-hover-bg, #eef); border: 1px solid var(--ln-border, #ccd);
  border-radius: 999px; padding: .1rem .5rem; font-size: .78rem; display: inline-flex; align-items: center; gap: .3rem; }
.dist-chip i { cursor: pointer; }

/* Distribución de Gastos — editor modal */
.dist-cab { background: var(--ln-hover-bg, #f7f7f9); border-radius: 8px; padding: .6rem .8rem; }
.dist-pick-title { font-weight: 600; font-size: .85rem; margin-bottom: .3rem; }
.dist-checklist { max-height: 26vh; overflow: auto; border: 1px solid var(--ln-border, #ddd); border-radius: 6px; padding: .3rem .5rem; }
.dist-chk { display: block; font-size: .82rem; padding: .1rem 0; cursor: pointer; }
.dist-chk input { margin-right: .4rem; }
#dm-grid input.dm-pct, #dm-grid input.dm-imp { text-align: right; }
/* Concepto / Comentarios de la factura: texto libre del ERP, puede ser largo →
   se muestra completo pero con tope de alto y scroll propio. */
.dist-nota { font-size: .82rem; white-space: pre-wrap; max-height: 4.5rem; overflow: auto; }

/* Fecha de Clasificación heredada del ERP (la columna está en NULL): se atenúa
   para distinguirla de la que fijó una persona. Sin esta marca el usuario no
   puede saber cuál de las dos está viendo.
   Nota: el brief citaba --ln-text-muted, que no existe en theme-base.css (solo
   vive en los docs de spec/plan) — con var() sin fallback eso hubiera dejado
   el texto sin atenuar en los 11 temas, silenciosamente. --ln-fg-muted es el
   token real usado en todo premium-ui.css para este mismo propósito. */
.fc-omision {
  color: var(--ln-fg-muted);
  font-style: italic;
}
.fc-cell {
  white-space: nowrap;
}
.fc-cell .fc-input {
  display: inline-block;
  width: auto;
  min-width: 8.5rem;
}

/* Herramienta de búsqueda estándar (views/partials/buscador-modal.ejs)
   Nota: el brief citaba --ln-text-muted en .bs-vacio (mismo token inexistente
   ya corregido arriba en .fc-omision) — aquí se usa --ln-fg-muted, el real. */
.bs-tabla-wrap { max-height: 52vh; overflow: auto; }
.bs-tabla td.num, .bs-tabla th.num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.bs-tabla thead th { position: sticky; top: 0; z-index: 2; background: var(--ln-surface, #fff); cursor: pointer; user-select: none; }
.bs-tabla tbody tr { cursor: pointer; }
.bs-tabla tbody tr.bs-activa td { background: var(--ln-accent-soft, #e7f0f7); font-weight: 600; }
.bs-vacio { padding: 2rem 1rem; text-align: center; color: var(--ln-fg-muted, #6c757d); }

/* El buscador puede abrirse ENCIMA de otro modal (el editor de la factura de
   Caja Chica): Bootstrap 5.3 no soporta modales anidados y ambos usan por
   omisión el mismo z-index (.modal = 1055, .modal-backdrop = 1050). Como el
   backdrop (1050) siempre queda POR DEBAJO de cualquier .modal (1055) sin
   importar el orden en que se abrieron, el editor de abajo no se atenuaba
   cuando el buscador estaba abierto. Se sube #bsModal por encima de cualquier
   .modal por omisión; su backdrop lo marca public/js/buscador.js con esta
   clase justo después de mostrarlo (es el único backdrop nuevo — el del
   modal de abajo ya estaba puesto). */
#bsModal { z-index: 1075; }
.modal-backdrop.bs-backdrop-encima { z-index: 1070; }

/* Selector de usuario híbrido (combo + escribir para buscar), componente
   compartido (public/js/selector-persona.js). El ERP usa un combo
   (`cbopersonal` de xpedx.vcx); aquí se conserva esa conducta —se despliega
   al enfocar— y además filtra conforme se teclea. */
.sel-persona { position: relative; }
.sel-persona-lista { position: absolute; z-index: 1060; top: 100%; left: 0; right: 0;
  background: var(--ln-surface, #fff); border: 1px solid var(--ln-border, #ddd);
  border-radius: 6px; max-height: 260px; overflow: auto; box-shadow: 0 6px 18px rgba(0,0,0,.12); }
.sel-persona-op { padding: .35rem .6rem; cursor: pointer; font-size: .85rem; }
.sel-persona-op:hover,
.sel-persona-op.activa { background: var(--ln-hover-bg, #f2f2f2); }

/* Motor de Catálogos — campo que calcula el sistema, pintado "como etiqueta".
   Port de `lcomo_etiqueta` de la clase `txtreadonly` (basectrl.vcx), que el ERP
   usa en Saldo Actual y en Estado Actual de `abc_cajas_chicas`: un valor que no
   se captura no debe verse como una caja de captura apagada. */
.cat-valor {
  padding: .3rem .1rem;
  font-weight: 600;
  font-size: .95rem;
  color: var(--ln-accent, #2E5575);
  border-bottom: 1px dashed var(--ln-border, #d8d8d8);
  min-height: calc(1.5em + .5rem);
}
