:root {
  --bg:       #F1F5F9;
  --surface:  #FFFFFF;
  --resaltado: #FFFF95;
  --detalle-bg: #F8FAFC;
  --card:     #FFFFFF;
  --border:   #E2E8F0;
  --border-h: #CBD5E1;
  --accent:   #2563EB;
  --accent-l: #EFF6FF;
  --accent-m: rgba(37,99,235,.12);
  --text:     #0F172A;
  --text-2:   #334155;
  --muted:    #64748B;
  --muted-l:  #94A3B8;
  --sg:#16A34A;--sgb:#F0FDF4;--sgr:#BBF7D0;
  --sb:#2563EB;--sbb:#EFF6FF;--sbr:#BFDBFE;
  --so:#D97706;--sob:#FFFBEB;--sor:#FDE68A;
  --sr:#DC2626;--srb:#FEF2F2;--srr:#FECACA;
  --sd:#F6BC00;--sdb:#FEFCE8;--sdr:#FEF08A;
}
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

body {
  background: var(--bg);
  color: var(--text);
  font-family: 'Inter', sans-serif;
  font-size: 15px;
}

.topbar {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 0 28px;
  height: 58px;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
}
.logo {
  font-family: 'Plus Jakarta Sans', sans-serif;
  font-weight: 800;
  font-size: 1.05rem;
  letter-spacing: -0.03em;
  color: var(--text);
  text-decoration: none;
}
.logo-dot { color: var(--accent); }
.crumb {
  font-family: 'DM Mono', monospace;
  font-size: 0.78rem;
  color: var(--muted);
  padding-left: 14px;
  border-left: 1px solid var(--border);
}
.crumb > i:first-child { margin-right: 5px; }
.crumb-flecha { margin: 0 7px; font-size: 0.7em; color: var(--muted-l); }
.crumb-link { color: inherit; text-decoration: none; }
.crumb-link i:first-child { margin-right: 5px; }
.crumb-link:hover { color: var(--accent); text-decoration: underline; }
.total {
  margin-left: auto;
  font-family: 'DM Mono', monospace;
  font-size: 0.78rem;
  color: var(--muted);
}

.wrap { max-width: 1180px; margin: 0 auto; padding: 28px; }

/* ── Sidebar (dashboard autenticado) ──────────────────────────────── */
.app-shell { display: flex; min-height: 100vh; align-items: stretch; }

.sidebar {
  width: 224px;
  flex-shrink: 0;
  background: var(--surface);
  border-right: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  padding: 20px 14px;
  /* Se queda fijo al hacer scroll del contenido — `align-self:
     flex-start` es necesario porque `.app-shell` estira los hijos por
     default (`align-items: stretch`), lo que dejaría el sidebar del
     alto de `.app-main` y sticky no tendría margen para "pegarse". */
  position: sticky;
  top: 0;
  align-self: flex-start;
  height: 100vh;
  overflow-y: auto;
}
.sidebar-logo {
  font-family: 'Plus Jakarta Sans', sans-serif;
  font-weight: 800;
  font-size: 1.05rem;
  letter-spacing: -0.03em;
  color: var(--text);
  text-decoration: none;
  padding: 0 8px 20px;
}
.sidebar-logo i { color: var(--accent); margin-right: 7px; font-size: 0.92em; }
.sidebar-nav { display: flex; flex-direction: column; gap: 2px; flex: 1; }
.sidebar-link {
  display: flex;
  align-items: center;
  gap: 10px;
  font-family: 'Plus Jakarta Sans', sans-serif;
  font-size: 0.88rem;
  font-weight: 600;
  color: var(--muted);
  text-decoration: none;
  padding: 10px 12px;
  border-radius: 8px;
}
.sidebar-link i { width: 16px; text-align: center; font-size: 0.9em; }
.sidebar-link:hover { color: var(--text); background: var(--bg); }
.sidebar-link.activa { color: var(--accent); background: var(--accent-l); }

/* Botón "Configuración" — mismo look que un .sidebar-link, pero es un
   <button> (abre el modal), no un <a> con href. */
.sidebar-link-boton {
  width: 100%;
  background: none;
  border: none;
  cursor: pointer;
  text-align: left;
  font-family: inherit;
}
.sidebar-link-boton .sidebar-link-caret { margin-left: auto; width: auto; font-size: 0.65em; color: var(--muted-l); transition: transform .15s ease; }
.sidebar-link-boton.abierto { color: var(--text); background: var(--bg); }
.sidebar-link-boton.abierto .sidebar-link-caret { transform: rotate(180deg); }

/* Menú desplegable de "Configuración" — `position: fixed` y top/left
   los calcula el JS de base_v2.html (el overflow del sidebar recortaría
   un `absolute`). Grupos separados por un divisor gris tenue. */
.config-menu {
  position: fixed;
  z-index: 40;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 10px;
  box-shadow: 0 -6px 24px rgba(15, 23, 42, .10), 0 10px 28px rgba(15, 23, 42, .10);
  padding: 6px;
  animation: config-menu-entrar .12s ease-out;
}
.config-menu-abajo { animation-name: config-menu-entrar-abajo; }
@keyframes config-menu-entrar { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: none; } }
@keyframes config-menu-entrar-abajo { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: none; } }
.config-menu-grupo { display: flex; flex-direction: column; gap: 1px; }
.config-menu-divisor { border: none; border-top: 1px solid var(--border); margin: 5px 4px; }
.config-menu-item {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 8px 10px;
  border: none;
  border-radius: 7px;
  background: none;
  cursor: pointer;
  text-align: left;
  font-family: 'Inter', sans-serif;
  font-size: 0.85rem;
  color: var(--text-2);
  text-decoration: none;
  white-space: nowrap;
}
.config-menu-item i { width: 16px; text-align: center; font-size: 0.9em; color: var(--muted); }
.config-menu-item:hover, .config-menu-item:focus-visible { background: var(--bg); color: var(--text); outline: none; }
.config-menu-item:hover i, .config-menu-item:focus-visible i { color: var(--text-2); }

/* Submenú anidado bajo "Licitaciones" (Vigentes/Adjudicado/Otros) —
   "Guardadas" tenía uno igual (colapsable) pero se quitó: ahora es un
   link plano, la página misma trae sus propias tabs (feature 0027). */
.sidebar-grupo { display: flex; flex-direction: column; }
.sidebar-subnav {
  display: flex;
  flex-direction: column;
  gap: 1px;
  margin: 2px 0 4px 30px;
  border-left: 1px solid var(--border);
  padding-left: 12px;
}
.sidebar-sublink {
  display: flex;
  align-items: center;
  gap: 9px;
  font-family: 'Inter', sans-serif;
  font-size: 0.82rem;
  font-weight: 500;
  color: var(--muted);
  text-decoration: none;
  padding: 6px 8px;
  border-radius: 6px;
}
.sidebar-sublink i { width: 14px; text-align: center; font-size: 0.85em; }
.sidebar-sublink:hover { color: var(--text); background: var(--bg); }
.sidebar-sublink.activa { color: var(--accent); font-weight: 600; }

/* Mismo color por pestaña que ya usan las tarjetas de la página
   principal de Licitaciones (--sb/--sg/--so) — solo en el icono, el
   texto sigue el estado normal/hover/activo de arriba. */
.sidebar-sublink-vigentes i { color: var(--sb); }
.sidebar-sublink-adjudicado i { color: var(--sg); }
.sidebar-sublink-otros i { color: var(--so); }

/* Mismo look (ícono + nombre) que el sidebar, para la col. "Sección"
   de Guardadas > Búsquedas — mismos colores por sección (--sb/--sg/--so). */
.busqueda-seccion {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  font-family: 'Inter', sans-serif;
  font-size: 0.82rem;
  font-weight: 500;
  color: var(--muted);
}
.busqueda-seccion i { width: 14px; text-align: center; font-size: 0.85em; }
.busqueda-seccion-vigentes i { color: var(--sb); }
.busqueda-seccion-adjudicado i { color: var(--sg); }
.busqueda-seccion-otros i { color: var(--so); }

