/* ===========================================================================
   PerimetroX — Portal de clientes (zona privada)
   EXTENSIÓN de assets/styles.css (cárgalo ANTES). NO redefine el diseño base:
   reutiliza tokens (:root), .shell, .btn*, .sev*, .tag, .glass, .card-hover,
   .icon-badge, .site-header/.nav-inner, .site-footer y el fondo
   (.bg-layers: mesh/grid con parallax sutil por scroll, vía assets/app.js).
   Aquí solo viven los componentes propios del panel (KPIs, tablas, hallazgos…).
   =========================================================================== */

/* ---------- Layout base del portal ----------
   Fondo transparente: lo provee .bg-layers (igual que la landing). */
.px-body {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  background: transparent;
}
/* Eleva contenido y footer por encima del fondo fijo (.bg-layers, z-index:0).
   <main> ya recibe z-index:var(--z-base) por la regla global `main{}`. */
.px-main {
  position: relative;
  z-index: var(--z-base);
  flex: 1 0 auto;
  /* deja espacio para el header flotante fijo (.site-header: top 14px + nav-h) */
  padding-top: calc(var(--nav-h) + 46px);
  padding-bottom: clamp(40px, 6vw, 72px);
}
.px-body .site-footer { position: relative; z-index: var(--z-base); }
.px-main > .shell { display: grid; gap: clamp(16px, 2.4vw, 24px); }

