/* Deuda Municipal — sistema de diseño propio (heredado de Polideportivo Municipal).
   Paleta + tipografía Inter/Plus Jakarta Sans. */

:root {
  --font-heading: 'Plus Jakarta Sans', 'Segoe UI', system-ui, sans-serif;
  --font-body: 'Inter', 'Segoe UI', system-ui, sans-serif;

  /* Identidad: azul marino del isologo de la Dirección de Ingresos Públicos
     (#2E386B, sacado del propio archivo de logo), en distintos tonos. */
  --primary: #2E386B;
  --primary-dark: #1C2240;
  --primary-light: #515FA4;
  --primary-bg: #E6E8EF;
  --primary-bg-strong: #D3D6E4;

  --accent: #C98A3E;
  --accent-bg: #FBF1E1;

  --text: #1C2430;
  --text-secondary: #5C6675;
  --text-muted: #99A2B3;

  --border: #E6EAEF;
  --border-soft: #EEF1F5;
  --bg: #F6F8F9;
  --surface: #FFFFFF;

  --success: #3E8B60;
  --success-bg: #E9F5EE;
  --warning: #C1892E;
  --warning-bg: #FBF1E0;
  --danger: #C1524F;
  --danger-bg: #FBEAEA;

  --shadow-sm: 0 1px 2px rgba(23, 34, 43, .05);
  --shadow: 0 2px 10px rgba(23, 34, 43, .05), 0 1px 2px rgba(23, 34, 43, .04);
  --shadow-md: 0 8px 24px rgba(23, 34, 43, .08), 0 2px 6px rgba(23, 34, 43, .04);
  --shadow-lg: 0 20px 48px rgba(18, 32, 33, .16), 0 4px 12px rgba(18, 32, 33, .08);

  --radius-sm: 8px;
  --radius-md: 12px;
  --radius-lg: 20px;
}

* { box-sizing: border-box; }

/* Oculta visualmente pero deja accesible para lectores de pantalla -- ej. la
   etiqueta "Comentario" del campo de "Agregar comentario" en la ficha del
   contribuyente, que a propósito no muestra label (el placeholder alcanza). */
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}

/* El atributo hidden debe ganarle SIEMPRE a cualquier display:flex/grid que ponga
   una clase (.alert, .form-grid, .modal-overlay, etc) — si no, el elemento "oculto"
   sigue apareciendo porque la clase pisa el display:none por defecto del navegador. */
[hidden] { display: none !important; }

html, body {
  margin: 0;
  height: 100%;
}