/* `margin-top: auto` empuja el divisor (y todo lo que va después,
   Configuración) hasta el fondo del sidebar sin importar el alto de
   pantalla — usa el espacio sobrante de `.sidebar-nav` (flex: 1). */
.sidebar-divisor { border: none; border-top: 1px solid var(--border); margin: auto 4px 10px; }

/* Atajos de la página principal (resumen de Licitaciones) — una
   tarjeta por pestaña. El color queda solo en el icono y en el link
   de abajo (nada de fondos sólidos de color — más sutil), reusando
   los mismos colores semánticos que ya usan los `.pill-*` de estatus
   (--sb vigente/azul, --sg adjudicado/verde, --so "otros"/ámbar) —
   ninguno nuevo. */
.v2-atajos { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; margin: 4px 0 40px; }
.v2-atajo-card {
  display: flex;
  flex-direction: column;
  gap: 16px;
  min-height: 240px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 26px 24px;
  text-decoration: none;
  box-shadow: 0 2px 10px rgba(15, 23, 42, .04);
  transition: transform .15s ease, box-shadow .15s ease, border-color .15s ease;
}
.v2-atajo-card:hover { transform: translateY(-3px); box-shadow: 0 10px 24px rgba(15, 23, 42, .10); border-color: var(--border-h); }
.v2-atajo-card-header { display: flex; align-items: center; gap: 12px; }
.v2-atajo-card-icono {
  flex: 0 0 auto;
  width: 44px;
  height: 44px;
  border-radius: 12px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.15rem;
}
.v2-atajo-card-header h3 {
  font-family: 'Plus Jakarta Sans', sans-serif;
  font-size: 1.1rem;
  font-weight: 800;
  color: var(--text);
  margin: 0;
}
.v2-atajo-card-cuerpo { display: flex; flex-direction: column; gap: 10px; flex: 1; }
.v2-atajo-card-cuerpo p {
  font-family: 'Inter', sans-serif;
  font-size: 0.86rem;
  color: var(--muted);
  margin: 0;
}
.v2-atajo-card-boton {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-family: 'Plus Jakarta Sans', sans-serif;
  font-size: 0.85rem;
  font-weight: 700;
  /* Antes `margin-top: auto` (con el párrafo en `flex:1`) empujaba el
     botón hasta el fondo de la tarjeta, dejando un hueco grande — acá
     un margen fijo lo acerca a la mitad de ese espacio, sin importar
     cuánto sobre en la tarjeta. */
  margin-top: 24px;
}
.v2-atajo-card-vigentes .v2-atajo-card-icono { background: var(--sbb); color: var(--sb); }
.v2-atajo-card-vigentes .v2-atajo-card-boton { color: var(--sb); }
.v2-atajo-card-vigentes:hover { border-color: rgba(37, 99, 235, .6); }
.v2-atajo-card-adjudicado .v2-atajo-card-icono { background: var(--sgb); color: var(--sg); }
.v2-atajo-card-adjudicado .v2-atajo-card-boton { color: var(--sg); }
.v2-atajo-card-adjudicado:hover { border-color: rgba(22, 163, 74, .6); }
.v2-atajo-card-otros .v2-atajo-card-icono { background: var(--sob); color: var(--so); }
.v2-atajo-card-otros .v2-atajo-card-boton { color: var(--so); }
.v2-atajo-card-otros:hover { border-color: rgba(217, 119, 6, .6); }

@media (max-width: 780px) {
  .v2-atajos { grid-template-columns: 1fr; }
  .v2-atajo-card { min-height: 0; }
}

/* ── Página "sin permiso" (Guardadas/Alertas/Análisis) ────────────── */
.sin-permiso {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 14px;
  max-width: 420px;
  margin: 8vh auto 0;
  padding: 32px 24px;
}
.sin-permiso h1 { font-family: 'Plus Jakarta Sans', sans-serif; font-size: 1.15rem; color: var(--text); margin: 0; }
.sin-permiso-texto { color: var(--muted); font-size: 0.9rem; line-height: 1.5; margin: 0; }
.sin-permiso-grafico { color: var(--muted-l); }
.sp-anillo { fill: none; stroke: var(--border); stroke-width: 2; }
.sp-anillo-punteado { stroke: var(--accent-m); stroke-width: 1; stroke-dasharray: 3 6; }
.sp-candado-cuerpo { fill: var(--bg); stroke: var(--muted-l); stroke-width: 2.5; }
.sp-candado-arco { fill: none; stroke: var(--muted-l); stroke-width: 2.5; }
.sp-candado-ojo { fill: none; stroke: var(--surface); stroke: var(--muted); stroke-width: 3; stroke-linecap: round; }

.app-main { flex: 1; min-width: 0; }

.topbar-slim {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 0 28px;
  height: 58px;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
}
.topbar-slim .total { margin-left: auto; }
/* En login.html el `.crumb` sigue justo al logo (border-left los
   separa) — acá en topbar-slim es el primer elemento (el logo vive en
   el sidebar), así que ese borde queda huérfano sin nada a la
   izquierda. */
.topbar-slim .crumb { padding-left: 0; border-left: none; }

.user-menu { position: relative; }
.user-menu-toggle {
  display: flex;
  align-items: center;
  gap: 8px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 5px 12px 5px 5px;
  cursor: pointer;
  font-family: 'Inter', sans-serif;
  font-size: 0.82rem;
  color: var(--text);
}
.user-menu-toggle:hover { border-color: var(--border-h); }
.user-menu-avatar {
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: var(--accent);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 0.68rem;
  flex-shrink: 0;
}
.user-menu-email { max-width: 200px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.user-menu-caret { font-size: 0.6em; color: var(--muted); }

.user-menu-dropdown {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  min-width: 170px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 10px;
  box-shadow: 0 10px 28px rgba(15, 23, 42, .14);
  padding: 6px;
  z-index: 30;
}
.user-menu-item {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 10px;
  border-radius: 7px;
  font-family: 'Inter', sans-serif;
  font-size: 0.85rem;
  color: var(--text-2);
  text-decoration: none;
}
.user-menu-item:hover { background: var(--bg); color: var(--text); }
button.user-menu-item {
  width: 100%;
  border: none;
  background: none;
  text-align: left;
  cursor: pointer;
  margin-bottom: 2px;
}

.modal-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(15, 23, 42, .45);
  align-items: center;
  justify-content: center;
  padding: 20px;
  z-index: 100;
}
/* `display: flex` SOLO cuando no está `hidden` — si se declarara en
   `.modal-backdrop` directo, le ganaría en cascada al `[hidden] {
   display: none }` del navegador (misma especificidad, esta regla
   cae después en el CSS) y el modal quedaría siempre visible sin
   importar el atributo `hidden`. */
.modal-backdrop:not([hidden]) { display: flex; }
.modal-card {
  width: 100%;
  max-width: 420px;
  max-height: 90vh;
  overflow-y: auto;
  background: var(--surface);
  border-radius: 14px;
  padding: 22px 24px 24px;
  display: flex;
  flex-direction: column;
  gap: 16px;
}
.modal-header { display: flex; align-items: center; justify-content: space-between; }
.modal-header h2 {
  font-family: 'Plus Jakarta Sans', sans-serif;
  font-size: 1.05rem;
  font-weight: 700;
  color: var(--text);
}
.modal-cerrar {
  background: none;
  border: none;
  font-size: 1.4rem;
  line-height: 1;
  color: var(--muted);
  cursor: pointer;
  padding: 2px 6px;
}
.modal-cerrar:hover { color: var(--text); }

.modal-campos-solo-lectura {
  display: flex;
  flex-direction: column;
  gap: 10px;
  background: var(--bg);
  border-radius: 10px;
  padding: 12px 14px;
}
.modal-campos-solo-lectura > div { display: flex; flex-direction: column; gap: 2px; }