/* ---------- Header: usa .site-header de la landing; solo ajustes del portal ---------- */
.site-header .px-head-id {
  font-family: "JetBrains Mono", monospace;
  font-size: 12px;
  color: rgba(255, 255, 255, 0.82);
  max-width: 34ch;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.site-header .px-head-id strong { color: #fff; font-weight: 600; }
@media (max-width: 900px) { .site-header .nav-links { display: none; } }
@media (max-width: 560px) { .site-header .px-head-id { display: none; } .px-hide-sm { display: none; } }

/* Accesos del portal: son enlaces directos, no un menú desplegable. La
   navegación usa una segunda fila antes de que sus enlaces puedan invadir el
   logo, la identidad o las acciones de sesión.
   Escopado a `[data-px-page]` (solo el portal REAL autenticado, que trae
   client.js/portal.js e imprime ese atributo en <body>) y no a `.px-body`
   en general: /demo-portal.html también usa la clase `.px-body` para
   reutilizar las tarjetas/tablas de este archivo, pero reusa la MISMA
   navegación pública que el resto del sitio (sin .px-head-id ni sesión) y
   no debe partirse en una segunda fila tipo grid — eso es lo que la hacía
   "verse fea" ahí y en ningún otro lado. */
.px-body[data-px-page] .site-header .nav-links { min-width: 0; }
.px-body[data-px-page] .site-header .nav-inner {
  height: auto;
  min-height: var(--nav-h);
  flex-wrap: wrap;
  gap: 0;
  padding: 7px 12px 8px 20px;
  border-radius: 24px;
}
.px-body[data-px-page] .site-header .nav-links {
  order: 3;
  flex: 1 0 100%;
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  margin: 5px 0 0;
  padding-top: 5px;
  border-top: 1px solid rgba(255, 255, 255, 0.16);
}
.px-body[data-px-page] .site-header .nav-links > a {
  min-width: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
}
.px-body[data-px-page] .px-main { padding-top: calc(var(--nav-h) + 94px); }
.px-body[data-px-page] section[id] { scroll-margin-top: 142px; }
@media (max-width: 1080px) {
  .px-body[data-px-page] .site-header .px-head-id,
  .px-body[data-px-page] .site-header .nav-cta .btn-primary { display: none; }
  .px-body[data-px-page] .site-header .nav-links { margin: 0 4px; gap: 1px; }
  .px-body[data-px-page] .site-header .nav-links > a { padding: 8px 10px; font-size: 13px; }
}
@media (max-width: 900px) {
  .px-body[data-px-page] .site-header .nav-links { display: grid; }
}
@media (max-width: 720px) {
  .px-body[data-px-page] .site-header .nav-links {
    display: flex;
    justify-content: flex-start;
    overflow-x: auto; scrollbar-width: none; border-top: 1px solid rgba(255, 255, 255, 0.16);
  }
  .px-body[data-px-page] .site-header .nav-links::-webkit-scrollbar { display: none; }
  .px-body[data-px-page] .site-header .nav-links > a { flex: 0 0 auto; padding: 7px 10px; }
}

/* ---------- Breadcrumbs ---------- */
.px-crumbs {
  font-family: "JetBrains Mono", monospace;
  font-size: 12px;
  color: var(--text-dim);
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  align-items: center;
}
.px-crumbs a { color: var(--text-muted); }
.px-crumbs a:hover { color: var(--cyan); }
.px-crumbs .sep { opacity: 0.5; }

/* ---------- Encabezado de página ---------- */
.px-page-head { display: grid; gap: 8px; }
.px-admin-return { justify-self: start; margin-top: 6px; }
.px-h1 {
  font-family: "Space Grotesk", "Inter", sans-serif;
  font-size: clamp(26px, 4vw, 38px);
  font-weight: 600;
  line-height: 1.1;
}
.px-h2 {
  font-family: "Space Grotesk", "Inter", sans-serif;
  font-size: clamp(18px, 2.4vw, 22px);
  font-weight: 600;
}
.px-lead { color: var(--text-muted); max-width: 70ch; }
.px-muted { color: var(--text-muted); }
.px-mono { font-family: "JetBrains Mono", monospace; }
.px-mt { margin-top: 12px; }
.px-mt-lg { margin-top: 16px; }
/* Inventario: control "Mostrar más" (paginacion incremental por seccion). */
.px-inventory-more { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.px-inventory-more-info { font-size: 13px; color: var(--text-dim); }

/* ---------- Tarjetas: el look glass viene de .glass; aquí solo padding/cabecera ---------- */
.px-card { padding: clamp(16px, 2.4vw, 24px); overflow: hidden; }
.px-card-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  /* Franja de cabecera a sangre completa (tira los márgenes del propio
     padding de .px-card) para separar visualmente cada sección del panel,
     en vez de un simple borde inferior — mismo contenido/ids, solo look. */
  margin: calc(-1 * clamp(16px, 2.4vw, 24px)) calc(-1 * clamp(16px, 2.4vw, 24px)) 14px;
  padding: 14px clamp(16px, 2.4vw, 24px) 12px;
  background: var(--panel-2);
  border-bottom: 1px solid var(--line-soft);
}
.px-card-title { display: flex; align-items: center; gap: 12px; min-width: 0; }
.px-card-title h2, .px-card-title h3, .px-card-head h2, .px-card-head h3 {
  font-family: "Space Grotesk", "Inter", sans-serif;
  font-size: 16px;
  font-weight: 600;
}
/* badge de icono algo más compacto que en la landing (títulos de 16px) */
.px-card-title .icon-badge { width: 38px; height: 38px; border-radius: 11px; }
.px-card-title .icon-badge svg { width: 19px; height: 19px; }
.px-card-sub { color: var(--text-muted); font-size: 14px; }

/* ---------- Selector de dominio (varios dominios bajo el mismo cliente) ---------- */
.px-domain-switcher { margin-bottom: 14px; }
.px-domain-label {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 14px;
  color: var(--text-muted);
}
.px-domain-select {
  font: inherit;
  color: var(--text-strong, inherit);
  background: var(--surface-2, transparent);
  border: 1px solid var(--border, #ccc);
  border-radius: 8px;
  padding: 4px 8px;
}

/* ---------- Selector de reportes ---------- */
.px-report-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}
.px-report-tab {
  min-height: 42px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: rgba(255, 255, 255, 0.62);
  color: var(--text);
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 8px 12px;
  font: 700 13px/1.2 "Inter", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  cursor: pointer;
}
.px-report-tab:hover { border-color: var(--line-strong); }
.px-report-tab.is-active {
  border-color: rgba(167, 43, 67, 0.42);
  background: rgba(167, 43, 67, 0.09);
  color: var(--brand-dark);
}
.px-report-tab .meta {
  color: var(--text-dim);
  font-family: "JetBrains Mono", monospace;
  font-size: 11px;
  font-weight: 600;
}
.px-report-tab.is-hidden { opacity: 0.72; }

/* Agrupa las pestañas por bloque (lanzamiento comercial: país1/país2/merged
   de una misma contratación). Cada bloque ocupa su propia fila dentro del
   contenedor flex-wrap existente (width:100% fuerza el salto de línea). */
.px-report-tab-group {
  border: 1px solid var(--line-soft);
  border-radius: 10px;
  background: rgba(255, 255, 255, 0.42);
  width: 100%;
  overflow: hidden;
}
.px-report-tab-group-label {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 13px 14px;
  cursor: pointer;
  color: var(--text);
  font-size: 13px;
  list-style: none;
}
.px-report-tab-group-label::-webkit-details-marker { display: none; }
.px-report-tab-group-label::before {
  content: "+";
  color: var(--brand-dark);
  font: 700 16px/1 "JetBrains Mono", monospace;
}
.px-report-tab-group[open] .px-report-tab-group-label::before { content: "−"; }
.px-report-tab-group-label strong { margin-right: auto; }
.px-report-tab-group-count {
  color: var(--text-dim);
  font: 600 11px/1 "JetBrains Mono", monospace;
  white-space: nowrap;
}
.px-report-tab-group-content {
  display: grid;
  gap: 8px;
  padding: 0 14px 14px;
  border-top: 1px solid var(--line-soft);
}
.px-report-tabs-inner {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}

/* Subdivide cada bloque comercial en "trios" (Unificado + Region1 + Region2
   de un mismo lanzamiento de análisis). Cada trio es su propio grupo visual,
   separado del resto por un borde punteado sutil (no una caja cerrada, para
   no competir visualmente con .px-report-tab-group). */
.px-report-batch {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 6px 0 2px;
  border-top: 1px dashed var(--line-soft);
}
.px-report-batch:first-child {
  border-top: none;
  padding-top: 8px;
}
.px-report-batch-label {
  margin: 0;
  font-size: 11.5px;
  color: var(--text-muted);
}

/* ---------- Grids ---------- */
.px-grid { display: grid; gap: 16px; }
.px-grid--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.px-grid--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.px-grid--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
@media (max-width: 860px) {
  .px-grid--3, .px-grid--4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 560px) {
  .px-grid--2, .px-grid--3, .px-grid--4 { grid-template-columns: 1fr; }
}

/* ---------- Tiles de métrica ---------- */
.px-stat {
  background: var(--panel-solid);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  padding: 14px 16px;
  display: grid;
  gap: 4px;
}
.px-stat .num {
  font-family: "Space Grotesk", "Inter", sans-serif;
  font-size: clamp(22px, 3vw, 30px);
  font-weight: 700;
  line-height: 1;
}
.px-stat .lbl { font-size: 12px; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.03em; }
.px-stat .num--sm { font-size: 16px; }
.px-stat .num--md { font-size: 18px; }
/* align-items: start (no "end"): con 3 partes angostas ("Dominios activos" /
   "IPs directas" / "Servicios") la etiqueta mas larga envuelve a 2 lineas en
   pantallas chicas/medianas; con "end" eso desalinea los NUMEROS entre si
   (cada parte se ancla por abajo). Con "start" los numeros quedan siempre en
   la fila superior, alineados entre las 3 partes, sea cual sea el largo de
   cada etiqueta debajo. */
.px-stat--split { grid-template-columns: repeat(var(--px-stat-parts, 2), 1fr); align-items: start; }
.px-stat-part { display: grid; gap: 4px; }

/* ---------- Score + nivel de exposición ---------- */
.px-score { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; }
.px-score .val {
  font-family: "Space Grotesk", "Inter", sans-serif;
  font-size: clamp(40px, 7vw, 60px);
  font-weight: 700;
  line-height: 1;
  background: var(--grad-text);
  -webkit-background-clip: text;
          background-clip: text;
  -webkit-text-fill-color: transparent;
}
.px-score .max { color: var(--text-dim); font-size: 18px; }
.px-exposure {
  display: inline-flex; align-items: center; gap: 7px;
  font-family: "JetBrains Mono", monospace;
  font-size: 12px; font-weight: 600; text-transform: uppercase;
  padding: 5px 12px; border-radius: 999px; border: 1px solid currentColor;
}
.px-exposure .dot { width: 8px; height: 8px; border-radius: 50%; background: currentColor; box-shadow: 0 0 8px currentColor; }
.px-exposure--critico { color: var(--crit); background: rgba(167, 43, 67, 0.10); }
.px-exposure--alto    { color: var(--high); background: rgba(200, 71, 21, 0.10); }
.px-exposure--medio   { color: var(--med);  background: rgba(159, 119, 1, 0.10); }
.px-exposure--bajo    { color: var(--low);  background: rgba(4, 154, 237, 0.10); }
.px-meter { height: 10px; border-radius: 999px; background: rgba(100, 99, 100, 0.16); overflow: hidden; margin-top: 14px; }
.px-meter > i { display: block; height: 100%; border-radius: 999px; background: var(--grad-brand); }
/* La tarjeta de score responde al nivel real de exposición que ya calcula
   portal.js (clase .px-exposure--* existente, sin lógica nueva): un acento
   superior de color hace que el KPI más importante del panel destaque del
   resto de tarjetas a simple vista, en vez de verse igual que todas. */
.px-card:has(.px-exposure--critico) { border-top: 3px solid var(--crit); }
.px-card:has(.px-exposure--alto) { border-top: 3px solid var(--high); }
.px-card:has(.px-exposure--medio) { border-top: 3px solid var(--med); }
.px-card:has(.px-exposure--bajo) { border-top: 3px solid var(--low); }

/* ---------- Severidad: conteos ---------- */
.px-sevgrid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 12px; }
@media (max-width: 560px) { .px-sevgrid { grid-template-columns: repeat(2, 1fr); } }
.px-sevtile {
  border: 1px solid var(--line);
  border-top-width: 3px;
  border-radius: var(--r-md);
  padding: 14px 16px;
  display: grid;
  gap: 8px;
  background: var(--panel-solid);
  transition: transform 0.15s var(--ease), box-shadow 0.2s var(--ease);
}
.px-sevtile:hover { transform: translateY(-2px); box-shadow: var(--shadow-card); }
.px-sevtile .count { font-family: "Space Grotesk", "Inter", sans-serif; font-size: 30px; font-weight: 700; line-height: 1; }
.px-sevtile--crit { border-color: var(--line); border-top-color: var(--crit); }
.px-sevtile--crit .count { color: var(--crit); }
.px-sevtile--high { border-color: var(--line); border-top-color: var(--high); }
.px-sevtile--high .count { color: var(--high); }
.px-sevtile--med  { border-color: var(--line); border-top-color: var(--med); }
.px-sevtile--med .count { color: var(--med); }
.px-sevtile--low  { border-color: var(--line); border-top-color: var(--low); }
.px-sevtile--low .count { color: var(--low); }
.sev-info { color: var(--text-dim); background: rgba(100, 99, 100, 0.10); }

/* ---------- Tablas ---------- */
/* Contenedor con scroll horizontal (mouse/trackpad/táctil) sin ocultar
   columnas: min-width en la tabla obliga al navegador a mostrar la
   scrollbar en vez de comprimir cada celda hasta hacerla ilegible.
   tabindex="0" (puesto en el HTML) permite recorrerlo con teclado. */
.px-table-wrap {
  overflow-x: auto; -webkit-overflow-scrolling: touch;
  scrollbar-width: thin; max-width: 100%;
  min-width: 0;
}
/* min-width:0 en cualquier contenedor grid/flex que pueda envolver una
   .px-table-wrap: sin esto, un item de grid/flex usa min-width:auto (el
   tamaño min-content de su contenido, incluida la tabla ancha) y puede
   ensanchar la tarjeta/columna entera en vez de dejar que la tabla
   desplace horizontalmente DENTRO de su propio contenedor. */
.px-card, .px-grid > *, .form-grid > * { min-width: 0; }
.px-table-wrap:focus-visible { outline: 2px solid var(--cyan); outline-offset: -2px; }
.px-table { width: 100%; border-collapse: collapse; font-size: 14px; }
.px-table--sticky-actions { min-width: 960px; }
.px-table th, .px-table td { text-align: left; padding: 10px 12px; border-bottom: 1px solid var(--line-soft); vertical-align: top; }
.px-table th { font-size: 12px; text-transform: uppercase; letter-spacing: 0.03em; color: var(--text-dim); border-bottom: 1px solid var(--line); }
.px-table tbody tr:hover { background: rgba(4, 154, 237, 0.04); }
.px-table .mono { font-family: "JetBrains Mono", monospace; font-size: 13px; }

/* Fila de encabezado de bloque (agrupa reportes por lanzamiento comercial:
   país1/país2/merged de una misma contratación). Nunca recibe :hover ni
   acciones — es puramente informativa. */
.px-table tr.px-block-head td {
  background: var(--panel-2);
  font-size: 12.5px;
  color: var(--text-muted);
  padding-top: 14px;
  padding-bottom: 8px;
  border-bottom: 1px solid var(--line);
}
.px-table tr.px-block-head:hover td { background: var(--panel-2); }
.px-table tr.px-block-head td strong { color: var(--text); }

/* Fila de subgrupo "trio" (Unificado + Region1 + Region2 de un mismo
   lanzamiento) dentro de un bloque comercial. Más discreta que el
   encabezado de bloque: no repite el fondo, solo separa con texto tenue. */
.px-table tr.px-batch-head td {
  font-size: 11.5px;
  color: var(--text-muted);
  padding-top: 8px;
  padding-bottom: 4px;
  border-bottom: none;
}
.px-table tr.px-batch-head:hover td { background: transparent; }

/* Herramienta "Comparar reportes" (elección manual del usuario, distinta de
   la comparación automática de #pxComparisonSection): 2 selects + botón,
   resultado con deltas de score/severidad. */
.px-compare-pickers {
  display: flex; flex-wrap: wrap; align-items: flex-end; gap: 12px; margin-top: 10px;
}
.px-compare-pickers .field { flex: 1 1 220px; margin: 0; }
.px-compare-pickers .btn { flex: 0 0 auto; }
.px-compare-sevgrid {
  display: flex; flex-direction: column; gap: 6px; margin: 12px 0;
  border: 1px solid var(--line); border-radius: 10px; padding: 10px 14px;
}
.px-compare-sevrow {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  font-size: 13.5px;
}
.px-compare-sevrow-label { color: var(--text-dim); }
.px-compare-sevrow-count { font-family: "JetBrains Mono", monospace; color: var(--text); }
.px-compare-sevrow-arrow { font-weight: 700; font-family: "JetBrains Mono", monospace; min-width: 2.5em; text-align: right; }
.px-compare-sevrow-arrow--empeoro { color: var(--high); }
.px-compare-sevrow-arrow--mejoro { color: var(--ok); }
.px-compare-sevrow-arrow--sin_cambio { color: var(--text-dim); }

/* Comparaciones: el resultado se organiza por decisiones (riesgo, hallazgos,
   severidad e inventario), no como una lista de texto técnico. */
#pxComparison, #pxCompareResult { display: grid; gap: 16px; }
.px-compare-result-heading {
  margin: 0; color: var(--text-dim); font: 600 12px/1.45 "JetBrains Mono", monospace;
}
.px-comparison-overview { display: grid; gap: 12px; }
.px-comparison-risk {
  display: grid; gap: 4px; padding: 16px; border: 1px solid var(--line-strong);
  border-radius: 12px; background: linear-gradient(135deg, rgba(37, 99, 235, 0.08), rgba(255, 255, 255, 0.74));
}
.px-comparison-risk.is-empeoro { border-color: rgba(185, 45, 50, 0.35); background: linear-gradient(135deg, rgba(185, 45, 50, 0.10), rgba(255, 255, 255, 0.74)); }
.px-comparison-risk.is-mejoro { border-color: rgba(22, 138, 91, 0.34); background: linear-gradient(135deg, rgba(22, 138, 91, 0.10), rgba(255, 255, 255, 0.74)); }
.px-comparison-kicker, .px-comparison-inventory-label {
  color: var(--text-dim); font: 700 10px/1.2 "JetBrains Mono", monospace;
  letter-spacing: 0.07em; text-transform: uppercase;
}
.px-comparison-risk-score { color: var(--brand-dark); font: 700 28px/1 "Space Grotesk", "Inter", sans-serif; }
.px-comparison-risk-copy { color: var(--text); font-size: 13.5px; }
.px-comparison-impact { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 9px; }
.px-comparison-impact-card {
  display: grid; gap: 3px; min-width: 0; padding: 12px;
  border: 1px solid var(--line); border-radius: 10px; background: var(--panel-2);
}
.px-comparison-impact-card.is-new { border-top: 3px solid var(--high); }
.px-comparison-impact-card.is-persisting { border-top: 3px solid var(--brand); }
.px-comparison-impact-card.is-gone { border-top: 3px solid var(--ok); }
.px-comparison-impact-number { color: var(--brand-dark); font: 700 23px/1 "Space Grotesk", "Inter", sans-serif; }
.px-comparison-impact-label { color: var(--text); font-size: 13px; font-weight: 700; }
.px-comparison-impact-copy { color: var(--text-dim); font-size: 11.5px; line-height: 1.35; }
/* padding-block: 0 es necesario porque hay una regla global `section {
   padding-block: clamp(64px, 9vw, 120px); }` (styles.css, pensada para las
   secciones grandes de la landing) que por especificidad de selector de
   tipo (no de clase) se cuela en este <section> del portal si no se anula
   explícitamente, dejando ~115px de hueco vacío arriba y abajo de cada
   grupo de comparación. */
.px-comparison-group { display: grid; gap: 7px; padding-block: 0; }
.px-comparison-group > .px-h3, .px-comparison-group > .px-muted { margin: 0; }
.px-comparison-severity { margin: 0; background: var(--panel-2); }
.px-comparison-inventory { display: grid; grid-template-columns: repeat(auto-fit, minmax(145px, 1fr)); gap: 9px; }
.px-comparison-inventory-card {
  display: grid; gap: 5px; padding: 11px; border: 1px solid var(--line);
  border-radius: 10px; background: var(--panel-2);
}
.px-comparison-inventory-card.is-aumento { border-left: 3px solid var(--brand); }
.px-comparison-inventory-card.is-disminuyo { border-left: 3px solid var(--ok); }
.px-comparison-inventory-card.is-sin_cambio { border-left: 3px solid var(--text-dim); }
.px-comparison-inventory-values { color: var(--text); font: 700 16px/1.15 "JetBrains Mono", monospace; }
.px-comparison-inventory-delta { color: var(--text-dim); font-size: 11.5px; }
.px-comparison-detail {
  border: 1px solid var(--line); border-radius: 10px; padding: 0 13px; background: var(--panel-2);
}
.px-comparison-detail > summary {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  cursor: pointer; list-style: none; padding: 12px 0; color: var(--text);
}
.px-comparison-detail > summary::-webkit-details-marker { display: none; }
.px-comparison-detail > summary::before { content: "▸"; color: var(--text-dim); margin-right: 7px; transition: transform 0.15s var(--ease, ease); }
.px-comparison-detail[open] > summary::before { transform: rotate(90deg); }
.px-comparison-detail-count {
  margin-left: auto; color: var(--text-dim); font: 700 10px/1.2 "JetBrains Mono", monospace;
  text-transform: uppercase; white-space: nowrap;
}
.px-comparison-detail > .px-muted { margin: 0 0 9px; }
.px-comparison-finding-list { margin: 0 0 13px; }
@media (max-width: 600px) { .px-comparison-impact { grid-template-columns: 1fr; } }

/* Columna de acciones ("Ver") fija a la derecha: siempre visible sin tener
   que desplazar hasta el final de la tabla. */
.px-table--sticky-actions .px-table-action-col {
  position: sticky; right: 0; background: var(--panel-solid);
  box-shadow: -6px 0 8px -6px rgba(0, 0, 0, 0.35);
  white-space: nowrap;
}
.px-table--sticky-actions tbody tr:hover .px-table-action-col { background: var(--panel-solid); }

.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;
}