body {
  /* Red de seguridad: tooltips y otros elementos position:absolute (como
     .help-tip) cuentan para el ancho "scrolleable" de la página aunque estén
     invisibles (opacity:0) — sin esto, el celu deja un swipe horizontal
     fantasma hacia la derecha que no muestra nada. Va en <body>, no en <html>:
     en <html> el overflow se propaga al viewport de un modo que en Chrome
     rompe el scroll vertical de toda la página (confirmado — no es teórico).
  */
  overflow-x: hidden;
  font-family: var(--font-body);
  background: var(--bg);
  color: var(--text);
  font-size: 14px;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

a { color: inherit; text-decoration: none; }

h1, h2, h3, h4 { font-family: var(--font-heading); }

::-webkit-scrollbar { width: 8px; height: 8px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: #D3D9E0; border-radius: 8px; }
::-webkit-scrollbar-thumb:hover { background: #B9C1CC; }

input, select, textarea {
  font-family: inherit;
  font-size: 13.5px;
  padding: 10px 12px;
  border: 1.5px solid var(--border);
  border-radius: var(--radius-sm);
  background: #fff;
  color: var(--text);
  width: 100%;
  transition: border-color .15s, box-shadow .15s;
}
input:focus, select:focus, textarea:focus {
  border-color: var(--primary-light);
  box-shadow: 0 0 0 3px var(--primary-bg);
  outline: none;
}
.required-mark { color: var(--danger); font-weight: 700; }
.field-invalid { border-color: var(--danger) !important; box-shadow: 0 0 0 3px var(--danger-bg) !important; }
label {
  display: flex;
  flex-direction: column;
  gap: 6px;
  font-size: 12.5px;
  color: var(--text-secondary);
  font-weight: 500;
}

button { font-family: inherit; }

/* ===== Iconos SVG (reemplazan emojis) ===== */
.icon { display: inline-block; vertical-align: middle; flex-shrink: 0; }
.icon svg { display: block; width: 100%; height: 100%; }

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  padding: 10px 18px;
  border-radius: var(--radius-sm);
  border: 1.5px solid transparent;
  font-family: var(--font-heading);
  font-size: 13px;
  font-weight: 600;
  letter-spacing: .1px;
  cursor: pointer;
  transition: filter .15s, box-shadow .15s, transform .1s;
  white-space: nowrap;
}
.btn:hover { filter: brightness(1.05); }
.btn:active { transform: translateY(1px); }
.btn-primary { background: var(--primary); color: #fff; box-shadow: 0 2px 8px color-mix(in srgb, var(--primary) 28%, transparent); }
.btn-primary:hover { background: var(--primary-dark); }
.btn-secondary { background: var(--primary-bg); color: var(--primary-dark); border-color: transparent; }
.btn-secondary:hover { background: var(--primary-bg-strong); }
.btn-ghost { background: #fff; color: var(--text-secondary); border-color: var(--border); }
.btn-ghost:hover { border-color: var(--text-muted); color: var(--text); }
.btn-danger { background: var(--danger); color: #fff; }
.btn-sm { padding: 7px 12px; font-size: 12px; }
.btn-block { width: 100%; }
.btn:disabled { opacity: .5; cursor: not-allowed; }

.icon-btn {
  background: none;
  border: none;
  cursor: pointer;
  color: var(--text-secondary);
  padding: 7px;
  line-height: 1;
  border-radius: var(--radius-sm);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: background .15s, color .15s;
}
.icon-btn:hover { background: var(--border-soft); color: var(--text); }

/* ===== Shell / Sidebar / Topbar ===== */

.app-shell {
  display: flex;
  min-height: 100vh;
}

.sidebar {
  width: 240px;
  background: #fff;
  border-right: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  flex-shrink: 0;
  transition: width .18s ease;
}

.logout-icon-only { display: none; }

@media (min-width: 901px) {
  .sidebar.collapsed { width: 76px; }
  .sidebar.collapsed .sidebar-brand-text,
  .sidebar.collapsed .sidebar-org,
  .sidebar.collapsed .sidebar-link-label,
  .sidebar.collapsed .sidebar-user-name,
  .sidebar.collapsed .sidebar-user-role,
  .sidebar.collapsed .sidebar-user-info,
  .sidebar.collapsed .logout-full { display: none; }
  .sidebar.collapsed .sidebar-brand { justify-content: center; padding: 0; gap: 0; }
  .sidebar.collapsed .sidebar-link { justify-content: center; padding: 10px; }
  .sidebar.collapsed .sidebar-user-row { justify-content: center; margin-bottom: 8px; }
  .sidebar.collapsed .logout-icon-only { display: inline-flex; }
}

.sidebar-brand {
  height: 68px;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 0 18px;
  border-bottom: 1px solid var(--border-soft);
  flex-shrink: 0;
}
.sidebar-brand-mark {
  width: 34px; height: 34px;
  display: flex; align-items: center; justify-content: center;
  flex-shrink: 0;
}
.sidebar-brand-mark img { width: 100%; height: 100%; object-fit: contain; }
.sidebar-brand-text { font-family: var(--font-heading); font-weight: 700; color: var(--text); font-size: 14.5px; letter-spacing: -.1px; }

.sidebar-org {
  padding: 16px 18px;
  border-bottom: 1px solid var(--border-soft);
}
.sidebar-org-name { font-family: var(--font-heading); font-size: 13px; font-weight: 700; color: var(--text); }
.sidebar-org-sub { font-size: 10.5px; color: var(--text-muted); margin-top: 2px; letter-spacing: .5px; text-transform: uppercase; }
.sidebar-sigem-link {
  display: inline-flex; align-items: center; gap: 4px; margin-top: 10px;
  font-size: 11px; font-weight: 600; color: var(--primary);
}
.sidebar-sigem-link:hover { color: var(--primary-dark); }
@media (min-width: 901px) {
  .sidebar.collapsed .sidebar-sigem-link { display: none; }
}

.sidebar-nav {
  flex: 1;
  padding: 12px;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.sidebar-link {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 12px;
  border-radius: var(--radius-sm);
  color: var(--text-secondary);
  font-size: 13.5px;
  font-weight: 500;
  transition: background .15s, color .15s;
}
.sidebar-link:hover { background: var(--border-soft); color: var(--text); }
.sidebar-link.active {
  background: var(--primary-bg);
  color: var(--primary-dark);
  font-weight: 700;
}
.sidebar-link-icon { width: 18px; height: 18px; flex-shrink: 0; opacity: .85; }
.sidebar-link.active .sidebar-link-icon { opacity: 1; }

.sidebar-user {
  border-top: 1px solid var(--border-soft);
  padding: 14px 16px;
  flex-shrink: 0;
}
.sidebar-user-row { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; }
.sidebar-user-avatar {
  width: 34px; height: 34px; border-radius: 50%;
  background: var(--primary-bg); color: var(--primary-dark);
  display: flex; align-items: center; justify-content: center;
  font-family: var(--font-heading);
  font-size: 13px; font-weight: 700; flex-shrink: 0;
}
.sidebar-user-name { font-size: 12.5px; font-weight: 600; color: var(--text); }
.sidebar-user-role { font-size: 10.5px; color: var(--text-muted); margin-top: 1px; text-transform: capitalize; }

.main-area {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.topbar {
  min-height: 64px;
  background: rgba(255, 255, 255, .85);
  backdrop-filter: blur(6px);
  border-bottom: 1px solid var(--border);
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 0 28px;
  flex-shrink: 0;
  position: sticky;
  top: 0;
  z-index: 10;
}
.topbar-title { font-family: var(--font-heading); font-size: 17px; font-weight: 700; color: var(--text); letter-spacing: -.2px; }
.topbar-sync { display: flex; align-items: center; gap: 4px; font-size: 11.5px; color: var(--text-muted); margin-top: 2px; }
.topbar-sync svg { flex-shrink: 0; }

.topbar-conectados {
  margin-left: auto;
  display: flex;
  align-items: center;
}
.avatar-conectado {
  position: relative;
  width: 36px; height: 36px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  line-height: 1;
  color: #fff;
  font-family: var(--font-heading);
  font-size: 14px;
  font-weight: 700;
  border: 2px solid var(--surface);
  box-shadow: var(--shadow-sm);
  cursor: default;
  margin-left: -10px;
  transition: transform .12s ease, z-index .01s;
}
.avatar-conectado:first-child { margin-left: 0; }
.avatar-conectado:hover { transform: translateY(-3px); z-index: 2; }

.avatar-tooltip {
  position: absolute;
  top: calc(100% + 10px);
  /* Alineado al borde DERECHO del avatar (no centrado): el stack vive pegado
     al borde derecho de la pantalla, un tooltip centrado se corta afuera de
     la ventana -- así siempre se despliega hacia la izquierda, visible. */
  right: 0;
  transform: translateY(4px);
  background: var(--primary-dark);
  color: #fff;
  font-family: var(--font-body);
  font-size: 12px;
  font-weight: 600;
  line-height: 1.5;
  text-align: center;
  white-space: nowrap;
  padding: 7px 12px;
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-md);
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity .15s ease, transform .15s ease;
  z-index: 3;
}
.avatar-tooltip::after {
  content: '';
  position: absolute;
  bottom: 100%;
  right: 13px;
  border: 6px solid transparent;
  border-bottom-color: var(--primary-dark);
}
.avatar-tooltip-tiempo { font-weight: 400; color: var(--primary-bg-strong); font-size: 11px; }
.avatar-tooltip-tiempo--ahora { color: #4ADE80; font-weight: 700; }
.avatar-conectado:hover .avatar-tooltip {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
}

.page-content { padding: 28px; flex: 1; min-width: 0; }

.app-footer {
  padding: 14px 28px; text-align: center;
  font-size: 11px; color: var(--text-muted);
  border-top: 1px solid var(--border-soft);
}
/* Entrada suave de cada pantalla — que cargar una página no sea un salto seco,
   sobre todo llegando desde la transición de SIGEM. El sidebar/topbar quedan
   fijos, solo el contenido aparece con un fundido corto. */
.page-content { animation: page-content-in .6s ease-out; }
@keyframes page-content-in {
  from { opacity: 0; transform: translateY(14px); }
  to   { opacity: 1; transform: translateY(0); }
}
@media (prefers-reduced-motion: reduce) { .page-content { animation: none; } }

.mobile-only { display: none; }
.sidebar-overlay { display: none; }

@media (max-width: 900px) {
  .sidebar {
    position: fixed;
    top: 0; left: 0; height: 100vh; z-index: 1000;
    transform: translateX(-100%);
    transition: transform .2s ease;
  }
  .sidebar.open { transform: translateX(0); box-shadow: var(--shadow-lg); }
  .mobile-only { display: inline-flex; }
  .sidebar-overlay {
    display: block;
    position: fixed; inset: 0; background: rgba(15, 23, 27, .4); z-index: 999;
  }
  .sidebar-overlay[hidden] { display: none; }
  .page-content { padding: 16px; }
  .topbar { padding: 0 16px; }
  .card { padding: 16px; }

  /* Asistencia: prioridad — que se pueda tomar cómodo desde el celu. */
  .asist-resumen { flex-direction: column; align-items: stretch; padding: 16px; gap: 14px; }
  .asist-resumen-controles { flex-wrap: wrap; }
  .asist-resumen-total { text-align: left; }
  .asist-row { flex-direction: column; align-items: stretch; gap: 10px; position: relative; }
  .asist-controles { width: 100%; }
  .asist-btn { flex: 1; justify-content: center; padding: 12px 10px; font-size: 13px; }
  .asist-guardado { position: absolute; top: 10px; right: 12px; }
}

/* ===== Auth (login / setup) — panel partido ===== */

.auth-shell {
  min-height: 100vh;
  display: flex;
}
.auth-panel-left {
  flex: 0 0 34%;
  background:
    radial-gradient(560px 420px at 30% 20%, rgba(76, 139, 132, .35), transparent 60%),
    radial-gradient(480px 480px at 80% 85%, rgba(201, 138, 62, .18), transparent 55%),
    linear-gradient(160deg, #16302E 0%, #0E211F 60%, #0A1918 100%);
  color: #fff;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: 56px 48px;
  position: relative;
  overflow: hidden;
}
.auth-panel-right {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 32px;
  background: var(--bg);
}
@media (max-width: 860px) {
  .auth-shell { flex-direction: column; }
  .auth-panel-left { flex: none; padding: 36px 28px; }
  .auth-panel-right { padding: 28px 20px 48px; }
}

.auth-brand-block { display: flex; flex-direction: column; align-items: flex-start; gap: 26px; transform: translateY(-14vh); }
@media (max-width: 860px) {
  .auth-brand-block { transform: none; }
}
.auth-logo-badge {
  width: 184px; height: 184px;
  display: flex; align-items: center; justify-content: center;
  position: relative;
}
.auth-logo-badge img {
  width: 82%; height: 82%; object-fit: contain;
  filter: drop-shadow(0 3px 8px rgba(0, 0, 0, .2));
  position: relative; z-index: 1;
}
/* Fondo blanco chico y bien definido detrás del logo (tipo placa), con un
   borde apenas suavizado — y palpita (respira un poco de tamaño). */
.auth-logo-badge::before {
  content: '';
  position: absolute; top: 50%; left: 50%;
  width: 106%; height: 106%;
  transform: translate(-50%, -50%) scale(1);
  border-radius: 50%;
  background: radial-gradient(circle, #fff 0%, #fff 74%, rgba(255, 255, 255, .6) 88%, rgba(255, 255, 255, 0) 100%);
  box-shadow: 0 6px 18px rgba(0, 0, 0, .28);
  animation: auth-pulse 2.6s ease-in-out infinite;
  z-index: 0;
  pointer-events: none;
}
@keyframes auth-pulse {
  0%, 100% { transform: translate(-50%, -50%) scale(1); }
  50%      { transform: translate(-50%, -50%) scale(1.06); }
}
@media (prefers-reduced-motion: reduce) {
  .auth-logo-badge::before { animation: none; }
}

/* Ondas bien sutiles que se expanden desde el logo, al ritmo del palpitar. */
.auth-logo-wave {
  position: absolute; top: 50%; left: 50%;
  width: 106%; height: 106%;
  transform: translate(-50%, -50%) scale(1);
  border-radius: 50%;
  border: 1.5px solid rgba(255, 255, 255, .6);
  opacity: 0;
  animation: auth-wave 2.6s ease-out infinite;
  z-index: 0;
  pointer-events: none;
}
.auth-logo-wave-2 { animation-delay: 1.3s; }
@keyframes auth-wave {
  0%   { transform: translate(-50%, -50%) scale(1); opacity: .65; }
  70%  { transform: translate(-50%, -50%) scale(1.32); opacity: 0; }
  100% { opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .auth-logo-wave { animation: none; opacity: 0; }
}
@media (max-width: 860px) {
  .auth-logo-badge { width: 128px; height: 128px; }
}

.auth-org-name { font-family: var(--font-heading); font-size: 26px; font-weight: 700; line-height: 1.25; letter-spacing: -.3px; }
.auth-org-sub { font-size: 13px; color: rgba(255, 255, 255, .55); margin-top: 6px; }
.auth-divider { width: 40px; height: 3px; border-radius: 2px; background: var(--accent); margin: 16px 0 14px; }
.auth-pill {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 8px 14px; border-radius: 999px;
  background: rgba(255, 255, 255, .08);
  border: 1px solid rgba(255, 255, 255, .14);
  font-size: 11px; font-weight: 600; letter-spacing: .6px; text-transform: uppercase;
  color: rgba(255, 255, 255, .85);
}
.auth-footer-left {
  font-size: 11.5px; color: rgba(255, 255, 255, .4);
  position: absolute; left: 48px; bottom: 28px; z-index: 1;
}
@media (max-width: 860px) {
  .auth-footer-left { position: static; margin-top: 28px; }
}

.auth-form-wrap { width: 100%; max-width: 380px; }
.auth-eyebrow { font-family: var(--font-heading); font-size: 11.5px; font-weight: 700; letter-spacing: 1px; text-transform: uppercase; color: var(--primary); margin-bottom: 10px; }
.auth-heading { font-family: var(--font-heading); font-size: 27px; font-weight: 700; letter-spacing: -.4px; color: var(--text); margin: 0 0 8px; }
.auth-sub { font-size: 13.5px; color: var(--text-secondary); line-height: 1.55; margin: 0 0 28px; }

.auth-form-card {
  background: #fff;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-md);
  padding: 28px;
}
.auth-form { display: flex; flex-direction: column; gap: 16px; }
.auth-note {
  margin-top: 20px; padding: 13px 15px; background: var(--primary-bg); border-radius: var(--radius-sm);
  font-size: 11.5px; color: var(--primary-dark); line-height: 1.6;
}
.auth-note strong { display: block; color: var(--primary-dark); margin-bottom: 3px; font-family: var(--font-heading); }
.auth-footer { text-align: center; margin-top: 20px; color: var(--text-muted); font-size: 11px; }

/* ===== Cards / KPIs ===== */

.card {
  background: #fff;
  border: 1px solid var(--border);
  border-top: 3px solid var(--primary-light);
  border-radius: var(--radius-md);
  padding: 20px 22px;
  box-shadow: var(--shadow-sm);
}
.card + .card { margin-top: 16px; }
/* .card + .card es para cards apiladas una debajo de otra en flujo normal — pero la
   misma regla también "veía" como hermanos adyacentes a las cards puestas lado a lado
   dentro de un grid (.grid-2/.grid-3, que ya tienen su propio gap), empujando la
   segunda 16px hacia abajo y desalineando los dos paneles de una fila. */
.grid-2 > .card, .grid-3 > .card { margin-top: 0; }
.card-title {
  font-family: var(--font-heading); font-size: 14px; font-weight: 700; color: var(--text);
  margin: 0 0 16px; display: flex; align-items: center; justify-content: space-between; gap: 8px;
  letter-spacing: -.1px;
  /* flex-wrap: wrap -- bug real encontrado 2026-09-22 en celular real: el
     selector de rango (1 año/2 años/3 años/5 años/10 años) del gráfico de
     Evolución (dashboard y ficha de contribuyente) es un .btn-group-wrap de
     5 botones al lado del título. Sin wrap acá, ese grupo entero se corre
     a la derecha del título en una sola fila que no entra en una pantalla
     angosta -- y como <body> tiene overflow-x:hidden (a propósito, ver esa
     regla), el sobrante no se ve como scroll: el botón "10 años" queda
     directamente RECORTADO Y NO CLICKEABLE, sin ningún aviso visual de que
     existe. Con wrap, el título pasa a su propia línea y el grupo de
     botones baja completo debajo, visible y tocable entero. */
  flex-wrap: wrap;
}
/* Grupo de botones dentro de un .card-title (selector de rango de años, hoy
   en dashboard.php y gestion/detalle.php) -- mismo bug de fondo que el de
   arriba pero en el propio grupo: sin flex-wrap, los 5 botones ("10 años"
   incluido) intentan entrar en una sola fila y se recortan igual, ahora
   *dentro* de su propia línea aunque el título ya haya bajado. */
.btn-group-wrap { display: flex; gap: 4px; flex-wrap: wrap; }

.kpi-seccion-titulo {
  display: flex; align-items: center; gap: 7px;
  font-family: var(--font-heading); font-size: 12.5px; font-weight: 800;
  text-transform: uppercase; letter-spacing: .5px; color: var(--primary-dark);
  margin: 0 0 10px;
}
.kpi-plan-lista { display: flex; flex-direction: column; gap: 9px; }
.kpi-plan-fila { display: flex; align-items: center; gap: 10px; }
.kpi-plan-num { font-family: var(--font-heading); font-size: 18px; font-weight: 800; color: var(--text); min-width: 26px; text-align: right; flex-shrink: 0; }
.kpi-plan-info { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.kpi-plan-nombre { font-size: 11px; color: var(--text-secondary); font-weight: 600; }

.kpi-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  gap: 14px;
  margin-bottom: 20px;
}
.kpi-card {
  background: #fff; border: 1px solid var(--border); border-radius: var(--radius-md);
  padding: 18px 20px; box-shadow: var(--shadow-sm);
  display: flex; flex-direction: column; gap: 10px;
  transition: box-shadow .15s, transform .15s;
}
.kpi-card:hover { box-shadow: var(--shadow-md); transform: translateY(-1px); }

.kpi-card.tint-teal   { background: linear-gradient(160deg, #E9F5F2, #fff 65%); border-color: #CFE8E1; }
.kpi-card.tint-amber  { background: linear-gradient(160deg, #FCF2E1, #fff 65%); border-color: #F2DDB3; }
.kpi-card.tint-rose   { background: linear-gradient(160deg, #FBEAEA, #fff 65%); border-color: #F0CECE; }
.kpi-card.tint-violet { background: linear-gradient(160deg, #F1EBFA, #fff 65%); border-color: #DDCBF0; }
.kpi-card.tint-sky    { background: linear-gradient(160deg, #E9F1FA, #fff 65%); border-color: #C9DFF3; }

.kpi-card.tint-teal .kpi-icon   { background: #CFE8E1; color: #1F4D48; }
.kpi-card.tint-amber .kpi-icon  { background: #F2DDB3; color: #7A5312; }
.kpi-card.tint-rose .kpi-icon   { background: #F0CECE; color: #8C3A3A; }
.kpi-card.tint-violet .kpi-icon { background: #DDCBF0; color: #5B3A82; }
.kpi-card.tint-sky .kpi-icon    { background: #C9DFF3; color: #205081; }

/* Cualquier .kpi-card sin tint- explícito se colorea igual, rotando la misma
   paleta por posición — así toda grilla de KPIs del sistema queda con color
   aunque la vista no haya elegido un tinte a mano. */
.kpi-grid .kpi-card:nth-child(5n+1) { background: linear-gradient(160deg, #E9F5F2, #fff 65%); border-color: #CFE8E1; }
.kpi-grid .kpi-card:nth-child(5n+1) .kpi-icon { background: #CFE8E1; color: #1F4D48; }
.kpi-grid .kpi-card:nth-child(5n+2) { background: linear-gradient(160deg, #FCF2E1, #fff 65%); border-color: #F2DDB3; }
.kpi-grid .kpi-card:nth-child(5n+2) .kpi-icon { background: #F2DDB3; color: #7A5312; }
.kpi-grid .kpi-card:nth-child(5n+3) { background: linear-gradient(160deg, #FBEAEA, #fff 65%); border-color: #F0CECE; }
.kpi-grid .kpi-card:nth-child(5n+3) .kpi-icon { background: #F0CECE; color: #8C3A3A; }
.kpi-grid .kpi-card:nth-child(5n+4) { background: linear-gradient(160deg, #F1EBFA, #fff 65%); border-color: #DDCBF0; }
.kpi-grid .kpi-card:nth-child(5n+4) .kpi-icon { background: #DDCBF0; color: #5B3A82; }
.kpi-grid .kpi-card:nth-child(5n+5) { background: linear-gradient(160deg, #E9F1FA, #fff 65%); border-color: #C9DFF3; }
.kpi-grid .kpi-card:nth-child(5n+5) .kpi-icon { background: #C9DFF3; color: #205081; }

.kpi-top { display: flex; align-items: center; justify-content: space-between; }
.kpi-icon {
  width: 36px; height: 36px; border-radius: var(--radius-sm);
  background: var(--primary-bg); color: var(--primary-dark);
  display: flex; align-items: center; justify-content: center; flex-shrink: 0;
}
.kpi-icon svg { width: 18px; height: 18px; }
.kpi-label { font-size: 11.5px; color: var(--text-secondary); font-weight: 600; letter-spacing: .2px; }
.kpi-value { font-family: var(--font-heading); font-size: 28px; font-weight: 700; color: var(--text); letter-spacing: -.5px; }
.kpi-value .kpi-pct { font-size: 15px; font-weight: 600; color: var(--text-muted); letter-spacing: 0; }
.kpi-sub { font-size: 11.5px; color: var(--text-muted); }

/* ===== Tablas colapsables (mostrar 5 filas + botón "mostrar más") ===== */
.btn-link {
  border: none; background: none; padding: 10px 2px 0; margin: 0;
  color: var(--primary); font-size: 12.5px; font-weight: 700; cursor: pointer;
  font-family: inherit;
}
.btn-link:hover { text-decoration: underline; }

/* ===== Ranking con barras (Cobros por Empresa de Cobro) ===== */
.ranking-barras { display: flex; flex-direction: column; gap: 14px; }
.ranking-fila { display: grid; grid-template-columns: 190px 1fr 150px; align-items: center; gap: 14px; }
.ranking-etiqueta { display: flex; flex-direction: column; gap: 2px; font-size: 13px; font-weight: 600; color: var(--text); min-width: 0; }
.ranking-barra-wrap { background: var(--primary-bg); border-radius: 999px; height: 10px; overflow: hidden; }
.ranking-barra { background: linear-gradient(90deg, var(--primary), var(--accent, var(--primary))); height: 100%; border-radius: 999px; }
.ranking-monto { text-align: right; font-size: 13px; display: flex; flex-direction: column; gap: 2px; }
@media (max-width: 640px) {
  .ranking-fila { grid-template-columns: 1fr; gap: 6px; }
  .ranking-monto { text-align: left; }
}

/* ===== Turnos: contenedores grandes por actividad para elegir dónde anotar ===== */
.actividad-picker { display: grid; grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); gap: 16px; margin-bottom: 24px; }
.actividad-picker-card {
  display: flex; flex-direction: column; align-items: flex-start; gap: 14px;
  padding: 26px 22px;
  border-radius: var(--radius-md);
  border: 1px solid var(--border);
  border-top: 5px solid var(--color-actividad, var(--primary));
  background: color-mix(in srgb, var(--color-actividad, var(--primary)) 14%, white);
  box-shadow: var(--shadow-sm);
  transition: transform .12s ease, box-shadow .12s ease;
  /* .actividad-picker-card también se usa como <button> (Actividades) además de <a>
     (Turnos) — reseteamos los estilos nativos de botón para que se vea igual. */
  font: inherit; text-align: left; cursor: pointer; width: 100%;
}
.actividad-picker-card:hover { transform: translateY(-2px); box-shadow: var(--shadow-md); }
.actividad-picker-card-nueva {
  border-style: dashed; border-top-style: dashed; border-width: 2px;
  background: var(--bg); justify-content: center; align-items: center; text-align: center;
}
.actividad-picker-card-nueva .actividad-picker-icon { background: var(--primary-bg); color: var(--primary-dark); }
.actividad-picker-card-nueva:hover { border-color: var(--primary-light); }
.actividad-picker-icon {
  display: flex; align-items: center; justify-content: center;
  width: 46px; height: 46px; border-radius: 50%;
  background: color-mix(in srgb, var(--color-actividad, var(--primary)) 35%, white);
  color: color-mix(in srgb, var(--color-actividad, var(--primary)) 65%, black);
}
.actividad-picker-icon .icon { width: 22px; height: 22px; }
.actividad-picker-nombre { font-family: var(--font-heading); font-size: 19px; font-weight: 800; color: var(--text); letter-spacing: -.3px; line-height: 1.2; }
.actividad-picker-ocupacion {
  display: flex; align-items: center; gap: 4px; margin-top: 16px;
  font-size: 11.5px; font-weight: 600; color: var(--text-secondary); text-decoration: none;
}
.actividad-picker-ocupacion:hover { color: var(--text); }
.actividad-picker-ocupacion .icon { width: 13px; height: 13px; }

/* ===== Confirmar inscripción: plan + horarios agrupados por día ===== */
.plan-contratado-box {
  background: var(--primary-bg);
  border: 1px solid var(--primary-bg-strong);
  border-radius: var(--radius-md);
  padding: 16px 18px;
}
.plan-contratado-label {
  font-size: 11px; font-weight: 700; text-transform: uppercase;
  letter-spacing: .4px; color: var(--primary-dark);
}

.horarios-dias-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  gap: 14px;
  align-items: start;
}
.horario-dia-card {
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 12px;
  display: flex;
  flex-direction: column;
  gap: 7px;
}
.horario-dia-titulo {
  margin: 0 0 2px;
  font-family: var(--font-heading);
  font-size: 12px;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: .4px;
  color: var(--primary-dark);
}
.horario-check-card {
  display: flex;
  align-items: flex-start;
  gap: 9px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 9px 10px;
  cursor: pointer;
  transition: border-color .12s ease, background .12s ease;
}
.horario-check-card:hover { border-color: var(--primary-light); }
.horario-check-card:has(input:checked) { border-color: var(--primary); background: var(--primary-bg); }
.horario-check-card.is-lleno { opacity: .55; cursor: not-allowed; }
.horario-check-card input[type="checkbox"] { width: auto; flex-shrink: 0; margin-top: 2px; }
.horario-check-hora {
  font-weight: 700; font-size: 12.5px; color: var(--text); white-space: nowrap; flex-shrink: 0; min-width: 76px;
}
.horario-check-detalle {
  flex: 1; min-width: 0; font-size: 12px; color: var(--text-secondary);
  display: flex; flex-direction: column; gap: 2px;
}
.horario-check-prof { font-size: 10.5px; color: var(--text-muted); }
.horario-check-badges { display: flex; flex-direction: column; align-items: flex-end; gap: 4px; flex-shrink: 0; }

.grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; }
@media (max-width: 900px) {
  /* minmax(0, 1fr), no 1fr solo: un grid item (la .card con la tabla adentro)
     por defecto no encoge por debajo del ancho de su contenido (min-width:auto
     implícito de grid/flex) — eso empujaba toda la página a un scroll horizontal
     en el celu aunque la tabla de adentro ya tenía su propio overflow-x:auto. */
  .grid-2, .grid-3 { grid-template-columns: minmax(0, 1fr); }
}

.progress-bar {
  height: 8px; border-radius: 5px; background: var(--border-soft); overflow: hidden;
}
.progress-bar-fill { height: 100%; background: var(--primary); border-radius: 5px; transition: width .3s ease; }
.progress-bar-fill.warning { background: var(--warning); }
.progress-bar-fill.danger { background: var(--danger); }

/* ===== Primeros pasos (onboarding) ===== */

.quickstart {
  background: linear-gradient(155deg, var(--primary-dark), var(--primary));
  border-radius: var(--radius-lg);
  padding: 26px 28px;
  color: #fff;
  margin-bottom: 20px;
  box-shadow: var(--shadow-md);
}
.quickstart-title { font-family: var(--font-heading); font-size: 17px; font-weight: 700; margin: 0 0 4px; }
.quickstart-sub { font-size: 12.5px; color: rgba(255, 255, 255, .7); margin: 0 0 20px; }
.quickstart-steps { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 12px; }
.quickstart-step {
  background: rgba(255, 255, 255, .08);
  border: 1px solid rgba(255, 255, 255, .12);
  border-radius: var(--radius-md);
  padding: 16px;
  display: flex; flex-direction: column; gap: 10px;
}
.quickstart-step.done { background: rgba(255, 255, 255, .04); opacity: .6; }
.quickstart-num {
  width: 26px; height: 26px; border-radius: 50%;
  background: rgba(255, 255, 255, .16);
  display: flex; align-items: center; justify-content: center;
  font-family: var(--font-heading); font-size: 12px; font-weight: 700;
}
.quickstart-step.done .quickstart-num { background: var(--accent); }
.quickstart-step-title { font-size: 13px; font-weight: 700; }
.quickstart-step-desc { font-size: 11.5px; color: rgba(255, 255, 255, .65); line-height: 1.5; }
.quickstart-step a { font-size: 12px; font-weight: 700; color: #fff; text-decoration: underline; text-underline-offset: 2px; }

/* ===== Tabla ===== */

.table-wrap { overflow-x: auto; }
table { width: 100%; border-collapse: collapse; font-size: 13px; }
th, td { text-align: left; padding: 11px 12px; border-bottom: 1px solid var(--border-soft); white-space: nowrap; }
th { color: var(--primary-dark); font-weight: 700; font-size: 11px; text-transform: uppercase; letter-spacing: .4px; background: var(--primary-bg); }
thead tr:first-child th:first-child { border-top-left-radius: var(--radius-sm); }
thead tr:first-child th:last-child { border-top-right-radius: var(--radius-sm); }
tbody tr:hover { background: var(--bg); }
tbody tr:nth-child(even) { background: #FBFCFC; }
tbody tr:nth-child(even):hover { background: var(--bg); }
td.wrap { white-space: normal; }
/* El HTML del email (ver EmailPlantilla::tarjetaHtml()) se inyecta tal cual
   dentro de #previewCuerpo para la vista previa "¿confirmás el envío?" --
   no tiene su propia hoja de estilos (los emails reales no la respetan como
   la app), así que hereda el CSS global de la página, incluido el
   white-space:nowrap de la regla "th, td" de arriba (pensada para las
   tablas normales de datos de la app). Bug real encontrado 2026-09-22: eso
   impedía que el párrafo largo del cuerpo del mail hiciera salto de línea,
   disparando el ancho de la tabla de email a más de 1200px (muy por encima
   de los 600px reales que ve el destinatario) y cortando la vista previa
   contra el borde del modal. */
#previewCuerpo td, #previewCuerpo th { white-space: normal; }

/* ===== Badges / Alerts ===== */

.badge {
  display: inline-flex; align-items: center; gap: 4px; padding: 3px 10px; border-radius: 999px;
  font-size: 11px; font-weight: 600;
}
.badge-success { background: var(--success-bg); color: var(--success); }
.badge-warning { background: var(--warning-bg); color: var(--warning); }
.badge-danger { background: var(--danger-bg); color: var(--danger); }
.badge-info { background: var(--primary-bg); color: var(--primary-dark); }
.badge-violet { background: #F1EBFA; color: #5B3A82; }
.badge-neutral { background: var(--border-soft); color: var(--text-secondary); }

.alert {
  padding: 13px 15px; border-radius: var(--radius-sm); font-size: 12.5px; display: flex; align-items: center; gap: 10px;
  margin-bottom: 16px;
}
.alert .icon { flex-shrink: 0; }
.alert-error { background: var(--danger-bg); color: var(--danger); }
.alert-warning { background: var(--warning-bg); color: var(--warning); }
/* Para avisos que no queremos que se pierdan de vista con el resto (ej. notas de
   débito sin generar) — un pulso lento, no una alarma molesta. */
.alert-pulsante { animation: alerta-pulso 2.2s ease-in-out infinite; }
@keyframes alerta-pulso {
  0%, 100% { box-shadow: 0 0 0 0 rgba(193, 137, 46, .35); }
  50%      { box-shadow: 0 0 0 6px rgba(193, 137, 46, 0); }
}
/* Para llamados a la acción que no se deben pasar por alto (ej. "Verificar"
   datos de contacto vencidos) — un parpadeo de opacidad, más notorio que el
   pulso de .alert-pulsante. */
.badge-parpadeante { animation: badge-parpadeo 1.4s ease-in-out infinite; }
@keyframes badge-parpadeo {
  0%, 100% { opacity: 1; }
  50%      { opacity: .35; }
}
@media (prefers-reduced-motion: reduce) {
  .badge-parpadeante { animation: none; }
}
@media (prefers-reduced-motion: reduce) {
  .alert-pulsante { animation: none; }
}
.alert-info { background: var(--primary-bg); color: var(--primary-dark); }

/* ===== Forms ===== */

.form-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
/* !important acá a propósito -- bug real encontrado 2026-09-22 revisando
   Gestión de Deuda en un celular real: HAY 11+ lugares en las vistas que
   ponen un style="grid-template-columns:2fr 1fr 1fr 1fr" (o similar) inline
   directo en un .form-grid para el layout de escritorio (filtros, formularios
   de WhatsApp, edición de contacto, etc). Un inline style SIEMPRE le gana a
   cualquier regla de clase sin !important, sin importar el media query --
   así que ninguno de esos formularios colapsaba a 1 columna en mobile, por
   más angosta que fuera la pantalla (ver kpi-grid-4/form-grid-3 más abajo,
   que fue el primer parche puntual para 2 casos -- esto lo generaliza a
   TODOS, presentes y futuros, en un solo lugar). Ya no hace falta crear una
   clase nueva por cada combinación de columnas: cualquier .form-grid,
   tenga el inline style que tenga, colapsa a 1 columna bajo 700px. */
@media (max-width: 700px) { .form-grid { grid-template-columns: 1fr !important; } }
/* Variantes de 3/4 columnas fijas (KPIs) -- mismo bug, tabla en vez de form. */
.kpi-grid-4 { grid-template-columns: repeat(4, 1fr); }
.form-grid-3 { grid-template-columns: repeat(3, 1fr); }
@media (max-width: 700px) {
  .kpi-grid-4, .form-grid-3 { grid-template-columns: 1fr; }
}
@media (max-width: 700px) {
  /* Muchos formularios de filtro/carga (toolbar de Turnos, tramos de Valores,
     horarios de Actividades, etc.) usan style="display:flex;..." con labels
     de ancho fijo en px — cómodo en desktop, pero sin wrap se salen de la
     pantalla en el celu. El inline style no fija flex-wrap, así que esta
     regla puede pisarlo sin necesidad de !important. */
  form { flex-wrap: wrap; }
}

/* ===== Tabla -> tarjetas en mobile (.table-cards-mobile) =====
   Pedido explícito del usuario 2026-09-21: "no solo debo poder ver los
   datos, sino operar el sistema desde mi celular". Con overflow-x:auto
   nada más, una tabla de 15 columnas (ej. Gestión de Deuda, con teléfono,
   estado, checkboxes de notificación, botones de acción) obliga a deslizar
   fila por fila para llegar a lo importante -- inoperable de verdad, aunque
   técnicamente "andaba".
   Patrón: cada <tr> se convierte en una tarjeta, cada <td> en una fila
   etiqueta/valor usando su atributo data-label (puesto a mano en el PHP,
   sin duplicar el <thead> ni la lógica del backend). Clases especiales:
   .td-card-title (el dato principal, ej. Nº de imponible, se destaca como
   encabezado de la tarjeta en vez de fila con etiqueta) y .td-card-select
   (el checkbox de selección, se ubica arriba a la derecha de la tarjeta).
   Aplicar la clase "table-cards-mobile" al .table-wrap de cada tabla que se
   quiera convertir -- no es automático para todas, así no se arriesga
   romper alguna tabla simple de 2-3 columnas que ya se lee bien tal cual. */
@media (max-width: 700px) {
  .table-cards-mobile { overflow-x: visible; max-height: none !important; }
  .table-cards-mobile table,
  .table-cards-mobile thead,
  .table-cards-mobile tbody,
  .table-cards-mobile tr,
  .table-cards-mobile td { display: block; width: 100%; }
  .table-cards-mobile thead { display: none; }
  .table-cards-mobile tr {
    position: relative;
    background: var(--surface, #fff);
    /* Borde/sombra reforzados -- pedido explícito del usuario 2026-09-22
       viendo varias tarjetas seguidas en el celular real: con border-soft +
       sombra casi imperceptible (rgba .06), tarjetas contiguas casi se
       fusionan visualmente en una sola masa, cuesta ver dónde termina una y
       empieza la siguiente. */
    border: 1px solid var(--border);
    border-radius: var(--radius-sm, 10px);
    padding: 14px 14px 10px;
    margin-bottom: 14px;
    box-shadow: 0 2px 6px rgba(15, 23, 42, .1);
  }
  .table-cards-mobile td {
    display: flex; align-items: center; justify-content: space-between; gap: 10px;
    padding: 7px 0; border-bottom: 1px dashed var(--border-soft); white-space: normal;
    text-align: right;
  }
  .table-cards-mobile td:last-child { border-bottom: none; }
  .table-cards-mobile td[data-label]::before {
    content: attr(data-label);
    font-weight: 700; font-size: 11px; text-transform: uppercase; letter-spacing: .3px;
    color: var(--text-muted); text-align: left; flex-shrink: 0;
  }
  /* Celdas de contenido largo (clase .wrap, ya usada en varias tablas para
     texto que no debe truncarse -- dirección, recurso, detalle del
     historial): en vez de forzar label+valor en una sola fila apretada,
     el valor va DEBAJO del label, con su wrap normal. */
  .table-cards-mobile td.wrap {
    display: block; text-align: left;
  }
  .table-cards-mobile td.wrap::before {
    display: block; margin-bottom: 4px;
  }
  /* Inputs/selects dentro de una tarjeta: ocupan el lado del valor, no un
     ancho fijo en px pensado para columnas de escritorio. */
  .table-cards-mobile td[data-label] input,
  .table-cards-mobile td[data-label] select {
    width: auto; max-width: 62%; min-width: 0; flex: 1 1 auto;
  }
  .table-cards-mobile .td-card-title {
    padding-top: 0; padding-right: 34px; border-bottom: 1px solid var(--border-soft);
    margin-bottom: 6px; font-size: 15px;
  }
  .table-cards-mobile .td-card-title::before { display: none; }
  .table-cards-mobile .td-card-select {
    /* width:auto -- bug real encontrado 2026-09-22 en un celular real: sin
       esto, hereda width:100% de la regla ".table-cards-mobile td" de más
       arriba (nunca sobreescrita acá) -- con position:absolute, un ancho de
       100% lo estira invisible a lo ancho de TODA la tarjeta en esa franja
       (top:12px), tapando el link del imponible/título que vive justo ahí
       arriba. Se veía perfecto (el checkbox se dibuja en su lugar de
       siempre) pero CUALQUIER tap en esa franja, en cualquier punto del
       ancho de la tarjeta, caía en este <td> invisible en vez de en el link
       -- así que tocar el número de imponible no abría la ficha. */
    position: absolute; top: 12px; right: 12px; width: auto; padding: 0; border: none; display: block;
  }
  .table-cards-mobile .td-card-select input[type="checkbox"] { width: 20px; height: 20px; }
}
.form-actions { display: flex; gap: 10px; margin-top: 20px; }
.checkbox-row { display: flex; align-items: center; gap: 8px; flex-direction: row; }
.checkbox-row input { width: auto; }

/* Selector de hora 24hs (HH + MM), en vez de <input type="time"> — ese input nativo
   muestra AM/PM si así está configurada la región de Windows, sin importar el idioma
   de la página, y no hay forma confiable de forzarlo desde acá. */
.selector-hora { display: inline-flex; align-items: center; gap: 4px; }
.selector-hora select { width: 62px; padding: 10px 6px; text-align: center; }
.selector-hora-separador { font-weight: 700; color: var(--text-secondary); }

/* Chips seleccionables (días, profesores): el checkbox nativo queda invisible — el
   estado "elegido" se ve solo en el color del chip, sin tilde. */
.chip-toggle {
  position: relative;
  display: inline-flex; align-items: center; gap: 6px;
  border: 1.5px solid var(--border); border-radius: 999px;
  padding: 7px 14px; font-weight: 500; font-size: 13px;
  background: #fff; color: var(--text-secondary);
  cursor: pointer; user-select: none;
  transition: background .15s ease, border-color .15s ease, color .15s ease;
}
.chip-toggle input[type="checkbox"], .chip-toggle input[type="radio"] {
  position: absolute; opacity: 0; width: 0; height: 0; margin: 0; pointer-events: none;
}
.chip-toggle:hover { border-color: var(--primary-light); background: var(--primary-bg); color: var(--primary-dark); }
.chip-toggle:has(input:checked) { background: var(--success); border-color: var(--success); color: #fff; }
.chip-toggle:has(input:checked):hover { background: var(--primary-dark); border-color: var(--primary-dark); }
.chip-toggle:has(input:disabled) { opacity: .5; cursor: not-allowed; }
@keyframes chip-bounce { 0% { transform: scale(1); } 45% { transform: scale(1.1); } 100% { transform: scale(1); } }
.chip-toggle.chip-bounce { animation: chip-bounce .28s ease; }
@media (prefers-reduced-motion: reduce) {
  .chip-toggle.chip-bounce { animation: none; }
}
.field-hint { font-size: 11px; color: var(--text-muted); font-weight: 400; }

/* Input numérico con un símbolo fijo (ej. "$") superpuesto a la izquierda — usado
   en los filtros de rango de deuda de Exportar. */
.input-prefix { position: relative; display: flex; align-items: center; }
.input-prefix > span {
  position: absolute; left: 12px; color: var(--text-muted); font-weight: 600;
  font-size: 13px; pointer-events: none;
}
.input-prefix > input { padding-left: 26px; width: 100%; }

/* Desplegable de selección múltiple (filtro de Recurso en Exportar) — como un
   <select> pero con lista angosta y scroll, para cuando hay muchas más
   opciones de las que entran en una fila de chips. Cada opción es una fila de
   texto entera clickeable (sin cuadradito de checkbox a la vista) que se
   pinta de azul pastel cuando está elegida. */
.dropdown-check { position: relative; }
.dropdown-check-toggle {
  width: 100%; display: flex; align-items: center; justify-content: space-between; gap: 8px;
  border: 1px solid var(--border); border-radius: var(--radius-sm); background: #fff;
  padding: 10px 12px; font-size: 13px; font-weight: 500; color: var(--text);
  cursor: pointer; text-align: left; font-family: inherit;
}
.dropdown-check-toggle:hover { border-color: var(--primary-light); }
.dropdown-check-toggle[aria-expanded="true"] { border-color: var(--primary); }
.dropdown-check-arrow { color: var(--text-muted); font-size: 11px; }
.dropdown-check-panel {
  position: absolute; top: calc(100% + 4px); left: 0; right: 0; z-index: 20;
  background: #fff; border: 1px solid var(--border); border-radius: var(--radius-sm);
  box-shadow: var(--shadow-md); max-height: 260px; overflow-y: auto; padding: 6px;
}
.dropdown-check-item {
  display: block; padding: 10px 12px; border-radius: 6px;
  font-size: 13px; text-align: left; line-height: 1.4; cursor: pointer; user-select: none;
  transition: background .12s ease;
}
.dropdown-check-item input {
  position: absolute; opacity: 0; width: 0; height: 0; margin: 0; pointer-events: none;
}
.dropdown-check-item:hover { background: #F1F6FC; }
.dropdown-check-item:has(input:checked) { background: #DBEAFE; color: #1D4E89; font-weight: 600; }

.toolbar { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 16px; flex-wrap: wrap; }
.toolbar-search { max-width: 320px; }

.tabs { display: flex; gap: 4px; border-bottom: 1px solid var(--border); margin-bottom: 18px; }
.tab-link { padding: 10px 16px; font-size: 13px; color: var(--text-secondary); border-bottom: 2px solid transparent; transition: color .15s, border-color .15s; }
.tab-link:hover { color: var(--primary-dark); border-bottom-color: var(--primary-bg-strong); }
.tab-link.active { color: var(--primary); border-bottom-color: var(--primary); font-weight: 600; }

/* Franja de color a la izquierda de la página, detrás del título — un toque
   de identidad que evita que las cabeceras se vean todas iguales de blancas. */
.page-header h2 {
  position: relative;
  padding-left: 14px;
}
.page-header h2::before {
  content: '';
  position: absolute;
  left: 0; top: 2px; bottom: 2px;
  width: 4px;
  border-radius: 3px;
  background: linear-gradient(180deg, var(--primary-light), var(--accent));
}

.page-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 22px; flex-wrap: wrap; gap: 10px; }
.page-header h2 { margin: 0; font-family: var(--font-heading); font-size: 20px; font-weight: 700; color: var(--text); letter-spacing: -.3px; }
.page-header p { margin: 3px 0 0; font-size: 12.5px; color: var(--text-secondary); }

.empty-state { text-align: center; padding: 44px 20px; color: var(--text-muted); font-size: 13px; }
.empty-state .icon { margin: 0 auto 12px; color: var(--text-muted); opacity: .5; }

/* Fila clickeable de un resultado de búsqueda en vivo (buscadores tipo autocompletar). */
.search-result-row {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 8px 12px; border: 1px solid var(--border); border-radius: var(--radius-sm);
  margin-bottom: 5px; cursor: pointer; font-size: 13px; font-weight: 500;
  transition: background .12s, border-color .12s;
}
.search-result-row:hover { background: var(--primary-bg); border-color: var(--primary-bg-strong); }
.search-result-row:last-child { margin-bottom: 0; }

/* Overlay de transición al salir del módulo (Volver a SIGEM / Cerrar sesión)
   -- mismo lenguaje visual que la pantalla "Entrando a..." del hub de SIGEM
   (barrido de color + ícono con latido + mensaje), para que nunca se sienta
   un salto abrupto entre pantallas. Ver app.js: transicionSalida(). */
.transicion-salida {
  position: fixed; inset: 0; z-index: 9999;
  display: flex; align-items: center; justify-content: center;
  overflow: hidden;
  /* Fondo propio opaco -- sin esto, mientras .transicion-barrido todavía
     está en opacity:0 subiendo a 1 (fade-in de 1.1s), se transparenta el
     fondo claro de la página de atrás y se ve un destello gris/blanco antes
     de asentarse en el color oscuro del módulo. */
  background: var(--primary-dark);
}
.transicion-barrido {
  /* --primary-dark (no --primary a secas) -- "que el color de atrás no sea
     tan alarmante". Desvanecido suave (fade), no un barrido geométrico --
     "que las transiciones sean tranquilas, cambia de repente muy brusco". */
  position: fixed; inset: 0; background: var(--primary-dark);
  opacity: 0;
  animation: transicion-aparecer-fondo 1.1s ease-out forwards;
  /* Cuando el destino es SIGEM (otro color), este MISMO fondo cambia de
     color en el lugar -- pedido explícito: "que se transforme, no que el
     verde se deslice de izquierda a derecha tapando el azul". JS
     (transicionSalida) le cambia background-color directo, esta transición
     hace que el cambio se vea como un degradé suave, no un corte. */
  transition: background-color 1.8s ease-in-out;
  will-change: opacity, background-color;
}
@keyframes transicion-aparecer-fondo { to { opacity: 1; } }
/* El degradé REAL de la portada de SIGEM (mismo .launcher-shell de
   SIGEM/public/assets/css/app.css, copiado tal cual) -- pedido explícito:
   "el verde tiene que terminar siendo el mismo de ahora en SIGEM en la
   portada". Arranca invisible (estamos en el módulo, no en SIGEM) y aparece
   recién si el destino es SIGEM -- ver JS (transicionSalida), que le anima
   la opacidad al mismo tiempo que cambia el color de fondo. */
.transicion-fondo-sigem {
  position: fixed; inset: 0; z-index: 0;
  background:
    radial-gradient(560px 420px at 30% 20%, rgba(76, 139, 132, .35), transparent 60%),
    radial-gradient(480px 480px at 80% 85%, rgba(201, 138, 62, .18), transparent 55%);
  opacity: 0;
  transition: opacity 1.8s ease-in-out;
  will-change: opacity;
}
/* Manchas decorativas -- círculos sueltos en algunas esquinas, mismo azul
   pero en un tono más claro, bien difuminados. Nada de líneas ni patrones
   que cubran toda la pantalla (ver mismo ajuste en SIGEM/views/entrando.php). */
.transicion-mancha {
  position: fixed; z-index: 1; border-radius: 50%;
  background: var(--primary-light);
  opacity: 0; filter: blur(40px);
  animation: transicion-aparecer-mancha 1.2s ease-out .3s forwards;
  will-change: opacity;
}
@keyframes transicion-aparecer-mancha { to { opacity: .22; } }
.transicion-mancha-1 { width: 260px; height: 260px; top: -80px; left: -80px; }
.transicion-mancha-2 { width: 200px; height: 200px; bottom: -60px; right: -40px; }
.transicion-mancha-3 { width: 140px; height: 140px; bottom: 15%; left: 8%; }
.transicion-contenido {
  position: relative; z-index: 2; text-align: center; color: #fff;
  opacity: 0; animation: transicion-aparecer .4s ease-out .5s forwards;
}
@keyframes transicion-aparecer { to { opacity: 1; } }
/* Late suave (poca escala) AL MISMO TIEMPO que emite ondas -- pedido
   explícito: "son ambas, late suave y al expandirse emite ondas, como el
   latido de un corazón" -- mismo ritmo que .transicion-onda (2s, 2 veces)
   para que se sientan sincronizados. Mismo lenguaje visual que la pantalla
   "Entrando a..." del hub (ver SIGEM/views/entrando.php). */
.transicion-icono {
  position: relative; width: 240px; height: 240px; margin: 0 auto 4px;
  display: flex; align-items: center; justify-content: center; color: #fff;
  animation: transicion-latido-suave 2s ease-in-out .3s 2;
  will-change: transform;
}
@keyframes transicion-latido-suave { 0%, 100% { transform: scale(1) translateZ(0); } 50% { transform: scale(1.06) translateZ(0); } }
.transicion-icono svg { width: 110px; height: 110px; position: relative; z-index: 1; }
.transicion-icono img { max-width: 220px; max-height: 220px; width: auto; height: auto; position: relative; z-index: 1; }
/* Tamaño base ya más grande que el ícono (240px, radio 120px) para que la
   onda arranque JUSTO en su borde y crezca siempre hacia afuera -- nunca
   empieza más chica ni cruza por encima del ícono (pedido explícito: "que
   el logo siempre esté limpio"). Menos visibles -- pedido explícito: "deben
   ser menos visibles" (opacidad inicial .32, no .55; borde más fino). */
.transicion-onda {
  position: absolute; top: 50%; left: 50%; width: 240px; height: 240px;
  margin: -120px 0 0 -120px; border-radius: 50%;
  border: 1.5px solid rgba(255,255,255,.32);
  animation: transicion-onda-expandir 2s ease-out .3s 2;
  will-change: transform, opacity;
}
.transicion-onda:nth-child(2) { animation-delay: 1.3s; }
@keyframes transicion-onda-expandir { 0% { transform: scale(1) translateZ(0); opacity: .32; } 100% { transform: scale(1.5) translateZ(0); opacity: 0; } }
/* Tipografía del sistema, más liviana (600, no 800) -- pedido explícito:
   "más profesional, tipografía más de sistemas, no tan grueso". */
.transicion-contenido h1 {
  margin: 8px 0 0;
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  font-size: 19px; font-weight: 600; letter-spacing: -.1px;
}
@media (prefers-reduced-motion: reduce) {
  .transicion-barrido, .transicion-contenido, .transicion-icono { animation: none; opacity: 1; transform: none; }
  .transicion-mancha, .transicion-onda { animation: none; opacity: 0; }
}

.chart-wrap { position: relative; height: 260px; }
.chart-tooltip {
  position: absolute; top: 0; left: 0; pointer-events: none;
  background: #fff; border-radius: var(--radius-md); box-shadow: var(--shadow-md);
  border: 1px solid var(--border); padding: 10px 14px; min-width: 168px;
  opacity: 0; transition: opacity .1s ease;
  z-index: 5;
  /* --tooltip-gap: separación real hasta el punto, calculada en JS a partir
     del radio del ícono de ese día (ver dibujar() en gestion/detalle.php) --
     pedido explícito del usuario: "no me deja ver el ícono, que el
     mensajito esté por encima de cualquier ícono". Sin ícono ese día,
     JS no toca la variable y se usa el valor por default de acá (12px). */
  transform: translateY(calc(-100% - var(--tooltip-gap, 12px)));
}
.chart-tooltip::after {
  /* --flecha-x: distancia desde el borde izquierdo del recuadro hasta el
     punto real del gráfico -- se recalcula en JS en cada movimiento, así la
     flecha sigue apuntando al dato correcto aunque el recuadro se desplace
     para no salirse del gráfico (ver dibujar() en gestion/detalle.php). */
  content: ''; position: absolute; top: 100%; left: var(--flecha-x, 50%); transform: translateX(-50%);
  border: 6px solid transparent; border-top-color: #fff;
}
.chart-tooltip-fecha { font-family: var(--font-heading); font-size: 12.5px; font-weight: 700; color: var(--text); margin-bottom: 6px; }
.chart-tooltip-fila { display: flex; align-items: center; justify-content: space-between; gap: 14px; font-size: 12.5px; color: var(--text-muted); padding: 2px 0; }
.chart-tooltip-fila strong { color: var(--text); font-weight: 700; }
.chart-tooltip-fila .punto { width: 8px; height: 8px; border-radius: 50%; display: inline-block; margin-right: 6px; }
.chart-tooltip-fila-total { border-top: 1px solid var(--border); margin-top: 4px; padding-top: 6px; }
.chart-tooltip-fila-total strong { font-size: 13.5px; }
/* Fila de eventos (WhatsApp/mail/intimación/Veraz) del tooltip -- pedido
   explícito del usuario: "la leyenda de abajo que tenga algún fondo que me
   permita verla con mayor detenimiento", después "fondo en amarillo para
   que me llame la atención" y finalmente "letras en negro para que me
   llame la atención verlo" -- var(--warning-bg) resultó demasiado pálido
   para leerse como "amarillo" a simple vista, así que acá se usa un
   amarillo más saturado (no una variable del tema, es a propósito un
   llamado de atención puntual, no un estado "warning" más) con texto en
   --text (casi negro) en vez de --warning (marrón), para el contraste más
   alto posible.
*/
.chart-tooltip-evento {
  margin-top: 6px; padding: 6px 10px; border-radius: 8px;
  background: #FFE168; color: var(--text); font-weight: 700; font-size: 12px;
}

.color-dot { width: 11px; height: 11px; border-radius: 50%; display: inline-block; flex-shrink: 0; border: 1px solid rgba(0,0,0,.08); }

.now-card {
  border-radius: var(--radius-md);
  padding: 14px 16px;
  border: 1px solid var(--border);
  border-left-width: 4px;
  display: flex;
  flex-direction: column;
  gap: 4px;
  background: #fff;
  transition: box-shadow .15s, transform .15s;
}
a.now-card:hover {
  box-shadow: var(--shadow-md);
  transform: translateY(-1px);
  border-color: var(--border);
}
.now-list { display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); gap: 12px; }
.now-title { font-family: var(--font-heading); font-weight: 700; font-size: 13.5px; color: var(--text); }
.now-meta { font-size: 11.5px; color: var(--text-secondary); }

/* ===== Asistencia: lista interactiva con autoguardado ===== */

.asist-resumen {
  display: flex; align-items: center; justify-content: space-between; gap: 14px;
  background: linear-gradient(155deg, var(--primary-dark), var(--primary));
  border-radius: var(--radius-lg);
  padding: 20px 24px;
  color: #fff;
  margin-bottom: 18px;
  box-shadow: var(--shadow-md);
  flex-wrap: wrap;
}
.asist-resumen-fecha { display: flex; flex-direction: column; gap: 8px; }
.asist-resumen-fecha input[type="date"] {
  background: rgba(255,255,255,.12); border: 1px solid rgba(255,255,255,.24); color: #fff;
  font-family: var(--font-heading); font-weight: 600; font-size: 14px; width: auto;
}
.asist-resumen-fecha input[type="date"]::-webkit-calendar-picker-indicator { filter: invert(1); }
.asist-resumen-nav { display: flex; gap: 6px; }
.asist-resumen-nav button {
  background: rgba(255,255,255,.14); border: 1px solid rgba(255,255,255,.22); color: #fff;
  width: 30px; height: 30px; border-radius: 8px; cursor: pointer; display: flex; align-items: center; justify-content: center;
}
.asist-resumen-nav button:hover { background: rgba(255,255,255,.24); }
.asist-resumen-total { text-align: right; }
.asist-resumen-total .valor { font-family: var(--font-heading); font-size: 32px; font-weight: 800; letter-spacing: -.5px; line-height: 1; }
.asist-resumen-total .etiqueta { font-size: 11.5px; color: rgba(255,255,255,.7); margin-top: 4px; }

.asist-lista { display: flex; flex-direction: column; gap: 8px; }
.asist-row {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 10px 14px; border: 1px solid var(--border-soft); border-radius: var(--radius-md);
  transition: background .15s, border-color .15s;
}
.asist-row.is-presente { background: var(--success-bg); border-color: #CFE8D6; }
.asist-row.is-ausente { background: var(--danger-bg); border-color: #F2D3D2; }
.asist-persona { display: flex; align-items: center; gap: 12px; min-width: 0; }
.asist-avatar {
  width: 34px; height: 34px; border-radius: 50%; flex-shrink: 0;
  background: var(--primary-bg); color: var(--primary-dark);
  display: flex; align-items: center; justify-content: center;
  font-family: var(--font-heading); font-size: 12.5px; font-weight: 700;
}
.asist-nombre { font-size: 13.5px; font-weight: 600; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.asist-controles { display: flex; align-items: center; gap: 8px; flex-shrink: 0; }
.asist-btn {
  border: 1.5px solid var(--border); background: #fff; color: var(--text-secondary);
  font-family: var(--font-heading); font-size: 12px; font-weight: 700;
  padding: 8px 14px; border-radius: 999px; cursor: pointer;
  display: inline-flex; align-items: center; gap: 6px;
  transition: background .12s, border-color .12s, color .12s, transform .08s;
}
.asist-btn:active { transform: scale(.96); }
.asist-btn.asist-presente.active { background: var(--success); border-color: var(--success); color: #fff; }
.asist-btn.asist-ausente.active { background: var(--danger); border-color: var(--danger); color: #fff; }
.asist-guardado {
  color: var(--success); opacity: 0; transition: opacity .2s; display: inline-flex; width: 16px; height: 16px;
}
.asist-guardado.show { opacity: 1; }

.asist-historial { display: flex; gap: 8px; flex-wrap: wrap; }
.asist-historial a { text-decoration: none; }

/* ===== Modal de confirmación (reemplaza el confirm() feo del navegador) ===== */

.modal-overlay {
  position: fixed; inset: 0; z-index: 3000;
  background: rgba(15, 23, 27, .45);
  backdrop-filter: blur(2px);
  display: flex; align-items: center; justify-content: center;
  padding: 20px;
  animation: modal-fade .12s ease-out;
}
@keyframes modal-fade { from { opacity: 0; } to { opacity: 1; } }
.modal-box {
  background: #fff;
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  padding: 26px;
  max-width: 400px;
  width: 100%;
  text-align: center;
  /* Sin esto, un modal con una lista larga (ej. elegir actividad al tomar
     asistencia de un día con muchas clases) se corta contra los bordes de la
     pantalla sin ninguna forma de ver el resto. */
  max-height: calc(100vh - 40px);
  overflow-y: auto;
}
.modal-icon {
  width: 46px; height: 46px; border-radius: 50%; margin: 0 auto 14px;
  background: var(--danger-bg); color: var(--danger);
  display: flex; align-items: center; justify-content: center;
}
.modal-title { font-family: var(--font-heading); font-size: 16px; font-weight: 700; color: var(--text); margin: 0 0 8px; }
.modal-msg { font-size: 13.5px; color: var(--text-secondary); line-height: 1.55; margin: 0 0 22px; }
.modal-actions { display: flex; justify-content: center; gap: 10px; }

/* Variante ancha y alineada a la izquierda, para previsualizar contenido
   real (ej. "así queda el mail antes de mandarlo", como el compose de Gmail)
   en vez del mensaje corto centrado de .modal-box normal. */
/* 700px, no 620px -- bug real encontrado 2026-09-22: la vista previa del
   mail (ver #previewCuerpo en whatsapp/index.php) reusa el HTML EXACTO que
   se manda por email real, con una tabla de 600px de ancho fijo (necesario
   para que se vea bien en clientes de correo reales). Hay DOS paddings
   anidados entre el borde del modal y esa tabla: 22px de .modal-box-ancho +
   16px de #previewCuerpo = 38px de cada lado, 76px en total -- con 620px de
   modal quedaban solo 544px útiles para una tabla de 600px, muy por debajo;
   700px deja 624px útiles, con margen real de sobra. */
.modal-box-ancho { max-width: 700px; text-align: left; padding: 22px; }

/* Tooltip liviano para ayuda contextual (sin JS) */
.help-hint { position: relative; display: inline-flex; cursor: help; color: var(--text-muted); }
.help-hint:hover { color: var(--primary); }
.help-hint .help-tip {
  position: absolute; bottom: 130%; left: 50%; transform: translateX(-50%);
  background: var(--text); color: #fff; font-size: 11px; font-weight: 500;
  padding: 8px 10px; border-radius: 7px; white-space: normal; width: 220px;
  opacity: 0; pointer-events: none; transition: opacity .15s; z-index: 20;
  box-shadow: var(--shadow-md); line-height: 1.4;
}
.help-hint:hover .help-tip { opacity: 1; }

/* Placa con iniciales mientras no hay logo real cargado en assets/img/logo.png */
.logo-placeholder {
  font-family: var(--font-heading); font-weight: 800; font-size: 30px;
  color: var(--primary-dark); letter-spacing: -.5px;
}

/* Cinta de indicadores económicos (dólar, inflación) arriba de cada pantalla,
   estilo "zócalo" de noticiero — texto duplicado + animación continua para que
   no se note el corte cuando vuelve a empezar. */
.ticker-economico {
  background: var(--primary-dark); color: #fff; overflow: hidden;
  white-space: nowrap; height: 30px; display: flex; align-items: center;
}
.ticker-economico-track {
  display: inline-flex; gap: 0; animation: ticker-economico-desplazar 45s linear infinite;
}
.ticker-economico-track span {
  padding-right: 48px; font-size: 12px; font-weight: 500; letter-spacing: .2px;
}
@keyframes ticker-economico-desplazar {
  from { transform: translateX(0); }
  to { transform: translateX(-50%); }
}
@media (prefers-reduced-motion: reduce) {
  .ticker-economico-track { animation: none; overflow-x: auto; }
}

/* Switch deslizable NO/SÍ -- pedido explícito del usuario 2026-09-20: "que
   sea un botón que está como en No rojito y cuando lo selecciono se
   desliza y pinta de verde poniendo sí" (ver "Replicar a todos los
   imponibles del mismo CUIM" en gestion/detalle.php). Checkbox real debajo
   (accesible, funciona con teclado) visualmente oculto -- el track+thumb
   de acá abajo es puramente decorativo, refleja su estado con :checked. */
/* flex-direction: row -- bug real encontrado 2026-09-21: el <label> genérico
   de la app (usado en todos los "Etiqueta arriba, campo abajo") pone
   flex-direction: column por default; .toggle-switch pisaba el display pero
   no la dirección, así que la perilla y el texto quedaban apilados en vez
   de uno al lado del otro ("podemos poner el botón al lado de la leyenda"). */
.toggle-switch { display: inline-flex; flex-direction: row; align-items: center; gap: 8px; cursor: pointer; user-select: none; font-size: 12px; color: var(--text); }
.toggle-switch input { position: absolute; opacity: 0; width: 0; height: 0; }
.toggle-switch-track {
  position: relative; width: 50px; height: 26px; border-radius: 999px; flex-shrink: 0;
  background: var(--danger); transition: background .2s ease;
  box-shadow: inset 0 1px 2px rgba(0,0,0,.15);
}
.toggle-switch-thumb {
  position: absolute; top: 3px; left: 3px; width: 20px; height: 20px; border-radius: 50%;
  background: #fff; box-shadow: 0 1px 3px rgba(0,0,0,.3); transition: transform .2s ease; z-index: 2;
}
.toggle-switch-text {
  position: absolute; top: 50%; transform: translateY(-50%); font-size: 9px; font-weight: 700;
  color: rgba(255,255,255,.95); letter-spacing: .2px; transition: opacity .15s ease;
}
/* Geometría corregida 2026-09-21: el texto quedaba TAPADO por la perilla
   -- pedido explícito del usuario: "el SI y NO no se ven". La perilla
   ocupa 3-23px apagada y 27-47px prendida (en una pista de 50px); el
   texto tiene que ir en la zona LIBRE, del lado OPUESTO a donde está la
   perilla en cada estado, no del mismo lado. */
.toggle-switch-text-off { right: 6px; left: auto; opacity: 1; }
.toggle-switch-text-on { left: 6px; right: auto; opacity: 0; }
.toggle-switch input:checked + .toggle-switch-track { background: var(--success); }
.toggle-switch input:checked + .toggle-switch-track .toggle-switch-thumb { transform: translateX(24px); }
.toggle-switch input:checked + .toggle-switch-track .toggle-switch-text-off { opacity: 0; }
.toggle-switch input:checked + .toggle-switch-track .toggle-switch-text-on { opacity: 1; }
.toggle-switch input:focus-visible + .toggle-switch-track { outline: 2px solid var(--primary); outline-offset: 2px; }

/* Cartel centrado de estado (enviando/éxito/error) -- pedido explícito del
   usuario 2026-09-21: "que aparezca un cartelito en el medio de mi
   pantalla con un tilde, MAIL ENVIADO CORRECTAMENTE" y, para cuando falla o
   tarda, "poner un cartel de enviando" en vez de saltar directo a un
   estado que no es real. Un solo overlay reusable, cambia de contenido
   según el estado -- ver JS en views/whatsapp/index.php. */
.toast-centro-fondo {
  position: fixed; inset: 0; background: rgba(15,23,42,.35); z-index: 1000;
  display: flex; align-items: center; justify-content: center;
  opacity: 0; pointer-events: none; transition: opacity .15s ease;
}
.toast-centro-fondo.activo { opacity: 1; pointer-events: auto; }
.toast-centro {
  background: #fff; border-radius: 14px; padding: 20px 26px 22px; text-align: center;
  box-shadow: 0 12px 40px rgba(0,0,0,.25); min-width: 240px; max-width: 380px;
  transform: scale(.92); transition: transform .15s ease;
  border-top: 5px solid var(--border); /* color real lo pone la clase de estado de abajo */
}
.toast-centro-fondo.activo .toast-centro { transform: scale(1); }
/* Borde de color según estado -- pedido explícito del usuario 2026-09-21:
   "que este cartel sea más amigable, borde con colores... para todos los
   carteles de aviso". Va en la TARJETA entera (no solo en el círculo del
   ícono), así se nota de entrada qué tipo de aviso es. La advertencia usa
   rojo (--danger), no ámbar: pedido explícito ("que sea rojo, el ícono de
   advertencia no se nota nada") porque el ámbar se perdía contra el fondo. */
.toast-centro.exito { border-top-color: var(--success); }
.toast-centro.error { border-top-color: var(--danger); }
.toast-centro.cargando { border-top-color: var(--primary); }
.toast-centro.advertencia { border-top-color: var(--danger); }
.toast-centro-icono {
  width: 46px; height: 46px; border-radius: 50%; margin: 0 auto 12px;
  display: flex; align-items: center; justify-content: center; font-size: 24px; color: #fff;
}
.toast-centro-icono.exito { background: var(--success); }
.toast-centro-icono.error { background: var(--danger); }
.toast-centro-icono.cargando { background: var(--primary); }
.toast-centro-icono.advertencia { background: var(--danger); }
.toast-centro-icono.cargando svg { animation: toast-centro-girar 0.9s linear infinite; }
@keyframes toast-centro-girar { to { transform: rotate(360deg); } }
.toast-centro-texto { font-family: var(--font-heading); font-size: 14px; font-weight: 700; color: var(--text); letter-spacing: .2px; line-height: 1.4; }
.toast-centro-subtexto { font-size: 12px; color: var(--text-muted); margin-top: 5px; max-width: 320px; }
.toast-centro-botones { display: flex; gap: 10px; justify-content: center; margin-top: 16px; }

/* Confirmación "bonita" (reemplaza al confirm() nativo del navegador, feo y
   sin marca) -- pedido explícito del usuario 2026-09-21, mirando el
   confirm() nativo: "que este cartel sea más amigable, borde con colores,
   leyenda en otra letra, ícono de advertencia". Mismo lenguaje visual que
   .toast-centro (reusa esas clases de fondo/tarjeta/ícono/texto) para que
   todos los avisos del sistema se vean consistentes -- ver
   window.confirmarBonito() en app.js, disponible desde cualquier página sin
   tener que agregar HTML propio.