.modal-card form { display: flex; flex-direction: column; gap: 12px; }
.modal-campo { display: flex; flex-direction: column; gap: 5px; }
.modal-campo input {
  font-family: 'Inter', sans-serif;
  font-size: 0.88rem;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 9px 12px;
}
.modal-card .btn-filtrar { align-self: flex-start; margin-top: 4px; }

/* Tabs del modal de Configuración (General/Plan/Datos de facturación)
   — mismo diseño que `.v2-fuentes-tab`/`.v2-fuentes-panel`
   (dashboard-v2.css), copia propia para no acoplar 2 modales
   distintos a la misma clase. */
.config-tabs {
  display: flex;
  gap: 4px;
  align-items: flex-end;
  border-bottom: solid 1px var(--border);
  margin-bottom: 0;
}
.config-tab {
  display: flex;
  align-items: center;
  gap: 8px;
  font-family: 'Plus Jakarta Sans', sans-serif;
  font-size: 0.88rem;
  font-weight: 600;
  color: var(--muted);
  background: var(--bg);
  border: 1px solid var(--border);
  border-bottom: none;
  border-radius: 8px 8px 0 0;
  padding: 10px;
  cursor: pointer;
  position: relative;
}
.config-tab:hover { color: var(--text); }
.config-tab.activa {
  background: var(--surface);
  color: var(--accent);
  z-index: 2;
  margin-bottom: -1px;
  padding-bottom: 11px;
}
.config-tab-contenido {
  background: var(--surface);
  /* border: 1px solid var(--border); */
  border-radius: 0 8px 8px 8px;
  padding: 20px 24px;
  min-height: 336px;
  display: flex;
  flex-direction: column;
  gap: 16px;
}
/* Como `.modal-backdrop:not([hidden])` arriba: al ponerle `display`
   propio, empata en especificidad con el `[hidden] { display: none }`
   del navegador y gana el nuestro por venir después en cascada — hay
   que apagarlo explícito. */
.config-tab-contenido[hidden] { display: none; }

/* Los 3 botones "Guardar" del modal de Configuración (General,
   Facturación, Notificaciones) en outline — scoped a
   `.config-tab-contenido` para no tocar `.btn-filtrar` en el resto del
   sitio (Filtrar, Guardar búsqueda, etc., que siguen sólidos). */
.config-tab-contenido .btn-filtrar {
  background: transparent;
  color: var(--accent);
  border: 1px solid var(--accent);
}
.config-tab-contenido .btn-filtrar:hover { background: var(--accent-l); }

/* Modal más ancho para acomodar los formularios en 2 columnas — clase
   propia (no se toca `.modal-card` genérico, lo comparten otros
   modales). Alto fijo en `.config-tab-contenido` (arriba) para que
   cambiar de tab no salte de tamaño; el valor cubre el tab más alto
   (Datos de facturación, 6 campos + botón en 2 columnas). */
.config-modal-card { max-width: 620px; }

.modal-card form.config-form-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px 20px;
}
.config-campo-full { grid-column: 1 / -1; }
.config-form-grid .btn-filtrar { margin-top: 4px; }
/* Botón "Guardar" de General/Datos de facturación (tabs del modal de
   Configuración) — antes se estiraba a lo ancho de toda la fila
   (`.config-campo-full` hace `grid-column: 1 / -1`, y el grid estira
   los items por default); acá se fija un ancho angosto y se empuja al
   final de la fila con `margin-left: auto`. */
.config-form-grid .btn-filtrar.config-campo-full {
  width: 110px;
  justify-self: end;
  justify-content: center;
}

.config-readonly-grid.modal-campos-solo-lectura {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px 20px;
}

.config-plan-vacio { color: var(--muted); font-size: 0.85rem; }
.config-plan-features { display: flex; flex-direction: column; gap: 6px; }
.config-plan-features-lista { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.config-plan-features-lista li { display: flex; align-items: center; gap: 8px; font-size: 0.85rem; color: var(--text-2); }
.config-plan-features-lista i { color: var(--sg); }
.config-plan-features-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 6px 20px; }
/* Feature 0106 — funciones que se dan a mano ("Bajo solicitud"). */
.config-plan-bajo-solicitud-nota { margin: 2px 0 0; font-size: 0.78rem; color: var(--text-2); }

/* Tab "Plan" rediseñado en tarjetas (antes: grid de 4 pares dl/dv
   amontonados) — resumen del plan arriba, 3 stats con icono, y un
   banner de info al final. Reusa `.config-dl` (azul) para las
   etiquetas, mismo criterio de color que el resto del modal — no se
   introduce un color nuevo solo para este tab. */
.config-plan-resumen {
  display: flex;
  align-items: center;
  gap: 14px;
  background: var(--bg);
  border-radius: 10px;
  padding: 16px;
}
.config-plan-resumen-icono {
  flex: none;
  width: 48px;
  height: 48px;
  border-radius: 50%;
  background: var(--accent-l);
  color: var(--accent);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.2rem;
}
.config-plan-resumen-texto { flex: 1; min-width: 0; }
/* Botón "Ver planes" del tab Plan — abre el overlay de Planes (feature
   0138; antes copiaba hola@convoca.mx con `.copiable`). */
button.config-plan-cambiar-btn {
  flex: none;
  font-family: 'Inter', sans-serif;
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--accent);
  background: var(--accent-l);
  border: none;
  border-radius: 8px;
  padding: 9px 16px;
  cursor: pointer;
}
button.config-plan-cambiar-btn:hover { background: var(--accent-m); }
.config-plan-resumen-texto h3 {
  margin: 2px 0 0;
  font-family: 'Plus Jakarta Sans', sans-serif;
  font-size: 1.3rem;
  font-weight: 700;
  color: var(--text);
}
.config-plan-stats { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; }
.config-plan-stat {
  display: flex;
  flex-direction: column;
  gap: 4px;
  background: var(--bg);
  border-radius: 10px;
  padding: 14px;
}
.config-plan-stat-header { display: flex; align-items: center; gap: 8px; }
.config-plan-stat-icono {
  flex: none;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: var(--accent-l);
  color: var(--accent);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 0.78rem;
}
.config-plan-stat-num {
  font-family: 'Plus Jakarta Sans', sans-serif;
  font-size: 1.4rem;
  font-weight: 700;
  color: var(--text);
  text-align: center;
}
.config-plan-stat p { margin: 0; font-size: 0.76rem; line-height: 1.3; color: var(--muted); text-align: center; }
.config-plan-info {
  display: flex;
  gap: 10px;
  align-items: flex-start;
  background: var(--accent-l);
  border-radius: 10px;
  padding: 12px 14px;
}
.config-plan-info i { color: var(--accent); margin-top: 2px; }
.config-plan-info strong { display: block; font-size: 0.85rem; color: var(--text); margin-bottom: 2px; }
.config-plan-info p { margin: 0; font-size: 0.8rem; color: var(--text-2); }
.config-plan-info p a { color: var(--accent); font-weight: 600; text-decoration: none; }
.config-plan-info p a:hover { text-decoration: underline; }

/* Asientos de equipo (feature 0061) — reemplaza stats/Incluye/info
   del tab Plan solo para planes con limite_usuarios > 1 (Business).
   Misma fila para todos los estados (`.config-plan-asiento-fila`),
   solo cambia el color del borde izquierdo por estado — nunca se
   muestra identidad, solo estado. */