/* ---------- Filtros plegables ---------- */
.px-filters { margin-bottom: 4px; }
.px-filters-summary {
  cursor: pointer; list-style: none; user-select: none;
  font-weight: 600; font-size: 14px; color: var(--text);
  padding: 8px 0; display: flex; align-items: center; gap: 8px;
}
.px-filters-summary::-webkit-details-marker { display: none; }
.px-filters-summary::before {
  content: "▸"; display: inline-block; transition: transform 0.15s var(--ease, ease);
  color: var(--text-dim);
}
.px-filters[open] > .px-filters-summary::before { transform: rotate(90deg); }
/* Grid de filtros: auto-fit para aprovechar el ancho disponible sin
   forzar columnas fijas que se compriman en pantallas medianas. */
.px-filter-grid { grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); }

/* ---------- Acordeón de detalle ---------- */
.px-detail-section {
  border: 1px solid var(--line-soft); border-radius: var(--r-sm, 10px);
  margin-top: 12px; padding: 0 14px;
}
.px-detail-section > summary {
  cursor: pointer; list-style: none; user-select: none;
  font: 700 15px/1.3 "Space Grotesk", "Inter", sans-serif; color: var(--text);
  padding: 12px 0; display: flex; align-items: center; gap: 8px;
}
.px-detail-section > summary::-webkit-details-marker { display: none; }
.px-detail-section > summary::before {
  content: "▸"; display: inline-block; transition: transform 0.15s var(--ease, ease);
  color: var(--text-dim); flex: none;
}
.px-detail-section[open] > summary::before { transform: rotate(90deg); }
.px-detail-section > summary:focus-visible { outline: 2px solid var(--cyan); outline-offset: 2px; }
.px-detail-section-body { padding-bottom: 14px; }