.config-plan-asientos-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 10px; }
.config-plan-asiento-agregar-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: 'Inter', sans-serif;
  font-size: 0.82rem;
  font-weight: 600;
  color: #fff;
  background: var(--accent);
  border: none;
  border-radius: 8px;
  padding: 7px 14px;
  cursor: pointer;
}
.config-plan-asiento-agregar-btn:hover { background: #1D4ED8; }
.config-plan-asientos-lista { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.config-plan-asiento-fila {
  display: flex;
  align-items: center;
  gap: 10px;
  background: var(--bg);
  border-left: 3px solid var(--border-h);
  border-radius: 8px;
  padding: 10px 14px;
}
.config-plan-asiento-fila--principal { border-left-color: var(--accent); }
.config-plan-asiento-fila--activo { border-left-color: var(--sg); }
.config-plan-asiento-fila--pendiente { border-left-color: var(--so); }
.config-plan-asiento-numero { font-size: 0.85rem; font-weight: 600; color: var(--text); flex: none; }
.config-plan-asiento-estado { flex: 1; font-size: 0.82rem; color: var(--text-2); }
.config-plan-asiento-fila--principal .config-plan-asiento-estado i { color: var(--accent); }
.config-plan-asiento-fila--activo .config-plan-asiento-estado i { color: var(--sg); }
.config-plan-asiento-fila--pendiente .config-plan-asiento-estado i { color: var(--so); }
.config-plan-asiento-fila--disponible .config-plan-asiento-estado { color: var(--muted); }
.config-plan-asiento-remover-btn {
  flex: none;
  width: 26px;
  height: 26px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--muted);
  background: transparent;
  border: none;
  border-radius: 50%;
  cursor: pointer;
  font-size: 0.8rem;
}
.config-plan-asiento-remover-btn:hover { color: var(--sr); background: var(--srb); }

/* Tab "Notificaciones" — correo + botón en una sola línea (el botón
   solo tan ancho como su contenido, el correo se lleva el resto). */
.config-campo-inline { display: flex; align-items: flex-end; gap: 10px; }
.config-campo-inline-input { flex: 1; min-width: 0; }
#form-notificaciones .config-campo-inline-btn { flex: none; white-space: nowrap; align-self: flex-end; margin-top: 0; }

/* Tab "Notificaciones" — vinculación de Telegram (solo UI por ahora,
   el bot @convoca_mx_bot todavía no tiene backend real detrás). */
.config-telegram { border-top: 1px solid var(--border); padding-top: 16px; display: flex; flex-direction: column; gap: 12px; }
.config-telegram-encabezado { display: flex; align-items: center; gap: 10px; }
.config-telegram-qr { display: flex; gap: 16px; align-items: center; background: var(--bg); border-radius: 10px; padding: 14px; }
.config-telegram-qr-img, .config-telegram-logo { width: 140px; height: 140px; border-radius: 8px; flex: none; }
.config-telegram-texto { flex: 1; font-size: 0.84rem; color: var(--text-2); line-height: 1.45; margin: 0; }
.config-telegram-desvincular-form { margin-left: auto; }
.config-telegram-desvincular-btn {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-family: 'Inter', sans-serif;
  font-size: 0.74rem;
  font-weight: 600;
  color: var(--muted);
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 4px 9px;
  cursor: pointer;
}
.config-telegram-desvincular-btn:hover { color: var(--text); }

/* Etiquetas del modal de Configuración en azul (`--accent`) en vez del
   ámbar de `.dl` compartido — clase propia a propósito, para no
   cambiarle el color a `.dl` en el resto de pantallas (ficha, guardadas,
   etc.) que sí lo esperan ámbar. */
.config-dl { color: var(--accent); }

/* Texto de los inputs del modal de Configuración un poco menos oscuro
   que `--text` (casi negro) — solo acá, `.modal-campo input` en el
   resto de modales se queda igual. */
#config-modal .modal-campo input { color: var(--text-2); }

/* Fila de acciones del modal "Cambiar nombre" — "Guardar" (mismo
   `.btn-filtrar` sólido de siempre) al final, "Cancelar" (gris,
   `.btn-secundario`) a su izquierda; mismo patrón que
   `.modal-confirmar-acciones` del modal de confirmar-quitar. */
#renombrar-busqueda-form .modal-confirmar-acciones .btn-filtrar { margin-top: 0; }

@media (max-width: 780px) {
  .app-shell { flex-direction: column; min-height: 0; }
  .sidebar {
    width: auto;
    height: auto;
    flex-direction: row;
    align-items: center;
    padding: 10px 14px;
    gap: 4px;
    overflow-x: auto;
    overflow-y: visible;
  }
  .sidebar-logo { padding: 0 12px 0 0; }
  .sidebar-nav { flex-direction: row; flex: 0 0 auto; }
  .topbar-slim .crumb { display: none; }
  .user-menu-email { display: none; }
}

.chart-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 16px 18px;
  margin-bottom: 20px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
/* "Última actualización" por fuente, dentro de la misma tarjeta de
   "Licitaciones por fuente" — sale de `scraper_bitacora` (ver
   `Bitacora` en models.py). */
.ultima-actualizacion { padding-top: 20px; border-top: 1px solid var(--border); display: flex; flex-direction: column; gap: 8px; }
.ultima-actualizacion-lista { display: flex; flex-direction: column; gap: 5px; }
.ultima-actualizacion-fila {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  border-radius: 6px;
  transition: background-color .12s ease;
}
.ultima-actualizacion-fila:hover { background: var(--accent-l); }
.ultima-actualizacion-fila:hover .ultima-actualizacion-fuente { color: var(--text); }
.ultima-actualizacion-fila:hover .ultima-actualizacion-fecha { color: var(--accent); font-weight: 600; }
.ultima-actualizacion-fuente { font-family: 'Inter', sans-serif; font-size: 0.78rem; color: var(--text-2); }
.ultima-actualizacion-fecha { font-size: 0.76rem; color: var(--muted); }

.barchart { display: flex; flex-direction: column; gap: 8px; }
.barchart-row {
  display: grid;
  grid-template-columns: 260px 1fr 44px;
  align-items: center;
  gap: 10px;
  padding: 4px 8px;
  margin: 0 -8px;
  border-radius: 8px;
  transition: background-color .12s ease;
}
.barchart-row:hover { background: var(--accent-l); }
.barchart-row:hover .barchart-label { color: var(--text); }
.barchart-row:hover .barchart-n { color: var(--accent); font-weight: 600; }
.barchart-label { font-size: 0.8rem; color: var(--text-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.barchart-track { height: 10px; background: var(--bg); border-radius: 999px; overflow: hidden; }
.barchart-fill { height: 100%; background: var(--accent); border-radius: 999px; }
.barchart-n { font-family: 'DM Mono', monospace; font-size: 0.76rem; color: var(--muted); text-align: right; }

.ranking { list-style: none; display: flex; flex-direction: column; gap: 2px; counter-reset: rk; }
.ranking li {
  counter-increment: rk;
  display: grid;
  grid-template-columns: 22px 1fr auto;
  align-items: baseline;
  gap: 10px;
  padding: 8px 8px;
  margin: 0 -8px;
  border-radius: 8px;
  border-bottom: 1px solid var(--border);
  transition: background-color .12s ease;
}
.ranking li:last-child { border-bottom: none; }
.ranking li:hover { background: var(--accent-l); }
.ranking li::before {
  content: counter(rk) ".";
  font-family: 'DM Mono', monospace;
  color: var(--muted-l);
}
.ranking-nombre { font-size: 0.85rem; color: var(--text); font-weight: 500; text-decoration: none; }
.ranking-nombre:hover { color: var(--accent); text-decoration: underline; }
.ranking li:hover .ranking-datos { color: var(--text-2); }
.ranking-datos { font-family: 'DM Mono', monospace; font-size: 0.76rem; color: var(--muted); white-space: nowrap; }


.kpis {
  display: grid;
  grid-template-columns: repeat(2, minmax(160px, auto)) repeat(2, minmax(220px, 1fr));
  gap: 12px;
  margin-bottom: 20px;
}
.kpis-3 {
  grid-template-columns: minmax(150px, auto) minmax(150px, auto) minmax(220px, 1fr);
}
.kpi {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 14px 16px;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.kpi-label {
  font-family: 'DM Mono', monospace;
  font-size: 0.66rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--muted);
}
.kpi-value {
  font-family: 'Plus Jakarta Sans', sans-serif;
  font-size: 1.5rem;
  font-weight: 700;
  color: var(--text);
}
.kpi-chips { justify-content: flex-start; }
.chips { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 2px; }
.chip {
  font-family: 'DM Mono', monospace;
  font-size: 0.72rem;
  background: var(--accent-l);
  color: var(--accent);
  border: 1px solid var(--accent-m);
  padding: 3px 9px;
  border-radius: 999px;
}
.chip b { font-weight: 600; margin-left: 4px; }

.filters { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin-bottom: 18px; }
.filters select,
.filters .search {
  font-family: 'Inter', sans-serif;
  font-size: 0.85rem;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 8px 12px;
}
.filters .search { flex: 1 1 220px; min-width: 180px; }
.filters .search-dependencia { flex: 1 1 170px; min-width: 140px; }
.filters .search::placeholder { color: var(--muted-l); }
.btn-filtrar {
  font-family: 'Plus Jakarta Sans', sans-serif;
  font-size: 0.82rem;
  font-weight: 600;
  color: #fff;
  background: var(--accent);
  border: none;
  border-radius: 8px;
  padding: 8px 16px;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  text-decoration: none; /* también se usa como <a> (ej. cuenta_en_activacion.html) */
}
.btn-filtrar i { font-size: 0.85em; }
.limpiar {
  font-family: 'Inter', sans-serif;
  font-size: 0.8rem;
  color: var(--muted);
  text-decoration: underline;
}

.table-wrap {
  /* Sombras de scroll horizontal: dos "tapas" del color de la
     superficie (local, se mueven con el contenido) sobre dos sombras
     oscuras fijas (scroll, ancladas al borde del contenedor) — la
     sombra solo se asoma cuando la tapa se corre porque hay más
     contenido de ese lado. Técnica CSS pura, sin JS. */
  background:
    linear-gradient(to right, var(--surface) 30%, rgba(255,255,255,0)),
    linear-gradient(to left, var(--surface) 30%, rgba(255,255,255,0)) 100% 0,
    linear-gradient(to right, rgba(15,23,42,.15), rgba(15,23,42,0)),
    linear-gradient(to left, rgba(15,23,42,.15), rgba(15,23,42,0)) 100% 0;
  background-repeat: no-repeat;
  background-color: var(--surface);
  background-size: 32px 100%, 32px 100%, 12px 100%, 12px 100%;
  background-attachment: local, local, scroll, scroll;
  border: 1px solid var(--border);
  border-radius: 14px;
  overflow: auto;
}

table { width: 100%; border-collapse: collapse; font-size: 0.86rem; }
thead th {
  text-align: left;
  font-family: 'DM Mono', monospace;
  font-size: 0.68rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--muted);
  padding: 12px 16px;
  border-bottom: 1px solid var(--border);
  white-space: nowrap;
}
tbody td {
  padding: 12px 16px;
  border-bottom: 1px solid var(--border);
  color: var(--text-2);
  vertical-align: top;
}
tbody tr:last-child td { border-bottom: none; }
.mono { font-family: 'DM Mono', monospace; font-size: 0.8rem; color: var(--muted); white-space: nowrap; }
.titulo { color: var(--text); font-weight: 500; }
.empty { text-align: center; color: var(--muted); padding: 32px; }

.th-sort { color: inherit; text-decoration: none; white-space: nowrap; }
.th-sort.activa { color: var(--accent); }

.col-toggle { width: 28px; }
.chevron { display: inline-block; color: var(--muted-l); }
.lic-row { cursor: pointer; }
.lic-row:hover td { background: var(--accent-l); }
#tab-contenido-busquedas tbody tr:hover td { background: var(--accent-l); }
/* La columna "Resultados" puede tener 3 líneas (número + badge + "al
   guardar") — sin esto, las demás celdas (fecha, acciones) quedan
   ancladas arriba con espacio vacío debajo, por el
   `vertical-align: top` global de todas las tablas. */
#tab-contenido-busquedas tbody td { vertical-align: middle; }
/* Fila cuya Ficha Completa está (o estuvo) abierta — se queda marcada
   hasta que se abre otra (ver DEC-065/feature 0026), no solo mientras
   el modal está abierto. */
.lic-row.fila-activa td { background: var(--resaltado); }
/* Fila que se va a borrar — mientras el modal de confirmación está
   abierto, mismo lenguaje que el amarillo de selección pero en rojo,
   para que quede claro cuál fila disparó "Quitar"/"Borrar búsqueda". */
.fila-por-borrar td { background: var(--srr) !important; }

/* Modal de confirmación arrastrable (pedido explícito) — el header
   sirve de "asa" (cursor: move), excepto el botón de cerrar. La
   posición se resetea al cerrar (ver JS), así siempre reabre centrada. */
#confirmar-quitar-modal .modal-card { position: relative; }
#confirmar-quitar-modal .modal-header { cursor: move; user-select: none; }
#confirmar-quitar-modal .modal-header .modal-cerrar { cursor: pointer; }
/* Misma marca amarilla, pero para la fila de "última búsqueda
   ejecutada" en Guardadas — esa tabla no usa `.lic-row`. */
.busqueda-resumen { margin-top: 6px; }

/* Amarillo más tenue que `--resaltado` — solo para esta tabla, pedido
   explícito (la selección de licitaciones/ficha completa se queda
   con el amarillo original, comparten la clase `.fila-activa` pero no
   este color). */
#tab-contenido-busquedas tr.fila-activa td { background: #FBF3C7; }

/* "Quitar de guardadas" (feature 0027) — icono discreto, solo se nota
   al pasar el mouse por la fila. */
.btn-quitar-guardada {
  background: none;
  border: none;
  color: var(--muted-l);
  cursor: pointer;
  padding: 4px 6px;
  border-radius: 6px;
}
.btn-quitar-guardada:hover { color: var(--sr); background: var(--srb); }

.busqueda-acciones { display: flex; align-items: center; gap: 10px; justify-content: flex-end; }
.btn-ejecutar-busqueda {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: 'Inter', sans-serif;
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--accent);
  text-decoration: none;
}
.btn-ejecutar-busqueda:hover { text-decoration: underline; }

/* Columna "Resultados" en Guardadas > Búsquedas (feature 0028) —
   número grande (lo que más importa "ahora mismo") + badge de color
   solo si hay novedades + nota chica del conteo original al guardar,
   siempre visible. */
.busqueda-resultados { text-align: right; white-space: nowrap; }
.busqueda-resultado-num {
  display: block;
  font-family: 'DM Mono', monospace;
  font-size: 1rem;
  font-weight: 700;
  color: var(--text);
}
.busqueda-resultado-num.busqueda-resultado-vacio { color: var(--muted-l); font-weight: 400; }
.busqueda-resultado-badge {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-family: 'Inter', sans-serif;
  font-size: 0.72rem;
  font-weight: 700;
  color: var(--sg);
  background: var(--sgb);
  border: 1px solid var(--sgr);
  padding: 1px 7px;
  border-radius: 999px;
  margin-top: 2px;
}
.busqueda-resultado-badge i { font-size: 0.65rem; }
.busqueda-resultado-inicio {
  font-family: 'Inter', sans-serif;
  font-size: 0.72rem;
  color: var(--muted);
  margin-top: 2px;
}

/* Switch de "monitorear" (feature 0028) — mismo tamaño/estilo
   discreto que el resto de los botones de acción de esta fila. */
.switch-monitorear {
  position: relative;
  display: inline-block;
  width: 34px;
  height: 20px;
  flex: 0 0 auto;
  margin-right: 8px;
}
.switch-monitorear input { opacity: 0; width: 0; height: 0; }
.switch-monitorear-slider {
  position: absolute;
  inset: 0;
  background: var(--border-h);
  border-radius: 999px;
  cursor: pointer;
  transition: background .15s ease;
}
.switch-monitorear-slider::before {
  content: "";
  position: absolute;
  width: 14px;
  height: 14px;
  left: 3px;
  top: 3px;
  background: #fff;
  border-radius: 50%;
  transition: transform .15s ease;
  box-shadow: 0 1px 3px rgba(15, 23, 42, .3);
}
.switch-monitorear input:checked + .switch-monitorear-slider { background: var(--accent); }
.switch-monitorear input:checked + .switch-monitorear-slider::before { transform: translateX(14px); }
.switch-monitorear input:disabled + .switch-monitorear-slider { opacity: .6; cursor: wait; }

/* Panel de detalle expandible en Guardadas > Búsquedas — mismo patrón
   que usaba Licitaciones antes de la Ficha Completa (DEC-065/066):
   click en la fila abre un panel debajo, en vez de un modal. Reusa
   `.detalle-campos`/`.dl`/`.dv` (genéricos, ver abajo) para el
   contenido. */
.busqueda-row { cursor: pointer; }
.busqueda-row.expandida .chevron { transform: rotate(90deg); color: var(--accent); }
.busqueda-row.expandida td { background: var(--resaltado); }
.detail-row td { padding: 0; border-bottom: 1px solid var(--border); }
.detalle { padding: 16px 20px 20px 44px; background: var(--detalle-bg); }
.busqueda-acciones-detalle {
  display: flex;
  align-items: center;
  gap: 14px;
  border-top: solid 1px #eaeaea;
  padding-top: 15px;
}

/* "Cambiar nombre" + "Borrar búsqueda" — grupo de botones tipo
   Bootstrap `btn-group` + `btn-outline-*` (pedido explícito): pegados
   uno junto al otro (sin gap, el segundo se monta 1px sobre el borde
   del primero), esquinas exteriores redondeadas y esquina interior
   recta, cada botón con su propio color "outline" (azul = edición
   neutral, rojo = acción destructiva) que se invierte en hover. */
.btn-group-detalle { display: flex; margin-left: auto; }
.btn-group-detalle button {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: 'Inter', sans-serif;
  font-size: 0.82rem;
  font-weight: 600;
  padding: 6px 12px;
  background: none;
  color: var(--muted-l);
  border: 1px solid var(--border);
  border-radius: 0;
  cursor: pointer;
  transition: background .15s ease, color .15s ease, border-color .15s ease;
}
.btn-group-detalle button:first-child { border-radius: 8px 0 0 8px; }
.btn-group-detalle button:last-child { border-radius: 0 8px 8px 0; margin-left: -1px; }
.btn-group-detalle button:hover { position: relative; z-index: 1; }

.btn-group-detalle .btn-renombrar-busqueda:hover { color: var(--accent); background: var(--accent-l); border-color: var(--accent-m); }
.btn-group-detalle .btn-quitar-guardada:hover { color: var(--sr); background: var(--srb); border-color: var(--srr); }

/* Columna "Alertas" (pedido explícito) — separa "prender/apagar el
   monitoreo" de "ejecutar"/"quitar", que ahora viven en el panel de
   detalle. Hoy solo controla `monitorear` (recalcular conteo); enviar
   notificaciones de verdad es la otra mitad de "Alertas", todavía sin
   construir. El botón de la fila muestra una pill Sí/No explícita
   (antes era solo una campanita, se quitó a pedido explícito — más
   claro sin tener que aprenderse qué color significa qué). */
.col-alertas { width: 74px; text-align: center; }
.btn-alerta {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: none;
  border: none;
  color: var(--muted-l);
  cursor: pointer;
  padding: 6px 8px;
  border-radius: 8px;
  font-size: 1rem;
}
.btn-alerta:hover { background: var(--accent-l); color: var(--accent); }
.btn-alerta-activa { color: var(--accent); }
.btn-alerta-activa:hover { background: var(--accent-m); }

/* Variante con texto del mismo botón (panel de detalle de Guardadas >
   Búsquedas, ver `.detalle-campos` "Alerta") — la campanita +
   "Configurar" del panel de detalle. */
.btn-alerta-detalle {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: 'Inter', sans-serif;
  font-size: 0.78rem;
  font-weight: 600;
  padding: 3px 10px 3px 8px;
  margin-left: 6px;
}

.alertas-nombre-busqueda { color: var(--muted); font-size: 0.85rem; font-weight: 600; margin-bottom: 14px; }
.alertas-fila-switch { display: flex; align-items: center; gap: 12px; }
.alertas-fila-switch .switch-monitorear { margin-right: 0; }
.alertas-fila-switch span { white-space: nowrap; }

/* Checklist de canales de aviso (E-mail/Telegram/WhatsApp) — solo
   visual por ahora, todavía no hay envío real de notificaciones (la
   segunda mitad de "Alertas", ver sdd/features/0028-monitor-busquedas.md). */
.alertas-canales {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 18px;
  padding-top: 16px;
  border-top: 1px solid var(--border);
}
.alertas-canales-titulo {
  font-family: 'DM Mono', monospace;
  font-size: 0.68rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--muted);
  margin-bottom: 2px;
}
.alertas-canal {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 0.88rem;
  color: var(--text-2);
  cursor: pointer;
  padding: 6px 8px;
  margin: 0 -8px;
  border-radius: 8px;
  transition: background .15s ease;
}
.alertas-canal:hover { background: var(--bg); }
.alertas-canal input[type="checkbox"] {
  width: 16px;
  height: 16px;
  accent-color: var(--accent);
  cursor: pointer;
}
.alertas-canal i { width: 16px; text-align: center; color: var(--muted); }
/* Correo destino junto a "E-mail" — solo lectura, apagado; los correos
   largos se cortan con "…" en vez de romper la fila. */
.alertas-canal-destino {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 0.8rem;
  color: var(--muted);
}
.alertas-canal-deshabilitado { cursor: not-allowed; opacity: 0.5; }
.alertas-canal-deshabilitado:hover { background: none; }
.alertas-canal-deshabilitado input[type="checkbox"] { cursor: not-allowed; }
/* Canal que el plan no incluye (feature 0139): sigue apagado, pero el click
   abre el overlay de Planes. `pointer-events: none` en el checkbox
   deshabilitado para que el click siempre caiga en el label. */
.alertas-canal-bloqueado-plan { cursor: pointer; }
.alertas-canal-bloqueado-plan input[type="checkbox"] { pointer-events: none; }
.alertas-canal-candado { font-size: 0.72rem; color: var(--muted); margin-left: 2px; }
/* Un poco más ancho que el genérico `.modal-card-chica` (360px) —
   para que "Avisarme cuando haya resultados nuevos" quepa junto al
   switch en una sola línea. */
#alertas-modal .modal-card-chica { max-width: 420px; }
#confirmar-quitar-modal .modal-header h2 { color: var(--sr); }

.detalle-campos {
  display: grid;
  /* Antes `repeat(auto-fill/auto-fit, minmax(200px, 1fr))` — genérico
     para cualquier cantidad de campos, pero con pocos campos dejaba un
     bloque entero en blanco a la derecha (`auto-fill` reserva las
     columnas vacías igual; `auto-fit` las colapsa, pero un campo con
     `1 / -1` cuenta como "tocando" todas las columnas que el navegador
     generó antes de colapsar, así que tampoco colapsaban — mismo bug,
     ver captura del usuario). 3 columnas fijas, pedido explícito para
     Guardadas > Búsquedas (Guardada / Total de resultados / Alerta en
     la fila 1, Filtros abajo ocupando las 3 porque su lista puede
     crecer) — siempre reparten el ancho completo, sin huecos. */
  grid-template-columns: repeat(3, minmax(200px, 1fr));
  gap: 12px 20px;
  margin-bottom: 14px;
}
.detalle-campos > div { display: flex; flex-direction: column; gap: 2px; }
/* "Filtros" en el detalle de Guardadas > Búsquedas — a diferencia del
   resumen compacto de la fila (que sí puede recortarse visualmente si
   son muchos filtros), acá ocupa toda la fila (las 3 columnas) como un
   párrafo corrido, uno seguido de otro con coma — no en columnas ni
   apilados uno por línea (ambos se probaron, pedido explícito del
   usuario tras verlos: se veían raros/desperdiciaban espacio) — y usa
   el ancho completo para bajar de línea de forma natural solo cuando
   el texto no cabe. */