/* Accesos del detalle de contratación: se mantienen a la vista en escritorio
   y abren el acordeón elegido antes de desplazarlo a la posición correcta. */
.px-detail-workspace {
  display: grid;
  grid-template-columns: minmax(190px, 220px) minmax(0, 1fr);
  gap: 16px;
  align-items: start;
  margin-top: 14px;
}
.px-detail-content { min-width: 0; }
.px-detail-quicknav {
  position: sticky;
  top: calc(var(--nav-h) + 22px);
  display: grid;
  gap: 7px;
  padding: 14px;
  border: 1px solid var(--line-soft);
  border-radius: var(--r-md, 12px);
  background: rgba(255, 255, 255, 0.68);
  box-shadow: 0 12px 28px -24px rgba(18, 28, 44, 0.38);
}
.px-detail-quicknav-title {
  margin: 0 0 2px;
  color: var(--text-muted);
  font: 700 11px/1.2 "JetBrains Mono", monospace;
  letter-spacing: .07em;
  text-transform: uppercase;
}
.px-detail-quicknav-link {
  width: 100%;
  border: 1px solid transparent;
  border-radius: 9px;
  padding: 9px 10px;
  color: var(--text);
  background: transparent;
  text-align: left;
  font: 600 13px/1.25 "Inter", system-ui, sans-serif;
  cursor: pointer;
}
.px-detail-quicknav-link:hover,
.px-detail-quicknav-link:focus-visible {
  color: var(--brand-dark);
  background: rgba(167, 43, 67, 0.08);
  border-color: rgba(167, 43, 67, 0.2);
  outline: none;
}
@media (max-width: 960px) {
  .px-detail-workspace { grid-template-columns: 1fr; }
  .px-detail-quicknav {
    position: static;
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
  .px-detail-quicknav-title { grid-column: 1 / -1; }
}
@media (max-width: 560px) {
  .px-detail-quicknav { grid-template-columns: 1fr; }
}

/* ---------- Inventario completo ---------- */
.px-inventory-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 12px;
}
.px-inventory-tab {
  min-height: 36px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: rgba(255, 255, 255, 0.64);
  color: var(--text);
  padding: 7px 10px;
  font: 700 12px/1.2 "Inter", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  cursor: pointer;
}
.px-inventory-tab.is-active {
  border-color: rgba(4, 154, 237, 0.38);
  background: rgba(4, 154, 237, 0.08);
  color: var(--brand-dark);
}
.px-inventory-search {
  display: grid;
  gap: 6px;
  max-width: 420px;
  margin-bottom: 12px;
}
.px-inventory-search span {
  color: var(--text-muted);
  font-size: 12px;
  font-weight: 600;
}
.px-inventory-search input {
  min-height: 40px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: rgba(255, 255, 255, 0.88);
  color: var(--text);
  font: 500 14px/1.3 "Inter", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  padding: 8px 10px;
}
.px-inventory-search input:focus {
  outline: 0;
  border-color: rgba(4, 154, 237, 0.34);
  box-shadow: 0 0 0 4px rgba(4, 154, 237, 0.08);
}
.px-inventory-panel { display: grid; gap: 10px; }
.px-inventory-panel .px-table td { max-width: 380px; overflow-wrap: anywhere; }