.detalle-campo-ancho { grid-column: 1 / -1; }
/* La etiqueta de cada filtro (ej. "Buscar:") en negritas para separarla
   del valor, pero en `--muted` y peso 600 (no 700 default de `strong`)
   para que no compita tanto con el valor — pedido explícito, se veía
   "resaltando mucho" con el `strong` a secas. */
.detalle-filtro-etiqueta { color: var(--muted); font-weight: 600; }
.dl {
  font-family: 'DM Mono', monospace;
  font-size: 0.64rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: #E6A644;
}
.dv { font-size: 0.85rem; color: var(--text-2); }
.dv a { color: var(--accent); text-decoration: none; }
.dv-hint { display: block; font-size: 0.72rem; color: var(--muted); font-style: italic; margin-top: 2px; }

.copiable { cursor: pointer; border-bottom: 1px dashed var(--muted-l); }
.copiable:hover { color: var(--accent); border-bottom-color: var(--accent); }
.copiable.copiado { color: var(--sg); border-bottom-color: var(--sg); }

table.adjudicaciones {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.82rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 10px;
  overflow: hidden;
}
table.adjudicaciones th {
  text-align: left;
  font-family: 'DM Mono', monospace;
  font-size: 0.66rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--muted);
  padding: 8px 12px;
  border-bottom: 1px solid var(--border);
}
table.adjudicaciones td {
  padding: 8px 12px;
  border-bottom: 1px solid var(--border);
  color: var(--text-2);
}
table.adjudicaciones tr:last-child td { border-bottom: none; }
table.adjudicaciones a { color: var(--accent); text-decoration: none; }
.monto-resaltado { color: var(--accent); font-weight: 700; }
.ganador-resaltado { color: var(--accent); font-weight: 600; }
.sin-adjudicacion { font-size: 0.82rem; color: var(--muted); font-style: italic; }