/* Vistas agrupadas (puertos confirmados vs no reconocibles, directorios por status) */
.px-grouped { display: grid; gap: 14px; }
.px-group-head {
  font-size: 12px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.04em;
  color: var(--text-dim); padding-bottom: 2px; border-bottom: 1px solid var(--line);
}
/* VHosts con sus directorios */
.px-vhosts { display: grid; gap: 12px; }
.px-vhost-card { border: 1px solid var(--line-soft); border-radius: 12px; padding: 12px 14px; }
.px-vhost-head { display: flex; align-items: baseline; gap: 4px; flex-wrap: wrap; }
.px-vhost-sub {
  font-size: 11px; text-transform: uppercase; letter-spacing: 0.04em;
  color: var(--text-dim); margin: 10px 0 4px;
}
.px-route-list { margin: 0; padding-left: 18px; display: grid; gap: 2px; }
.px-route-list li {
  font-family: "JetBrains Mono", monospace; font-size: 13px; overflow-wrap: anywhere;
}
.px-route-list--restr li { color: var(--text-muted); }

/* ---------- Banner de identidad / avisos ---------- */
.px-banner {
  display: flex; gap: 12px; align-items: flex-start;
  border-radius: var(--r-md); padding: 14px 16px;
  border: 1px solid var(--line); background: var(--panel-solid);
}
.px-banner .ic { flex: none; width: 20px; height: 20px; margin-top: 2px; }

/* Descargas del reporte (artifacts en R2) */
.px-downloads { margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--line); }
.px-downloads-head { display: flex; align-items: center; gap: 8px; margin-bottom: 10px; font-weight: 600; color: var(--text); }
.px-downloads-head .ic { flex: none; width: 18px; height: 18px; }
.px-downloads-actions { display: flex; flex-wrap: wrap; gap: 10px; }
.px-downloads-actions .btn { gap: 6px; }
.px-downloads-actions .ic { flex: none; width: 16px; height: 16px; }

/* Hint del panel de monitoreo (admin) */
.px-mon-hint { font-size: 0.85rem; margin: 0.25rem 0 0.7rem; }
.px-mon-actions { display: flex; gap: 8px; flex-wrap: wrap; }
.px-banner .bd { display: grid; gap: 2px; color: var(--text); }
.px-banner .bd strong { font-weight: 600; }
.px-banner--warn { color: var(--high); border-color: rgba(200, 71, 21, 0.35); background: rgba(200, 71, 21, 0.07); }
.px-banner--ok   { color: var(--ok);   border-color: rgba(22, 138, 91, 0.35); background: rgba(22, 138, 91, 0.07); }
.px-banner--info { color: var(--cyan); border-color: rgba(4, 154, 237, 0.32); background: rgba(4, 154, 237, 0.06); }
.px-banner .bd .t { color: inherit; }

/* ---------- Aviso de datos ficticios ---------- */
.px-notice {
  font-size: 13px; color: var(--text-muted);
  border: 1px dashed var(--line-strong); border-radius: var(--r-md);
  padding: 10px 14px; background: rgba(159, 119, 1, 0.06);
}

/* ---------- Hallazgos ---------- */
.px-findings { display: grid; gap: 12px; }
.px-findings-list { display: grid; gap: 12px; }
.px-finding-toolbar {
  display: flex;
  align-items: end;
  flex-wrap: wrap;
  gap: 12px;
  padding: 12px;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: rgba(255, 255, 255, 0.48);
}
.px-filter {
  display: grid;
  gap: 6px;
  min-width: min(100%, 210px);
}
.px-filter span {
  color: var(--text-muted);
  font-size: 12px;
  font-weight: 600;
}
.px-filter select {
  min-height: 40px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: rgba(255, 255, 255, 0.88);
  color: var(--text);
  font: 500 14px/1.3 "Inter", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  padding: 8px 10px;
}
.px-filter select:focus {
  outline: 0;
  border-color: rgba(167, 43, 67, 0.34);
  box-shadow: 0 0 0 4px rgba(167, 43, 67, 0.08);
}
.px-finding-count {
  margin-left: auto;
  color: var(--text-dim);
  font-family: "JetBrains Mono", monospace;
  font-size: 12px;
  padding-bottom: 11px;
}
.px-finding {
  border: 1px solid var(--line); border-left-width: 3px; border-radius: var(--r-md);
  padding: 14px 16px; background: var(--panel-solid);
  display: grid; gap: 8px;
}
.px-finding > summary {
  cursor: pointer;
  list-style: none;
}
.px-finding > summary::-webkit-details-marker { display: none; }
.px-finding--critical { border-left-color: var(--crit); }
.px-finding--high { border-left-color: var(--high); }
.px-finding--medium { border-left-color: var(--med); }
.px-finding--low { border-left-color: var(--low); }
.px-finding .fh { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.px-finding .fid { font-family: "JetBrains Mono", monospace; font-size: 12px; color: var(--text-dim); }
.px-finding .ft { flex: 1 1 260px; min-width: 0; font-weight: 600; font-family: "Space Grotesk", "Inter", sans-serif; }
.px-finding .fasset { font-family: "JetBrains Mono", monospace; font-size: 13px; color: var(--text-muted); }
.px-finding .frec { font-size: 14px; }
.px-finding .frec b { color: var(--text); font-weight: 600; }
.px-finding .fev {
  font-family: "JetBrains Mono", monospace; font-size: 12px; color: var(--text-dim);
  background: var(--bg-2); border-radius: var(--r-sm); padding: 6px 10px; overflow-x: auto;
}
.px-detail-cta {
  color: var(--brand);
  font-size: 13px;
  font-weight: 700;
  white-space: nowrap;
}
.px-verification {
  display: inline-flex;
  align-items: center;
  padding: 4px 10px;
  border: 1px solid currentColor;
  border-radius: 999px;
  font-family: "JetBrains Mono", monospace;
  font-size: 11px;
  font-weight: 600;
}
.px-verification--confirmed { color: var(--ok); background: rgba(22, 138, 91, 0.10); }
.px-verification--probable { color: var(--med); background: rgba(159, 119, 1, 0.10); }
.px-verification--potential { color: var(--high); background: rgba(200, 71, 21, 0.10); }
.px-verification--unknown { color: var(--text-dim); background: rgba(100, 99, 100, 0.10); }
.px-validation-note {
  border: 1px solid rgba(159, 119, 1, 0.28);
  border-radius: var(--r-sm);
  background: rgba(159, 119, 1, 0.08);
  color: var(--text);
  font-size: 13px;
  padding: 8px 10px;
}
.px-finding-detail {
  border-top: 1px solid var(--line-soft);
  margin-top: 4px;
  padding-top: 12px;
}
.px-detail-grid {
  display: grid;
  gap: 8px;
  margin: 0;
}
.px-detail-row {
  display: grid;
  grid-template-columns: minmax(130px, 0.28fr) 1fr;
  gap: 12px;
}
.px-detail-row dt {
  color: var(--text-dim);
  font-size: 12px;
  font-weight: 700;
}
.px-detail-row dd {
  min-width: 0;
  margin: 0;
  color: var(--text);
  overflow-wrap: anywhere;
}
.px-detail-row.mono dd,
.px-detail-row.evidence dd {
  font-family: "JetBrains Mono", monospace;
  font-size: 12px;
}
.px-detail-row.evidence dd {
  background: var(--bg-2);
  border-radius: var(--r-sm);
  color: var(--text-dim);
  padding: 8px 10px;
}
@media (max-width: 680px) {
  .px-finding-count { width: 100%; margin-left: 0; padding-bottom: 0; }
  .px-filter { flex: 1 1 100%; }
  .px-detail-row { grid-template-columns: 1fr; gap: 3px; }
  .px-detail-cta { width: 100%; }
}

/* ---------- Listas ---------- */
.px-list { display: grid; gap: 10px; }
.px-list li { display: flex; gap: 10px; align-items: flex-start; }
.px-list li::before {
  content: ""; flex: none; width: 7px; height: 7px; margin-top: 8px;
  border-radius: 50%; background: var(--cyan); box-shadow: 0 0 8px rgba(4, 154, 237, 0.5);
}

/* ---------- Recomendaciones priorizadas ---------- */
.px-recommendations {
  display: grid;
  gap: 10px;
  margin: 16px 0 0;
  padding: 0;
  list-style: none;
}
.px-recommendations-toggle { margin-top: 14px; }
.px-recommendations-open { width: 100%; justify-content: center; }
.px-recommendation {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 12px;
  align-items: start;
  padding: 16px;
  border: 1px solid var(--line-soft);
  border-radius: 12px;
  background: linear-gradient(135deg, rgba(4, 154, 237, 0.08), rgba(122, 88, 237, 0.05));
  box-shadow: 0 8px 24px rgba(20, 41, 66, 0.04);
}
.px-recommendation-number {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border-radius: 10px;
  color: var(--brand-dark);
  background: rgba(4, 154, 237, 0.12);
  border: 1px solid rgba(4, 154, 237, 0.25);
  font: 700 12px/1 "JetBrains Mono", monospace;
}
.px-recommendation-body { min-width: 0; }
.px-recommendation-text { margin: 0; color: var(--text); font-size: 14px; line-height: 1.55; }
.px-recommendation-text strong { color: var(--brand-dark); font-weight: 750; }
.px-recommendation-meta {
  display: grid;
  grid-template-columns: 126px minmax(0, 1fr);
  gap: 8px;
  margin-top: 10px;
  font-size: 12px;
  line-height: 1.45;
}
.px-recommendation-meta-label {
  color: var(--text-dim);
  font: 700 10px/1.45 "JetBrains Mono", monospace;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
.px-recommendation-reason { color: var(--text-dim); }
.px-recommendation-assets { display: flex; flex-wrap: wrap; gap: 5px; }
.px-recommendation-asset {
  padding: 3px 6px;
  border: 1px solid rgba(4, 154, 237, 0.18);
  border-radius: 5px;
  background: rgba(4, 154, 237, 0.07);
  color: var(--brand-dark);
  font: 500 11px/1.25 "JetBrains Mono", monospace;
  overflow-wrap: anywhere;
}
.px-recommendation-code {
  padding: 1px 4px;
  border-radius: 4px;
  background: rgba(4, 154, 237, 0.10);
  color: var(--brand-dark);
  font: 500 0.9em/1.35 "JetBrains Mono", monospace;
}
.px-recommendation-origin {
  display: block;
  margin-top: 8px;
  color: var(--text-dim);
  font-size: 12px;
}
@media (max-width: 520px) {
  .px-recommendation { gap: 10px; padding: 12px; }
  .px-recommendation-number { width: 30px; height: 30px; border-radius: 9px; }
  .px-recommendation-meta { grid-template-columns: 1fr; gap: 3px; }
}

/* ---------- Acciones / botones placeholder ---------- */
.px-actions { display: flex; flex-wrap: wrap; gap: 10px; }
.px-soon { position: relative; opacity: 0.62; cursor: not-allowed; }
.px-soon::after {
  content: "Próximamente"; font-family: "JetBrains Mono", monospace; font-size: 9px;
  text-transform: uppercase; letter-spacing: 0.04em;
  background: var(--med); color: #fff; border-radius: 999px; padding: 1px 6px; margin-left: 8px;
}

/* ---------- Tarjeta de cliente (portal index) ---------- */
.px-client-card { display: grid; gap: 12px; }
.px-client-card .row { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.px-status {
  display: inline-flex; align-items: center; gap: 7px;
  font-family: "JetBrains Mono", monospace; font-size: 11px; text-transform: uppercase; font-weight: 600;
  padding: 4px 11px; border-radius: 999px;
  color: var(--ok); background: rgba(22, 138, 91, 0.10); border: 1px solid currentColor;
}
.px-status .dot { width: 7px; height: 7px; border-radius: 50%; background: currentColor; }
.px-selected-report {
  display: grid; gap: 10px; padding: 14px;
  border: 1px solid var(--line-strong); border-radius: 12px;
  background: linear-gradient(135deg, rgba(167, 43, 67, 0.09), rgba(255, 255, 255, 0.72));
  box-shadow: 0 8px 22px rgba(47, 24, 29, 0.06);
}
.px-selected-report-kicker {
  color: var(--brand); font: 700 10px/1.2 "JetBrains Mono", monospace;
  letter-spacing: 0.08em; text-transform: uppercase;
}
.px-selected-report-ref {
  color: var(--brand-dark); font: 700 16px/1.35 "JetBrains Mono", monospace;
  letter-spacing: -0.02em;
  overflow-wrap: anywhere;
}
.px-selected-report-meta { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
.px-selected-report-meta-item {
  display: grid; gap: 3px; min-width: 0; padding: 8px 9px;
  border: 1px solid rgba(47, 24, 29, 0.10); border-radius: 8px;
  background: rgba(255, 255, 255, 0.66);
}
.px-selected-report-meta-label {
  color: var(--text-dim); font: 700 9px/1.2 "JetBrains Mono", monospace;
  letter-spacing: 0.06em; text-transform: uppercase;
}
.px-selected-report-meta-value { color: var(--text); font-size: 12px; font-weight: 650; overflow-wrap: anywhere; }
@media (max-width: 440px) { .px-selected-report-meta { grid-template-columns: 1fr; } }

/* ---------- Router visual de Access ---------- */
.px-auth { display: grid; place-items: center; min-height: calc(100vh - var(--nav-h) - 120px); }
.px-authcard { width: 100%; max-width: 440px; }
.px-auth-head { display: grid; gap: 6px; margin-bottom: 18px; text-align: center; }
.px-auth-badge {
  justify-self: center;
  display: inline-flex; align-items: center; gap: 7px;
  font-family: "JetBrains Mono", monospace; font-size: 11px; text-transform: uppercase; font-weight: 600;
  color: var(--brand-dark); background: rgba(167, 43, 67, 0.10);
  border: 1px solid var(--line-strong); padding: 4px 11px; border-radius: 999px;
}
.px-auth-badge svg { width: 14px; height: 14px; }
.px-form { display: grid; gap: 14px; }
.px-form .btn { width: 100%; margin-top: 4px; }
.px-form .btn[disabled] { cursor: progress; opacity: 0.72; transform: none; }
.px-form-status {
  margin: 0; min-height: 1.3em; font-size: 13.5px; text-align: center; color: var(--text-dim);
}
.px-form-status.is-sending { color: var(--brand); }
.px-form-status.is-error { color: var(--high); }
.px-form-status.is-success { color: var(--ok); }
/* Avisos/aclaraciones que exigen una decisión del usuario (p.ej. "escribe la
   referencia para confirmar", "solo puedes elegir una opción"): diferenciados
   del resto del texto con color de marca + negrita + subrayado, nunca solo
   color (igual de legibles sin percepción de color). */
.px-form-status.is-notice {
  color: var(--cyan); font-weight: 700; text-decoration: underline; text-align: left;
}

.px-bulk-bar {
  display: flex; align-items: center; gap: 12px; margin: 10px 0;
  padding: 10px 14px; border-radius: 10px;
  background: rgba(167, 43, 67, 0.08); border: 1px solid rgba(167, 43, 67, 0.24);
  font-weight: 600; font-size: 13.5px;
}

.px-modal-overlay {
  position: fixed; inset: 0; z-index: 200; display: grid; place-items: center;
  background: rgba(10, 8, 9, 0.62); padding: 20px;
}
.px-modal { width: 100%; max-width: 520px; display: grid; gap: 14px; }
.px-modal .form-grid { gap: 12px; }
.px-launch-fallback { width: 100%; min-height: 88px; resize: vertical; }
.px-launch-commands { display: grid; gap: 8px; margin-top: 10px; }
.px-launch-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.px-launch-row .px-launch-country { font-weight: 600; min-width: 2.5em; }
.px-center { text-align: center; }
.px-link { color: var(--brand); font-weight: 600; border-bottom: 1px solid rgba(167, 43, 67, 0.26); }
.px-link:hover { color: var(--brand-dark); border-color: currentColor; }
.px-access-router { display: grid; gap: 16px; }
.px-auth-actions { display: grid; gap: 10px; }
.px-auth-actions .btn { width: 100%; }
.px-denied-shell { display: grid; place-items: center; min-height: calc(100vh - var(--nav-h) - 160px); }
.px-denied-card { width: 100%; max-width: 520px; text-align: center; }
.px-denied-card .px-auth-actions { margin-top: 18px; }

/* ---------- Utilidades ---------- */
.px-row { display: flex; gap: 12px; flex-wrap: wrap; align-items: center; }
.px-spread { display: flex; gap: 12px; flex-wrap: wrap; align-items: center; justify-content: space-between; }
[hidden] { display: none !important; }
.px-skel { color: var(--text-dim); font-family: "JetBrains Mono", monospace; font-size: 13px; }

/* ---------- Clickwrap legal: modal BLOQUEANTE (Términos + Privacidad) ---------- */
.px-legal-locked { overflow: hidden; }
.px-legal-overlay {
  position: fixed;
  inset: 0;
  z-index: 9999;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
  background: rgba(8, 10, 14, 0.72);
  -webkit-backdrop-filter: blur(4px);
  backdrop-filter: blur(4px);
}
.px-legal-card {
  width: 100%;
  max-width: 460px;
  padding: clamp(22px, 3vw, 30px);
  background: var(--panel-solid);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}
.px-legal-title { margin: 0 0 8px; font-size: 20px; color: var(--text); }
.px-legal-text { margin: 0 0 16px; color: var(--text-muted); }
.px-legal-links { display: flex; flex-wrap: wrap; gap: 16px; margin-bottom: 16px; }
.px-legal-links a {
  color: var(--brand);
  font-weight: 700;
  border-bottom: 1px solid rgba(167, 43, 67, 0.26);
}
.px-legal-links a:hover { color: var(--brand-dark); border-color: currentColor; }
.px-legal-check {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  color: var(--text);
  font-size: 14px;
  cursor: pointer;
}
.px-legal-check input[type="checkbox"] {
  margin-top: 2px;
  width: 17px;
  height: 17px;
  flex: 0 0 auto;
  accent-color: var(--brand);
  cursor: pointer;
}
.px-legal-error { margin: 12px 0 0; color: var(--brand-dark); font-size: 13px; }
.px-legal-actions { margin-top: 20px; display: flex; justify-content: flex-end; }
.px-legal-actions .btn[disabled] { opacity: 0.55; cursor: not-allowed; }

/* --- Calendario de escaneos: tarjetas de cadencia + vista previa editable
   (mi-calendario-de-escaneos.html). Antes usaban clases (px-review-grid,
   px-review-block, px-purchase-mode-option) que ninguna hoja de este sitio
   definía, así que se veían como texto plano sin agrupar; estas reglas les
   dan forma real. ------------------------------------------------------- */
.px-review-grid { display: grid; gap: 14px; margin-top: 10px; }
@media (min-width: 640px) {
  .px-review-grid { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
}
.px-review-block {
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  padding: 14px 16px;
}
.px-purchase-mode-option {
  display: flex;
  flex-direction: column;
  gap: 6px;
  cursor: pointer;
  transition: border-color 0.15s ease, background 0.15s ease;
}
.px-purchase-mode-option:hover { border-color: var(--line-strong); }
.px-purchase-mode-option:has(input:checked) {
  border-color: var(--brand);
  background: rgba(167, 43, 67, 0.06);
}
.px-purchase-mode-option input[type="radio"] {
  margin: 0;
  accent-color: var(--brand);
  width: 17px;
  height: 17px;
}

.px-scan-dates-preview { margin-top: 18px; }
.px-scan-dates-preview > .px-muted { margin: 0 0 10px; }
.px-scan-dates-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: 12px;
}
.px-scan-dates-grid .field { margin: 0; }
.px-scan-dates-grid .field span {
  font-size: 12.5px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--text-dim);
}

/* Evolución en los últimos análisis: grilla de tarjetas de tendencia
   compactas (una por métrica — score, cada severidad, cada categoría de
   inventario), cada una con su propia mini línea de tiempo con TODOS los
   períodos del historial (d.history en el portal real / DATA.history en la
   demo pública — ver buildTrendCard en portal.js y en demo-portal.js), no
   solo "antes/ahora". Compactas a propósito: al ser muchas tarjetas juntas,
   una por una con leyenda y ejes grandes se vería saturado — acá el
   valor+variación va en el encabezado de la tarjeta y la línea solo aporta
   la forma de la tendencia. Compartido entre el portal real (clientes/) y
   la demo pública (demo-portal.html) para que se vean idénticas. */
.px-trend-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 10px 14px;
  margin: 4px 0 6px;
}
@media (max-width: 900px) { .px-trend-grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 480px) { .px-trend-grid { grid-template-columns: 1fr; } }
.px-trend-card {
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--panel-solid);
  padding: 10px 12px 8px;
}
.px-trend-card-head { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
.px-trend-card-title { font-size: 12.5px; font-weight: 600; color: var(--text-muted); }
.px-trend-card-value { font: 700 15px "JetBrains Mono", monospace; color: var(--text); white-space: nowrap; }
.px-trend-card-delta { display: inline-block; margin-left: 6px; font-size: 11px; font-weight: 700; }
.px-trend-card-delta.is-mejoro { color: var(--ok); }
.px-trend-card-delta.is-empeoro { color: var(--crit); }
.px-trend-card-delta.is-sin_cambio { color: var(--text-dim); }
.px-trend-card-delta.is-neutral { color: var(--text-dim); }
.px-trend-card-svg { width: 100%; height: 44px; display: block; margin-top: 4px; }
.px-trend-baseline { stroke: var(--line-soft); stroke-width: 1; }
.px-trend-line { fill: none; stroke-width: 2; opacity: 0.9; stroke: var(--brand); }
.px-trend-dot { fill: var(--brand); stroke: var(--panel-solid); stroke-width: 1.5; }
.px-trend-dot.is-last { stroke-width: 2; }
.px-trend-card-foot { display: flex; justify-content: space-between; font-size: 10px; color: var(--text-dim); margin-top: 2px; }
.px-trend-card.is-score .px-trend-line, .px-trend-card.is-score .px-trend-dot { stroke: var(--brand); fill: var(--brand); }
.px-trend-card.is-critical .px-trend-line, .px-trend-card.is-critical .px-trend-dot { stroke: var(--crit); fill: var(--crit); }
.px-trend-card.is-high .px-trend-line, .px-trend-card.is-high .px-trend-dot { stroke: var(--high); fill: var(--high); }
.px-trend-card.is-medium .px-trend-line, .px-trend-card.is-medium .px-trend-dot { stroke: var(--med); fill: var(--med); }
.px-trend-card.is-low .px-trend-line, .px-trend-card.is-low .px-trend-dot { stroke: var(--low); fill: var(--low); }
.px-trend-card.is-neutral-subdomains .px-trend-line, .px-trend-card.is-neutral-subdomains .px-trend-dot { stroke: var(--cyan); fill: var(--cyan); }
.px-trend-card.is-neutral-cloud .px-trend-line, .px-trend-card.is-neutral-cloud .px-trend-dot { stroke: var(--teal); fill: var(--teal); }
.px-trend-card.is-neutral-cctv .px-trend-line, .px-trend-card.is-neutral-cctv .px-trend-dot { stroke: var(--violet); fill: var(--violet); }
.px-trend-caption { margin-top: 2px; }