.tag-fuente {
  font-family: 'DM Mono', monospace;
  font-size: 0.72rem;
  background: var(--accent-l);
  color: var(--accent);
  border: 1px solid var(--accent-m);
  padding: 2px 8px;
  border-radius: 999px;
}

.pill {
  display: inline-block;
  font-family: 'DM Mono', monospace;
  font-size: 0.72rem;
  font-weight: 600;
  padding: 2px 9px;
  border-radius: 999px;
}
.pill-adjudicado { background: var(--sgb); color: var(--sg); border: 1px solid var(--sgr); }
.pill-vigente { background: var(--sbb); color: var(--sb); border: 1px solid var(--sbr); }
.pill-en_seguimiento { background: var(--sbb); color: var(--sb); border: 1px solid var(--sbr); }
.pill-cancelado, .pill-desierto { background: var(--srb); color: var(--sr); border: 1px solid var(--srr); }
.pill-adjudicado_parcial { background: var(--sob); color: var(--so); border: 1px solid var(--sor); }
.pill-alerta-si { background: var(--sgb); color: var(--sg); border: 1px solid var(--sgr); }
.pill-alerta-no { background: var(--border); color: var(--muted); border: 1px solid var(--border); }
/* Fila de Licitaciones al llegar desde "Ejecutar búsqueda" de una
   búsqueda guardada con licitaciones nuevas (feature 0032, DEC-071:
   `BusquedaGuardada.ids_nuevos`). Azul de marca (`--accent`), no el
   verde de `.busqueda-resultado-badge` — pedido explícito. */
.etiqueta-nueva {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-family: 'Inter', sans-serif;
  font-size: 0.68rem;
  font-weight: 700;
  color: var(--accent);
  background: var(--accent-l);
  border: 1px solid var(--accent-m);
  border-radius: 3px;
  padding: 1px 7px 1px 6px;
  margin-left: 6px;
  text-transform: lowercase;
  line-height: 1.6;
  white-space: nowrap;
}
.etiqueta-nueva i { font-size: 0.75em; }

.pager {
  display: flex;
  align-items: center;
  gap: 16px;
  justify-content: center;
  margin-top: 18px;
}
.pager a {
  font-family: 'Plus Jakarta Sans', sans-serif;
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--accent);
  text-decoration: none;
}
/* Tope de páginas por consulta (feature 0070) — solo en la última
   página permitida, cuando hay más resultados que el tope. */
.aviso-tope-paginas {
  text-align: center;
  margin: 10px 0 0;
  font-size: 0.82rem;
  color: var(--muted);
}
.aviso-tope-paginas i { color: var(--accent); margin-right: 4px; }

@media (max-width: 900px) {
  .kpis { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 560px) {
  .kpis { grid-template-columns: 1fr; }
}
@media (max-width: 720px) {
  /* La columna Dependencia es la que menos cabe en mobile — se
     esconde de la fila principal; el dato sigue accesible en la Ficha
     Completa (sección "Datos generales", ver DEC-065/feature 0026). */
  .col-dependencia { display: none; }
}

.logout {
  font-family: 'Inter', sans-serif;
  font-size: 0.8rem;
  color: var(--muted);
  text-decoration: none;
  margin-left: 16px;
}

.login-wrap {
  min-height: calc(100vh - 58px);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 28px;
}
.login-card {
  width: 100%;
  max-width: 360px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 28px;
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.login-card h1 {
  font-family: 'Plus Jakarta Sans', sans-serif;
  font-size: 1.3rem;
  font-weight: 800;
  color: var(--text);
}
.login-sub { font-size: 0.85rem; color: var(--muted); margin-top: -8px; }
.login-error {
  font-size: 0.82rem;
  color: var(--sr);
  background: var(--srb);
  border: 1px solid var(--srr);
  border-radius: 8px;
  padding: 8px 12px;
}
.login-mensaje {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 0.82rem;
  color: var(--sg);
  background: var(--sgb);
  border: 1px solid var(--sgr);
  border-radius: 8px;
  padding: 8px 12px;
}
.login-card label { display: flex; flex-direction: column; gap: 5px; }
.login-card input {
  font-family: 'Inter', sans-serif;
  font-size: 0.9rem;
  color: var(--text);
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 10px 12px;
}
.login-card .btn-filtrar { margin-top: 6px; padding: 10px 16px; }
.login-olvide {
  align-self: center;
  font-family: 'Inter', sans-serif;
  font-size: 0.82rem;
  color: var(--muted);
  text-decoration: none;
}
.login-olvide:hover { color: var(--accent); text-decoration: underline; }

/* Sesión única (feature 0071) — aviso de por qué se cerró la sesión
   anterior, y la tarjeta de la sesión activa en la pantalla intermedia. */
.login-aviso {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 0.82rem;
  color: var(--so);
  background: var(--sob);
  border: 1px solid var(--sor);
  border-radius: 8px;
  padding: 8px 12px;
}
/* Feature 0120 — aviso de pausa por intentos fallidos (texto largo con link). */
.login-aviso-pausa { align-items: flex-start; line-height: 1.45; }
.login-aviso-pausa i { margin-top: 3px; }
.login-aviso-pausa a { color: inherit; font-weight: 600; }
.login-sesion-activa {
  display: flex;
  align-items: center;
  gap: 12px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 12px 14px;
}
.login-sesion-activa > i { font-size: 1.2rem; color: var(--sb); }
.login-sesion-activa b { display: block; font-size: 0.9rem; color: var(--text); }
.login-sesion-activa span { font-size: 0.8rem; color: var(--muted); }

/* Aceptación de términos (feature 0080) — la casilla va en línea con su
   texto, no apilada como los demás <label> de .login-card. */
.login-card label.aceptar-terminos-check { flex-direction: row; align-items: flex-start; gap: 10px; font-size: 0.85rem; color: var(--text); line-height: 1.4; }
.login-card label.aceptar-terminos-check input { width: auto; margin-top: 3px; }

/* Magic-link (feature 0062) — mismo layout de .login-card, reusado
   para "olvidé mi contraseña" y "pon tu contraseña" (activación +
   reset, misma pantalla). */
.password-fuerza-barra {
  display: flex;
  gap: 4px;
  margin-top: -6px;
}
.password-fuerza-segmento {
  flex: 1;
  height: 4px;
  border-radius: 2px;
  background: var(--border);
  transition: background-color .15s ease;
}
.password-fuerza-texto {
  font-size: 0.76rem;
  color: var(--muted);
  margin-top: -6px;
}
.password-fuerza-texto--debil { color: var(--sr); }
.password-fuerza-texto--media { color: var(--so); }
.password-fuerza-texto--fuerte { color: var(--sg); }

/* Notificación global (feature 0027) — "ya guardada", "límite
   alcanzado", confirmaciones. Ver `window.mostrarToast` en
   base_v2.html. */
.toast {
  position: fixed;
  top: 28px;
  left: 50%;
  transform: translateX(-50%) translateY(-12px);
  background: var(--text);
  color: #fff;
  font-family: 'Inter', sans-serif;
  font-size: 0.85rem;
  font-weight: 600;
  padding: 12px 20px;
  border-radius: 10px;
  box-shadow: 0 8px 24px rgba(15, 23, 42, .25);
  z-index: 300;
  opacity: 0;
  transition: opacity .2s ease, transform .2s ease;
  max-width: min(420px, calc(100vw - 32px));
  text-align: center;
}
.toast-visible { opacity: 1; transform: translateX(-50%) translateY(0); }
.toast-exito { background: var(--sg); }
.toast-error { background: var(--sr); }
.toast i { margin-right: 6px; }

/* Tabs de Guardadas (feature 0027) — Licitaciones/Búsquedas en la
   misma página, sin recargar. */
/* Tabs tipo "carpeta" (feature 0027, referencia visual del usuario) —
   cada tab es su propia tarjeta con fondo; la activa se ve "levantada"
   y conectada al panel de contenido de abajo (mismo fondo, sin borde
   compartido — ver `.guardadas-panel`). */
.guardadas-tabs {
  display: flex;
  gap: 4px;
  align-items: flex-end;
}
.guardadas-tab {
  display: flex;
  align-items: center;
  gap: 8px;
  font-family: 'Plus Jakarta Sans', sans-serif;
  font-size: 0.88rem;
  font-weight: 600;
  color: var(--muted);
  background: var(--bg);
  border: 1px solid var(--border);
  border-bottom: none;
  border-radius: 8px 8px 0 0;
  padding: 12px 20px;
  cursor: pointer;
  position: relative;
}
.guardadas-tab:hover { color: var(--text); }
.guardadas-tab.activa {
  background: var(--surface);
  color: var(--accent);
  z-index: 2;
  /* Tapa el borde del panel justo debajo, para que se vea de una sola
     pieza (tab + panel), sin la línea divisoria entre ambos. */
  margin-bottom: -1px;
  padding-bottom: 13px;
}
.guardadas-tab-n {
  font-family: 'DM Mono', monospace;
  font-size: 0.72rem;
  background: var(--surface);
  color: var(--muted);
  padding: 1px 7px;
  border-radius: 999px;
}
.guardadas-tab.activa .guardadas-tab-n { background: var(--accent-l); color: var(--accent); }

.guardadas-panel {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 0 8px 8px 8px;
  padding: 20px;
}
.guardadas-panel .table-wrap { border: none; border-radius: 0; }

/* Modal chico de confirmación (feature 0027) — "¿Quitar de guardadas?" */
.modal-card-chica { max-width: 360px; }
.modal-confirmar-acciones { display: flex; justify-content: flex-end; gap: 10px; }
.btn-secundario {
  font-family: 'Inter', sans-serif;
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--muted);
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 8px 16px;
  cursor: pointer;
}
.btn-secundario:hover { color: var(--text); }
.btn-peligro {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: 'Inter', sans-serif;
  font-size: 0.85rem;
  font-weight: 600;
  color: #fff;
  background: var(--sr);
  border: 1px solid var(--sr);
  border-radius: 8px;
  padding: 8px 16px;
  cursor: pointer;
}
.btn-peligro:hover { background: #B91C1C; }

/* Feature 0106 — "Contactar soporte". */
.soporte-panel { max-width: 640px; display: flex; flex-direction: column; gap: 12px; }
.soporte-form { display: flex; flex-direction: column; gap: 12px; }
.soporte-form textarea {
  font-family: 'Inter', sans-serif; font-size: 0.88rem; color: var(--text); background: var(--surface);
  border: 1px solid var(--border); border-radius: 8px; padding: 8px 10px; resize: vertical;
}
.soporte-form .btn-filtrar { align-self: flex-end; }
.soporte-prioritario { margin: 0; font-size: 0.85rem; color: var(--text-2); }
.soporte-prioritario i { color: var(--accent); }
/* Tarjeta para planes sin soporte prioritario: solo el correo, sin formulario. */
.soporte-info {
  display: flex; gap: 16px; align-items: flex-start;
  background: var(--surface); border: 1px solid var(--border); border-radius: 14px; padding: 22px 24px;
}
.soporte-info-icono {
  width: 40px; height: 40px; flex-shrink: 0; border-radius: 10px;
  display: flex; align-items: center; justify-content: center;
  background: var(--accent-l); color: var(--accent);
}
.soporte-info-texto { display: flex; flex-direction: column; gap: 6px; }
.soporte-info-texto strong { font-family: 'Plus Jakarta Sans', sans-serif; font-size: 0.95rem; color: var(--text); }
.soporte-info-texto p { margin: 0; font-size: 0.88rem; line-height: 1.5; color: var(--text-2); }
.soporte-info-texto .copiable { font-weight: 600; }

/* Feature 0095 — "Tu prueba terminó". */
.prueba-card { max-width: 920px; width: 100%; }
.prueba-planes { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: 14px; margin: 18px 0 12px; }
.prueba-plan { border: 1px solid var(--border); border-radius: 12px; padding: 16px; display: flex; flex-direction: column; gap: 8px; background: var(--surface); }
.prueba-plan h2 { margin: 0; font-size: 1.05rem; }
.prueba-plan-precio { margin: 0; font-size: 1.3rem; font-weight: 700; color: var(--text); }
.prueba-plan-precio span { font-size: 0.8rem; font-weight: 400; color: var(--text-2); }
.prueba-plan ul { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 4px; flex: 1; }
.prueba-plan li { font-size: 0.82rem; color: var(--text-2); padding-left: 16px; position: relative; }
.prueba-plan li::before { content: '✓'; position: absolute; left: 0; color: var(--sg); font-weight: 700; }
.prueba-plan li.prueba-plan-bajo-solicitud::before { content: '✉'; color: var(--text-2); font-weight: 400; }
.prueba-plan li span { font-size: 0.75rem; }
.prueba-plan form .btn-filtrar { width: 100%; justify-content: center; }
.prueba-plan-elegido { opacity: 0.85; }
.prueba-nota { font-size: 0.82rem; color: var(--text-2); margin: 0; }
.prueba-salir { font-size: 0.82rem; }

/* Feature 0096 — franja de la prueba Demo. */
.aviso-prueba {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; margin: 0 0 14px; padding: 9px 14px;
  border: 1px solid var(--border); border-radius: 10px; background: var(--sob, #FFF7ED); color: var(--text); font-size: 0.85rem;
}
.aviso-prueba i { color: var(--accent); }
.aviso-prueba a { font-weight: 600; color: var(--accent); text-decoration: none; }
.aviso-prueba a:hover { text-decoration: underline; }
.aviso-prueba-solicitada { color: var(--text-2); }
