/* =====================================================================
   satsm · PANEL — capa de Púlsar para las pantallas de trabajo
   ---------------------------------------------------------------------
   Carga SOLO la Consola (oscura, cian) y el área de cliente (clara, azul).
   La web comercial no la ve: sus 29 páginas siguen con pulsar.css tal cual,
   así que nada de lo que hay aquí puede romperlas.

   Todo lo nuevo va con prefijo `px-`. No es manía: cuando las vistas, el
   CSS y el JavaScript se escriben seguidos es facilísimo que cada uno
   adopte un vocabulario distinto y dejen de encajar SIN dar ni un error —
   el JavaScript se descarga, se ejecuta y no hace nada. El prefijo único
   permite cruzar los tres lados con una prueba (PanelFrontContractTest).

   Orden del fichero:
     0 · Fichas de color, sombra y movimiento
     1 · Armazón (barra lateral, barra superior, lienzo)
     2 · Cabecera de página y pestañas
     3 · Paneles y tarjetas de cifra
     4 · Gráficos
     5 · Tablas de trabajo
     6 · Listas, cronología y estados vacíos
     7 · Avisos, paleta de comandos y cajón
     8 · Pantallas de acceso — piezas comunes
     9 · Ajustes: pestañas, imágenes de marca y barra de guardar
    9b · La Consola renovada: componentes (botones, campos, tablas, cifras…)
    9c · Cabeceras y piezas propias de pantalla (una regla para todas)
    10 · Salud (/salud)
    11 · Mis empresas: continuidad con la web pública
    12 · Tamaños pequeños, impresión y movimiento reducido
     · El centro de avisos y los mensajes (cabecera de la Consola)
   ===================================================================== */


/* =====================================================================
   0 · FICHAS
   ===================================================================== */

:root {
  --px-company-icon-bg: #FFFFFF;
  /* --- Armazón */
  --px-rail: 244px;          /* ancho de la barra lateral desplegada */
  --px-rail-min: 60px;       /* plegada: solo iconos */
  --px-top: 60px;            /* alto de la barra superior */
  --px-gap: 20px;            /* aire entre bloques del lienzo */

  /* --- Movimiento. Una sola curva para todo el panel: mezclar curvas
         hace que dos cosas que se mueven juntas no parezcan la misma. */
  --px-ease: cubic-bezier(.22, .61, .36, 1);
  --px-fast: .14s;
  --px-slow: .26s;

  /* --- Elevación. Tres niveles y ni uno más: en un panel denso cada
         sombra nueva es una capa que el ojo tiene que ordenar. */
  --px-e1: 0 1px 2px rgba(11, 21, 38, .05), 0 1px 3px rgba(11, 21, 38, .06);
  --px-e2: 0 8px 24px -12px rgba(11, 21, 38, .18), 0 2px 6px -2px rgba(11, 21, 38, .06);
  --px-e3: 0 32px 64px -24px rgba(11, 21, 38, .26), 0 4px 12px rgba(11, 21, 38, .07);

  /* --- Colores de DATO (no de interfaz). Validados con el comprobador de
         paletas en su superficie: banda de claridad, suelo de croma,
         separación para daltonismo y contraste contra el fondo.

         s1 es una serie sola; s1/s2 son dos IDENTIDADES distintas. Cuando
         dos series significan bien y mal (altas y bajas) NO se usan estas
         fichas: se usan las de estado, que tienen ese significado
         reservado. */
  --px-s1: #2E5BFF;
  --px-s2: #D9700F;

  /* Rampa ORDINAL (escalones de un proceso: embudo). Una sola tinta en
     pasos de claridad; el paso más claro mantiene 2,05:1 sobre blanco. */
  --px-ord-1: #9DB2FF;
  --px-ord-2: #7090FF;
  --px-ord-3: #3F66FF;
  --px-ord-4: #2448D8;
  --px-ord-5: #15309E;

  /* Rampa SECUENCIAL (magnitud continua: mapa de calor). El tramo 0 es
     «nada» y se parece al fondo a propósito: cero no es poco. */
  --px-seq-0: #EEF1F7;
  --px-seq-1: #C9D6FF;
  --px-seq-2: #9DB2FF;
  --px-seq-3: #5B7CFF;
  --px-seq-4: #2448D8;

  --px-grid: #E8EDF5;        /* rejilla de los gráficos */
  --px-track: #EDF1F8;       /* canal de barras y medidores */
}

/* --- Consola: oscura y con el cian de la plataforma ------------------ */
[data-surface="console"] {
  --px-e1: 0 1px 2px rgba(0, 0, 0, .3);
  --px-e2: 0 10px 28px -14px rgba(0, 0, 0, .55), 0 2px 6px rgba(0, 0, 0, .28);
  --px-e3: 0 36px 72px -28px rgba(0, 0, 0, .7), 0 6px 16px rgba(0, 0, 0, .4);

  /* El cian de marca es el color de UNA serie: brillante, 8,6:1 sobre el
     panel, y sin problema de discriminación porque está solo. Para DOS
     identidades se usan s1a/s2, que sí están dentro de la banda oscura y
     se separan 9,1 ΔE bajo deuteranopia. */
  --px-s1: #22D3EE;
  --px-s1a: #0FA3BF;
  --px-s2: #8A7CF0;

  --px-ord-1: #7FE4F5;
  --px-ord-2: #3FCBE3;
  --px-ord-3: #15A9C6;
  --px-ord-4: #0E7E96;
  --px-ord-5: #0A5A6C;

  --px-seq-0: #16233C;
  --px-seq-1: #12465A;
  --px-seq-2: #0F6E87;
  --px-seq-3: #139DBA;
  --px-seq-4: #22D3EE;

  --px-grid: #1C2A45;
  --px-track: #1A2740;

  /* EL MENÚ CRECE CON LA PANTALLA (29/09/2026). Con 244 px, letra de 13 y
     filas de 32 fijos, en un monitor grande —el del dueño: unos 2.500 px
     útiles al 150 %— la barra lateral se quedaba en una tira diminuta al
     lado de una página enorme. Cada medida va de un mínimo algo mayor que
     el de antes (en un portátil ya se leía justo) a un tope, en proporción
     al ancho: a 1.280 px sale 260 · 14 · 36; a 1.920, 321 · 14,5 · 40; y
     desde unos 2.200, el tope 328 · 15,5 · 42. */
  --px-rail: clamp(260px, 11vw + 110px, 328px);
  --px-rail-min: clamp(60px, 1vw + 46px, 72px);
  --px-nav-fs: clamp(.875rem, .22vw + .64rem, .96875rem);
  --px-nav-h: clamp(36px, .55vw + 29px, 42px);
  --px-nav-ico: clamp(18px, .18vw + 15.7px, 20px);
  --px-nav-cap: clamp(.71875rem, .12vw + .6rem, .78125rem);
}


/* =====================================================================
   1 · ARMAZÓN
   ---------------------------------------------------------------------
   Espacio de trabajo continuo. Desplazamiento de ventana para preservar
   enlaces con ancla, impresión y navegación por teclado.
   ===================================================================== */

/* Lo que ocupa la cabecera pegajosa desde arriba de la ventana. Lo usan
   las piezas pegajosas de las pantallas (listas laterales, índices) para
   quedarse DEBAJO de la barra, y las anclas para no esconderse tras ella.
   Abajo, lo que ocupan los avisos flotantes mientras los haya: lo pone
   panel.js en --px-toasts-reserve (ver «Avisos cortos», bloque 7), para
   que el control que recibe el foco no quede debajo de ellos. */
[data-surface="console"] {
  --px-top: calc(var(--px-top-h) + var(--px-sheet-gap));
  scroll-padding-top: calc(var(--px-top) + 16px);
  scroll-padding-bottom: var(--px-toasts-reserve, 0px);
}
[data-surface="console"] body:has(> .px-shell) { background: var(--canvas); }

/* Las fichas del armazón (--dur-*, --r-ctl, --canvas…) se escriben SIN valor
   de respaldo: todo lo de este bloque solo existe dentro de la Consola, que
   las define siempre (pulsar.css, «LA CONSOLA RENOVADA»). Los respaldos que
   había no se usaban nunca y ni siquiera coincidían entre sí. Lo que
   comparte el área de cliente (los avisos) sí conserva los suyos. */
.px-shell {
  display: grid;
  grid-template-columns: var(--px-rail) minmax(0, 1fr);
  min-height: 100vh;
  min-height: 100dvh;
  transition: grid-template-columns var(--dur-3) var(--ease-out);
}

/* --- Barra lateral ---------------------------------------------------
   Sin fondo propio: es el lienzo. El `z-index` NO es decorativo. Una barra
   pegajosa crea su propio contexto de apilamiento, y sin número propio el
   menú flotante de la barra plegada (fixed, z 70 DENTRO de ese contexto)
   quedaba debajo de la página: cuatro de las cinco entradas de «Negocio»
   no se podían pulsar porque encima había un campo de búsqueda y una
   cabecera de tabla. */
.px-side {
  position: sticky;
  top: 0;
  z-index: var(--z-flyout);
  height: 100vh;
  height: 100dvh;
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: var(--px-sheet-gap) 10px 12px 12px;
  overflow: hidden;
}

/* --- La cabecera de la barra: quién eres y dónde estás ---------------
   Mide lo mismo que la barra superior de la hoja y empieza a la misma
   altura: el logo y las migas quedan en la misma línea. */
.px-side-top {
  flex: none;
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: var(--px-top-h);
  padding-inline: 4px 2px;
}

.px-brand {
  display: flex;
  align-items: center;
  gap: 9px;
  min-width: 0;
  flex: 1;
  padding: 4px 6px;
  font-family: var(--font-display);
  font-weight: 800;
  font-size: calc(var(--px-nav-fs) + .25rem);
  letter-spacing: -.03em;
  color: var(--ink);
  min-height: 36px;
}
.px-brand:hover { color: var(--ink); }
/* Cuando hay logo subido sustituye al símbolo Y al nombre: un logo ya lleva
   el nombre dentro, y ponerlo dos veces lo dice dos veces. Manda la altura y
   no el ancho, para que un logo apaisado y uno cuadrado ocupen la misma
   franja. */
.px-brand-img { height: calc(var(--px-nav-h) - 10px); width: auto; max-width: 100%; object-fit: contain; display: block; }
/* El icono cuadrado de la marca solo sale con la barra plegada. */
.px-brand-ico { display: none; width: 28px; height: 28px; border-radius: 8px; object-fit: contain; flex: none; }
.px-side .px-brand { padding: 4px 6px; min-height: 36px; border-radius: var(--r-ctl); }
.px-side .px-brand:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.px-brand .px-mark {
  width: calc(var(--px-nav-h) - 6px);
  height: calc(var(--px-nav-h) - 6px);
  border-radius: 9px;
  display: grid;
  place-items: center;
  flex: none;
  background: linear-gradient(135deg, var(--accent), color-mix(in srgb, var(--accent) 55%, #FFFFFF));
  color: var(--on-accent);
  box-shadow: 0 2px 10px -3px color-mix(in srgb, var(--accent) 60%, transparent);
}
.px-brand .px-mark svg { width: calc(var(--px-nav-ico) - 2px); height: calc(var(--px-nav-ico) - 2px); max-width: none; }

/* EN QUÉ ENTORNO ESTÁS. Es lo único que queda de la cinta cian de arriba, y
   aquí no se va con el desplazamiento. En local, una chapa neutra que no
   compite con nada; en PRODUCCIÓN, ámbar macizo, que es cuando hay que
   fijarse. Ámbar y no verde: aquí verde diría «todo bien» cuando lo que
   dice es «cuidado, esto es real». */
.px-env {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 20px;
  padding: 0 8px 0 7px;
  border: 1px solid var(--line-2);
  border-radius: var(--r-full);
  color: var(--muted);
  font-size: var(--t-2xs);
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
  line-height: 1;
}
.px-env b { font-weight: 600; }
/* La misma chapa en la cabecera solo sale en ≤1000 px, donde la barra lateral
   es un cajón cerrado (ver el bloque de 1000). */
.px-top .px-env { display: none; }
.px-env-dot {
  flex: none;
  width: 6px;
  height: 6px;
  border-radius: var(--r-full);
  background: currentColor;
}
.px-env.is-live {
  color: var(--warn-soft);
  border-color: var(--warn);
  background: var(--warn);
}

/* La × del cajón: solo existe en el móvil (ver el bloque de ≤1000 px). Con
   las dos clases, para ganarle al `display` del botón de icono. */
.px-iconbtn.px-side-x { display: none; }

.px-nav {
  display: flex;
  flex-direction: column;
  gap: 1px;
  overflow-y: auto;
  overflow-x: hidden;
  flex: 1;
  padding: 2px 2px 8px;
  /* Al saltar con el tabulador, la fila que recibe el foco no puede quedarse
     pegada al borde de la zona que se desplaza: WCAG 2.2 pide que el foco se
     siga viendo, y 40 px es una fila con su aire. */
  scroll-padding-block: 40px;
  /* Barra de desplazamiento discreta: en una lista de veinte entradas la
     barra del sistema ocupa más atención que cualquiera de ellas. */
  scrollbar-width: thin;
  scrollbar-color: var(--line-2) transparent;
}
.px-nav::-webkit-scrollbar { width: 6px; }
.px-nav::-webkit-scrollbar-thumb { background: var(--line-2); border-radius: 3px; }

/* FILTRAR EL MENÚ. Discreto a propósito: la búsqueda de verdad es la
   paleta (Ctrl/⌘ K) y esto solo acota la lista. Pero es un campo, y su
   borde es lo que dice dónde se escribe: --border-control (3:1 sobre el
   lienzo, WCAG 1.4.11). Con --line se quedaba en 1,47:1 y el campo no se
   veía. */
.px-nav-search {
  display: none;
  align-items: center;
  gap: 8px;
  flex: none;
  height: calc(var(--px-nav-h) - 2px);
  margin: 2px 2px 8px;
  padding: 0 6px 0 11px;
  border: 1px solid var(--border-control);
  border-radius: var(--r-ctl);
  background: color-mix(in srgb, var(--surface) 45%, transparent);
  color: var(--muted);
  transition: border-color var(--dur-1) var(--ease-out),
              box-shadow var(--dur-1) var(--ease-out),
              background-color var(--dur-1) var(--ease-out);
}
.px-js .px-nav-search { display: flex; }
.px-nav-search > svg { flex: none; width: calc(var(--px-nav-ico) - 2px); height: calc(var(--px-nav-ico) - 2px); max-width: none; }
.px-nav-search:hover { border-color: var(--border-hover); }
.px-nav-search:focus-within {
  border-color: var(--accent);
  background: var(--surface-sunken);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 20%, transparent);
}
/* Con el id: las reglas generales de los campos de la Consola (alto,
   fondo, borde) no pueden meterse dentro de esta caja. */
.px-nav-search #px-nav-q {
  width: 100%;
  min-width: 0;
  height: 100%;
  border: 0;
  outline: 0;
  box-shadow: none;
  background: transparent;
  padding: 0;
  color: var(--ink);
  font: inherit;
  font-size: var(--px-nav-fs);
  line-height: normal;
}
.px-nav-search #px-nav-q::placeholder { color: var(--placeholder); opacity: 1; }
.px-nav-search #px-nav-q::-webkit-search-cancel-button { display: none; }
.px-nav-search button { flex: none; border: 0; background: transparent; color: var(--muted); width: 24px; height: 24px; padding: 0; border-radius: 6px; display: grid; place-items: center; cursor: pointer; }
.px-nav-search button:hover { background: var(--surface-hover); color: var(--ink); }
.px-nav-search button:focus-visible { outline: 2px solid var(--accent); outline-offset: 0; }
/* La lupa que abre la paleta: solo con la barra plegada. */
.px-nav-search .px-nav-find { display: none; }
/* El atajo se anuncia mientras el campo está en reposo y se quita en cuanto
   hay foco (ahí ya sobra y le roba sitio al texto), en las pantallas
   táctiles y con los atajos de una tecla apagados (ver «Sin teclado no se
   ofrecen atajos» y «Atajos de una tecla apagados» en el bloque 12). */
.px-nav-kbd { flex: none; }
.px-nav-search:focus-within .px-nav-kbd { display: none; }

/* Rótulo de bloque («Accesos rápidos»): plano, como los de los grupos. */
.px-nav-caption {
  display: flex;
  align-items: center;
  gap: 6px;
  margin: 0;
  padding: 14px 12px 6px;
  font-size: var(--px-nav-cap);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--muted);
  /* Es un rótulo y no se pulsa: la flecha de siempre, no la mano ni la
     barra de texto, para no confundirlo con los grupos de debajo. */
  cursor: default;
}
.px-nav-caption > span:first-child { flex: none; }
.px-nav-caption-n {
  flex: none;
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  border-radius: var(--r-full);
  background: var(--surface-3);
  color: var(--muted);
  font-size: var(--t-2xs);
  font-weight: 600;
  letter-spacing: 0;
  font-variant-numeric: tabular-nums;
  display: grid;
  place-items: center;
}
.px-nav-caption-n:empty { display: none; }

.px-nav-favorites { flex: none; }

/* LOS GRUPOS SON RÓTULOS PLANOS, no cajas. Un grupo abierto se dibujaba
   como una caja con fondo y filo: un acordeón de plantilla de
   administración. Ahora es un rótulo de 11 px en mayúsculas y las entradas
   debajo, alineadas con él. Pero un rótulo plano con el galón escondido
   parecía un título inerte: con los grupos cerrados, «CLIENTES, NEGOCIO,
   SISTEMA» sin nada debajo no invitaba a abrir nada. Así que el galón se
   ve siempre (tenue, sin competir con las entradas), y al pasar el ratón
   el grupo se ilumina como una entrada más. */
.px-nav-section { flex: none; margin-top: 8px; }
.px-nav-section > summary {
  display: flex;
  align-items: center;
  gap: 6px;
  min-height: calc(var(--px-nav-h) - 4px);
  padding: 4px 10px 4px 12px;
  border-radius: var(--r-ctl);
  color: var(--muted);
  cursor: pointer;
  list-style: none;
  user-select: none;
  font-size: var(--px-nav-cap);
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
  transition: background-color var(--dur-1) var(--ease-out), color var(--dur-1) var(--ease-out);
}
.px-nav-section > summary::-webkit-details-marker { display: none; }
.px-nav-section > summary:hover { background: var(--surface-hover); }
.px-nav-section > summary:hover,
.px-nav-section > summary.is-active { color: var(--ink-2); }

/* La baldosa del grupo solo existe con la barra plegada, donde es TODO lo
   que queda del grupo (ver más abajo). Desplegada, los iconos son de las
   entradas. */
.px-nav-tile { display: none; }
.px-nav-tile svg { width: var(--px-nav-ico); height: var(--px-nav-ico); max-width: none; }
.px-nav-label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.px-nav-section .px-nav-chevron {
  flex: none;
  width: 14px;
  height: 14px;
  color: var(--muted);
  opacity: .55;
  rotate: -90deg;
  transition: rotate var(--dur-2) var(--ease-out), opacity var(--dur-1) var(--ease-out);
}
:root[dir="rtl"] .px-nav-section .px-nav-chevron { rotate: 90deg; }
.px-nav-section[open] .px-nav-chevron { rotate: 0deg; }
.px-nav-section > summary:hover .px-nav-chevron,
.px-nav-section > summary:focus-visible .px-nav-chevron { opacity: 1; }

/* El número del grupo, solo con el grupo CERRADO: abierto se leen los de
   dentro, y el mismo número dos veces era ruido. */
.px-nav-section[open] > summary > .px-n { display: none; }

.px-nav-entries { padding: 2px 0 0; }

.px-nav-entry { display: flex; align-items: center; position: relative; min-width: 0; }
.px-nav .px-nav-entry > a { flex: 1; min-width: 0; }
.px-nav-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.px-nav .px-nav-top { margin-bottom: 2px; }

/* FIJAR MUEVE, NO COPIA. Mientras una entrada está en accesos rápidos sale
   de su grupo, así que ningún destino aparece dos veces ni hay dos filas
   con «estás aquí». Durante una búsqueda vuelven todas: se busca en el menú
   entero, y ahí los accesos rápidos se esconden. */
.px-nav:not(.is-searching) .px-nav-entries > .px-nav-entry.is-pinned { display: none; }
.px-nav:not(.is-searching) .px-nav-section.is-emptied { display: none; }

/* LA ESTRELLA DE FIJAR, escondida hasta que se pasa por la fila o se
   llega con el teclado: tres estrellas cian encendidas siempre eran tres
   manchas de ruido en la zona más mirada del menú. La de una entrada ya
   fijada sale tenue; se enciende al apuntarla. Mientras se ve, tapa el
   número de la fila (que sigue en el texto accesible). En pantallas
   táctiles, donde no hay «pasar por encima», se ven siempre y la fila les
   deja sitio. */
.px-nav-pin {
  display: none;
  position: absolute;
  inset-inline-end: 3px;
  top: 50%;
  transform: translateY(-50%);
  width: 26px;
  height: 26px;
  border: 0;
  border-radius: 6px;
  background: transparent;
  color: var(--muted);
  cursor: pointer;
  opacity: 0;
  transition: opacity var(--dur-1) var(--ease-out), color var(--dur-1) var(--ease-out),
              background-color var(--dur-1) var(--ease-out);
}
.px-js .px-nav-pin { display: grid; place-items: center; }
.px-nav-pin svg { width: 15px; height: 15px; max-width: none; }
.px-nav-pin-off, .px-nav-pin-on { display: grid; place-items: center; }
.px-nav-pin[aria-pressed="false"] .px-nav-pin-on,
.px-nav-pin[aria-pressed="true"] .px-nav-pin-off { display: none; }
.px-nav-entry:hover .px-nav-pin, .px-nav-entry:focus-within .px-nav-pin { opacity: 1; }
.px-js .px-nav-entry:hover > a > .px-n, .px-js .px-nav-entry:focus-within > a > .px-n { visibility: hidden; }
.px-nav-pin:hover { background: var(--surface-hover); color: var(--accent); }
.px-nav-pin[aria-pressed="true"] { color: color-mix(in srgb, var(--muted) 70%, transparent); }
.px-nav-pin[aria-pressed="true"]:hover { color: var(--accent); }
.px-nav a:focus-visible, .px-nav-pin:focus-visible, .px-nav-section > summary:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

/* Lo que ha coincidido con lo escrito, marcado en la propia fila: sin esto,
   una búsqueda de tres letras devuelve seis entradas y no se ve por qué. */
.px-nav-hit { background: color-mix(in srgb, var(--accent) 26%, transparent); color: var(--ink); border-radius: 3px; padding: 0 1px; }

.px-nav-empty, .px-nav-feedback { margin: 8px 10px; font-size: var(--t-2xs); line-height: 1.6; color: var(--muted); }
.px-nav-feedback { padding: 8px 10px; border: 1px solid var(--line-2); border-radius: var(--r-ctl); background: color-mix(in srgb, var(--surface) 60%, transparent); }

@media (hover: none) {
  .px-nav-pin { opacity: 1; }
  .px-js .px-nav .px-nav-entry > a { padding-inline-end: 40px; }
  .px-js .px-nav-entry:hover > a > .px-n, .px-js .px-nav-entry:focus-within > a > .px-n { visibility: visible; }
}
/* Con el dedo la estrella mide 44 (ver «Con el dedo», al final del
   fichero) y la fila le deja 48. Va AQUÍ, delante de la barra plegada, a
   propósito: pesa lo mismo que su `padding: 0` y así solo vale con la barra
   desplegada (y en el cajón del móvil). Detrás, en una tableta táctil de
   más de 1000 px con la barra plegada, corría el icono de los accesos
   rápidos a la izquierda y lo cortaba. */
@media (pointer: coarse) {
  .px-js .px-nav .px-nav-entry > a { padding-inline-end: 48px; }
}

/* --- LA BARRA PLEGADA (solo en escritorio) ----------------------------
   Todo lo plegado vive dentro de `min-width: 1001px`: en el móvil la barra
   es un cajón y una preferencia de escritorio no puede esconderle las
   etiquetas (antes hacía falta un bloque entero para deshacerlo). Los
   iconos no se mueven de su fila al plegar: si todo salta, la mano que ya
   sabe dónde está «Cuentas» deja de servir. */
@media (min-width: 1001px) {
  :root.px-rail-off .px-shell { grid-template-columns: var(--px-rail-min) minmax(0, 1fr); }
  :root.px-rail-off .px-side { padding-inline: 8px; }
  :root.px-rail-off .px-side-top { flex-direction: column; justify-content: center; gap: 6px; padding-inline: 0; }
  :root.px-rail-off .px-side .px-brand { flex: none; justify-content: center; padding: 4px; }
  :root.px-rail-off .px-brand-img { display: none; }
  :root.px-rail-off .px-brand-ico { display: block; }
  /* El entorno queda en un punto; su nombre sigue en el texto oculto y en
     el globo del ratón. En producción, el punto es ámbar. */
  :root.px-rail-off .px-env { width: 10px; height: 10px; padding: 0; gap: 0; border: 0; background: none; justify-content: center; }
  :root.px-rail-off .px-env.is-live { color: var(--warn); }
  :root.px-rail-off .px-env b { display: none; }
  :root.px-rail-off .px-env-dot { width: 8px; height: 8px; }

  :root.px-rail-off .px-nav-search { justify-content: center; height: auto; margin: 0 0 6px; padding: 0; border: 0; background: none; box-shadow: none; }
  :root.px-rail-off .px-nav-search > :not(.px-nav-find) { display: none !important; }
  :root.px-rail-off .px-nav-search .px-nav-find { display: grid; width: calc(var(--px-rail-min) - 20px); height: var(--px-nav-h); border-radius: var(--r-ctl); color: var(--muted); }
  :root.px-rail-off .px-nav-search .px-nav-find svg { width: var(--px-nav-ico); height: var(--px-nav-ico); }
  :root.px-rail-off .px-nav-search .px-nav-find:hover { background: var(--surface-hover); color: var(--ink); }

  :root.px-rail-off .px-nav-caption { display: none; }
  :root.px-rail-off .px-nav-favorites { padding-bottom: 6px; margin-bottom: 2px; border-bottom: 1px solid var(--line); }
  :root.px-rail-off .px-nav a { width: calc(var(--px-rail-min) - 20px); height: var(--px-nav-h); min-height: var(--px-nav-h); margin-inline: auto; padding: 0; justify-content: center; }
  :root.px-rail-off .px-nav a > svg { width: var(--px-nav-ico); height: var(--px-nav-ico); }
  :root.px-rail-off .px-nav-pin { display: none; }

  /* Los nombres se esconden a la vista pero NO al lector de pantalla: son
     el nombre accesible de cada enlace, grupo y botón. Con `display: none`,
     plegada, «Solicitudes» se anunciaba como su contador («44 pendientes»)
     y el logo, sin logo subido, se quedaba sin nombre. */
  :root.px-rail-off :is(.px-brand-name, .px-nav a > .px-nav-name, .px-nav-section > summary > .px-nav-label, .px-side-link-t) {
    position: absolute; width: 1px; height: 1px; overflow: hidden;
    clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
  }

  /* LOS CONTADORES NO DESAPARECEN AL PLEGAR: quedan como un punto sobre el
     icono, del color de lo que corre, y con su número en el menú flotante.
     Antes la regla que escondía los rótulos se llevaba también el número
     (era otro `span`) y la barra plegada no avisaba de nada. */
  :root.px-rail-off .px-nav .px-n,
  :root.px-rail-off .px-nav-section[open] > summary > .px-n {
    display: block;
    position: absolute;
    top: 6px;
    inset-inline-end: 7px;
    min-width: 0;
    width: 8px;
    height: 8px;
    padding: 0;
    border-radius: var(--r-full);
    background: var(--muted);
    box-shadow: 0 0 0 2px var(--canvas);
    visibility: visible;
  }
  :root.px-rail-off .px-nav .px-n.is-danger { background: var(--danger); }
  :root.px-rail-off .px-nav .px-n.is-warn { background: var(--warn); }
  :root.px-rail-off .px-nav .px-n.is-accent { background: var(--accent); }
  :root.px-rail-off .px-nav .px-n > [aria-hidden] { display: none; }
  /* Plegada no hay estrella que enseñar: el número no se esconde al pasar. */
  :root.px-rail-off .px-nav-entry:hover > a > .px-n,
  :root.px-rail-off .px-nav-entry:focus-within > a > .px-n { visibility: visible; }

  :root.px-rail-off .px-nav-section { margin-top: 2px; }
  /* Sin el fondo del rótulo desplegado: aquí se ilumina la baldosa. */
  :root.px-rail-off .px-nav-section > summary { position: relative; justify-content: center; width: calc(var(--px-rail-min) - 20px); height: var(--px-nav-h); min-height: var(--px-nav-h); margin-inline: auto; padding: 0; background: none; }
  :root.px-rail-off .px-nav-chevron,
  :root.px-rail-off .px-nav-section:not(.px-nav-flyout) > .px-nav-entries { display: none; }
  :root.px-rail-off .px-nav-tile {
    display: grid;
    place-items: center;
    width: calc(var(--px-rail-min) - 20px);
    height: var(--px-nav-h);
    border-radius: var(--r-ctl);
    color: var(--muted);
    transition: background-color var(--dur-1) var(--ease-out), color var(--dur-1) var(--ease-out);
  }
  :root.px-rail-off .px-nav-section > summary:hover .px-nav-tile,
  :root.px-rail-off .px-nav-flyout > summary .px-nav-tile { background: var(--surface-hover); color: var(--ink); }
  /* El grupo de la pantalla actual se marca… salvo si esa pantalla está en
     los accesos rápidos: ahí ya se ilumina su icono, y dos marcas de «estás
     aquí» para una sola pantalla no dicen dónde estás. */
  :root.px-rail-off .px-nav-favorites:not(:has([aria-current="page"])) ~ .px-nav-section > summary.is-active .px-nav-tile { background: var(--surface-selected); color: var(--accent); }

  :root.px-rail-off .px-side-foot { justify-items: center; }
  :root.px-rail-off .px-side-link { width: calc(var(--px-rail-min) - 20px); height: var(--px-nav-h); min-height: var(--px-nav-h); padding: 0; justify-content: center; }
  :root.px-rail-off .px-side-link .px-kbd { display: none; }

  /* EL MENÚ FLOTANTE DE LA BARRA PLEGADA.
     Plegada, un grupo era un icono que al pulsarlo desplegaba la barra
     entera: cuatro pasos para llegar a «Salud». Ahora el grupo saca sus
     entradas al lado, como cualquier menú, y se llega en uno. Va en
     `position: fixed` porque la barra recorta lo que se sale (overflow) y
     la lista se desplaza; lo coloca panel.js. Es una capa flotante más:
     la misma superficie, sombra y entrada que los menús. */
  .px-nav-flyout > .px-nav-entries {
    position: fixed;
    z-index: var(--z-flyout);
    min-width: 224px;
    max-width: 290px;
    padding: 6px;
    border: 1px solid var(--line-2);
    border-radius: var(--r-pop);
    background: var(--surface-overlay);
    box-shadow: var(--e3);
    animation: px-flyout-in var(--dur-2) var(--ease-out);
  }
  /* Plegada no se sabe de qué grupo es cada icono: el flotante lo dice. */
  .px-nav-flyout > .px-nav-entries::before {
    content: attr(data-title);
    display: block;
    padding: 4px 10px 6px;
    font-size: var(--t-2xs);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .06em;
    color: var(--muted);
  }
  /* Un puente invisible sobre los 8 px que separan el icono del flotante:
     sin él, llevar el ratón hacia el menú lo cerraba a medio camino (se
     salía del grupo antes de llegar) y solo se podía usar pulsando. */
  .px-nav-flyout > .px-nav-entries::after {
    content: "";
    position: absolute;
    inset-block: 0;
    inset-inline-start: -10px;
    width: 10px;
  }
  :root.px-rail-off .px-nav .px-nav-flyout a { width: auto; height: auto; min-height: 32px; margin: 0; padding: 5px 10px; justify-content: flex-start; }
  :root.px-rail-off .px-nav .px-nav-flyout a > svg { width: 16px; height: 16px; }
  /* En el flotante el nombre vuelve a verse (deshace el recorte de arriba). */
  :root.px-rail-off .px-nav .px-nav-flyout .px-nav-name { position: static; width: auto; height: auto; clip: auto; clip-path: none; }
  :root.px-rail-off .px-nav .px-nav-flyout .px-n {
    position: static;
    width: auto;
    min-width: 18px;
    height: 18px;
    padding: 0 5px;
    display: inline-grid;
    box-shadow: none;
    background: var(--surface-3);
    color: var(--muted);
  }
  :root.px-rail-off .px-nav .px-nav-flyout .px-n.is-danger { background: var(--danger-soft); color: var(--danger); }
  :root.px-rail-off .px-nav .px-nav-flyout .px-n.is-warn { background: var(--warn-soft); color: var(--warn); }
  :root.px-rail-off .px-nav .px-nav-flyout .px-n.is-accent { background: var(--accent-soft); color: var(--accent); }
  :root.px-rail-off .px-nav .px-nav-flyout .px-n > [aria-hidden] { display: inline; }
}

@keyframes px-flyout-in { from { opacity: 0; translate: -4px 0; } }

/* LAS ENTRADAS: de 14 a 15,5 px y de 36 a 42 de alto según la pantalla
   (--px-nav-fs y --px-nav-h, bloque 0), radio de control. La activa no
   lleva degradado, filo ni marca lateral: fondo seleccionado y el icono en
   el acento. Se lee «estás aquí» sin que la fila grite más que la página. */
.px-nav a {
  display: flex;
  align-items: center;
  gap: 12px;
  min-height: var(--px-nav-h);
  padding: 6px 12px;
  border-radius: var(--r-ctl);
  font-size: var(--px-nav-fs);
  font-weight: 500;
  line-height: 1.3;
  color: var(--ink-2);
  position: relative;
  transition: background-color var(--dur-1) var(--ease-out), color var(--dur-1) var(--ease-out);
}
.px-nav a > svg { width: var(--px-nav-ico); height: var(--px-nav-ico); max-width: none; flex: none; color: var(--muted); transition: color var(--dur-1) var(--ease-out); }
.px-nav a:hover { background: var(--surface-hover); color: var(--ink); }
.px-nav a:hover > svg { color: var(--ink-2); }

.px-nav a[aria-current="page"] {
  background: var(--surface-selected);
  color: var(--ink);
  font-weight: 600;
}
.px-nav a[aria-current="page"] > svg { color: var(--accent); }

/* LOS CONTADORES DICEN CUÁNTO CORRE (ConsoleNav::tonoDe): rojo para lo roto
   o lo que vence, ámbar para lo que tiene un plazo corriendo, acento para
   lo que espera una respuesta, neutro para lo informativo. Antes eran todos
   rojos, y un rojo que sale siempre —el de soporte, el de las solicitudes—
   enseña a no mirar el rojo. Pastilla de 18 px con cifras tabulares: «9» y
   «10» miden lo mismo de alto y el número no baila al cambiar. */
.px-nav .px-n {
  flex: none;
  min-width: 20px;
  height: 20px;
  padding: 0 6px;
  border-radius: var(--r-full);
  background: var(--surface-3);
  color: var(--muted);
  font-size: var(--px-nav-cap);
  font-weight: 600;
  line-height: 1;
  letter-spacing: 0;
  text-transform: none;
  font-variant-numeric: tabular-nums;
  display: inline-grid;
  place-items: center;
}
.px-nav .px-n.is-danger { background: var(--danger-soft); color: var(--danger); }
.px-nav .px-n.is-warn { background: var(--warn-soft); color: var(--warn); }
.px-nav .px-n.is-accent { background: var(--accent-soft); color: var(--accent); }

/* --- El pie de la barra: atajos y la web ---------------------------- */
.px-side-foot {
  flex: none;
  display: grid;
  gap: 1px;
  padding-top: 8px;
  border-top: 1px solid var(--line);
}
.px-side-link {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  min-height: var(--px-nav-h);
  padding: 6px 12px;
  border: 0;
  border-radius: var(--r-ctl);
  background: transparent;
  color: var(--muted);
  font: inherit;
  font-size: var(--px-nav-fs);
  line-height: 1.3;
  text-align: start;
  cursor: pointer;
  transition: background-color var(--dur-1) var(--ease-out), color var(--dur-1) var(--ease-out);
}
.px-side-link:hover { background: var(--surface-hover); color: var(--ink); }
.px-side-link:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.px-side-link > svg { width: var(--px-nav-ico); height: var(--px-nav-ico); max-width: none; flex: none; }
.px-side-link-t { flex: 1; min-width: 0; }

.px-av {
  flex: none;
  width: 32px;
  height: 32px;
  border-radius: var(--r-full);
  display: grid;
  place-items: center;
  background: var(--accent);
  color: var(--on-accent);
  font-weight: 700;
  font-size: var(--t-sm);
  text-transform: uppercase;
  letter-spacing: 0;
}
.px-av-sm { width: 26px; height: 26px; font-size: var(--t-xs); }
.px-av-lg { width: 38px; height: 38px; font-size: var(--t-base); }

/* --- La hoja -------------------------------------------------------- */
.px-main {
  min-width: 0;
  display: flex;
  flex-direction: column;
  margin: 0;
  min-height: calc(100vh - 2 * var(--px-sheet-gap));
  min-height: calc(100dvh - 2 * var(--px-sheet-gap));
  background: var(--bg);
  border: 0;
  border-radius: 0;
}
/* --- La barra superior (56 px, dentro de la hoja) -------------------
   Fondo MACIZO y sin desenfoque, a propósito: un `backdrop-filter` la
   convertiría en el bloque contenedor de todo lo que va `fixed` dentro —
   las capas flotantes de ≤560 px dejarían de medirse contra la pantalla. */
.px-top {
  position: sticky;
  top: var(--px-sheet-gap);
  z-index: var(--z-topbar);
  display: flex;
  align-items: center;
  gap: 6px;
  height: var(--px-top-h);
  margin: 0;
  padding: 0 12px 0 10px;
  background: var(--bg);
  border: 0;
  border-bottom: 1px solid var(--line);
  border-radius: 0;
}
/* Con una capa abierta (menú de cuenta, campana), la barra sube por encima
   de los avisos flotantes: un «guardado» no puede tapar el menú que se
   acaba de abrir. */
.px-top:has(details[open]) { z-index: calc(var(--z-toast) + 1); }
/* EN PRODUCCIÓN, UNA LÍNEA ÁMBAR bajo la barra, a todas las anchuras. La
   chapa de entorno está en la barra lateral o, en ≤1000 px, en la cabecera,
   y en ≤400 px se queda en un punto: la línea dice «esto es real» aunque la
   chapa esté plegada o escondida. Es una sombra por dentro, que no ocupa
   sitio ni mueve nada, y el mismo ámbar de la chapa (--warn). */
.px-top.is-live { box-shadow: inset 0 -2px 0 var(--warn); }

/* Botón de icono de la cabecera: plegar, menú, campana, mensajes. Visible
   a todas las anchuras (antes la campana compartía clase con «plegar» y
   desaparecía con él por debajo de 1000 px). */
.px-iconbtn {
  flex: none;
  position: relative;
  display: inline-grid;
  place-items: center;
  width: var(--ctl-sm);
  height: var(--ctl-sm);
  padding: 0;
  border: 1px solid transparent;
  border-radius: var(--r-ctl);
  background: transparent;
  color: var(--muted);
  cursor: pointer;
  list-style: none;
  transition: background-color var(--dur-1) var(--ease-out), color var(--dur-1) var(--ease-out);
}
.px-iconbtn::-webkit-details-marker { display: none; }
.px-iconbtn:hover,
details[open] > .px-iconbtn { background: var(--surface-hover); color: var(--ink); }
.px-iconbtn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.px-iconbtn svg { width: 18px; height: 18px; max-width: none; }

/* La hamburguesa solo en el móvil; plegar solo en escritorio. */
.px-burger { display: none; }

/* Migas: «Grupo › Sección › Título». Se lee la última con más peso: es
   donde estás. El grupo no es enlace (no tiene pantalla propia). */
.px-crumbs {
  flex: 0 1 auto;
  min-width: 0;
  margin-inline-start: 2px;
  font-size: var(--t-ui);
  color: var(--muted);
}
.px-crumbs ol { display: flex; align-items: center; gap: 0; min-width: 0; margin: 0; padding: 0; list-style: none; }
.px-crumbs li { display: flex; align-items: center; min-width: 0; white-space: nowrap; }
.px-crumbs li:not(:last-child) { flex: none; }
.px-crumbs-group { padding: 4px 6px; }
.px-crumbs a { color: var(--muted); padding: 4px 6px; border-radius: 6px; transition: color var(--dur-1) var(--ease-out), background-color var(--dur-1) var(--ease-out); }
.px-crumbs a:hover { color: var(--ink); background: var(--surface-hover); }
.px-crumbs a:focus-visible { outline: 2px solid var(--accent); outline-offset: 0; }
.px-crumbs .px-sep { display: inline-grid; place-items: center; flex: none; color: var(--line-strong); }
.px-crumbs .px-sep svg { width: 14px; height: 14px; max-width: none; }
:root[dir="rtl"] .px-crumbs .px-sep svg { scale: -1 1; }
.px-crumbs-now { min-width: 0; padding: 4px 6px; color: var(--ink); font-weight: 600; overflow: hidden; text-overflow: ellipsis; }
/* La sección de una pantalla de dentro («Cuentas» en la ficha de una
   empresa) es el camino de vuelta: cede ancho antes que el título. */
.px-crumbs li.px-crumbs-up { flex: 0 1 auto; min-width: 48px; }
.px-crumbs-up a { overflow: hidden; text-overflow: ellipsis; }

.px-top-right { display: flex; align-items: center; gap: 4px; margin-inline-start: auto; flex: none; }

/* Buscador: no es un campo, es un botón que abre la paleta. Un campo
   vacío en la barra invita a escribir ahí y luego el resultado aparece en
   otro sitio; el botón dice la verdad sobre lo que va a pasar. La tecla,
   ⌘K o Ctrl K, la decide panel-boot.js antes de pintar (`px-mac`). */
.px-search {
  position: relative;
  display: flex;
  align-items: center;
  gap: 8px;
  height: var(--ctl-sm);
  min-width: 232px;
  margin-inline-end: 6px;
  padding: 0 5px 0 10px;
  border: 1px solid var(--line-2);
  border-radius: var(--r-ctl);
  background: var(--surface-raised);
  color: var(--muted);
  font: inherit;
  font-size: var(--t-ui);
  cursor: pointer;
  transition: border-color var(--dur-1) var(--ease-out), color var(--dur-1) var(--ease-out);
}
.px-search:hover { border-color: var(--border-hover); color: var(--ink-2); }
.px-search:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.px-search > svg { width: 15px; height: 15px; max-width: none; flex: none; }
.px-search-t { flex: 1; text-align: start; }

.px-kbd {
  display: inline-grid;
  place-items: center;
  min-width: 20px;
  height: 20px;
  padding: 0 5px;
  border: 1px solid var(--line-2);
  border-radius: 5px;
  background: var(--surface);
  color: var(--muted);
  font-family: var(--font-mono);
  font-size: var(--t-2xs);
  font-weight: 500;
  line-height: 1;
  white-space: nowrap;
}
/* ⌘ en un Mac, Ctrl en el resto: el marcado trae las dos. */
:root:not(.px-mac) .px-kbd-mac,
:root.px-mac .px-kbd-pc { display: none; }

/* --- El menú de cuenta (cabecera, a la derecha) ---------------------- */
.px-menu > .px-me-btn {
  display: grid;
  place-items: center;
  width: var(--ctl-sm);
  height: var(--ctl-sm);
  margin-inline-start: 2px;
  border-radius: var(--r-full);
}
/* El avatar de la cabecera, NEUTRO: en esa esquina el acento quiere decir
   «hay algo nuevo» (las pastillas de Mensajes y Avisos), y una «A» cian al
   lado le quitaba fuerza a la señal y se confundía con el primario. */
.px-me-btn .px-av {
  width: 28px;
  height: 28px;
  background: var(--surface-3);
  color: var(--ink);
  font-size: var(--t-ui);
  box-shadow: inset 0 0 0 1px var(--line-2);
  transition: box-shadow var(--dur-1) var(--ease-out);
}
.px-me-btn:hover .px-av,
.px-me[open] > .px-me-btn .px-av { box-shadow: inset 0 0 0 1px var(--line-2), 0 0 0 2px var(--bg), 0 0 0 4px var(--line-2); }
.px-me-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.px-menu-pop.px-me-pop { width: 280px; min-width: 0; }
.px-me-card { display: flex; align-items: center; gap: 12px; padding: 8px 8px 10px; }
.px-me-id { display: grid; gap: 1px; min-width: 0; }
.px-me-name { overflow: hidden; color: var(--ink); font-size: var(--t-sm); font-weight: 600; text-overflow: ellipsis; white-space: nowrap; }
.px-me-mail { color: var(--muted); font-size: var(--t-xs); overflow-wrap: anywhere; }
.px-me-role {
  justify-self: start;
  margin-top: 5px;
  padding: 2px 8px;
  border-radius: var(--r-full);
  background: var(--accent-soft);
  color: var(--accent);
  font-size: var(--t-2xs);
  font-weight: 600;
  line-height: 1.4;
}
.px-me-switch-t { display: grid; flex: 1; min-width: 0; gap: 1px; }
.px-me-switch-t small { color: var(--muted); font-size: var(--t-2xs); line-height: 1.3; }

/* El interruptor: un sí/no de verdad (`role="switch"`), no un botón que
   cambia de color. La pastilla apagada lleva filo de control (3:1). */
.px-switch {
  flex: none;
  position: relative;
  width: 30px;
  height: 18px;
  border-radius: var(--r-full);
  background: var(--surface-3);
  box-shadow: inset 0 0 0 1px var(--border-control);
  transition: background-color var(--dur-1) var(--ease-out), box-shadow var(--dur-1) var(--ease-out);
}
.px-switch::after {
  content: "";
  position: absolute;
  top: 3px;
  inset-inline-start: 3px;
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: var(--ink-2);
  transition: translate var(--dur-2) var(--ease-out), background-color var(--dur-1) var(--ease-out);
}
[aria-checked="true"] > .px-switch { background: var(--accent); box-shadow: inset 0 0 0 1px var(--accent); }
[aria-checked="true"] > .px-switch::after { translate: 12px 0; background: var(--on-accent); }
:root[dir="rtl"] [aria-checked="true"] > .px-switch::after { translate: -12px 0; }

/* A PANTALLA COMPLETA, SIN TOPE (29/09/2026). Hubo un tope de 1.680 px
   centrado, y en un monitor grande dejaba dos bandas vacías a los lados
   de cada pantalla: el dueño lo quiere todo a lo ancho. Lo que no debe
   estirarse sin límite lo acota cada pieza por dentro, no la página: los
   párrafos van a 72ch, las rejillas de cifras reparten columnas según el
   ancho y las tablas lo aprovechan entero. El aire lateral sí crece con la
   pantalla, para que el contenido no quede pegado al filo de la hoja. */
.px-body { flex: 1; width: 100%; padding: 20px clamp(16px, 1.8vw, 44px) 56px; min-width: 0; }
.px-body > * + * { margin-top: var(--px-gap); }


/* --- Armazón del ÁREA DE CLIENTE ------------------------------------
   Sin barra lateral, y a propósito: quien entra aquí tiene una tienda —dos
   o tres como mucho— y viene a hacer una cosa concreta antes de meterse en
   su ERP. Una lateral de catorce entradas para tres pantallas es ruido.

   La cabecera se comparte con la web; el contenido mantiene su jerarquía
   y los formularios conservan una columna de lectura cómoda. */
.px-app { min-height: 100vh; min-height: 100dvh; display: flex; flex-direction: column; background: var(--bg); }

.px-appmain { flex: 1; width: 100%; min-width: 0; max-width: none; margin-inline: auto; padding: var(--s-6) var(--wrap-pad) var(--s-9); }
.px-app > .site-head > .wrap { max-width: none; }
.px-appmain > * + * { margin-top: var(--px-gap); }
/* Las pantallas de un solo formulario (perfil, empresa nueva) no necesitan
   1120 px: una columna de texto de 60 caracteres se lee mejor. */
.px-appmain.is-narrow { max-width: 760px; }


/* =====================================================================
   2 · CABECERA DE PÁGINA Y PESTAÑAS
   ===================================================================== */

.px-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--s-4);
  flex-wrap: wrap;
}
.px-head-txt { min-width: 0; max-width: 68ch; }
.px-head h1 {
  font-size: clamp(1.5rem, 2.4vw, 1.875rem);
  letter-spacing: -.03em;
  line-height: 1.1;
}
.px-head p { color: var(--muted); font-size: var(--t-sm); margin-top: 6px; }
.px-head-act { display: flex; align-items: center; gap: var(--s-2); flex-wrap: wrap; }

.px-eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 8px;
}
.px-eyebrow::before {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--accent);
}

/* Volver al listado. NO es un antetítulo: el punto de color del antetítulo
   delante de una flecha «←» se lee como dos marcas seguidas sin relación. */
.px-back {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: var(--t-sm);
  color: var(--muted);
  margin-bottom: 10px;
  min-height: 28px;
}
.px-back:hover { color: var(--ink); }
.px-back svg { width: 14px; height: 14px; max-width: none; rotate: 180deg; }

.px-tabs {
  display: flex;
  gap: 2px;
  overflow-x: auto;
  border-bottom: 1px solid var(--line);
  scrollbar-width: none;
}
.px-tabs::-webkit-scrollbar { display: none; }
.px-tabs a {
  position: relative;
  padding: 10px 14px;
  font-size: var(--t-sm);
  font-weight: 500;
  color: var(--muted);
  white-space: nowrap;
  border-radius: var(--r-sm) var(--r-sm) 0 0;
}
.px-tabs a:hover { color: var(--ink); background: var(--surface-3); }
.px-tabs a[aria-current] { color: var(--accent); font-weight: 600; }
.px-tabs a[aria-current]::after {
  content: "";
  position: absolute;
  inset-inline: 10px;
  bottom: -1px;
  height: 2px;
  border-radius: 2px 2px 0 0;
  background: var(--accent);
}

/* Selector de tramo (30 / 90 / 365 días) */
.px-seg {
  display: inline-flex;
  padding: 3px;
  border: 1px solid var(--line-2);
  border-radius: var(--r-md);
  background: var(--surface-2);
  gap: 2px;
}
.px-seg a, .px-seg button {
  padding: 6px 12px;
  border: 0;
  border-radius: 7px;
  background: transparent;
  font-size: var(--t-xs);
  font-weight: 600;
  color: var(--muted);
  cursor: pointer;
  white-space: nowrap;
}
.px-seg a:hover, .px-seg button:hover { color: var(--ink); background: var(--surface-3); }
.px-seg [aria-current="true"], .px-seg [aria-pressed="true"] {
  background: var(--surface);
  color: var(--ink);
  box-shadow: var(--px-e1);
}


/* =====================================================================
   3 · PANELES Y TARJETAS DE CIFRA
   ===================================================================== */

.px-panel {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  box-shadow: var(--px-e1);
  overflow: hidden;
}
.px-panel-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-4);
  padding: 14px 18px;
  border-bottom: 1px solid var(--line);
  flex-wrap: wrap;
}
.px-panel-head h2, .px-panel-head h3 { font-size: var(--t-base); letter-spacing: -.01em; }
.px-panel-head p { font-size: var(--t-xs); color: var(--muted); margin-top: 2px; }
/* El bloque de texto encoge y el enlace no. Sin esto, un subtítulo un poco
   largo empujaba el «Ver todo →» a su propia línea, debajo del título y
   pegado al contenido: parecía un enlace del panel, no de la cabecera. */
.px-panel-head > :first-child { flex: 1 1 12rem; min-width: 0; }
.px-panel-head > :last-child:not(:first-child) { flex: none; }
.px-panel-tools { display: flex; align-items: center; gap: var(--s-2); flex-wrap: wrap; }
.px-panel-body { padding: 18px; }
/* Aire entre bloques de un panel. 24 px y no 16: la mayoría de estos
   paneles son formularios, y con 16 la etiqueta del campo siguiente queda
   pegada al campo anterior — parecen su pie, no el título del de abajo. */
.px-panel-body > * + * { margin-top: var(--s-5); }
.px-panel-foot {
  padding: 12px 18px;
  border-top: 1px solid var(--line);
  background: var(--surface-2);
  font-size: var(--t-xs);
  color: var(--muted);
}

/* El panel de lo que no tiene vuelta atrás. El marco rojo no es decoración:
   es lo que hace que nadie llegue aquí creyendo que está en la ficha. */
.px-danger { border-color: var(--danger); }
.px-danger .px-panel-head { border-bottom-color: color-mix(in srgb, var(--danger) 35%, var(--line)); }
.px-danger .px-panel-head h2 { color: var(--danger); display: flex; align-items: center; gap: 8px; }
.px-danger .px-panel-head h2 svg { flex: none; }
/* Una tabla llena el panel de borde a borde: el relleno del panel más el de
   las celdas dejaría el texto a 36 px del borde y la tabla parecería flotar
   dentro de otra caja. Por eso una tabla va DIRECTA dentro de `.px-panel`,
   sin `.px-panel-body` en medio, y no hace falta ninguna clase extra. */

/* Rejillas del lienzo. `auto-fit` y no un número de columnas fijo: con
   columnas fijas en una pantalla estrecha cada tarjeta se queda en 90 px y
   el texto se sale. */
/* `minmax(0, 1fr)` y no el `auto` que pone el navegador: una columna `auto`
   crece hasta su contenido más ancho, así que una rejilla simple con una
   tabla dentro se estiraba hasta los 576 px de la tabla y empujaba el ANCHO
   DEL DOCUMENTO — la página entera se desplazaba de lado en un móvil,
   aunque la tabla tuviera su propio desplazamiento. Es la trampa más
   repetida de CSS Grid y no da ningún error. */
.px-grid { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--px-gap); align-items: start; }
.px-g2 { grid-template-columns: repeat(auto-fit, minmax(330px, 1fr)); }
.px-g3 { grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); }
/* Dos columnas desiguales: lo principal a la izquierda, el apoyo a la
   derecha. Se apila en cuanto no caben las dos. */
.px-split { grid-template-columns: minmax(0, 1.6fr) minmax(300px, 1fr); }
@media (max-width: 1080px) { .px-split { grid-template-columns: minmax(0, 1fr); } }

/* --- Tarjeta de cifra ------------------------------------------------ */
.px-kpis {
  display: grid;
  gap: var(--s-4);
  grid-template-columns: repeat(auto-fit, minmax(216px, 1fr));
}

.px-kpi {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 16px 18px 14px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  box-shadow: var(--px-e1);
  overflow: hidden;
  transition: border-color var(--px-fast) var(--px-ease), box-shadow var(--px-fast) var(--px-ease);
}
a.px-kpi:hover { border-color: var(--line-strong); box-shadow: var(--px-e2); color: var(--ink); }

.px-kpi-k {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: var(--t-xs);
  font-weight: 600;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--muted);
}
.px-kpi-k svg { width: 14px; height: 14px; max-width: none; flex: none; }

/* La cifra va con las cifras PROPORCIONALES de la fuente, no tabulares:
   `tabular-nums` da a cada dígito el ancho de un cero y a 34 px un «121»
   queda suelto y descolocado. Las tabulares son para columnas de números
   que tienen que alinearse (tablas y marcas de eje). */
.px-kpi-v {
  font-family: var(--font-display);
  font-size: clamp(1.75rem, 2.6vw, 2.125rem);
  font-weight: 800;
  letter-spacing: -.035em;
  line-height: 1.05;
  font-variant-numeric: normal;
  color: var(--ink);
}
.px-kpi-v small { font-size: .5em; font-weight: 600; color: var(--muted); letter-spacing: 0; }
.px-kpi-d { font-size: var(--t-xs); color: var(--muted); line-height: 1.5; }
.px-kpi-spark { margin-top: 8px; }

/* Variación. El color dice la dirección, pero el signo va SIEMPRE escrito
   y la flecha también: un verde y un rojo sin signo obligan a recordar
   cuál era cuál, y para quien no distingue esos dos colores no dicen nada. */
.px-delta {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: var(--t-xs);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  padding: 3px 8px;
  border-radius: var(--r-full);
  background: var(--surface-3);
  color: var(--muted);
}
.px-delta svg { width: 11px; height: 11px; max-width: none; }
.px-delta.is-up { background: var(--ok-soft); color: var(--ok); }
.px-delta.is-down { background: var(--danger-soft); color: var(--danger); }
/* Cuando bajar es bueno (bajas, trabajos fallidos) se invierte el color
   pidiéndolo, no adivinando. */
.px-delta.is-good { background: var(--ok-soft); color: var(--ok); }
.px-delta.is-bad { background: var(--danger-soft); color: var(--danger); }

.px-kpi-top { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--s-3); }


/* --- Pares de cifra dentro de un panel ------------------------------ */
.px-pair {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: var(--s-4);
  padding-top: var(--s-4);
  border-top: 1px solid var(--line);
}
.px-pair .k { font-size: var(--t-xs); text-transform: uppercase; letter-spacing: .05em; color: var(--muted); font-weight: 700; }
.px-pair .v {
  font-family: var(--font-display);
  font-size: var(--t-2xl);
  font-weight: 800;
  letter-spacing: -.03em;
  margin-top: 3px;
}
.px-pair .d { font-size: var(--t-xs); color: var(--muted); margin-top: 3px; line-height: 1.5; }

/* --- Ficha de datos en dos columnas --------------------------------- */
.px-defs { display: grid; gap: 0; }
.px-def {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s-4);
  padding: 9px 0;
  border-bottom: 1px solid var(--line);
  font-size: var(--t-sm);
}
.px-def:last-child { border-bottom: 0; }
.px-def dt { color: var(--muted); flex: none; }
.px-def dd {
  margin: 0;
  text-align: end;
  min-width: 0;
  overflow-wrap: anywhere;
  font-family: var(--font-mono);
  font-size: var(--t-xs);
}

/* --- Pasos de un asistente ------------------------------------------- */
.px-steps ol { list-style: none; display: grid; gap: 2px; margin: 0; padding: 0; position: sticky; top: 84px; }
.px-steps a {
  display: flex;
  align-items: center;
  gap: 11px;
  min-height: 42px;
  padding: 9px 12px;
  border-radius: var(--r-md);
  font-size: var(--t-sm);
  color: var(--muted);
}
.px-steps a:hover { background: var(--surface-3); color: var(--ink); }
.px-step-n {
  flex: none;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  border: 1.5px solid var(--line-2);
  color: var(--muted);
}
.px-step-n svg { width: 14px; height: 14px; max-width: none; }
.px-steps .is-done a { color: var(--ink); }
.px-steps .is-done .px-step-n { background: var(--ok); border-color: var(--ok); color: #fff; }
.px-steps .is-now a { background: var(--accent-soft); color: var(--accent); font-weight: 600; }
.px-steps .is-now .px-step-n { border-color: var(--accent); color: var(--accent); }

/* --- Tarjeta que se elige (radio o casilla) --------------------------
   La etiqueta ENTERA es el objetivo, no solo el cuadradito de 18 px: en
   una lista de doce módulos, acertar la casilla con el dedo es un ejercicio
   de puntería. El borde de color dice qué está elegido sin depender de ver
   la marca del control. */
.px-pick {
  display: flex;
  gap: 12px;
  align-items: flex-start;
  padding: 14px 16px;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--surface);
  cursor: pointer;
  transition: border-color var(--px-fast) var(--px-ease), background var(--px-fast) var(--px-ease);
}
.px-pick:hover { border-color: var(--line-strong); }
.px-pick input { margin-top: 2px; flex: none; width: 18px; height: 18px; accent-color: var(--accent); cursor: pointer; }
.px-pick:has(input:checked) { border-color: var(--accent); background: var(--accent-soft); }
/* Lo que no se puede desmarcar (un módulo del núcleo) se ve como lo que
   es: elegido y fuera de discusión, no roto. */
.px-pick.is-fixed { cursor: default; opacity: .85; }
.px-pick.is-fixed input { cursor: default; }
.px-pick:has(input:focus-visible) { outline: 2px solid var(--accent); outline-offset: 2px; }
.px-pick-body { display: grid; gap: 4px; min-width: 0; flex: 1; }
.px-pick-top { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.px-pick-ic { color: var(--accent); display: inline-flex; flex: none; }
.px-pick-ic svg { width: 18px; height: 18px; max-width: none; }

/* --- Medidor -------------------------------------------------------- */
.px-meter {
  height: 6px;
  border-radius: 3px;
  background: var(--px-track);
  overflow: hidden;
}
.px-meter > i {
  display: block;
  height: 100%;
  border-radius: 3px;
  background: var(--accent);
  transition: width var(--px-slow) var(--px-ease);
}
.px-meter.is-tight > i { background: var(--warn); }
.px-meter.is-over > i { background: var(--danger); }


/* =====================================================================
   4 · GRÁFICOS
   Los rótulos son HTML y solo las marcas son SVG: ver platform/Core/Chart.php.
   ===================================================================== */

.px-fig { margin: 0; }
.px-fig figcaption { font-size: var(--t-xs); color: var(--muted); margin-top: 10px; line-height: 1.55; }

/* Rejilla del dibujo: columna de rótulos del eje vertical + lienzo, y
   debajo los rótulos del eje horizontal alineados con el lienzo. */
.px-plot {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  grid-template-rows: var(--px-alto, 190px) auto;
  column-gap: 10px;
  row-gap: 6px;
}
.px-axis-y {
  grid-column: 1;
  grid-row: 1;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  align-items: flex-end;
  font-size: 10px;
  font-variant-numeric: tabular-nums;
  color: var(--muted);
  /* Medio renglón arriba y abajo para que el número quede centrado en su
     línea de la rejilla y no flotando encima. */
  padding-block: 0;
  translate: 0 -.5em;
  height: calc(var(--px-alto, 190px) + 1em);
}
.px-canvas { grid-column: 2; grid-row: 1; position: relative; min-width: 0; }
/* EL DIBUJO MIDE LO MISMO QUE SU EJE. El ancho se estira y el alto no
   (preserveAspectRatio="none"), pero la regla base `svg{height:auto}` de
   pulsar.css le quitaba el alto que pone Chart.php y lo sacaba de la
   proporción del viewBox: sobre un eje de 190 px la línea medía 101 a 1280 px
   al 150 % —el cero quedaba a media altura— y 250 a 2560, montada sobre los
   rótulos y el pie. */
.px-svg { display: block; width: 100%; height: var(--px-alto, 190px); }
/* Solo las rayas del SVG. Se llaman igual que la rejilla de paneles
   (`.px-grid`, arriba) y el trazo se hereda: sin acotarlo, todo lo que no
   trae trazo propio dentro de una rejilla de paneles —las zonas sensibles de
   cada mes, el velo del área— salía con filo, y cada mes pintaba una raya
   vertical que no era dato. */
.px-svg .px-grid { stroke: var(--px-grid); stroke-width: 1; }
.px-hit { fill: transparent; cursor: crosshair; }

/* Punto del último valor, colocado en porcentaje sobre el lienzo: dentro
   del SVG se deformaría en óvalo al estirarse el dibujo. */
.px-dot {
  position: absolute;
  left: var(--px-dot-x);
  top: var(--px-dot-y);
  width: 9px;
  height: 9px;
  border-radius: 50%;
  translate: -50% -50%;
  /* Anillo del color del panel: sin él el punto se pierde donde cruza la
     línea, y además agranda lo que se puede señalar. */
  box-shadow: 0 0 0 2.5px var(--surface);
  pointer-events: none;
}
.px-axis-x {
  grid-column: 2;
  grid-row: 2;
  display: flex;
  justify-content: space-between;
  font-size: 10px;
  font-variant-numeric: tabular-nums;
  color: var(--muted);
  gap: 2px;
}
.px-axis-x > span {
  flex: 1;
  min-width: 0;
  text-align: center;
  white-space: nowrap;
  overflow: visible;
}
.px-axis-x > span:first-child { text-align: start; }
.px-axis-x > span:last-child { text-align: end; }

/* --- Columnas agrupadas --------------------------------------------- */
.px-cols {
  display: flex;
  align-items: flex-end;
  gap: 6px;
  height: var(--px-alto, 150px);
}
.px-col { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 6px; height: 100%; }
.px-col-bars {
  flex: 1;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  /* Los 2 px de hueco son del color del panel, no un borde alrededor de
     cada barra: un borde añade tinta que no es dato. */
  gap: 2px;
  min-height: 0;
}
.px-col-bars > i {
  display: block;
  width: 45%;
  max-width: 14px;
  min-height: 0;
  /* Redondeado solo arriba, cuadrado en la base: la barra nace de la
     línea del cero y no debe parecer que flota. */
  border-radius: 4px 4px 0 0;
  transition: height var(--px-slow) var(--px-ease);
}
.px-col-lbl {
  font-size: 10px;
  color: var(--muted);
  text-align: center;
  font-variant-numeric: tabular-nums;
}

.px-legend {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-4);
  margin-bottom: 12px;
  font-size: var(--t-xs);
  color: var(--muted);
}
.px-legend span { display: inline-flex; align-items: center; gap: 6px; }
.px-legend i { width: 9px; height: 9px; border-radius: 3px; flex: none; }

/* --- Ranking -------------------------------------------------------- */
.px-rank { list-style: none; display: grid; gap: 14px; margin: 0; padding: 0; }
.px-rank-head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--s-3); margin-bottom: 6px; }
.px-rank-name { font-size: var(--t-sm); min-width: 0; display: grid; gap: 1px; }
.px-rank-name i { font-style: normal; font-size: var(--t-xs); color: var(--muted); font-family: var(--font-mono); }
.px-rank-val { font-size: var(--t-sm); font-weight: 700; white-space: nowrap; }
.px-rank-bar { height: 8px; border-radius: 4px; background: var(--px-track); overflow: hidden; }
.px-rank-bar > i { display: block; height: 100%; border-radius: 4px; }

/* --- Embudo --------------------------------------------------------- */
.px-funnel { list-style: none; display: grid; gap: 18px; margin: 0; padding: 0; }
.px-funnel-head { display: flex; align-items: baseline; gap: var(--s-4); margin-bottom: 7px; }
.px-funnel-n {
  font-family: var(--font-display);
  font-size: var(--t-2xl);
  font-weight: 800;
  letter-spacing: -.03em;
  min-width: 3ch;
}
.px-funnel-txt { display: grid; gap: 1px; flex: 1; min-width: 0; }
.px-funnel-txt b { font-size: var(--t-sm); }
.px-funnel-txt i { font-style: normal; font-size: var(--t-xs); color: var(--muted); }
.px-funnel-pct {
  font-size: var(--t-sm);
  font-weight: 700;
  text-align: end;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
  color: var(--ok);
}
.px-funnel-pct.is-weak { color: var(--warn); }
.px-funnel-pct i { display: block; font-style: normal; font-size: 10px; font-weight: 500; color: var(--muted); }
.px-funnel-bar { height: 10px; border-radius: 5px; background: var(--px-track); overflow: hidden; }
.px-funnel-bar > i { display: block; height: 100%; border-radius: 5px; transition: width var(--px-slow) var(--px-ease); }

.px-ord-1 { background: var(--px-ord-1); }
.px-ord-2 { background: var(--px-ord-2); }
.px-ord-3 { background: var(--px-ord-3); }
.px-ord-4 { background: var(--px-ord-4); }
.px-ord-5 { background: var(--px-ord-5); }

/* --- Mapa de calor -------------------------------------------------- */
/* Las columnas se reparten el ancho del panel en vez de medir 12 px fijos:
   con medida fija, tres meses de calendario ocupaban un tercio de su panel
   y el resto era hueco. El mínimo evita que en un móvil las celdas queden
   tan finas que no se puedan pulsar. */
.px-cal {
  display: grid;
  grid-auto-flow: column;
  grid-template-rows: repeat(7, 1fr);
  grid-auto-columns: minmax(10px, 1fr);
  gap: 3px;
  overflow-x: auto;
  padding-bottom: 2px;
}
.px-cal-d { width: 100%; aspect-ratio: 1; border-radius: 3px; display: block; }
.px-cal-key .px-cal-d { width: 11px; aspect-ratio: auto; height: 11px; }
.px-cal-key {
  display: flex;
  align-items: center;
  gap: 4px;
  margin-top: 10px;
  font-size: 10px;
  color: var(--muted);
}
.px-cal-key span:first-child { margin-inline-end: 2px; }
.px-cal-key span:last-child { margin-inline-start: 2px; }

.px-seq-0 { background: var(--px-seq-0); }
.px-seq-1 { background: var(--px-seq-1); }
.px-seq-2 { background: var(--px-seq-2); }
.px-seq-3 { background: var(--px-seq-3); }
.px-seq-4 { background: var(--px-seq-4); }

/* --- Minigráfico ---------------------------------------------------- */
/* A su tamaño de dibujo (120 × 34, Chart::mini()), con el alto fijado por la
   misma razón que arriba. Estirado a lo ancho con ese alto, el punto del
   último valor, que va dentro del SVG, saldría en óvalo. */
.px-mini { display: block; height: 34px; }

/* --- Gemelo en tabla ------------------------------------------------ */
.px-data { margin-top: 12px; }
.px-data > summary {
  font-size: var(--t-xs);
  color: var(--muted);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 0;
  min-height: 28px;
  list-style: none;
}
.px-data > summary::-webkit-details-marker { display: none; }
.px-data > summary::before {
  content: "";
  width: 0;
  height: 0;
  border-inline-start: 5px solid currentColor;
  border-block: 4px solid transparent;
  transition: rotate var(--px-fast) var(--px-ease);
}
.px-data[open] > summary::before { rotate: 90deg; }
.px-data > summary:hover { color: var(--ink); }
.px-data table { margin-top: 8px; }
.px-data .data th, .px-data .data td { padding: 7px 12px; }

.px-chart-empty {
  font-size: var(--t-sm);
  color: var(--muted);
  padding: var(--s-6) 0;
  text-align: center;
}

/* --- Globo de datos (lo pinta panel.js) ----------------------------- */
.px-tip {
  position: fixed;
  z-index: 130;
  pointer-events: none;
  max-width: 280px;
  padding: 7px 10px;
  border-radius: var(--r-sm);
  border: 1px solid var(--line-2);
  background: var(--surface);
  color: var(--ink);
  box-shadow: var(--px-e2);
  font-size: var(--t-xs);
  line-height: 1.45;
  font-variant-numeric: tabular-nums;
  opacity: 0;
  transition: opacity var(--px-fast) var(--px-ease);
}
.px-tip.is-on { opacity: 1; }


/* =====================================================================
   5 · TABLAS DE TRABAJO
   ===================================================================== */

.px-tablebox { border: 1px solid var(--line); border-radius: var(--r-lg); background: var(--surface); overflow: hidden; }
.px-panel .px-tablebox { border: 0; border-radius: 0; }

.px-toolbar {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  padding: 12px 14px;
  border-bottom: 1px solid var(--line);
  background: var(--surface-2);
  flex-wrap: wrap;
}
.px-toolbar form { display: flex; align-items: center; gap: var(--s-2); flex-wrap: wrap; }

/* El campo con lupa NO está acotado a la barra de herramientas: también se
   usa en la cabecera de página (editar un idioma, por ejemplo). Estaba
   escrito como `.px-toolbar .px-find`, así que fuera de la barra el <span>
   no era un contenedor posicionado y la lupa se iba a la esquina de la
   página, flotando por encima del campo. */
.px-find { position: relative; display: block; min-width: 200px; flex: 1; max-width: 340px; }
.px-find svg {
  position: absolute;
  inset-inline-start: 11px;
  top: 50%;
  translate: 0 -50%;
  width: 15px;
  height: 15px;
  max-width: none;
  color: var(--muted);
  pointer-events: none;
  z-index: 1;
}
.px-find input { padding-inline-start: 34px; }
.px-toolbar-right { margin-inline-start: auto; display: flex; align-items: center; gap: var(--s-2); flex-wrap: wrap; }
.px-count { font-size: var(--t-xs); color: var(--muted); font-variant-numeric: tabular-nums; white-space: nowrap; }

/* Filtros en UNA fila encima de todo lo que filtran, nunca dentro de una
   tarjeta: un filtro metido en un panel parece filtrar solo ese panel. */
.px-chips { display: flex; gap: 6px; flex-wrap: wrap; }
.px-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 11px;
  border: 1px solid var(--line-2);
  border-radius: var(--r-full);
  background: var(--surface);
  font-size: var(--t-xs);
  font-weight: 600;
  color: var(--muted);
  cursor: pointer;
  white-space: nowrap;
  min-height: 30px;
}
.px-chip:hover { border-color: var(--line-strong); color: var(--ink); }
.px-chip[aria-pressed="true"], .px-chip[aria-current="true"] {
  background: var(--accent-soft);
  border-color: color-mix(in srgb, var(--accent) 40%, transparent);
  color: var(--accent);
}
.px-chip .px-n { font-variant-numeric: tabular-nums; opacity: .8; }

/* `position: relative` NO ES DECORATIVO. Un `.sr-only` (absoluto) dentro de
   la tabla —el «Acciones» oculto de la última columna— busca el antecesor
   posicionado más cercano; si no lo hay dentro de la caja, se escapa de su
   desplazamiento y ESTIRA LA PÁGINA: en Chrome de Android, /trabajos medía
   1.018 px de ancho en un móvil de 390. Lo tapaba por casualidad el
   `sticky` de la cabecera (una celda pegajosa también está posicionada);
   al quitar ese sticky, que no servía, la contención tiene que ser a
   propósito y en el sitio correcto: la caja que desplaza. */
.px-scroll { overflow-x: auto; position: relative; }
.px-content-preview { overflow-wrap: anywhere; line-height: 1.75; }
.px-content-form .px-panel-body { display:grid; gap:18px; }
.px-translation-form { display:grid; gap:var(--s-4); min-width:0; }
/* El formulario ocupa el hueco libre de la barra (29/09/2026): sin crecer, el
   buscador se quedaba en sus 200 px mínimos y cortaba el texto de ayuda
   («Buscar por nombre, sub…») con media barra vacía al lado. */
.px-account-filters { display:flex; flex:1 1 auto; align-items:center; gap:8px; flex-wrap:wrap; }
.px-account-filters select { width:auto; max-width:100%; }
@media(max-width:720px) { .px-account-filters { width:100%; } .px-account-filters .px-find { width:100%; } .px-account-filters select { flex:1 1 120px; } }
.px-content-preview img { max-width: 100%; height: auto; }
.px-content-preview pre, .px-content-preview table { display: block; max-width: 100%; overflow-x: auto; }
/* Un historial no se estruja: por debajo de este ancho se desplaza. 58rem y
   no los 62 de antes (992 px), que eran más que la hoja entera a 1280 px al
   150 % (958): /soporte y /uso, que caben en menos de 700, se desplazaban
   34 px solo para esconder su última columna. */
.px-scroll > table.px-record-table { min-width: 58rem; }
.px-record-table .px-cell-main { min-width: 12rem; }
.px-record-table td { vertical-align: top; }
.px-history-filters { display: flex; flex-wrap: wrap; align-items: end; gap: 12px; margin-bottom: 20px; }
.px-history-filters[id] { scroll-margin-top: 90px; }
#support-history { scroll-margin-top: 90px; }
/* El vacío de «Abiertas ahora» en /soporte: en línea y no centrado, porque
   vive en un panel estrecho. Misma baldosa que `.px-empty`. */
.px-support-empty { display:flex; align-items:center; gap:14px; padding:20px 18px; }
.px-support-empty>span { display:grid; place-items:center; flex:none; width:44px; height:44px; border-radius:12px; border:1px solid var(--line-2); background:var(--surface-raised); color:var(--muted); }
.px-support-empty h3 { margin:0 0 4px; font-size:.9375rem; font-weight:600; letter-spacing:-.01em; }
.px-support-empty p { margin:0; color:var(--muted); font-size:var(--t-ui); line-height:1.55; }
.px-history-filters .field { margin: 0; min-width: 0; }
.px-history-filters .px-history-query { flex: 1 1 240px; }
.px-history-filters input, .px-history-filters select { max-width: 100%; }
/* Los 13rem son para leer el detalle ABIERTO. Cerrado, un «Ver detalle» de
   90 px reservaba igual 208 y empujaba la tabla fuera de su caja. */
.px-record-detail { max-width: 34rem; }
.px-record-detail[open] { min-width: 13rem; }
.px-record-detail summary { cursor: pointer; color: var(--accent); }
.px-record-detail pre { white-space: pre-wrap; overflow-wrap: anywhere; max-height: 24rem; overflow-y: auto; font: inherit; }

/* AQUÍ HABÍA UNA CABECERA «PEGAJOSA» QUE NUNCA SE PEGÓ (27/09/2026).
   `position: sticky` se pega al contenedor con desplazamiento más cercano,
   y todas las tablas del panel van dentro de `.px-scroll` (overflow-x:auto)
   para poder desplazarse de lado en un móvil. Ese contenedor no se desplaza
   en vertical, así que la cabecera se iba con la página: medido, tras bajar
   1.500 px quedaba en top −1.419. No hay forma de tener las dos cosas solo
   con CSS, y el desplazamiento lateral es el que no se puede perder (sin
   él, una tabla ancha estira la página entera). Se quita la regla en vez
   de dejar algo que dice hacer lo que no hace. */
.px-tablebox table.data tbody tr { transition: background var(--px-fast) var(--px-ease); }

/* Columna ordenable. El estado se anuncia con aria-sort, no solo con una
   flecha. */
th[data-px-sort] { cursor: pointer; -webkit-user-select: none; user-select: none; }
th[data-px-sort]:hover { color: var(--ink); }
th[data-px-sort]::after {
  content: "";
  display: inline-block;
  margin-inline-start: 6px;
  width: 0;
  height: 0;
  border-inline: 3.5px solid transparent;
  border-top: 4px solid currentColor;
  opacity: .3;
  vertical-align: middle;
}
th[aria-sort="ascending"]::after { rotate: 180deg; opacity: 1; }
th[aria-sort="descending"]::after { opacity: 1; }

/* Acciones de fila: siempre presentes para el teclado y los lectores de
   pantalla, atenuadas hasta que el ratón pasa por la fila. Esconderlas con
   `display:none` las saca del orden de tabulación y deja la tabla sin
   acciones para quien no usa ratón. */
.px-row-act { display: flex; gap: 6px; justify-content: flex-end; opacity: .45; transition: opacity var(--px-fast) var(--px-ease); }
tr:hover .px-row-act, .px-row-act:focus-within { opacity: 1; }

/* Celda con nombre y dirección debajo: el patrón más repetido del panel. */
.px-cell-main { display: grid; gap: 3px; min-width: 0; }
/* El nombre se PARTE en varias líneas si hace falta; no se recorta. En una
   tabla de cuentas, «Mostra…» y «Mostrador Centro» son indistinguibles, y
   el nombre es justo lo que se viene a leer. Lo que sí se recorta con
   puntos suspensivos es la línea de abajo (el subdominio), que es un dato
   técnico y se reconoce por el principio. */
.px-cell-main > strong, .px-cell-main > a { font-weight: 600; overflow-wrap: anywhere; }
/* La línea de abajo (subdominio, correo, código) TAMPOCO se recorta. Con
   puntos suspensivos, «demo1@satsm.t…» e «info@mundopho…» son dos correos
   que no se pueden ni copiar ni distinguir, y en una tabla de equipo el
   correo es justo lo que se viene a mirar. Antes se partía la palabra; que
   ocupe dos líneas es infinitamente mejor que esconder la mitad. */
.px-cell-main > span {
  font-family: var(--font-mono);
  font-size: var(--t-xs);
  color: var(--muted);
  overflow-wrap: anywhere;
}

/* Copiar un dato técnico (nombre de base, subdominio, clave). Discreto
   hasta que el ratón pasa por su fila: es una ayuda, no una acción. */
.px-copy {
  display: inline-grid;
  place-items: center;
  width: 26px;
  height: 26px;
  flex: none;
  border: 0;
  border-radius: var(--r-sm);
  background: transparent;
  color: var(--muted);
  cursor: pointer;
  opacity: .5;
  transition: opacity var(--px-fast) var(--px-ease), color var(--px-fast) var(--px-ease);
}
.px-copy svg { width: 14px; height: 14px; max-width: none; }
.px-copy:hover, .px-copy:focus-visible { opacity: 1; color: var(--ink); background: var(--surface-3); }
.px-def:hover .px-copy { opacity: 1; }
.px-copy.is-done { color: var(--ok); opacity: 1; }

/* Cuando el filtro del navegador no deja ninguna fila. Sin esto, la tabla
   se queda con la cabecera y un hueco blanco debajo, y no está claro si es
   que no hay nada o que se ha roto algo. */
.px-nohits { padding: var(--s-7) var(--s-5); text-align: center; font-size: var(--t-sm); color: var(--muted); }

/* Densidad compacta: quien revisa cuarenta cuentas quiere ver cuarenta
   filas, no doce. Se recuerda en este equipo. */
:root.px-dense table.data th, :root.px-dense table.data td { padding-block: 6px; }
:root.px-dense .px-panel-body { padding: 12px 14px; }
:root.px-dense { --px-gap: 12px; }


/* =====================================================================
   6 · LISTAS, CRONOLOGÍA Y ESTADOS VACÍOS
   ===================================================================== */

.px-list { display: grid; gap: 0; }
.px-list > * { padding: 12px 0; border-bottom: 1px solid var(--line); }
.px-list > *:last-child { border-bottom: 0; }
.px-list-row { display: flex; align-items: center; justify-content: space-between; gap: var(--s-3); }

/* Cronología. La línea vertical la dibuja el borde del punto, no un
   pseudoelemento suelto: así nunca se descuelga del último elemento. */
.px-feed { list-style: none; display: grid; margin: 0; padding: 0; }
.px-feed > li { display: grid; grid-template-columns: 24px minmax(0, 1fr); gap: var(--s-3); padding-bottom: 16px; }
.px-feed > li:last-child { padding-bottom: 0; }
.px-feed-mark { position: relative; display: flex; justify-content: center; }
.px-feed-mark::before {
  content: "";
  width: 9px;
  height: 9px;
  margin-top: 5px;
  border-radius: 50%;
  background: var(--accent);
  flex: none;
  z-index: 1;
}
.px-feed > li:not(:last-child) .px-feed-mark::after {
  content: "";
  position: absolute;
  top: 18px;
  bottom: -16px;
  width: 1px;
  background: var(--line);
}
.px-feed-mark.is-ok::before { background: var(--ok); }
.px-feed-mark.is-warn::before { background: var(--warn); }
.px-feed-mark.is-bad::before { background: var(--danger); }
.px-feed-txt { display: grid; gap: 2px; min-width: 0; font-size: var(--t-sm); }
.px-feed-txt time { font-size: var(--t-xs); color: var(--muted); font-variant-numeric: tabular-nums; }
.px-feed-txt code { font-family: var(--font-mono); font-size: var(--t-xs); color: var(--ink-2); }

.px-empty { text-align: center; padding: var(--s-8) var(--s-5); }
.px-empty-ic {
  width: 52px;
  height: 52px;
  margin: 0 auto 16px;
  border-radius: var(--r-lg);
  background: var(--surface-3);
  color: var(--muted);
  display: grid;
  place-items: center;
}
.px-empty-ic svg { width: 24px; height: 24px; max-width: none; }
.px-empty h3 { font-size: var(--t-lg); margin-bottom: 8px; }
.px-empty p { font-size: var(--t-sm); color: var(--muted); max-width: 48ch; margin-inline: auto; }
.px-empty .btn { margin-top: 20px; }
.px-empty code { font-family: var(--font-mono); font-size: var(--t-xs); }

/* Aquí había un esqueleto de carga y un «contenido viejo atenuado». Se han
   quitado: NINGUNA pantalla del panel carga nada aparte — todas llegan
   pintadas desde el servidor—, así que eran veinte líneas de CSS que no
   usaba nadie. Un estilo que no se usa le dice al siguiente que lo lea que
   existe un patrón que no existe, y encima pesa en cada carga. Cuando haya
   un bloque que llegue después, se escribe entonces. */


/* =====================================================================
   7 · AVISOS, PALETA DE COMANDOS Y CAJÓN
   ===================================================================== */

/* AVISOS CORTOS. Los que exigen decidir algo NO son avisos: van en la
   página, donde no se pueden perder. Son una tarjeta flotante con la
   baldosa del tono, el texto, una × de 32 px y una barra que se vacía: la
   barra ES el temporizador (panel.js), así que lo que dice que queda es lo
   que queda.

   En la Consola salen ABAJO a la derecha. Arriba tapaban primero el
   buscador y luego, debajo de la cabecera, las acciones de cada pantalla:
   un error, que no se va solo, dejaba escondido del todo el botón que
   recibía el foco. Si tocan una barra de guardar que se ve, panel.js los
   sube encima de ella (--px-toasts-bottom) midiendo la barra de verdad: el
   `bottom: 112px` fijo que había solo valía con la barra pegada al pie, y
   al final de la página tapaba «Guardar cambios». La región está siempre
   en la página, pero no se pinta mientras esté vacía: sin avisos no hay ni
   una caja invisible ni un punto de referencia vacío. */
.px-toasts {
  position: fixed;
  top: 14px;
  inset-inline-end: 14px;
  z-index: 140;
  display: flex;
  flex-direction: column;
  gap: 8px;
  width: min(380px, calc(100vw - 28px));
  pointer-events: none;
}
.px-toasts:not(:has(.px-toast)) { display: none; }
[data-surface="console"] .px-toasts {
  top: auto;
  bottom: var(--px-toasts-bottom, calc(var(--px-sheet-gap) + 12px));
  inset-inline-end: calc(var(--px-sheet-gap) + 12px);
}
/* SIN panel.js NO HAY QUIEN MIDA. Mientras quede un aviso escrito por el
   servidor (`data-px-flash`: panel.js los cambia al cargar), y si la página
   tiene barra de guardar, el aviso se sube por encima de donde esa barra se
   queda pegada (lo mismo que reserva scroll-padding-bottom en 9c). Sin esto,
   con panel.js bloqueado, un error sin × ni reloj tapaba «Guardar cambios». */
[data-surface="console"]:has(.px-saver, .px-plan-savebar, .lng-savebar, .bl-savebar) .px-toasts:has(> [data-px-flash]) { bottom: 112px; }
@media (max-width: 600px) {
  [data-surface="console"]:has(.px-saver, .px-plan-savebar, .lng-savebar, .bl-savebar) .px-toasts:has(> [data-px-flash]) { bottom: 160px; }
}
/* Y como sin panel.js el aviso no tiene nada que pulsar (ni × ni enlaces),
   deja pasar el clic: cuando la barra está en su sitio natural —al final de
   la página, o en una página corta— y el número fijo de arriba no la
   esquiva, el botón de debajo sigue funcionando. */
[data-surface="console"] .px-toast[data-px-flash] { pointer-events: none; }
.px-toast {
  position: relative;
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 10px 8px 10px 12px;
  overflow: hidden;
  border-radius: var(--r-md);
  border: 1px solid var(--line-2);
  background: var(--surface);
  box-shadow: var(--px-e3);
  font-size: var(--t-sm);
  line-height: 1.45;
  pointer-events: auto;
  animation: px-toast-in var(--px-slow) var(--px-ease) both;
}
[data-surface="console"] .px-toast {
  padding-inline-start: 10px;
  border-radius: var(--r-pop);
  background: var(--surface-overlay);
  box-shadow: var(--e3);
  animation-duration: var(--dur-2);
  animation-timing-function: var(--ease-out);
}
.px-toast.is-out { animation: px-toast-out var(--px-fast) var(--px-ease) both; }
.px-toast-ic {
  flex: none;
  width: 28px;
  height: 28px;
  display: grid;
  place-items: center;
  border-radius: var(--r-ctl, 8px);
  background: var(--surface-3);
  color: var(--muted);
}
.px-toast-ic svg, .px-toast > svg { width: 16px; height: 16px; max-width: none; flex: none; }
/* El área de cliente pinta el icono suelto, sin baldosa. */
.px-toast > svg { margin-top: 2px; }
.px-toast-txt { flex: 1; min-width: 0; padding-block: 4px; color: var(--ink); overflow-wrap: anywhere; }
.px-toast-x {
  flex: none;
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  margin-block: -2px;
  padding: 0;
  border: 0;
  border-radius: var(--r-ctl, 8px);
  background: none;
  color: var(--muted);
  font: inherit;
  line-height: 1;
  cursor: pointer;
  transition: background-color var(--dur-1, .12s) var(--ease-out, ease), color var(--dur-1, .12s) var(--ease-out, ease);
}
.px-toast-x svg { width: 16px; height: 16px; max-width: none; }
.px-toast-x:hover { background: var(--surface-hover, var(--surface-3)); color: var(--ink); }
.px-toast-x:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.px-toast.is-ok .px-toast-ic { background: var(--ok-soft); color: var(--ok); }
.px-toast.is-error .px-toast-ic { background: var(--danger-soft); color: var(--danger); }
.px-toast.is-warn .px-toast-ic { background: var(--warn-soft); color: var(--warn); }
.px-toast.is-info .px-toast-ic { background: var(--info-soft); color: var(--info); }
.px-toast.is-ok > svg { color: var(--ok); }
.px-toast.is-error > svg { color: var(--danger); }
.px-toast.is-warn > svg { color: var(--warn); }
.px-toast.is-info > svg { color: var(--info); }
.px-toast-bar {
  position: absolute;
  inset-inline: 0;
  bottom: 0;
  height: 2px;
  background: var(--muted);
  opacity: .75;
  transform-origin: left center;
  pointer-events: none;
}
:root[dir="rtl"] .px-toast-bar { transform-origin: right center; }
.px-toast.is-ok .px-toast-bar { background: var(--ok); }
.px-toast.is-warn .px-toast-bar { background: var(--warn); }
.px-toast.is-info .px-toast-bar { background: var(--info); }
/* Con el movimiento reducido la barra no se ve, pero el reloj sigue. */
@media (prefers-reduced-motion: reduce) { .px-toast-bar { opacity: 0; } }

@keyframes px-toast-in { from { opacity: 0; translate: 0 -4px; } to { opacity: 1; translate: 0 0; } }
@keyframes px-toast-out { to { opacity: 0; translate: 0 -4px; } }

/* --- Paleta de comandos ---------------------------------------------
   Arriba y no centrada: la lista crece hacia abajo y una caja centrada
   que crece mueve el campo de texto mientras se escribe. Es una capa
   flotante: la misma superficie y sombra que los menús. */
.px-cmd::backdrop { background: var(--scrim); -webkit-backdrop-filter: blur(var(--scrim-blur)); backdrop-filter: blur(var(--scrim-blur)); }
.px-cmd {
  width: min(640px, calc(100vw - 32px));
  max-height: min(72vh, 580px);
  padding: 0;
  border: 1px solid var(--line-2);
  border-radius: var(--r-pop);
  background: var(--surface-overlay);
  color: var(--ink);
  box-shadow: var(--e3);
  margin: 12vh auto auto;
  overflow: hidden;
}
/* `display` solo cuando está abierta: puesto en `.px-cmd` a secas, ganaría
   al `display: none` del navegador y la paleta saldría siempre. */
.px-cmd[open] { display: flex; flex-direction: column; animation: px-dialog-in var(--dur-2) var(--ease-out); }
.px-cmd-head { flex: none; display: flex; align-items: center; gap: 10px; height: 54px; padding: 0 12px 0 16px; border-bottom: 1px solid var(--line); }
.px-cmd-head > svg { width: 18px; height: 18px; max-width: none; color: var(--muted); flex: none; }
/* Con el id: las reglas generales de los campos no entran aquí. */
.px-cmd-head #px-cmd-q {
  flex: 1;
  min-width: 0;
  height: 100%;
  border: 0;
  border-radius: 0;
  background: none;
  box-shadow: none;
  outline: none;
  padding: 0;
  color: var(--ink);
  font: inherit;
  font-size: var(--t-base);
  line-height: normal;
}
/* --muted y no --placeholder: sobre la capa flotante aquel da 4,46:1 y este
   5,28:1 (texto de 16 px, WCAG 1.4.3 pide 4,5). */
.px-cmd-head #px-cmd-q::placeholder { color: var(--muted); opacity: 1; }
.px-cmd-list { flex: 1; min-height: 0; overflow-y: auto; padding: 6px; scroll-padding-block: 32px; }
.px-cmd-group {
  padding: 10px 10px 4px;
  font-size: var(--t-2xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--muted);
}
.px-cmd-item {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  min-height: 40px;
  padding: 6px 10px 6px 8px;
  border: 0;
  border-radius: var(--r-ctl);
  background: none;
  color: var(--ink-2);
  font-size: var(--t-sm);
  text-align: start;
  text-decoration: none;
  cursor: pointer;
}
.px-cmd-ic {
  flex: none;
  width: 28px;
  height: 28px;
  display: grid;
  place-items: center;
  border-radius: 7px;
  background: var(--surface-3);
  color: var(--muted);
}
.px-cmd-ic svg { width: 16px; height: 16px; max-width: none; }
.px-cmd-t { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.px-cmd-meta { flex: none; max-width: 45%; overflow: hidden; color: var(--muted); font-size: var(--t-xs); text-overflow: ellipsis; white-space: nowrap; }
.px-cmd-meta.is-mono { font-family: var(--font-mono); }
/* El resaltado va por clase y no por :hover: la lista se recorre con las
   flechas, y si el ratón se queda quieto encima de otra línea habría dos
   cosas resaltadas a la vez. */
.px-cmd-item.is-on { background: var(--surface-selected); color: var(--ink); }
.px-cmd-item.is-on .px-cmd-ic { background: var(--accent-soft); color: var(--accent); }
/* Sobre la fila activa, --muted se quedaba en 4,28:1: un paso más claro. */
.px-cmd-item.is-on .px-cmd-meta { color: var(--ink-2); }
.px-cmd-foot {
  flex: none;
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 8px 16px;
  border-top: 1px solid var(--line);
  background: var(--surface-raised);
  font-size: var(--t-xs);
  color: var(--muted);
  flex-wrap: wrap;
}
.px-cmd-foot span { display: inline-flex; align-items: center; gap: 4px; }
.px-cmd-none { margin: 0; padding: 28px 14px; text-align: center; font-size: var(--t-sm); color: var(--muted); }

@keyframes px-dialog-in { from { opacity: 0; translate: 0 6px; scale: .985; } }

/* --- Los atajos de teclado (tecla «?») ------------------------------ */
.px-keys {
  width: min(480px, calc(100vw - 32px));
  padding: 0;
  border: 1px solid var(--line-2);
  border-radius: var(--r-pop);
  background: var(--surface-overlay);
  color: var(--ink);
  box-shadow: var(--e3);
}
.px-keys[open] { animation: px-dialog-in var(--dur-3) var(--ease-out); }
.px-keys::backdrop { background: var(--scrim); -webkit-backdrop-filter: blur(var(--scrim-blur)); backdrop-filter: blur(var(--scrim-blur)); }
.px-keys-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 12px 12px 4px 18px; }
.px-keys-head form { margin: 0; }
.px-keys-t { display: flex; align-items: center; gap: 10px; font-size: var(--t-base); font-weight: 650; letter-spacing: -.01em; }
.px-keys-t svg { width: 18px; height: 18px; color: var(--muted); }
.px-keys-lead { padding: 0 18px 14px; color: var(--muted); font-size: var(--t-ui); line-height: 1.5; }
/* Con los atajos de una tecla apagados (menú de cuenta), sus tres filas se
   van y lo dice un aviso en línea (.alert, el de siempre): ofrecer «/», «[»
   y «?» sin que hagan nada engañaba a quien los había apagado, o a quien
   comparte el equipo. */
.px-keys-note { display: none; margin: 0 18px 14px; }
.px-keys-off .px-keys-note { display: flex; }
.px-keys-off .px-keys-single { display: none; }
.px-keys-list { display: grid; gap: 2px; margin: 0; padding: 8px 10px 12px; border-top: 1px solid var(--line); }
.px-keys-list > div { display: grid; grid-template-columns: 120px minmax(0, 1fr); align-items: center; gap: 12px; padding: 7px 8px; border-radius: var(--r-ctl); }
.px-keys-list > div:hover { background: var(--surface-hover); }
.px-keys-list dt { display: flex; flex-wrap: wrap; gap: 4px; }
.px-keys-list dd { margin: 0; color: var(--ink-2); font-size: var(--t-ui); line-height: 1.4; }

/* --- «¿Seguimos?» (data-px-confirm) ---------------------------------
   Sustituye a window.confirm (30/09/2026). Estrecho y centrado: es una
   pregunta, no una pantalla. Misma capa que la paleta y los atajos. El
   icono va en rojo; en azul si lo que se confirma es la acción primaria.
   Lo usan la Consola Y el área de cliente, y las capas (--surface-overlay,
   --scrim, --r-pop, --e3…) solo las define la superficie de la Consola:
   cada una lleva su valor para la web clara, o el diálogo salía
   transparente, con el texto encima de la página. */
.px-confirm {
  width: min(440px, calc(100vw - 32px));
  padding: 0;
  border: 1px solid var(--line-2);
  border-radius: var(--r-pop, 16px);
  background: var(--surface-overlay, var(--surface));
  color: var(--ink);
  box-shadow: var(--e3, var(--sh-lg));
}
.px-confirm[open] { animation: px-dialog-in var(--dur-2, 180ms) var(--ease-out, ease-out); }
.px-confirm::backdrop {
  background: var(--scrim, rgba(11, 21, 38, .45));
  -webkit-backdrop-filter: blur(var(--scrim-blur, 4px));
  backdrop-filter: blur(var(--scrim-blur, 4px));
}
.px-confirm-sheet { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 0 14px; margin: 0; padding: 20px 20px 16px; }
.px-confirm-ic { flex: none; width: 40px; height: 40px; border-radius: 12px; display: grid; place-items: center; background: var(--danger-soft); color: var(--danger); }
.px-confirm-ic svg { width: 20px; height: 20px; max-width: none; }
.px-confirm.is-neutral .px-confirm-ic { background: var(--accent-soft); color: var(--accent); }
.px-confirm-txt { min-width: 0; padding-top: 1px; }
.px-confirm-t { margin: 0; font-size: var(--t-base); font-weight: 650; line-height: 1.45; letter-spacing: -.01em; overflow-wrap: anywhere; }
.px-confirm-d { margin: 6px 0 0; color: var(--ink-2); font-size: var(--t-ui, var(--t-sm)); line-height: 1.55; overflow-wrap: anywhere; }
.px-confirm-acts { grid-column: 1 / -1; display: flex; justify-content: flex-end; gap: 8px; margin-top: 18px; }
.px-confirm-acts .btn { flex: none; }
.px-reauth { width:min(480px,calc(100vw - 32px)); max-height:calc(100dvh - 32px); overflow:auto; }
.px-reauth .px-confirm-sheet { padding:24px; }
.px-reauth .px-confirm-t { font-size:1.2rem; }
.px-reauth-field,.px-reauth-context { grid-column:1 / -1; min-width:0; margin:20px 0 0; }
.px-reauth-context { display:grid; gap:4px; padding:12px 14px; border:1px solid var(--line); border-radius:var(--r-md,10px); font-size:var(--t-sm); overflow-wrap:anywhere; }
.px-reauth-context>span { color:var(--muted); }
.px-reauth-field label { display:block; margin-bottom:8px; }
.px-reauth-field input { width:100%; min-height:46px; font-size:1rem; }
.px-reauth .btn { min-height:44px; white-space:normal; }
.px-reauth-error { margin:10px 0 0; color:var(--danger); line-height:1.5; font-size:var(--t-sm); }
.px-reauth [hidden] { display:none !important; }
@media (prefers-reduced-motion:reduce) { .px-reauth[open] { animation:none; } }
@media (max-width: 480px) {
  .px-confirm-acts { flex-direction: column-reverse; }
  .px-confirm-acts .btn { width: 100%; justify-content: center; }
}

/* --- Menú desplegable -----------------------------------------------
   Se abre hacia ABAJO: el único que se abría hacia arriba era el de cuenta
   al pie de la barra lateral, que ahora vive en la cabecera. Las fichas
   siguen pudiendo pedirlo con `.px-menu-down` (es lo mismo). */
.px-menu { position: relative; }
.px-menu > summary { list-style: none; cursor: pointer; display: inline-flex; align-items: center; }
.px-menu > summary::-webkit-details-marker { display: none; }

/* CAPAS FLOTANTES: menús, campana, mensajes. Todo lo que flota comparte
   superficie (--surface-overlay), sombra (--e3), filo (--line-2), radio
   (--r-pop) y entrada: opacidad y 4 px en --dur-2. Anclado al final de la
   línea con propiedades lógicas (en árabe, al principio). En ≤560 px las de
   la cabecera ocupan todo el ancho bajo la barra (ver el bloque de 560).
   Para colgar una nueva: <details data-px-pop="…"> + `summary.px-iconbtn`
   + `div.px-pop` (panel.js, sección 2). */
.px-pop,
.px-menu-pop {
  position: absolute;
  inset-inline-end: 0;
  top: calc(100% + 6px);
  z-index: var(--z-pop);
  min-width: 232px;
  max-width: min(400px, calc(100vw - 16px));
  padding: 6px;
  border: 1px solid var(--line-2);
  border-radius: var(--r-pop);
  background: var(--surface-overlay);
  color: var(--ink);
  box-shadow: var(--e3);
  text-align: start;
}
/* Las de la cabecera cuelgan del BORDE de la barra, no del botón: 6 px por
   debajo de un botón de 32 en una barra de 56 montaban 5 px sobre su filo.
   El 50 % es la mitad del botón, que va centrado: sirve con 32 y con 44. */
.px-top .px-pop,
.px-top .px-menu-pop { top: calc(50% + var(--px-top-h) / 2 + 4px); }
.px-menu-pop { display: grid; gap: 1px; }
details[open] > .px-pop,
details[open] > .px-menu-pop { animation: px-pop-in var(--dur-2) var(--ease-out) both; }
@keyframes px-pop-in { from { opacity: 0; translate: 0 -4px; } }
.px-menu-down .px-menu-pop { top: calc(100% + 6px); bottom: auto; }
/* Un menú entre las acciones de la cabecera de una página («Suspender» en
   la ficha de una empresa). En el móvil el botón baja a la segunda fila y
   el desplegable, anclado a su borde derecho y con sus 320 px, se salía
   por la izquierda con el campo del motivo cortado (30/09/2026). Por
   debajo de 560 px cuelga de la cabecera entera y ocupa su ancho. */
@media (max-width: 560px) {
  .px-head:has(.px-head-act .px-menu) { position: relative; }
  .px-head-act .px-menu { position: static; }
  .px-head-act .px-menu-pop { inset-inline: 0; }
}
.px-menu-pop a:not(.btn), .px-menu-pop button:not(.btn) {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  min-height: 34px;
  padding: 6px 10px;
  border: 0;
  border-radius: var(--r-ctl);
  background: none;
  color: var(--ink-2);
  font: inherit;
  font-size: var(--t-ui);
  line-height: 1.3;
  text-align: start;
  text-decoration: none;
  cursor: pointer;
  transition: background-color var(--dur-1) var(--ease-out), color var(--dur-1) var(--ease-out);
}
.px-menu-pop a:not(.btn) > span, .px-menu-pop button:not(.btn) > span:not(.px-me-switch-t) { flex: 1; min-width: 0; }
.px-menu-pop a:not(.btn):hover, .px-menu-pop button:not(.btn):hover { background: var(--surface-hover); color: var(--ink); }
.px-menu-pop a:not(.btn):focus-visible, .px-menu-pop button:not(.btn):focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.px-menu-pop a:not(.btn) > svg, .px-menu-pop button:not(.btn) > svg { width: 16px; height: 16px; max-width: none; color: var(--muted); flex: none; }
.px-menu-pop hr { border: 0; border-top: 1px solid var(--line); margin: 5px 4px; }
.px-menu-pop form { display: contents; }

/* Aquí había un cajón lateral. Se ha quitado por lo mismo que el
   esqueleto: ninguna pantalla lo abre. Las fichas del panel son páginas
   completas, que es lo correcto —se pueden enlazar, marcar y abrir en otra
   pestaña, y un cajón no—. */


/* =====================================================================
   8 · PANTALLAS DE ACCESO — piezas comunes
   ---------------------------------------------------------------------
   La lámina partida (la clase px-sheet: panel oscuro + formulario, dirección
   «A · Marco» del lienzo Docs/diseno/acceso) se retiró el 25/09/2026:
   el acceso, el alta y el segundo factor van sobre `.px-stage` (más
   abajo) y las pantallas de un solo mensaje —invitación, recuperar la
   contraseña, verificar el correo— sobre `.px-card-page`. Aquí queda lo
   que comparten.
   ===================================================================== */

/* El aviso de cookies es fijo y se sienta ENCIMA: tapaba justo el pie del
   panel oscuro, que es donde están la ayuda y el idioma — o sea, las dos
   salidas de quien no consigue entrar. Se le reserva sitio DENTRO de la
   página y no como relleno del cuerpo: a sangre, ese relleno sería una
   franja de color al pie de la pantalla.

   Se engancha al atributo `data-cookie-banner` y NO a su clase: la clase
   pasó de `.cookie-banner` a `.ck` mientras esto estaba escrito y el hueco
   dejó de reservarse sin que nada avisara. El atributo es el contrato entre
   las dos partes; la clase es de quien maquete el aviso. */
body:has([data-cookie-banner]) .px-card-page { padding-bottom: 190px; }


/* Nota de seguridad bajo el formulario. No es relleno: en una pantalla
   donde se teclea una contraseña, saber cómo se trata es parte de poder
   teclearla tranquilo. (En el acceso dice «Conexión cifrada» y solo se
   pinta por https: ver auth/login.php.) */
.px-auth-note {
  display: flex;
  align-items: center;
  gap: 9px;
  margin-top: 22px;
  font-size: .8125rem;
  color: var(--muted);
  line-height: 1.5;
}
.px-auth-note svg { width: 15px; height: 15px; max-width: none; flex: none; opacity: .75; }
/* La primera capa de privacidad bajo el botón del alta (plan RGPD, 2.5): se
   INFORMA, no se acepta. Letra menor que la nota de seguridad y alineada
   arriba, porque son tres líneas y no una. */
.px-privacy-layer { align-items: flex-start; margin-top: 12px; font-size: .75rem; }
.px-privacy-layer svg { margin-top: 2px; }
/* La coletilla de «¿trabajas en otra tienda?» va DESPUÉS de la nota de
   seguridad y con su propio aire: sin esto las dos líneas se leían como
   un párrafo partido por la mitad, y no tienen nada que ver. */
.px-otra { margin-top: 14px; font-size: var(--t-xs); color: var(--muted); }

/* =====================================================================
   EL ACCESO — «cartel sobre cristal» (19/09/2026)
   ---------------------------------------------------------------------
   Fondo oscuro con dos auroras del color de la tienda; a la izquierda el
   cartel (marca, titular enorme, frase, áreas, inicial gigante de marca de
   agua) y a la derecha el formulario en una lámina de cristal esmerilado.
   Abajo, las salidas. Fusión de las direcciones 02 y 04 del lienzo
   Docs/diseno/acceso/propuestas-2026-09-19.html.

   El registro y el segundo factor van también sobre `.px-stage`.

   Sobre el contraste: todo el texto es blanco. Donde el fondo es tinta
   (#0B1526) sobra; donde la aurora aclara el color de la tienda solo hay
   texto GRANDE (la marca y el titular), que con 3:1 cumple. La aurora
   clara se apaga antes de llegar a la frase y a las chapas.
   ===================================================================== */
.px-stage {
  --px-band: var(--brand, #2E5BFF);
  --ring: 0 0 0 3px rgba(255, 255, 255, .28);
  position: relative;
  isolation: isolate;
  overflow: hidden;
  min-height: 100vh;
  min-height: 100dvh;
  display: grid;
  /* CON MEDIDA. El fondo va a sangre, pero el cartel y la lámina no crecen
     con la pantalla: en un monitor de 3800 px el cartel se iba al borde
     izquierdo, la lámina al derecho y en medio quedaba medio metro de
     nada. Las dos columnas tienen tope y se centran juntas. */
  grid-template-columns: minmax(0, 640px) minmax(0, 440px);
  grid-template-rows: minmax(0, 1fr) auto;
  justify-content: center;
  column-gap: clamp(40px, 7vw, 140px);
  row-gap: 28px;
  align-items: center;
  padding: clamp(28px, 4vw, 48px) clamp(20px, 6vw, 96px) clamp(22px, 3vw, 36px);
  color: #fff;
  background:
    radial-gradient(900px 620px at 12% 0%, color-mix(in srgb, var(--px-band) 80%, #fff) 0%, transparent 58%),
    radial-gradient(760px 540px at 88% 100%, color-mix(in srgb, var(--px-band) 55%, #000) 0%, transparent 60%),
    linear-gradient(160deg, #0B1526 0%, color-mix(in srgb, var(--px-band) 38%, #0B1526) 55%, #0B1526 100%);
}

/* ─── El cartel ─────────────────────────────────────────────────────── */
.px-stage-scene {
  grid-column: 1;
  grid-row: 1;
  position: relative;
  align-self: stretch;
  display: grid;
  grid-template-rows: auto minmax(0, 1fr);
  gap: 28px;
  min-width: 0;
}
.px-stage-brand { position: relative; z-index: 1; }
.px-stage-scene .px-brand { color: #fff; padding: 0; min-height: 0; font-size: 1.375rem; gap: 12px; text-shadow: 0 2px 10px rgba(11, 21, 38, .45); }
.px-stage-scene .px-brand:hover { color: #fff; }
/* EL LOGO DE LA TIENDA es el titular de la pantalla, no una pestaña: va
   grande, y con una sombra suave para que se despegue de la aurora clara
   que tiene detrás (un logo blanco sobre un azul claro se fundía). */
.px-stage-scene .px-brand .brand-logo { height: 52px; max-width: 280px; filter: drop-shadow(0 2px 10px rgba(11, 21, 38, .45)); }
/* Sobre fondo oscuro el chip de iniciales va en blanco con las letras del
   color de la tienda: del color de la tienda sobre su propia aurora se
   perdía. */
.px-stage-scene .mark-iniciales { width: 44px; height: 44px; border-radius: 12px; font-size: 17px; background: #fff; color: var(--px-band); box-shadow: 0 2px 10px rgba(11, 21, 38, .35); }
/* La inicial gigante: decoración al 5 % de blanco, detrás de todo y sin
   clics. Se sale por arriba y por la derecha a propósito: es una marca de
   agua, no un rótulo. */
.px-stage-giant {
  position: absolute;
  inset-inline-end: -.08em;
  top: -.2em;
  z-index: 0;
  font-family: var(--font-display);
  font-weight: 800;
  font-size: clamp(14rem, 34vw, 32rem);
  line-height: 1;
  letter-spacing: -.06em;
  color: rgba(255, 255, 255, .055);
  pointer-events: none;
  user-select: none;
}
.px-stage-say { position: relative; z-index: 1; align-self: center; display: grid; gap: 20px; max-width: 36rem; }
.px-stage-say h1 {
  color: #fff;
  font-size: clamp(2.75rem, 6.4vw, 5.75rem);
  line-height: .95;
  font-weight: 800;
  letter-spacing: -.045em;
}
.px-stage-lead { color: rgba(255, 255, 255, .84); font-size: clamp(1.0625rem, 1.4vw, 1.25rem); line-height: 1.5; max-width: 34ch; }

/* Las tres áreas, como chapas. Orientación, no publicidad.
   SIN BORDE (26/09/2026): con borde y relleno eran tres botones de manual
   —dan ganas de pulsar «Taller» para entrar directo al taller— y no hacen
   nada. Sin el borde se leen como lo que son: rótulos. */
.px-stage-areas { list-style: none; margin: 4px 0 0; padding: 0; display: flex; flex-wrap: wrap; gap: 10px; }
.px-stage-areas li {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-family: var(--font-mono);
  font-size: var(--t-xs);
  letter-spacing: .02em;
  color: #fff;
  padding: 7px 14px 7px 8px;
  border-radius: var(--r-full);
  background: rgba(255, 255, 255, .07);
}
.px-stage-areas .px-ic { width: 22px; height: 22px; border-radius: 7px; display: grid; place-items: center; background: rgba(255, 255, 255, .14); color: #fff; }
.px-stage-areas .px-ic svg { width: 14px; height: 14px; max-width: none; }

/* El escaparate: la última novedad de la Consola (solo en el dominio del
   producto). Lámina translúcida y enlace subrayado: UNA acción principal. */
.px-stage-news {
  display: grid;
  gap: 6px;
  justify-items: start;
  width: 100%;
  max-width: 30rem;
  margin-top: 4px;
  padding: 16px 18px;
  border-radius: var(--r-lg);
  background: rgba(255, 255, 255, .1);
  border: 1px solid rgba(255, 255, 255, .18);
}
.px-stage-news-tag { font-family: var(--font-mono); font-size: 10px; letter-spacing: .12em; text-transform: uppercase; color: #fff; opacity: .85; }
.px-stage-news b { color: #fff; font-family: var(--font-display); font-size: var(--t-lg); line-height: 1.25; }
.px-stage-news span:not(.px-stage-news-tag) { color: #fff; opacity: .85; font-size: var(--t-sm); line-height: 1.5; }
.px-stage-news a { color: #fff; font-weight: 600; font-size: var(--t-sm); text-decoration: underline; text-underline-offset: 3px; }
.px-stage-news a:hover { opacity: .85; }

/* ─── La lámina de cristal ──────────────────────────────────────────── */
.px-stage-card {
  grid-column: 2;
  grid-row: 1 / 3;
  align-self: center;
  justify-self: end;
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: 440px;
  padding: clamp(24px, 3vw, 36px);
  border-radius: 24px;
  color: #fff;
  background: rgba(255, 255, 255, .10);
  border: 1px solid rgba(255, 255, 255, .22);
  -webkit-backdrop-filter: blur(18px);
  backdrop-filter: blur(18px);
  box-shadow: 0 40px 80px -30px rgba(0, 0, 0, .6), inset 0 1px 0 rgba(255, 255, 255, .25);
}
/* Sin desenfoque (navegadores viejos) la lámina se vuelve tinta translúcida:
   se pierde el cristal, no la legibilidad. */
@supports not (backdrop-filter: blur(1px)) {
  .px-stage-card { background: rgba(11, 21, 38, .78); }
}
.px-stage-card .alert { margin-bottom: var(--s-5); }
/* LOS CAMPOS DEL ACCESO SON MÁS GRANDES QUE LOS DEL RESTO DEL PANEL, y a
   propósito: aquí solo hay dos, uno se teclea a ciegas y muchas veces de
   pie con el móvil en una mano. El tamaño de letra es de 1 rem y no es
   negociable: por debajo de 16 px, Safari en iPhone hace zoom al tocar el
   campo y deja el botón de «Entrar» fuera de la pantalla. */
.px-stage-card .field { margin-bottom: var(--s-5); }
.px-stage-card .field > label,
.px-stage-card .field-head > label { color: #fff; }
/* El campo que termina en «¿Olvidaste la contraseña?» ya trae su aire en el
   propio enlace (margen y área de toque): con el margen entero debajo, la
   casilla quedaba descolgada, más lejos de su campo que del botón. */
.px-stage-card .field:has(> .field-forgot) { margin-bottom: var(--s-3); }
/* En la Consola no hay casilla y el botón va justo detrás: vuelve el aire
   entero, el mismo que separa la casilla del botón en la web. */
.px-stage-card .field:has(> .field-forgot):has(+ .btn) { margin-bottom: var(--s-5); }
.px-stage-card input[type="email"],
.px-stage-card input[type="text"],
.px-stage-card input[type="password"] {
  font-size: 1rem;
  padding: 14px 15px;
  min-height: 52px;
  color: #fff;
  background: rgba(255, 255, 255, .08);
  border-color: rgba(255, 255, 255, .32);
  transition: border-color .2s ease, box-shadow .2s ease, background .2s ease;
}
.px-stage-card input:focus { border-color: #fff; background: rgba(255, 255, 255, .12); box-shadow: var(--ring); }
.px-stage-card input::placeholder { color: rgba(255, 255, 255, .5); }
/* El autorrelleno de Chrome pinta el campo de blanco con letra negra: se
   le devuelve el fondo oscuro y la letra blanca. */
.px-stage-card input:-webkit-autofill,
.px-stage-card input:-webkit-autofill:focus {
  -webkit-text-fill-color: #fff;
  -webkit-box-shadow: 0 0 0 1000px color-mix(in srgb, var(--px-band) 22%, #0B1526) inset;
  caret-color: #fff;
}
.px-stage-card .field.has-error input { border-color: #F26D6D; }
.px-stage-card .input-reveal input { padding-inline-end: 54px; }
.px-stage-card .input-reveal .reveal { width: 52px; color: rgba(255, 255, 255, .72); }
.px-stage-card .input-reveal .reveal:hover { color: #fff; }
.px-stage-card .field-forgot { color: rgba(255, 255, 255, .85); font-size: .8125rem; }
.px-stage-card .field-forgot:hover { color: #fff; text-decoration: underline; }
/* Los avisos de mayúsculas y espacios: el ámbar del tema claro no se ve
   sobre tinta; el del tema oscuro sí. */
.px-stage-card .hint-warn { color: #F0B34E; }
/* La casilla es objetivo de dedo, no adorno. */
.px-stage-remember { margin-bottom: var(--s-5); padding: 4px 0; color: #fff; }
.px-stage-remember input { accent-color: #fff; }
/* LA CASILLA, DIBUJADA (26/09/2026). La nativa con `accent-color: #fff` es
   un cuadrado BLANCO también sin marcar: sobre tinta, «marcada» y «sin
   marcar» solo se distinguían por el tic. Aquí sin marcar es un hueco con
   borde; marcada, blanca con el tic en tinta. Vale para todas las casillas
   de la escena: «no cerrar sesión», «no me lo vuelvas a pedir» y el alta. */
.px-stage-card .check input[type="checkbox"] {
  -webkit-appearance: none;
  appearance: none;
  width: 20px;
  height: 20px;
  margin: 1px 0 0;
  border: 1.5px solid rgba(255, 255, 255, .62);
  border-radius: 6px;
  background: rgba(255, 255, 255, .06) center / 14px 14px no-repeat;
  transition: background-color .15s ease, border-color .15s ease;
}
.px-stage-card .check input[type="checkbox"]:hover { border-color: #fff; }
.px-stage-card .check input[type="checkbox"]:checked {
  border-color: #fff;
  background-color: #fff;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%230B1526' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3.5 8.5l3 3 6-7'/%3E%3C/svg%3E");
}
.px-stage-card .check input[type="checkbox"]:focus-visible { outline: none; box-shadow: var(--ring); }
@media (prefers-reduced-motion: reduce) {
  .px-stage-card .check input[type="checkbox"] { transition: none; }
}
.px-stage-card .btn-lg { min-height: 52px; }
/* El botón va en blanco: el color de la tienda ya es toda la pantalla, y
   un botón blanco sobre cristal es lo que más se ve. */
.px-stage-card .btn-primary { background: #fff; border-color: #fff; color: #0B1526; box-shadow: 0 12px 28px -12px rgba(0, 0, 0, .6); }
.px-stage-card .btn-primary:hover { background: #E9EEF8; border-color: #E9EEF8; color: #0B1526; }
.px-stage-card .px-auth-note { color: rgba(255, 255, 255, .66); }
/* El enlace de la nota (la política de privacidad del alta) salía en el azul
   del acento, sobre el azul de la escena: no se leía. Blanco y subrayado,
   como los demás enlaces de la lámina. */
.px-stage-card .px-auth-note a { color: #fff; text-decoration: underline; text-underline-offset: 3px; }
.px-stage-card .px-otra { color: rgba(255, 255, 255, .6); }
.px-stage-card .known-hi { color: #fff; }
.px-stage-card .known-id { background: rgba(255, 255, 255, .08); border-color: rgba(255, 255, 255, .2); }
.px-stage-card .known-mail { color: rgba(255, 255, 255, .9); }
.px-stage-card .known-av { background: #fff; color: var(--px-band); }
.px-stage-card .known-switch { color: #fff; }
.px-stage-card .known-switch:hover { background: rgba(255, 255, 255, .12); }

/* ─── Lo que la lámina lleva en el SEGUNDO paso (two-factor.php) ────── */
.px-stage-card-title { color: #fff; font-size: var(--t-2xl); font-weight: 800; letter-spacing: -.03em; }
.px-stage-card .px-sub { color: rgba(255, 255, 255, .72); font-size: var(--t-sm); margin: 8px 0 24px; }
.px-stage-card .muted { color: rgba(255, 255, 255, .62); }
.px-stage-card .btn-ghost { color: #fff; }
.px-stage-card .btn-ghost:hover { background: rgba(255, 255, 255, .12); color: #fff; }
/* Las casillas del código, sobre cristal. */
.px-stage-card .px-code { color: #fff; }
.px-stage-card .px-otp-cell { color: #fff; background: rgba(255, 255, 255, .08); border-color: rgba(255, 255, 255, .32); }
.px-stage-card .px-otp-cell.is-on { border-color: #fff; background: rgba(255, 255, 255, .12); }
.px-stage-card .px-otp.is-focus .px-otp-cell.is-active { border-color: #fff; box-shadow: var(--ring); }
.px-stage-card .px-otp.is-focus .px-otp-cell.is-active:empty::after { background: #fff; }
.px-stage-card .px-otp-clock { color: rgba(255, 255, 255, .7); }
.px-stage-card .px-otp-clock.is-over { color: #F26D6D; }
.px-stage-card .px-otp-tag { border-color: rgba(255, 255, 255, .35); background: rgba(255, 255, 255, .06); margin-bottom: 20px; }
.px-stage-card .px-otp-tag-k, .px-stage-card .px-otp-tag-d { color: rgba(255, 255, 255, .65); }
.px-stage-card .px-otp-tag-v { color: #fff; }
.px-stage-card .px-otp-trust { color: #fff; }
.px-stage-card .px-otp-trust input { accent-color: #fff; }
.px-stage-card .px-otp-foot { border-top-color: rgba(255, 255, 255, .16); }
.px-stage-card .px-otp-bail-b { color: rgba(255, 255, 255, .75); }
.px-stage-card .px-otp-bail-b:hover { color: #F26D6D; }
.px-stage-card .px-otp-foot .px-auth-note { text-align: start; margin-top: 12px; }

/* Las tres respuestas del segundo paso, en el cartel: icono, qué y cómo. */
.px-stage-points { list-style: none; margin: 6px 0 0; padding: 0; display: grid; gap: 14px; max-width: 30rem; }
.px-stage-points li { display: grid; grid-template-columns: 30px minmax(0, 1fr); column-gap: 12px; row-gap: 2px; align-items: start; }
.px-stage-points .px-ic { grid-row: 1 / 3; width: 30px; height: 30px; border-radius: 9px; display: grid; place-items: center; background: rgba(255, 255, 255, .12); color: #fff; margin-top: 1px; }
.px-stage-points .px-ic svg { width: 16px; height: 16px; max-width: none; }
.px-stage-points b { color: #fff; font-size: var(--t-sm); font-weight: 700; line-height: 1.3; }
.px-stage-points i { color: rgba(255, 255, 255, .72); font-size: var(--t-xs); font-style: normal; line-height: 1.45; }

/* ─── Las salidas ───────────────────────────────────────────────────── */
.px-stage-foot {
  grid-column: 1;
  grid-row: 2;
  position: relative;
  z-index: 1;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px 22px;
  font-size: var(--t-xs);
  color: rgba(255, 255, 255, .62);
}
.px-stage-host { font-family: var(--font-mono); color: rgba(255, 255, 255, .78); letter-spacing: .02em; }
.px-stage-foot p { margin: 0; font-size: var(--t-sm); color: rgba(255, 255, 255, .72); }
/* Los enlaces llevan relleno para medir 44 px de alto al tacto. */
.px-stage-foot p a { color: #fff; text-decoration: underline; text-underline-offset: 3px; display: inline-block; padding: 8px 0; }
.px-stage-foot p a:hover { opacity: .85; }
.px-stage-signup a { font-weight: 600; }
.px-stage-langs { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }
.px-stage-langs a { color: rgba(255, 255, 255, .62); display: inline-block; padding: 8px 0; }
.px-stage-langs a:hover { color: #fff; }
.px-stage-langs a[aria-current="true"] { color: #fff; font-weight: 700; }
/* La firma va con los idiomas y no empujada al final de la columna: en un
   monitor ancho ese final cae a media pantalla y la firma flotaba sola. */
.px-stage-sign { font-family: var(--font-mono); font-size: 11px; color: rgba(255, 255, 255, .5); }

/* El aviso de cookies es fijo y se sienta ENCIMA de las salidas. Se le
   reserva sitio, igual que en `.px-card-page` (mismo gancho `data-cookie-banner`). */
body:has([data-cookie-banner]) .px-stage { padding-bottom: 190px; }

/* Modo de contraste forzado (Windows): la inicial gigante dejaría de ser
   un 5 % de blanco y se pintaría OPACA encima de todo. Fuera. La lámina
   pierde el cristal y se queda con los colores del sistema, que es lo
   correcto. */
@media (forced-colors: active) {
  .px-stage-giant { display: none; }
  .px-stage-card { backdrop-filter: none; -webkit-backdrop-filter: none; border: 1px solid CanvasText; }
  /* El tic dibujado es tinta sobre blanco, y en contraste forzado el blanco
     pasa a ser el fondo del sistema: la casilla nativa sí se adapta. */
  .px-stage-card .check input[type="checkbox"] { -webkit-appearance: auto; appearance: auto; }
}
/* Quien tiene la transparencia reducida en el sistema no quiere leer a
   través de un cristal: tinta casi sólida. */
@media (prefers-reduced-transparency: reduce) {
  .px-stage-card { backdrop-filter: none; -webkit-backdrop-filter: none; background: rgba(11, 21, 38, .88); }
}

/* Por debajo de 1080 px las dos columnas no caben: 640 de cartel + 440 de
   lámina + el hueco. Entre 900 y 1080 se apretaban las dos y la lámina se
   salía por abajo. */
@media (max-width: 1080px) {
  /* Una columna: el cartel arriba, la lámina debajo, las salidas al pie.
     El formulario NO se centra en la pantalla: con el teclado abierto la
     mitad desaparece y un bloque centrado se va con ella. */
  .px-stage { grid-template-columns: minmax(0, 640px); grid-template-rows: auto auto auto; justify-content: center; row-gap: 22px; align-items: start; padding: 22px 16px 26px; }
  .px-stage-scene { grid-column: 1; grid-row: 1; align-self: start; grid-template-rows: auto auto; gap: 18px; }
  .px-stage-say { gap: 12px; }
  .px-stage-say h1 { font-size: clamp(2.5rem, 11vw, 3.25rem); }
  .px-stage-lead { font-size: var(--t-base); }
  .px-stage-giant { font-size: 11rem; top: -.12em; inset-inline-end: -.1em; }
  .px-stage-scene .px-brand .brand-logo { height: 44px; }
  .px-stage-card { grid-column: 1; grid-row: 2; justify-self: stretch; max-width: none; border-radius: 20px; }
  .px-stage-foot { grid-column: 1; grid-row: 3; gap: 2px 18px; }
  .px-stage-sign { margin-inline-start: 0; }
  body:has([data-cookie-banner]) .px-stage { padding-bottom: 340px; }
}

/* ─── El modal de recuperar la contraseña ────────────────────────────
   Un <dialog> nativo: el navegador pone la capa superior, atrapa el foco y
   deja inerte lo de detrás. Aquí solo se viste. La lámina lleva el mismo
   radio y la misma sombra que la tarjeta del acceso: es la misma familia. */
.px-modal {
  border: 0;
  padding: 0;
  background: transparent;
  width: 100%;
  max-width: min(440px, calc(100vw - 32px));
  margin: auto;
  color: var(--ink);
}
.px-modal::backdrop { background: rgba(11, 21, 38, .55); backdrop-filter: blur(4px); }
.px-modal-sheet {
  position: relative;
  display: grid;
  gap: 8px;
  background: var(--surface);
  border-radius: 22px;
  padding: 30px 30px 28px;
  box-shadow: var(--px-e3);
}
.px-modal-sheet h2 { font-size: var(--t-xl); letter-spacing: -.02em; padding-inline-end: 40px; }
.px-modal-sub { font-size: var(--t-sm); color: var(--muted); line-height: 1.55; margin-bottom: 12px; }
.px-modal-ic {
  width: 48px;
  height: 48px;
  border-radius: 14px;
  display: grid;
  place-items: center;
  margin-bottom: 8px;
  background: color-mix(in srgb, var(--px-band) 12%, #fff);
  color: var(--px-band);
}
.px-modal-ic.is-ok { background: var(--ok-soft); color: var(--ok); }
.px-modal-ic svg { width: 22px; height: 22px; max-width: none; }
/* La cruz mide 40 px al tacto aunque el dibujo sea de 18. */
.px-modal-x {
  position: absolute;
  top: 14px;
  right: 14px;
  width: 40px;
  height: 40px;
  border: 0;
  border-radius: 10px;
  background: transparent;
  color: var(--muted);
  display: grid;
  place-items: center;
  cursor: pointer;
  transition: background .18s ease, color .18s ease;
}
.px-modal-x:hover { background: var(--surface-3); color: var(--ink); }
.px-modal-x svg { width: 18px; height: 18px; max-width: none; }
.px-modal .field { margin-bottom: var(--s-4); }
.px-modal input[type="email"] { font-size: 1rem; padding: 14px 15px; min-height: 52px; }
.px-modal .btn-lg { min-height: 52px; }
.px-modal .btn-primary { box-shadow: 0 10px 24px -10px color-mix(in srgb, var(--px-band) 65%, transparent); }
/* Solo el contenido se desplaza cuando el teclado o el zoom dejan poco alto. */
.px-modal.px-recovery { overflow:hidden; border-radius:18px; max-height:calc(100dvh - 32px); }
.px-recovery .px-modal-sheet { max-height:calc(100dvh - 34px); overflow-y:auto; overscroll-behavior:contain; scrollbar-width:thin; scrollbar-color:#a2afbf transparent; box-shadow:none; }
.px-recovery .px-modal-sheet[hidden], .px-recovery [hidden] { display:none!important; }
.px-recovery [data-recover-done] { text-align:center; padding-top:32px; gap:14px; }
.px-recovery [data-recover-done] .px-modal-ic { margin:0 auto 2px; }
.px-recovery [data-recover-done] h2 { padding:0; margin:0; }
.px-recovery [data-recover-done] .px-modal-sub { margin:0 0 6px; line-height:1.65; }
.px-recovery .px-modal-sheet > .btn { flex-shrink:0; box-shadow:none; }
.px-modal.px-recovery[open] { animation:none; }
@media (prefers-reduced-motion: no-preference) {
  .px-modal[open] { animation: px-modal-in .22s cubic-bezier(.2, .7, .2, 1); }
  .px-modal[open]::backdrop { animation: px-modal-fade .22s ease; }
}
@keyframes px-modal-in { from { opacity: 0; transform: translateY(10px) scale(.98); } }
@keyframes px-modal-fade { from { opacity: 0; } }

/* Tarjeta suelta centrada (código de verificación, recuperar contraseña,
   avisos del alta). Misma lámina, sin panel oscuro. */
.px-card-page { min-height: 100vh; min-height: 100dvh; display: grid; place-items: center; padding: 32px 20px 56px; background: var(--bg); }
.px-card-page > * { width: 100%; max-width: 460px; }
.px-card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-xl);
  box-shadow: var(--px-e2);
  padding: 32px;
}
.px-card-ic {
  width: 56px;
  height: 56px;
  border-radius: var(--r-lg);
  display: grid;
  place-items: center;
  margin: 0 auto 20px;
  background: var(--accent-soft);
  color: var(--accent);
}
.px-card-ic svg { width: 26px; height: 26px; max-width: none; }
.px-card-ic.is-ok { background: var(--ok-soft); color: var(--ok); }
.px-card-ic.is-warn { background: var(--warn-soft); color: var(--warn); }

/* El campo del código de seis cifras. La separación entre letras deja un
   hueco de más al final de la caja, así que el relleno de la izquierda lo
   compensa: sin eso el número se ve descentrado y parece mal alineado. */
.px-code {
  font-family: var(--font-mono);
  font-size: 1.6rem;
  letter-spacing: .5em;
  text-align: center;
  padding-inline-start: calc(14px + .5em);
}

/* ---------------------------------------------------------------------
   EL CÓDIGO DE UN SOLO USO — una casilla por cifra, y UN SOLO CAMPO
   ---------------------------------------------------------------------
   La regla de arriba (`.px-code`) es lo que se ve SIN JavaScript: un campo
   largo con las cifras separadas. Funciona, y tiene que seguir
   funcionando: esta pantalla es el paso donde alguien entra o no entra, y
   no puede depender de que un script llegue.

   Con JavaScript, platform.js le pone `is-ready` al contenedor y pinta una
   caja por cifra. Entonces el `<input>` de verdad se vuelve invisible y se
   estira por encima de las cajas: sigue siendo él quien recibe el teclado,
   el pegado de una sola vez, el autorrelleno del gestor de contraseñas y
   el `one-time-code` que ofrece el móvil. Las cajas son un dibujo.

   Por qué así y no ocho `<input>` de verdad, que es lo que se hace por
   ahí: ocho campos se pegan mal (el navegador mete las ocho cifras en el
   primero), se navegan peor con teclado, obligan a inventar el borrado y
   el retroceso a mano, los gestores de contraseñas no saben cuál rellenar,
   y un lector de pantalla anuncia ocho campos sin etiqueta en vez de uno
   con la suya. Aquí no se paga nada de eso.
   --------------------------------------------------------------------- */

/* El bloque central de esta pantalla ocupa la MISMA fila y la MISMA medida
   que el formulario del acceso: la columna clara es una rejilla de tres
   filas (remate, formulario, pie) y aquí hay que entrar por la de en medio.
   Si se colocara suelto, cada trozo —formulario, reenvío, aviso de
   desarrollo— se llevaría una fila propia y el pie dejaría de estar abajo.

   Es un bloque y no tres hermanos porque debajo del botón hay otra
   conversación entera (reenviar, qué hacer si no llega, salir) y tiene que
   viajar con el formulario, no repartirse por la columna. */

.px-otp { position: relative; }

/* El campo real, ya con casillas debajo. Sigue en el sitio y en el orden
   de tabulación; lo único que cambia es que no se ve. */
.px-otp.is-ready .px-code {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: var(--r-md);
  background: transparent;
  box-shadow: none;
  color: transparent;
  caret-color: transparent;
  letter-spacing: normal;
  text-align: center;
  /* 16 px exactos: por debajo de eso, Safari en iPhone hace zoom al
     enfocar el campo y la pantalla se queda torcida a media escritura. El
     texto no se ve, pero el tamaño sigue contando para esa regla. */
  font-size: 16px;
  z-index: 2;
  cursor: text;
}
.px-otp.is-ready .px-code:focus { outline: none; box-shadow: none; }
/* El resalte de selección dibuja el código aunque la tinta sea
   transparente: con Ctrl+A se veía el número entero en azul. */
.px-otp.is-ready .px-code::selection { background: transparent; color: transparent; }

.px-otp-cells { display: none; gap: 8px; justify-content: center; }
.px-otp.is-ready .px-otp-cells { display: flex; }

.px-otp-cell {
  flex: 1 1 0;
  min-width: 0;
  max-width: 58px;
  height: 62px;
  display: grid;
  place-items: center;
  font-family: var(--font-mono);
  font-size: 1.5rem;
  font-weight: 500;
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-md);
  transition: border-color var(--px-fast) var(--px-ease),
              box-shadow var(--px-fast) var(--px-ease),
              background var(--px-fast) var(--px-ease);
}
/* El aire entre grupos (4+4, o 3+3 si el código es de seis). Leer ocho
   cifras de una tirada obliga a volver al correo a media escritura. */
.px-otp-cell[data-gap] { margin-inline-start: 16px; }
.px-otp-cell.is-on { border-color: var(--ink); background: var(--surface); }

/* La casilla donde va a caer la siguiente cifra. El anillo es el foco:
   el campo real no puede dibujarlo porque no se ve. */
.px-otp.is-focus .px-otp-cell.is-active {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 22%, transparent);
}
/* La barra que parpadea solo en la casilla VACÍA donde va a caer la
   siguiente cifra. Con el código completo, la última casilla se queda con
   el anillo pero sin barra: dibujarla encima del número lo tacha. */
.px-otp.is-focus .px-otp-cell.is-active:empty::after {
  content: "";
  width: 2px;
  height: 26px;
  border-radius: 1px;
  background: var(--accent);
  animation: px-otp-caret 1.1s steps(2, jump-none) infinite;
}
@keyframes px-otp-caret { 0%, 49% { opacity: 1; } 50%, 100% { opacity: 0; } }

/* Se ha escrito mal. El temblor dura 300 ms y no se repite: es una señal,
   no un castigo. */
.px-otp.is-wrong .px-otp-cell { border-color: var(--danger); }
.px-otp.is-wrong { animation: px-otp-no .3s var(--px-ease); }
@keyframes px-otp-no {
  0%, 100% { transform: translateX(0); }
  20% { transform: translateX(-6px); }
  50% { transform: translateX(5px); }
  80% { transform: translateX(-3px); }
}

/* La cuenta atrás, en la misma línea que la etiqueta. */
.px-otp-clock {
  font-family: var(--font-mono);
  font-size: var(--t-xs);
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}
.px-otp-clock.is-over { color: var(--danger); }

/* La marca del intento: la misma que trae el correo. */
.px-otp-tag {
  display: grid;
  grid-template-columns: auto auto;
  justify-content: start;
  align-items: center;
  gap: 4px 10px;
  margin-top: 18px;
  padding: 12px 14px;
  border: 1px dashed var(--line-strong);
  border-radius: var(--r-md);
  background: var(--surface-2);
}
.px-otp-tag-k { font-size: var(--t-xs); color: var(--muted); text-transform: uppercase; letter-spacing: .08em; }
.px-otp-tag-v {
  font-family: var(--font-mono);
  font-size: 1rem;
  letter-spacing: .12em;
  color: var(--ink);
}
.px-otp-tag-d { grid-column: 1 / -1; font-size: var(--t-xs); color: var(--muted); line-height: 1.5; }

.px-otp-trust { margin: 20px 0 22px; cursor: pointer; }
.px-otp-trust strong { display: block; font-size: var(--t-sm); }

/* El pie del formulario: reenviar, la pista del correo no deseado y la
   salida. Separados del botón por una línea, porque son otra conversación
   —qué hacer si esto no va— y no la acción principal. */
.px-otp-foot {
  margin-top: 26px;
  padding-top: 22px;
  border-top: 1px solid var(--line);
  display: grid;
  justify-items: center;
  gap: 10px;
  text-align: center;
}
/* «No he sido yo». Es un botón de formulario (cierra sesión, así que va
   por POST con token) disfrazado de enlace: pintarlo como botón de verdad
   lo pondría a competir con «Verificar», que es lo que casi todo el mundo
   viene a pulsar. */
.px-otp-bail { display: flex; align-items: baseline; gap: 6px; flex-wrap: wrap; justify-content: center; }
.px-otp-bail-b {
  border: 0;
  background: none;
  padding: 0;
  font: inherit;
  font-size: var(--t-xs);
  font-weight: 600;
  color: var(--muted);
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}
.px-otp-bail-b:hover { color: var(--danger); }

.px-otp-dev { margin-top: 20px; font-size: var(--t-xs); }


/* =====================================================================
   9 · AJUSTES: PESTAÑAS, IMÁGENES DE MARCA Y BARRA DE GUARDAR
   =====================================================================
   La pantalla de Ajustes es la única con un formulario largo repartido en
   pestañas, y sus piezas viven aquí en vez de pegadas con `style=` en la
   vista: un `max-width` escrito a mano en catorce campos es imposible de
   cambiar a la vez y se descuadra en cuanto se añade el decimoquinto.
   ===================================================================== */

.px-set { display: grid; gap: var(--px-gap); }

/* Los campos de un formulario de ajustes no llevan el margen inferior de
   `.field`: quien reparte el aire es la rejilla del panel. */
.px-field { margin: 0; min-width: 0; }
.px-field > input, .px-field > select { width: 100%; }

/* Un campo suelto dentro de un panel —sin rejilla que lo acote— no se estira
   hasta el borde de la pantalla: en 1440 px, «Días de prueba» era una caja de
   1.100 px para escribir «30». La línea corta hace legible además la pista
   que va debajo. */
.px-panel-body > .px-field { max-width: 34rem; }
.px-field > input[type="number"], .px-field > input[type="date"] { max-width: 12rem; }

/* ── Pestañas ─────────────────────────────────────────────────────────
   Sin JavaScript no se pintan: son botones que no harían nada, y la
   página entera está debajo de todas formas. La clase `px-js` la pone
   panel-boot.js desde la cabecera, antes del primer pintado, para que
   nadie vea las cinco secciones desplegarse y encogerse al cargar. */
:root:not(.px-js) .px-set > .px-tabs { display: none; }

.px-tabs button {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 10px 14px;
  border: 0;
  background: transparent;
  border-radius: var(--r-sm) var(--r-sm) 0 0;
  font: inherit;
  font-size: var(--t-sm);
  font-weight: 500;
  color: var(--muted);
  white-space: nowrap;
  cursor: pointer;
}
.px-tabs button svg { width: 15px; height: 15px; max-width: none; flex: none; }
.px-tabs button:hover { color: var(--ink); background: var(--surface-3); }
.px-tabs button[aria-selected="true"] { color: var(--accent); font-weight: 600; }
.px-tabs button[aria-selected="true"]::after {
  content: "";
  position: absolute;
  inset-inline: 10px;
  bottom: -1px;
  height: 2px;
  border-radius: 2px 2px 0 0;
  background: var(--accent);
}
.px-tabs button:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

/* Cada panel reparte sus secciones con el mismo aire que la rejilla. */
[data-px-tabpanel] { display: grid; gap: var(--px-gap); }

/* ── Imágenes de marca ────────────────────────────────────────────────
   La vista previa va sobre el fondo en el que se va a ver de verdad: un
   logo en tinta negra parece perfecto sobre blanco y desaparece en la
   barra lateral de la Consola, que es oscura. */
.px-media {
  display: grid;
  grid-template-columns: 120px minmax(0, 1fr);
  gap: var(--s-4);
  align-items: start;
  padding: 14px;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--surface-2);
}
.px-media-view {
  display: grid;
  place-items: center;
  height: 84px;
  padding: 10px;
  border-radius: var(--r-sm);
  border: 1px solid var(--line-2);
  /* Damero: sin él, un PNG transparente sobre un fondo liso parece tener
     el fondo de ese color, y se vuelve a subir «porque salía con fondo». */
  background-color: #FFFFFF;
  background-image:
    linear-gradient(45deg, rgba(0, 0, 0, .06) 25%, transparent 25%, transparent 75%, rgba(0, 0, 0, .06) 75%),
    linear-gradient(45deg, rgba(0, 0, 0, .06) 25%, transparent 25%, transparent 75%, rgba(0, 0, 0, .06) 75%);
  background-size: 14px 14px;
  background-position: 0 0, 7px 7px;
}
.px-media-view.is-dark {
  background-color: #0B1526;
  background-image:
    linear-gradient(45deg, rgba(255, 255, 255, .07) 25%, transparent 25%, transparent 75%, rgba(255, 255, 255, .07) 75%),
    linear-gradient(45deg, rgba(255, 255, 255, .07) 25%, transparent 25%, transparent 75%, rgba(255, 255, 255, .07) 75%);
}
.px-media-img { max-width: 100%; max-height: 64px; width: auto; object-fit: contain; }
.px-media-img.is-icon { max-height: 32px; }
/* El «sin imagen» va sobre el damero BLANCO (o el oscuro): su tinta es la
   del fondo en que se pinta, no la del panel. El gris de antes daba 3,07:1
   sobre blanco. */
.px-media-none { font-size: var(--t-xs); color: #5A6B85; text-align: center; }
.px-media-view.is-dark .px-media-none { color: #8C9AB5; }
.px-media-ctl { display: grid; gap: 6px; min-width: 0; }
.px-media-ctl > strong { font-size: var(--t-sm); }
.px-media-act { display: flex; flex-wrap: wrap; gap: var(--s-2); margin-top: 4px; }

/* El `input file` de fábrica enseña «Sin archivos seleccionados» en el
   idioma del navegador y no se puede estilar. Se tapa con su etiqueta y se
   deja DENTRO de ella: así el clic, el tabulador y el lector de pantalla
   siguen llegando al control de verdad. `opacity:0` y no `display:none`
   porque un campo oculto del todo no recibe foco. */
.px-media-pick { position: relative; overflow: hidden; cursor: pointer; }
.px-media-pick input[type="file"] {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  opacity: 0;
  cursor: pointer;
}
.px-media-pick:focus-within { outline: 2px solid var(--accent); outline-offset: 2px; }
.px-media-del { color: var(--danger); }
.px-media-del:hover { background: var(--danger-soft); border-color: transparent; }

/* ── Color de marca ───────────────────────────────────────────────────
   La rueda del sistema y el código escrito, atados: el código es el que
   lleva el `name`, así que sin JavaScript sigue guardándose. */
.px-color { display: flex; align-items: center; gap: var(--s-2); }
.px-color-dot {
  flex: none;
  width: 44px;
  height: 40px;
  padding: 3px;
  border: 1px solid var(--line-2);
  border-radius: var(--r-sm);
  background: var(--surface-2);
  cursor: pointer;
}
.px-color input[type="text"] { flex: 1; min-width: 0; font-family: var(--font-mono); text-transform: uppercase; }

/* ── Nota dentro de un panel ─────────────────────────────────────────── */
.px-note {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 11px 13px;
  border-radius: var(--r-sm);
  border: 1px solid var(--line-2);
  background: var(--surface-2);
  font-size: var(--t-xs);
  color: var(--muted);
}
.px-note svg { flex: none; margin-top: 1px; color: var(--accent); }

/* ── Pie del bloque de correo ───────────────────────────────────────── */
.px-mail-foot { display: flex; align-items: center; gap: var(--s-3); flex-wrap: wrap; }
.px-mail-foot .hint { flex: 1 1 12rem; min-width: 0; }
.px-mail-env { margin-inline-start: auto; color: var(--muted); }

/* Una casilla dentro de un campo (quitar la contraseña guardada): más
   estrecha que la de un ajuste suelto, que allí es la fila principal. */
.px-pick-thin { margin-top: 8px; padding: 9px 11px; }

/* ── Barra de guardar ─────────────────────────────────────────────────
   Pegada abajo para tenerla a mano después de recorrer la pestaña, y con
   sombra propia para que se despegue del panel que pasa por debajo. */
.px-saver { position: sticky; bottom: var(--s-4); z-index: 20; box-shadow: var(--px-e3); }
.px-saver .px-panel-body {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-4);
  flex-wrap: wrap;
  padding: 12px 18px;
}

/* La fila de idiomas no es un dato que se copie: ni fuente de máquina de
   escribir ni botón de copiar. */
.px-def-plain { font-family: var(--font-sans); font-size: var(--t-sm); }
.px-def-link { margin-inline-start: 8px; }


/* =====================================================================
   9b · LA CONSOLA RENOVADA · COMPONENTES (27/09/2026)
   ---------------------------------------------------------------------
   Cabecera de página, pestañas, selector segmentado, paneles, cifras,
   tablas, filtros, estados vacíos y modo denso de la superficie oscura,
   con las fichas de pulsar.css («LA CONSOLA RENOVADA»). Los botones,
   campos, chapas y avisos en línea están en pulsar.css, junto a su regla
   base.

   Dos decisiones explican el bloque entero:

    · VA DETRÁS DE `:where([data-surface="console"])`. Estas piezas también
      las pinta el área de cliente (clara, azul), que no cambia. El `:where`
      no suma especificidad: cada regla pesa lo mismo que la de arriba a la
      que sustituye, gana solo por venir después, y las hojas de cada
      pantalla —que se cargan detrás de esta— la siguen pudiendo ajustar.

    · ESTÁ AQUÍ, ANTES DE SALUD Y DE LOS TAMAÑOS PEQUEÑOS, y no al final.
      Lo de Salud es más concreto y manda sobre esto; y las reglas de móvil
      del bloque 12 vienen detrás, así que la cabecera sigue bajando sus
      acciones y las cifras siguen yendo a una columna sin repetirlo aquí.
   ===================================================================== */

/* --- Cabecera de página ----------------------------------------------
   Título de 24 a 28 px (antes hasta 30, y cada hoja de pantalla lo subía a
   su manera). Las acciones se alinean ARRIBA, con el título, y no con la
   última línea de la entradilla: con una entradilla de dos líneas, los
   botones quedaban flotando a media altura. En estrecho bajan solas. */
:where([data-surface="console"]) .px-head { align-items: flex-start; gap: var(--s-3) var(--s-5); }
:where([data-surface="console"]) .px-head-txt { flex: 1 1 26rem; max-width: none; }
:where([data-surface="console"]) .px-head h1 {
  font-size: clamp(1.5rem, 1.15rem + .9vw, 1.75rem);
  font-weight: 650;
  letter-spacing: -.02em;
  line-height: 1.15;
}
:where([data-surface="console"]) .px-head p { max-width: 72ch; margin-top: 6px; font-size: var(--t-sm); line-height: 1.5; color: var(--muted); }
:where([data-surface="console"]) .px-head-act { gap: 8px; padding-top: 2px; }
/* Un desplegable entre los botones pequeños de la cabecera va a su talla:
   un campo de 38 junto a botones de 32 dejaba la fila escalonada. */
:where([data-surface="console"]) .px-head-act select { height: var(--ctl-sm); font-size: var(--t-ui); width: auto; max-width: 100%; }
/* Y los botones de la cabecera, todos a la talla pequeña: había pantallas
   que mezclaban un 36 con un 40 en la misma fila (agentes, idiomas,
   actualizaciones). La cabecera no es donde se trabaja, es donde se sale. */
:where([data-surface="console"]) .px-head-act .btn { --btn-h: var(--ctl-sm); padding-inline: 12px; gap: 6px; font-size: var(--t-ui); }

/* Antetítulo: 11 px, monoespaciada porque suele ser una fecha o un código,
   y el punto cian con un halo suave para que no parezca una viñeta. */
:where([data-surface="console"]) .px-eyebrow {
  gap: 8px;
  margin-bottom: 10px;
  font-size: var(--t-2xs);
  font-weight: 500;
  letter-spacing: .06em;
  line-height: 1.3;
}
:where([data-surface="console"]) .px-eyebrow::before { box-shadow: 0 0 0 3px var(--accent-soft); }

/* Volver: un botón fantasma pequeño. La flecha se alinea con el borde del
   título (el margen negativo compensa el relleno) y el fondo solo aparece
   al pasar el ratón. Antes era texto de 28 px de alto, difícil de acertar. */
:where([data-surface="console"]) .px-back {
  min-height: var(--ctl-xs);
  padding: 0 10px 0 6px;
  margin-block: 0 10px;
  margin-inline: -6px 0;
  gap: 6px;
  border-radius: var(--r-ctl);
  font-size: var(--t-ui);
  font-weight: 500;
  color: var(--muted);
  transition: background-color var(--dur-1) var(--ease-out), color var(--dur-1) var(--ease-out);
}
:where([data-surface="console"]) .px-back:hover { color: var(--ink); background-color: var(--surface-hover); }
:where([data-surface="console"]) .px-back:active { background-color: var(--surface-pressed); }

/* --- Pestañas --------------------------------------------------------
   Subrayado de 2 px en acento y el texto activo en tinta, no en cian: el
   cian ya está en la raya, y dos marcas de color para decir lo mismo
   compiten con el botón principal. El número de cada pestaña va en su
   propia pastilla: en las vistas es el único <span> del enlace (Trabajos)
   o un `.px-count` detrás del rótulo (la ficha de una cuenta). */
:where([data-surface="console"]) .px-tabs { gap: 4px; }
:where([data-surface="console"]) .px-tabs :is(a, button) {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 40px;
  padding: 0 12px;
  border-radius: var(--r-ctl) var(--r-ctl) 0 0;
  font-size: var(--t-sm);
  font-weight: 500;
  color: var(--muted);
  transition: color var(--dur-1) var(--ease-out), background-color var(--dur-1) var(--ease-out);
}
:where([data-surface="console"]) .px-tabs :is(a, button):hover { color: var(--ink); background-color: var(--surface-hover); }
:where([data-surface="console"]) .px-tabs :is(a, button):active { background-color: var(--surface-pressed); }
:where([data-surface="console"]) .px-tabs :is(a, button):focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
:where([data-surface="console"]) .px-tabs :is(a[aria-current]:not([aria-current="false"]), button[aria-selected="true"]) {
  color: var(--ink);
  font-weight: 600;
}
:where([data-surface="console"]) .px-tabs :is(a[aria-current]:not([aria-current="false"]), button[aria-selected="true"])::after {
  content: "";
  position: absolute;
  inset-inline: 8px;
  bottom: -1px;
  height: 2px;
  border-radius: 2px 2px 0 0;
  background: var(--accent);
}
:where([data-surface="console"]) .px-tabs :is(a, button) > :is(span:only-child, .px-count) {
  display: inline-grid;
  place-items: center;
  min-width: 20px;
  height: 18px;
  padding: 0 6px;
  border-radius: var(--r-full);
  background: var(--surface-3);
  color: var(--muted);
  font-size: var(--t-2xs);
  font-weight: 600;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}
:where([data-surface="console"]) .px-tabs :is(a[aria-current]:not([aria-current="false"]), button[aria-selected="true"]) > :is(span:only-child, .px-count) {
  background: var(--accent-soft);
  color: var(--accent);
}

/* --- Selector segmentado (30 / 90 / 365 días) -------------------------
   Mide 32, lo mismo que un botón pequeño, para ir en la misma fila que
   ellos. El tramo elegido sube un paso de superficie y lleva filo: con
   solo un gris un poco más claro no se distinguía cuál estaba puesto. */
:where([data-surface="console"]) .px-seg {
  align-items: center;
  padding: 2px;
  gap: 2px;
  border: 1px solid var(--border-control);
  border-radius: var(--r-ctl);
  background: var(--surface-sunken);
}
:where([data-surface="console"]) .px-seg :is(a, button) {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: calc(var(--ctl-sm) - 6px);
  padding: 0 10px;
  border-radius: 6px;
  font-size: var(--t-ui);
  font-weight: 600;
  line-height: 1;
  color: var(--muted);
  transition: color var(--dur-1) var(--ease-out), background-color var(--dur-1) var(--ease-out), box-shadow var(--dur-1) var(--ease-out);
}
:where([data-surface="console"]) .px-seg :is(a, button):hover { color: var(--ink); background-color: var(--surface-hover); }
:where([data-surface="console"]) .px-seg :is(a, button):disabled { opacity: .45; cursor: not-allowed; }
:where([data-surface="console"]) .px-seg :is([aria-current]:not([aria-current="false"]), [aria-pressed="true"]),
:where([data-surface="console"]) .px-seg :is([aria-current]:not([aria-current="false"]), [aria-pressed="true"]):hover {
  background-color: var(--surface-raised-hover);
  color: var(--ink);
  box-shadow: inset 0 0 0 1px var(--line-2), var(--e1);
}

/* --- Paneles ---------------------------------------------------------
   Radio 14 (el de la hoja), filo y la elevación de oscuro. El título a
   15 px y 600: a 16 y 700 cada panel gritaba lo mismo que el título de la
   página, y en una pantalla con diez paneles no había jerarquía. */
:where([data-surface="console"]) .px-panel { border-color: var(--line); border-radius: var(--r-panel); box-shadow: var(--e1); }
:where([data-surface="console"]) .px-panel-head { min-height: 52px; padding: 12px 18px; gap: var(--s-3); }
:where([data-surface="console"]) .px-panel-head :is(h2, h3) {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: .9375rem;
  font-weight: 600;
  letter-spacing: -.01em;
  line-height: 1.3;
}
:where([data-surface="console"]) .px-panel-head :is(h2, h3) > svg { flex: none; max-width: none; color: var(--muted); }
/* Con la hoja a todo lo ancho (29/09/2026) la explicación de un panel salía
   en renglones de casi 2.000 px (la del embudo, en una sola línea que no se
   podía seguir). La medida la pone el texto, no la pantalla: como la entradilla
   de la página (.px-head-txt, 68ch), aquí algo más porque la letra es menor. */
:where([data-surface="console"]) .px-panel-head p { max-width: 100ch; margin-top: 3px; font-size: var(--t-xs); line-height: 1.45; }
:where([data-surface="console"]) .px-panel-foot { background: var(--surface-raised); border-top-color: var(--line); }
:where([data-surface="console"]) .px-danger { border-color: var(--danger-border); }
:where([data-surface="console"]) .px-danger .px-panel-head h2 > svg { color: var(--danger); }
/* Los campos de Ajustes (`.px-field`) se quitaban TODO el margen y la pista
   de uno quedaba pegada a la etiqueta del siguiente. Recuperan el aire del
   panel —el de `.px-panel-body > * + *`— cuando van uno detrás de otro. */
:where([data-surface="console"]) .px-panel-body > * + .px-field { margin-top: var(--s-5); }
/* En el móvil, lo que va a la derecha de la cabecera (un «Facturación →»)
   baja debajo del texto en cuanto el texto no cabe a su lado en una línea.
   Con la base de escritorio (12rem), a 390 px el botón se quedaba al lado y
   estrujaba el título en dos renglones y la entradilla en cinco. Un título
   corto con su «Ver todo →» sigue en la misma línea. */
@media (max-width: 560px) {
  :where([data-surface="console"]) .px-panel-head > :first-child { flex-basis: auto; }
}

/* --- Cifras ----------------------------------------------------------
   Un solo peso (700; había 600, 700 y 800 según la pantalla).

   Y CIFRAS PROPORCIONALES, NO TABULARES, aunque se probó lo contrario: en
   Schibsted las tabulares ensanchan también la coma y el punto, y a 32 px
   «81,07 €» se leía «81 , 07 €», con un hueco a cada lado de la coma. Las
   tabulares se quedan para las columnas de las tablas, donde sí hace falta
   que los números se alineen. */
:where([data-surface="console"]) .px-kpi {
  gap: 6px;
  padding: 16px 18px;
  border-color: var(--line);
  border-radius: var(--r-panel);
  box-shadow: var(--e1);
  transition: border-color var(--dur-1) var(--ease-out), background-color var(--dur-1) var(--ease-out), box-shadow var(--dur-1) var(--ease-out);
}
:where([data-surface="console"]) a.px-kpi:hover { border-color: var(--border-control); background-color: var(--surface-raised); box-shadow: var(--e2); }
:where([data-surface="console"]) .px-kpi-k { gap: 7px; font-size: var(--t-2xs); font-weight: 600; letter-spacing: .06em; line-height: 1.35; }
:where([data-surface="console"]) .px-kpi-v {
  font-size: clamp(1.625rem, 1.3rem + 1vw, 2rem);
  font-weight: 700;
  letter-spacing: -.025em;
  line-height: 1.1;
}
:where([data-surface="console"]) .px-kpi-d { font-size: var(--t-xs); line-height: 1.45; }
/* SIN TARJETAS HUÉRFANAS (28/09/2026). Las cifras iban en `auto-fit` de
   216 px y las columnas salían de lo que cupiera: ocho tarjetas en 5 + 3,
   cuatro en 3 + 1 (la ficha a 1366 px al 150 %), seis en 4 + 2. Ahora las
   columnas DIVIDEN el número de tarjetas —cuatro van de cuatro en cuatro,
   de dos en dos o de una en una; seis, de seis, tres, dos o una— y se toma
   el mayor divisor con el que ninguna baja de --kpi-min.
   Lo decide el ANCHO DE LA PROPIA REJILLA (un porcentaje en una pista es
   del contenedor) y no un @media: da igual que la barra lateral esté
   desplegada, plegada o en cajón, que la rejilla vaya en la hoja o dentro de
   un panel, o que haya barra de desplazamiento. Y sin `container-type`, que
   en `.px-body` haría de la hoja el contenedor de todo lo `position: fixed`.
   Cada escalón es `clamp(A, (umbral - 100%) * 999, B)`: vale A si la rejilla
   llega al umbral (caben k tarjetas de --kpi-min) y B si no. A es el ancho
   de una tarjeta con k columnas, y con él `auto-fit` pone justo k; el píxel
   de menos es para que un redondeo no deje fuera la última. */
:where([data-surface="console"]) .px-kpis {
  --kpi-min: 216px;
  --kpi-gap: var(--s-4);
  --kpi-2: clamp((100% - var(--kpi-gap)) / 2, (2 * var(--kpi-min) + var(--kpi-gap) - 100%) * 999, 100%);
  --kpi-4: clamp((100% - 3 * var(--kpi-gap)) / 4, (4 * var(--kpi-min) + 3 * var(--kpi-gap) - 100%) * 999, var(--kpi-2));
  --kpi-col: var(--kpi-min);
  gap: var(--kpi-gap);
  grid-template-columns: repeat(auto-fit, minmax(calc(var(--kpi-col) - 1px), 1fr));
}
:where([data-surface="console"]) .px-kpis:where(:has(> :nth-child(2):last-child)) { --kpi-col: var(--kpi-2); }
:where([data-surface="console"]) .px-kpis:where(:has(> :nth-child(3):last-child)) {
  --kpi-col: clamp((100% - 2 * var(--kpi-gap)) / 3, (3 * var(--kpi-min) + 2 * var(--kpi-gap) - 100%) * 999, 100%);
}
:where([data-surface="console"]) .px-kpis:where(:has(> :nth-child(4):last-child)) { --kpi-col: var(--kpi-4); }
:where([data-surface="console"]) .px-kpis:where(:has(> :nth-child(6):last-child)) {
  --kpi-col: clamp((100% - 5 * var(--kpi-gap)) / 6, (6 * var(--kpi-min) + 5 * var(--kpi-gap) - 100%) * 999,
             clamp((100% - 2 * var(--kpi-gap)) / 3, (3 * var(--kpi-min) + 2 * var(--kpi-gap) - 100%) * 999, var(--kpi-2)));
}
:where([data-surface="console"]) .px-kpis:where(:has(> :nth-child(8):last-child)) {
  --kpi-col: clamp((100% - 7 * var(--kpi-gap)) / 8, (8 * var(--kpi-min) + 7 * var(--kpi-gap) - 100%) * 999, var(--kpi-4));
}
/* Interlineado propio: heredaba el 1,65 del cuerpo, y con un número de una
   cifra la chapa salía más alta que ancha (el «1» de «Piden un plan» en
   «Hoy»). El ancho mínimo la deja en pastilla, con el número centrado. */
:where([data-surface="console"]) .px-delta {
  justify-content: center;
  min-width: 1.9em;
  padding: 2px 7px;
  border: 1px solid color-mix(in srgb, currentColor 22%, transparent);
  font-size: var(--t-2xs);
  font-weight: 600;
  line-height: 1.2;
}
:where([data-surface="console"]) .px-pair .k { font-size: var(--t-2xs); font-weight: 600; letter-spacing: .06em; }
:where([data-surface="console"]) .px-pair .v { font-weight: 700; letter-spacing: -.025em; }
:where([data-surface="console"]) .px-meter,
:where([data-surface="console"]) .px-meter > i { border-radius: var(--r-full); }

/* --- Gráficos: ningún rótulo por debajo de 11 px ----------------------
   Los ejes, los meses de las columnas, el «del paso anterior» del embudo y
   la escala del mapa de actividad iban a 10. */
:where([data-surface="console"]) :is(.px-axis-y, .px-axis-x, .px-col-lbl, .px-funnel-pct i, .px-cal-key) { font-size: var(--t-2xs); }

/* --- Tablas de trabajo y filtros -------------------------------------
   La barra de herramientas va en la superficie de las barras, y TODO lo que
   filtra —campo, desplegable, botón, chip— mide 32: antes el campo medía 49
   y el botón de al lado 36, y en cada barra el campo sobresalía. */
:where([data-surface="console"]) .px-tablebox { border-color: var(--line); border-radius: var(--r-panel); box-shadow: var(--e1); }
:where([data-surface="console"]) .px-toolbar { gap: 8px 12px; padding: 10px 14px; background: var(--surface-raised); border-bottom-color: var(--line); }
:where([data-surface="console"]) .px-toolbar form { gap: 8px; }
:where([data-surface="console"]) :is(.px-toolbar, .px-history-filters, .px-account-filters) :is(input:not([type="checkbox"], [type="radio"], [type="file"]), select) {
  height: var(--ctl-sm);
  font-size: var(--t-ui);
}
:where([data-surface="console"]) :is(.px-toolbar, .px-history-filters, .px-account-filters) .btn { --btn-h: var(--ctl-sm); }
:where([data-surface="console"]) .px-find svg { inset-inline-start: 10px; width: 14px; height: 14px; }
:where([data-surface="console"]) .px-find input { padding-inline-start: 32px; }
:where([data-surface="console"]) .px-history-filters { gap: 12px; }

/* HAY MÁS A LA DERECHA. Una tabla ancha se desplaza dentro de su caja, y a
   1280 px al 150 % la última columna de seis pantallas quedaba escondida sin
   ninguna pista («Ver deta» en /auditoria). Ahora el borde por el que sigue
   lleva sombra: las dos tapas, del color del panel, viajan con la tabla
   (`local`) y cubren la sombra al llegar a cada extremo; las sombras se
   quedan quietas en los bordes de la caja (`scroll`). */
:where([data-surface="console"]) .px-scroll {
  background:
    linear-gradient(to right, var(--surface) 40%, transparent) left / 40px 100% no-repeat local,
    linear-gradient(to left, var(--surface) 40%, transparent) right / 40px 100% no-repeat local,
    linear-gradient(to right, rgb(0 0 0 / .5), transparent) left / 16px 100% no-repeat scroll,
    linear-gradient(to left, rgb(0 0 0 / .5), transparent) right / 16px 100% no-repeat scroll;
}
/* Y a 1300 px o menos (el portátil al 150 % se queda en 1280), las columnas
   más juntas: 10 px a cada lado del hueco entre dos y no 14. En una tabla
   de siete columnas son 48 px, lo que les faltaba a /ingresos y a /cuentas
   para caber en ese portátil. Los bordes del panel conservan sus 14. */
@media (max-width: 1300px) {
  :where([data-surface="console"] .px-body) table.data :is(th, td):not(:first-child) { padding-inline-start: 10px; }
  :where([data-surface="console"] .px-body) table.data :is(th, td):not(:last-child) { padding-inline-end: 10px; }
}

:where([data-surface="console"]) .px-chip {
  min-height: var(--ctl-sm);
  padding: 0 12px;
  border-color: var(--border-control);
  border-radius: var(--r-ctl);
  background: transparent;
  font-size: var(--t-ui);
  color: var(--ink-2);
  transition: background-color var(--dur-1) var(--ease-out), border-color var(--dur-1) var(--ease-out), color var(--dur-1) var(--ease-out);
}
:where([data-surface="console"]) :is(a, button).px-chip:hover { border-color: var(--border-hover); background-color: var(--surface-hover); color: var(--ink); }
:where([data-surface="console"]) :is(a, button).px-chip:active { background-color: var(--surface-pressed); }
:where([data-surface="console"]) .px-chip:is(:disabled, [aria-disabled="true"]) { opacity: .45; cursor: not-allowed; }
:where([data-surface="console"]) .px-chip:is([aria-pressed="true"], [aria-current="true"]),
:where([data-surface="console"]) :is(a, button).px-chip:is([aria-pressed="true"], [aria-current="true"]):hover {
  background-color: var(--accent-soft);
  border-color: var(--accent-border);
  color: var(--accent);
}
/* La ficha elegida lleva además una marca que no es color: un ✓ delante,
   dibujado con dos bordes. Con el cian solo, quien no lo distingue del gris
   no sabía cuál estaba puesta (del texto de una al de otra hay 1,12:1 de
   luminosidad). La que ya trae su icono —el filtro activo con su «×»— no la
   necesita. */
:where([data-surface="console"]) .px-chip:is([aria-pressed="true"], [aria-current="true"]):not(:has(> svg))::before {
  content: "";
  flex: none;
  width: 9px;
  height: 5px;
  margin-block-end: 3px;
  border: solid currentColor;
  border-width: 0 0 2px 2px;
  rotate: -45deg;
}
/* En las fichas que se ALTERNAN sin recargar (`aria-pressed`, las de
   /salud) el sitio de la ✓ está reservado en todas —el mismo relleno de
   entrada: 12 + 9 de la marca + 6 de hueco— y la ✓ va encima, en posición
   absoluta y en el mismo punto que ocupaba. Dentro del flujo, marcar otra
   cambiaba el ancho de dos fichas y movía 15 px a todas las de al lado. */
:where([data-surface="console"]) .px-chip[aria-pressed]:not(:has(> svg)) { position: relative; padding-inline-start: 27px; }
:where([data-surface="console"]) .px-chip[aria-pressed="true"]:not(:has(> svg))::before { position: absolute; top: calc(50% - 4px); inset-inline-start: 12px; margin: 0; }
:where([data-surface="console"]) .px-chip .px-n { font-size: var(--t-2xs); font-weight: 600; color: var(--muted); opacity: 1; }
:where([data-surface="console"]) .px-chip:is([aria-pressed="true"], [aria-current="true"]) .px-n { color: inherit; }

/* Acciones de fila: el botón secundario más pequeño (28) y atenuado a
   .72, no a .45: a .45 se confundía con un botón apagado, que ahora usa
   esa misma opacidad. */
:where([data-surface="console"]) .px-row-act { opacity: .72; }
:where([data-surface="console"]) .px-row-act .btn { --btn-h: var(--ctl-xs); padding: 0 10px; font-size: var(--t-xs); }
:where([data-surface="console"]) tr:hover .px-row-act,
:where([data-surface="console"]) .px-row-act:focus-within { opacity: 1; }

/* Copiar un dato: 28 px y el radio de los controles. */
:where([data-surface="console"]) .px-copy { width: var(--ctl-xs); height: var(--ctl-xs); border-radius: var(--r-ctl); }
:where([data-surface="console"]) .px-copy:hover,
:where([data-surface="console"]) .px-copy:focus-visible { background: var(--surface-hover); }

/* El globo de los gráficos es una capa flotante: superficie de encima. */
:where([data-surface="console"]) .px-tip { border-color: var(--line-2); border-radius: var(--r-ctl); background: var(--surface-overlay); box-shadow: var(--e2); }

/* --- Estados vacíos --------------------------------------------------
   Icono en una baldosa con filo, título a 15 px y el texto a 13: el de
   antes era una baldosa de 52 px con un título de 18, más grande que el
   título del panel que lo contenía. */
:where([data-surface="console"]) .px-empty { padding: 40px 24px; }
:where([data-surface="console"]) .px-empty-ic {
  width: 44px;
  height: 44px;
  margin-bottom: 14px;
  border: 1px solid var(--line-2);
  border-radius: 12px;
  background: var(--surface-raised);
  box-shadow: var(--e1);
}
:where([data-surface="console"]) .px-empty-ic svg { width: 20px; height: 20px; }
:where([data-surface="console"]) .px-empty h3 { margin-bottom: 6px; font-size: .9375rem; font-weight: 600; letter-spacing: -.01em; }
:where([data-surface="console"]) .px-empty p { max-width: 46ch; font-size: var(--t-ui); line-height: 1.55; }
:where([data-surface="console"]) .px-empty .btn { margin-top: 16px; }

/* --- Piezas de formulario ------------------------------------------- */
:where([data-surface="console"]) .px-pick { border-color: var(--line-2); border-radius: 10px; }
:where([data-surface="console"]) .px-pick:hover { border-color: var(--border-hover); }
:where([data-surface="console"]) .px-pick:has(input:checked) { border-color: var(--accent-border); background: var(--accent-soft); }
:where([data-surface="console"]) .px-media { border-radius: 10px; background: var(--surface-raised); }
:where([data-surface="console"]) .px-color-dot { height: var(--ctl-md); border-color: var(--border-control); border-radius: var(--r-ctl); background: var(--surface-sunken); }
:where([data-surface="console"]) .px-note {
  gap: 10px;
  padding: 10px 12px;
  border-color: var(--line);
  border-radius: 10px;
  background: var(--surface-raised);
  font-size: var(--t-ui);
  line-height: 1.5;
  color: var(--ink-2);
}
/* La barra de guardar flota sobre lo que pasa por debajo: es una capa. */
:where([data-surface="console"]) .px-saver { border-color: var(--line-2); background: var(--surface-overlay); box-shadow: var(--e3); }
:where([data-surface="console"]) .px-saver .px-panel-body { padding: 10px 14px 10px 18px; }
/* El sitio que se le reserva al desplazar está en 9c, junto al de las
   barras de guardar propias de cada pantalla: una sola regla para todas. */

/* --- Modo denso ------------------------------------------------------
   Antes solo apretaba las celdas y el cuerpo de los paneles (−10 px por
   fila). Ahora aprieta también cabeceras de panel, cifras, barras,
   pestañas y listas: el que lo activa quiere ver más filas por pantalla,
   no la misma pantalla con las celdas un poco más juntas. */
:root.px-dense:where([data-surface="console"]) .px-panel-head { min-height: 44px; padding-block: 8px; }
:root.px-dense:where([data-surface="console"]) .px-kpi { padding: 12px 14px; gap: 2px; }
:root.px-dense:where([data-surface="console"]) .px-kpi-v { font-size: 1.5rem; }
:root.px-dense:where([data-surface="console"]) .px-toolbar { padding: 8px 12px; }
:root.px-dense:where([data-surface="console"]) .px-tabs :is(a, button) { min-height: 34px; }
:root.px-dense:where([data-surface="console"]) .px-empty { padding: 24px 16px; }
:root.px-dense:where([data-surface="console"]) .px-list > * { padding-block: 8px; }
:root.px-dense:where([data-surface="console"]) .px-def { padding-block: 6px; }
:root.px-dense:where([data-surface="console"]) table.data thead th { padding-block: 6px; }

/* --- Tacto y contraste forzado --------------------------------------
   Con el dedo nada baja de 44, también en una tableta de más de 1000 px
   (la regla del bloque 12 solo llega hasta ahí). */
@media (pointer: coarse) {
  :where([data-surface="console"]) :is(.px-chip, .px-back, .px-tabs a, .px-tabs button, .px-seg a, .px-seg button) { min-height: 44px; }
  :where([data-surface="console"]) .px-seg :is(a, button) { height: auto; }
  :where([data-surface="console"]) :is(.px-toolbar, .px-history-filters, .px-account-filters) :is(input:not([type="checkbox"], [type="radio"], [type="file"]), select) { height: 44px; }
  /* La muestra del color de marca, a la altura de su campo (que ya va a 44). */
  :where([data-surface="console"]) .px-color-dot { height: 44px; }
}
/* Cuando el sistema impone sus colores, el fondo deja de distinguir el
   tramo, el chip o la pestaña elegidos: necesitan una marca propia. La del
   tramo y la del chip es el color de selección del sistema, y NO un
   contorno: el contorno es el del foco, y con los dos iguales se veían dos
   cosas «enfocadas» a la vez. */
@media (forced-colors: active) {
  :where([data-surface="console"]) .px-tabs :is(a[aria-current]:not([aria-current="false"]), button[aria-selected="true"])::after { background: Highlight; forced-color-adjust: none; }
  :where([data-surface="console"]) .px-seg :is([aria-current]:not([aria-current="false"]), [aria-pressed="true"]),
  :where([data-surface="console"]) .px-chip:is([aria-pressed="true"], [aria-current="true"]) {
    forced-color-adjust: none;
    border-color: Highlight;
    background: Highlight;
    color: HighlightText;
    box-shadow: none;
  }
}




/* =====================================================================
   9c · CABECERAS Y PIEZAS PROPIAS DE PANTALLA (28/09/2026)
   ---------------------------------------------------------------------
   Correo, Solicitudes, Idiomas, Planes, Facturación, Actualizaciones,
   Copias, Proveedores, Catálogo e IMEI traen su hoja y su marcado propios,
   y cada hoja copiaba los valores de las piezas comunes: antetítulo,
   título, chapa y botones de la cabecera y de los filtros. Las copias ya
   no coincidían entre sí. Aquí va UNA regla por pieza con las clases de
   cada pantalla; en cada hoja quedan sus tonos y lo que es solo suyo.

   LISTAS DE SELECTORES Y NO `:is()` CUANDO LOS PESOS DIFIEREN. Un `:is()`
   pesa lo que su entrada más pesada: una sola de dos clases subiría la
   regla entera y pisaría los ajustes de móvil que cada hoja hace con una.
   En una lista, cada selector pesa lo mismo que la copia que sustituye; y
   como las hojas de pantalla se cargan detrás, lo que ajustan con ese
   mismo peso lo siguen ajustando.
   ===================================================================== */

/* Antetítulo: el de .px-eyebrow. Cada entrada pesa lo justo para ganar a
   la regla de su pantalla que lo pisaba: `.up-health p` en
   Actualizaciones, `.bl-workspace p` en Facturación, el `.sc-eyebrow` del
   ERP en el Catálogo y el rótulo de sección de Planes. */
:where([data-surface="console"]) .ml-eyebrow,
:where([data-surface="console"]) .inb-eyebrow,
:where([data-surface="console"]) .lng-eyebrow,
:where([data-surface="console"]) .imei-hero__eyebrow,
:where([data-surface="console"]) .up-center .up-eyebrow,
:where([data-surface="console"]) .up-dialog .up-eyebrow,
:where([data-surface="console"]) .bl-workspace .bl-eyebrow,
:where([data-surface="console"]) .scatalog .sc-eyebrow,
:where([data-surface="console"]) .px-plans-hero .px-plans-eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 10px;
  font: 500 var(--t-2xs)/1.3 var(--font-mono);
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--muted);
}
/* El punto, salvo en IMEI, que lo lleva en su marcado (.imei-pulse-dot). */
:where([data-surface="console"]) .ml-eyebrow::before,
:where([data-surface="console"]) .inb-eyebrow::before,
:where([data-surface="console"]) .lng-eyebrow::before,
:where([data-surface="console"]) .up-center .up-eyebrow::before,
:where([data-surface="console"]) .up-dialog .up-eyebrow::before,
:where([data-surface="console"]) .bl-workspace .bl-eyebrow::before,
:where([data-surface="console"]) .scatalog .sc-eyebrow::before,
:where([data-surface="console"]) .px-plans-hero .px-plans-eyebrow::before {
  content: "";
  flex: none;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}

/* Título: el de .px-head h1, de 24 a 28 px. */
:where([data-surface="console"]) .up-head h1,
:where([data-surface="console"]) .bl-workspace h1,
:where([data-surface="console"]) .px-plans-hero h1,
:where([data-surface="console"]) .cc-page-header h1,
:where([data-surface="console"]) .imei-hero__title {
  font-family: var(--font-display);
  font-size: clamp(1.5rem, 1.15rem + .9vw, 1.75rem);
  font-weight: 650;
  letter-spacing: -.02em;
  line-height: 1.15;
}

/* Botones de la cabecera, a la talla pequeña como en .px-head-act: la
   cabecera no es donde se trabaja, es donde se sale. */
:where([data-surface="console"]) .up-head .up-actions .btn,
:where([data-surface="console"]) .bl-header .bl-actions .btn,
:where([data-surface="console"]) .px-plans-hero > .btn {
  --btn-h: var(--ctl-sm);
  padding-inline: 12px;
  gap: 6px;
  font-size: var(--t-ui);
}

/* Un dato en la cabecera (cuándo se midió el uso): texto atenuado con su
   icono, no una ficha con borde que parezca otro botón. */
:where([data-surface="console"]) .px-head-note { display: inline-flex; align-items: center; gap: 6px; font-size: var(--t-xs); color: var(--muted); white-space: nowrap; }
:where([data-surface="console"]) .px-head-note svg { flex: none; }

/* Chapa de 22 px: la de .pill. Aquí todas pesan una clase y un `:is()`
   no cambia nada; el tono de cada estado, en su hoja. */
:where([data-surface="console"]) :is(.up-pill, .lng-status, .ml-state, .bl-status, .vf-state, .ps-demand, .px-backup-state, .px-backup-encryption) {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 22px;
  padding: 0 9px;
  border: 1px solid color-mix(in srgb, currentColor 26%, transparent);
  border-radius: var(--r-full);
  background: var(--surface-raised);
  color: var(--ink-2);
  font-size: var(--t-xs);
  font-weight: 600;
  line-height: 1;
  white-space: nowrap;
}

/* Barras de filtros propias: campo, desplegable y botón a 32 px, como
   .px-toolbar. Con el dedo suben a 44 por la regla táctil de pulsar.css.
   Aquí el `:is()` sube el desplegable al peso del campo a propósito: con
   el suyo, el `.px-plans select` de Planes (14 px) lo dejaba más grande
   que la búsqueda de al lado. */
:where([data-surface="console"]) :is(.inb-filters, .ml-filters, .bl-filters, .up-filter, .px-backup-filters, .px-plans-filters) :is(input:not([type="checkbox"], [type="radio"], [type="file"]), select) {
  height: var(--ctl-sm);
  font-size: var(--t-ui);
}
:where([data-surface="console"]) :is(.inb-filters, .ml-filters, .bl-filters, .up-filter, .px-backup-filters) .btn { --btn-h: var(--ctl-sm); }

/* Barras de guardar que flotan abajo (la común .px-saver de Ajustes, y
   las de plan, idioma y factura): al tabular, el navegador deja el campo
   enfocado pegado al borde inferior, que es donde está la barra, y lo
   tapaba (en /ajustes, cuatro paradas seguidas enteras). Al desplazarse,
   el documento reserva ese alto: 60-68 px de barra, su separación del
   borde y aire, y en el móvil, donde se parten en dos filas, hasta 140.
   Si hay avisos flotando encima (panel.js, --px-toasts-reserve), manda lo
   que ocupen ellos cuando es más. El editor del Catálogo, que desplaza
   dentro de su diálogo, lo hace en repair-catalog.css. */
:where([data-surface="console"]):has(.px-saver, .px-plan-savebar, .lng-savebar, .bl-savebar) { scroll-padding-bottom: max(104px, var(--px-toasts-reserve, 0px)); }
@media (max-width: 600px) {
  :where([data-surface="console"]):has(.px-saver, .px-plan-savebar, .lng-savebar, .bl-savebar) { scroll-padding-bottom: max(152px, var(--px-toasts-reserve, 0px)); }
}




/* =====================================================================
   10 · SALUD (/salud)
   ---------------------------------------------------------------------
   Una sola pantalla, pero la más densa del panel: un pulso, ocho cifras
   que filtran, tarjetas de medición, hallazgos, una gráfica de barras
   apiladas, tres tablas y una consola de registro.

   Cuatro decisiones que explican casi todo lo de abajo:

    · EL ESTADO VA EN `data-nivel`, NO EN UNA CLASE. Lo pinta el
      JavaScript a partir de lo que dice el servidor (`ok`, `warn`,
      `crit`), y engancharlo a un atributo de datos y no a una clase es
      lo que evita que el día que alguien renombre una clase el color
      deje de aparecer sin dar ni un error.
    · CUATRO TINTAS DE DATO Y NI UNA MÁS: base, lentitud, PHP y TPV.
      Son cuatro IDENTIDADES (no una magnitud), así que no se usa la
      rampa secuencial. Las de estado (--ok/--warn/--danger) se reservan
      para lo que significa bien o mal, que aquí es otra cosa.
    · LA GRÁFICA ES HTML, NO SVG. El texto de un SVG que se estira se
      estira con él y deja los rótulos ilegibles; aquí las marcas son
      cajas y los rótulos son texto normal del documento.
    · EL REGISTRO ES OSCURO EN LAS DOS SUPERFICIES. Es la única pieza
      del panel que lo es: un volcado de error_log se lee como lo que
      es, un terminal, y cambiarle el fondo según el tema lo convierte
      en un párrafo más de la página.
   ===================================================================== */

/* --- Tintas de dato de esta pantalla ------------------------------- */
:root {
  --px-h-db:   #D92D20;   /* base de datos */
  --px-h-slow: #B45309;   /* lentitud y 5xx */
  --px-h-php:  #7C3AED;   /* errores de PHP */
  --px-h-tpv:  #0E7490;   /* microcortes vistos por el TPV */
}
[data-surface="console"] {
  /* Sobre el panel oscuro las mismas cuatro tintas no llegan al contraste
     mínimo, así que se suben de claridad manteniendo el tono: lo que
     identifica a una serie es el tono, no la luminosidad. */
  --px-h-db:   #F87171;
  --px-h-slow: #FBBF24;
  --px-h-php:  #A78BFA;
  --px-h-tpv:  #22D3EE;
}

.px-ink-db   { background: var(--px-h-db); }
.px-ink-slow { background: var(--px-h-slow); }
.px-ink-php  { background: var(--px-h-php); }
.px-ink-tpv  { background: var(--px-h-tpv); }

/* --- El pulso: qué pasa AHORA MISMO -------------------------------- */
.px-pulse {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  padding: 14px 18px;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--surface);
  box-shadow: var(--px-e1);
}
.px-pulse-dot {
  width: 12px; height: 12px;
  border-radius: 50%;
  background: var(--muted);
  flex: none;
}
.px-pulse-txt { display: grid; gap: 2px; min-width: 0; flex: 1; }
.px-pulse-txt b { font-size: var(--t-sm); font-weight: 700; }
.px-pulse-txt i { font-style: normal; font-size: var(--t-xs); color: var(--muted); }

.px-pulse[data-estado="ok"]         { border-color: color-mix(in srgb, var(--ok) 40%, var(--line)); }
.px-pulse[data-estado="ok"]         .px-pulse-dot { background: var(--ok); }
.px-pulse[data-estado="ok"]         .px-pulse-txt b { color: var(--ok); }
.px-pulse[data-estado="aviso"]      { border-color: color-mix(in srgb, var(--warn) 40%, var(--line)); }
.px-pulse[data-estado="aviso"]      .px-pulse-dot { background: var(--warn); }
.px-pulse[data-estado="aviso"]      .px-pulse-txt b { color: var(--warn); }
.px-pulse[data-estado="incidencia"] { border-color: color-mix(in srgb, var(--danger) 45%, var(--line)); }
.px-pulse[data-estado="incidencia"] .px-pulse-dot { background: var(--danger); }
.px-pulse[data-estado="incidencia"] .px-pulse-txt b { color: var(--danger); }

/* El latido solo cuando hay algo que mirar. Un punto que late siempre
   deja de significar nada a los dos días.
   El halo es un ::after del mismo rojo que crece y se apaga (encima del
   punto no se nota): animar `scale` y `opacity` lo hace la tarjeta gráfica,
   mientras que el box-shadow de antes repintaba en cada fotograma todo el
   rato que durase la incidencia. Con movimiento reducido se para del todo:
   la regla general solo lo acortaba a 0,01 ms, y un bucle así parpadea. */
.px-pulse[data-estado="incidencia"] .px-pulse-dot { position: relative; }
.px-pulse[data-estado="incidencia"] .px-pulse-dot::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: var(--danger);
  opacity: 0;
  animation: px-latido 1.6s var(--px-ease) infinite;
}
@keyframes px-latido {
  0%, 100% { opacity: .55; scale: 1; }
  70%      { opacity: 0; scale: 2.5; }
}
@media (prefers-reduced-motion: reduce) {
  .px-pulse[data-estado="incidencia"] .px-pulse-dot::after { animation: none; }
}

.px-pulse-auto {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  flex: none;
  font-size: var(--t-xs);
  color: var(--muted);
  cursor: pointer;
  -webkit-user-select: none;
  user-select: none;
}
.px-pulse-auto input { width: 16px; height: 16px; accent-color: var(--accent); cursor: pointer; }

/* Un desplegable en la cabecera crece hasta el ancho que le den, y con el
   nombre largo de una empresa se comía la fila entera: los botones caían
   debajo y la barra de herramientas dejaba de leerse como una. */
.px-head-act select { max-width: 260px; }

/* --- Las cifras, que además filtran la tabla ----------------------- */
/* Cada una es un número y un rótulo corto: caben en 180 px. Con los 216 de
   las demás cifras, en un portátil de 1366 px al 150 % las ocho iban de dos
   en dos, en cuatro filas; así van de cuatro en cuatro (ver «SIN TARJETAS
   HUÉRFANAS» en 9b). */
.px-health-kpis { --kpi-min: 180px; }
.px-kpi-btn {
  width: 100%;
  text-align: start;
  cursor: pointer;
  font: inherit;
  color: inherit;
  transition: border-color var(--px-fast) var(--px-ease), transform var(--px-fast) var(--px-ease);
}
.px-kpi-btn:hover { border-color: var(--line-strong); transform: translateY(-1px); }
.px-kpi-btn[aria-pressed="true"] { border-color: var(--accent); background: var(--accent-soft); }
/* Un cero no se tiñe: si todo va coloreado, el color deja de avisar. */
.px-kpi-btn[data-nivel="ok"]   .px-kpi-v { color: var(--muted); }
.px-kpi-btn[data-nivel="warn"] .px-kpi-v { color: var(--warn); }
.px-kpi-btn[data-nivel="crit"] .px-kpi-v { color: var(--danger); }

/* --- Tarjetas de medición (chequeo en vivo y sonda del techo) ------ */
.px-checks {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  gap: 12px;
}
.px-checks + .px-checks { margin-top: 12px; }
.px-check {
  display: grid;
  gap: 4px;
  padding: 13px 15px;
  border: 1px solid var(--line);
  border-inline-start-width: 3px;
  border-radius: var(--r-md);
  background: var(--surface-2);
  min-width: 0;
}
.px-check-k { font-size: var(--t-xs); color: var(--muted); font-weight: 600; }
.px-check-v {
  font-family: var(--font-mono);
  font-size: var(--t-base);
  font-weight: 600;
  overflow-wrap: anywhere;
}
.px-check-d { font-size: var(--t-xs); color: var(--muted); line-height: 1.55; overflow-wrap: anywhere; }

.px-check[data-nivel="ok"]   { border-inline-start-color: var(--ok); }
.px-check[data-nivel="ok"]   .px-check-v { color: var(--ok); }
.px-check[data-nivel="warn"] { border-inline-start-color: var(--warn); }
.px-check[data-nivel="warn"] .px-check-v { color: var(--warn); }
.px-check[data-nivel="crit"] { border-inline-start-color: var(--danger); }
.px-check[data-nivel="crit"] .px-check-v { color: var(--danger); }
.px-check[data-nivel="info"] { border-inline-start-color: var(--info); }

/* --- Hallazgos del análisis automático ----------------------------- */
.px-finding {
  display: grid;
  gap: 3px;
  padding: 12px 15px;
  border-inline-start: 3px solid var(--line-2);
  border-radius: 0 var(--r-md) var(--r-md) 0;
  background: var(--surface-2);
  font-size: var(--t-sm);
  line-height: 1.6;
}
.px-finding + .px-finding { margin-top: 9px; }
.px-finding-t { font-weight: 700; }
.px-finding span { color: var(--muted); }
.px-finding[data-nivel="ok"]   { border-inline-start-color: var(--ok); background: var(--ok-soft); }
.px-finding[data-nivel="info"] { border-inline-start-color: var(--info); }
.px-finding[data-nivel="warn"] { border-inline-start-color: var(--warn); background: var(--warn-soft); }
.px-finding[data-nivel="crit"] { border-inline-start-color: var(--danger); background: var(--danger-soft); }
.px-finding[data-nivel="crit"] .px-finding-t { color: var(--danger); }

/* --- Línea temporal: barras apiladas en HTML ----------------------- */
.px-bars {
  display: flex;
  align-items: flex-end;
  gap: 2px;
  height: 168px;
  padding-top: 8px;
}
.px-bar {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column-reverse;   /* apilar desde abajo */
  justify-content: flex-start;
  align-self: stretch;
  justify-self: stretch;
  border-radius: 3px;
  cursor: crosshair;
}
/* Un cubo sin nada no se deja en blanco: se pinta la huella del canal,
   porque «no pasó nada aquí» es un dato y un hueco no lo parece. */
.px-bar[data-vacio="1"] { background: linear-gradient(to top, var(--px-track) 3px, transparent 3px); }
.px-bar:hover, .px-bar:focus-visible { background-color: var(--surface-3); }
.px-bar-seg { display: block; width: 100%; border-radius: 2px; }
.px-bar-seg + .px-bar-seg { margin-bottom: 1px; }

/* --- Terminales que reportaron microcortes ------------------------- */
.px-terms { display: flex; flex-wrap: wrap; gap: 6px; padding: 0 18px 14px; }
.px-term {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 4px 10px;
  border: 1px solid var(--line);
  border-radius: var(--r-full);
  background: var(--surface-3);
  font-size: var(--t-xs);
  font-family: var(--font-mono);
  color: var(--ink-2);
}
.px-term b { color: var(--warn); }

/* --- Celda de detalle: larga por naturaleza ------------------------ */
.px-detail {
  max-width: 46ch;
  overflow-wrap: anywhere;
  white-space: pre-wrap;
  line-height: 1.5;
}
/* El detalle largo llega como <details> con el texto en su <summary>
   (salud.js): cerrado, dos líneas y puntos suspensivos; abierto, entero.
   Entero siempre, cada fila medía 200-250 px y la pantalla, más de
   10 000. El texto sigue en la página: se lee, se busca y se copia. */
.px-detail summary {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  overflow: hidden;
  cursor: pointer;
  border-radius: var(--r-sm);
}
.px-detail summary::-webkit-details-marker { display: none; }
.px-detail summary:hover { color: var(--ink-2); }
.px-detail details[open] > summary { display: block; }

/* --- Consola del registro de PHP ----------------------------------- */
.px-log {
  max-height: 420px;
  overflow: auto;
  padding: 12px 14px;
  border-radius: var(--r-md);
  background: #0B1526;
  color: #C3CCDC;
  font-family: var(--font-mono);
  font-size: var(--t-xs);
  line-height: 1.6;
}
.px-log .px-nohits { color: #8C9AB5; }
.px-log-l {
  margin: 0 0 2px;
  padding-inline-start: 10px;
  border-inline-start: 2px solid transparent;
  overflow-wrap: anywhere;
  white-space: pre-wrap;
}
.px-log-t { color: #6B7C9E; }
/* Los colores de aquí NO salen de las fichas del tema: este bloque es
   oscuro en las dos superficies, así que las fichas claras no valdrían. */
.px-log-l[data-nivel="fatal"]      { border-inline-start-color: #F26D6D; color: #FFB4B4; }
.px-log-l[data-nivel="db_fail"]    { border-inline-start-color: #F26D6D; color: #FFC9C9; }
.px-log-l[data-nivel="db_retry"]   { border-inline-start-color: #F0B34E; color: #FFE0AE; }
.px-log-l[data-nivel="db_other"]   { border-inline-start-color: #F0B34E; }
.px-log-l[data-nivel="warning"]    { border-inline-start-color: #F0B34E; color: #F3DCB4; }
.px-log-l[data-nivel="deprecated"] { border-inline-start-color: #8A7CF0; color: #CFC7FA; }
.px-log-l[data-nivel="notice"]     { border-inline-start-color: #6C8CFF; }


/* =====================================================================
   11 · MIS EMPRESAS: continuidad con la web pública
   ===================================================================== */
.px-appmain:has(.px-ws-page) { padding-top: clamp(20px, 2vw, 32px); }
.px-ws-page { width: 100%; }
.px-ws-page > .alert { margin-bottom: 20px; }
.px-ws-breadcrumb { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin-bottom: 12px; font-size: var(--t-sm); color: var(--muted); }
.px-ws-breadcrumb a { display: inline-flex; align-items: center; min-height: 44px; color: var(--muted); }
.px-ws-breadcrumb a:hover { color: var(--accent); }
.px-ws-page .px-head { align-items: center; margin-bottom: 24px; gap: 20px; }
.px-ws-page .px-head h1 { font-size: clamp(30px, 3vw, 42px); letter-spacing: -.04em; line-height: 1.15; text-wrap: balance; }
.px-ws-page .px-head p { margin-top: 8px; font-size: clamp(16px, 1.4vw, 19px); line-height: 1.5; }
.px-ws-create { min-height: 48px; border-color: var(--accent); color: var(--accent); background: var(--surface); }
.px-ws-create:hover { background: var(--accent-soft); }
.px-ws-list { display: grid; gap: 20px; align-content: start; }
.px-ws-list .px-empty h2 { font-size: var(--t-lg); }
.px-ws { --ws-pad: clamp(18px, 2vw, 28px); background: var(--surface); border: 1px solid var(--line); border-radius: 18px; box-shadow: var(--px-e1); min-width: 0; }
.px-ws-note { display: flex; align-items: flex-start; gap: 10px; margin: 0 var(--ws-pad) 16px; padding: 12px 16px; border: 1px solid var(--line); border-radius: 10px; font-size: var(--t-sm); font-weight: 500; line-height: 1.6; overflow-wrap: anywhere; }
.px-ws-note svg { flex: none; margin-top: 3px; }
.px-ws-note.is-warn { background: var(--warn-soft); color: color-mix(in srgb, var(--warn) 82%, var(--ink)); }
.px-ws-note.is-danger { background: var(--danger-soft); color: color-mix(in srgb, var(--danger) 82%, var(--ink)); }
.px-ws-top { display: flex; align-items: center; gap: 20px; padding: 22px var(--ws-pad); }
.px-ws-av { flex: none; width: 80px; height: 80px; border-radius: 15px; display: grid; place-items: center; background: var(--accent-soft); color: var(--accent); font: 800 32px var(--font-display); letter-spacing: -.03em; }
.px-ws-av.has-logo { position: relative; width: 180px; background: var(--surface); }
.px-ws-logo { position: absolute; inset: 0; display: block; width: 100%; height: 100%; object-fit: contain; opacity: 0; }
.px-ws-av.is-loaded .px-ws-logo { opacity: 1; }
.px-ws-av.is-loaded .px-ws-initials { visibility: hidden; }
.px-ws-top .px-ws-av { width: 64px; height: 64px; font-size: 26px; }
.px-ws-top .px-ws-av.has-logo { width: 148px; }

/* Icono cuadrado de empresa en la tabla de la consola. */
.px-account-brand { display: flex; align-items: center; gap: 12px; }
.px-account-brand .px-ws-av.px-account-icon {
  width: 40px; height: 40px; border-radius: 9px;
  font-size: 16px; letter-spacing: 0;
  background: var(--accent-soft); color: var(--accent);
}
.px-account-brand .px-account-icon.is-loaded { background: var(--px-company-icon-bg); }
.px-account-brand .px-ws-logo { padding: 3px; border-radius: inherit; }
.px-account-brand .px-cell-main { min-width: 0; }
.px-ws-id { flex: 1 1 14rem; min-width: 0; }
.px-ws-name { font-size: clamp(22px, 2vw, 28px); letter-spacing: -.03em; line-height: 1.25; overflow-wrap: anywhere; }
.px-ws-host { display: flex; align-items: center; gap: 8px; margin-top: 2px; color: var(--muted); font-size: 16px; min-width: 0; }
.px-ws-host > span { overflow-wrap: anywhere; }
.px-ws-host .px-copy { min-width: 44px; min-height: 44px; flex: none; }
.px-ws-tags { display: flex; flex-wrap: wrap; gap: 8px; justify-content: flex-end; }
.px-ws-tags .pill { padding: 6px 12px; font-size: var(--t-sm); }
.px-ws-facts { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.2fr) minmax(0, .8fr) minmax(0, 1.4fr); margin: 0 var(--ws-pad) 20px; padding: 20px; border: 1px solid var(--line); border-radius: 12px; background: var(--surface-2); gap: 24px; }
.px-ws-fact { min-width: 0; }
.px-ws-fact + .px-ws-fact { padding-inline-start: 24px; border-inline-start: 1px solid var(--line); }
.px-ws-fact dt { font-size: var(--t-sm); font-weight: 500; color: var(--muted); }
.px-ws-fact dd { margin: 8px 0 0; color: var(--ink); font-size: clamp(18px, 1.6vw, 22px); font-weight: 700; letter-spacing: -.025em; line-height: 1.35; font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
.px-ws-fact dd .muted { color: var(--muted); font-size: .8em; font-weight: 500; letter-spacing: 0; }
.px-ws-fact dd.is-over { color: var(--danger); }
.px-ws-expiry dt { display: flex; align-items: center; gap: 6px; }
.px-ws-expiry dt svg { flex: none; }
.px-ws-fact-sub { display: block; margin-top: 4px; color: var(--muted); font-size: var(--t-xs); font-weight: 500; letter-spacing: 0; line-height: 1.5; }
.px-ws-no-date { color: var(--muted); font-size: var(--t-base); font-weight: 500; letter-spacing: 0; }
.px-ws-flag { display: block; margin-top: 6px; font-size: var(--t-xs); font-weight: 600; letter-spacing: 0; }
.px-ws-pending { display: flex; align-items: center; gap: 8px; min-height: 44px; margin: 0 var(--ws-pad) 12px; color: color-mix(in srgb, var(--warn) 75%, var(--ink)); font-size: var(--t-sm); }
.px-ws-pending:hover { text-decoration: underline; }
.px-ws-act { display: flex; align-items: center; justify-content: space-between; gap: 16px; flex-wrap: wrap; margin: 0 var(--ws-pad); padding: 18px 0; border-top: 1px solid var(--line); }
.px-ws-links { display: flex; align-items: center; gap: clamp(16px, 2vw, 28px); flex-wrap: wrap; }
.px-ws-links a { display: inline-flex; align-items: center; gap: 9px; min-height: 44px; font-size: var(--t-sm); font-weight: 600; color: var(--accent); }
.px-ws-links a:hover { text-decoration: underline; text-underline-offset: 4px; }
.px-ws-links svg { flex: none; }
.px-ws-buttons { display: flex; gap: 12px; margin-inline-start: auto; flex-wrap: wrap; }
.px-ws-buttons .btn { min-height: 48px; padding-inline: 20px; }
.px-ws-go { gap: 14px; }
.px-ws-assurance { display: flex; align-items: center; gap: 12px; padding: 12px 16px; margin-top: 20px; border-radius: 12px; background: color-mix(in srgb, var(--accent-soft) 65%, var(--bg)); color: var(--muted); font-size: var(--t-sm); }
.px-ws-assurance > span { display: grid; place-items: center; width: 44px; height: 44px; flex: none; border-radius: 50%; color: var(--accent); background: var(--accent-soft); }
.px-ws-foot { display: flex; align-items: center; justify-content: space-between; gap: 24px; margin-top: 20px; padding: 20px 24px; border: 1px solid var(--line); border-radius: 16px; background: color-mix(in srgb, var(--surface) 45%, transparent); }
.px-ws-foot-t { font: 700 19px var(--font-display); letter-spacing: -.02em; }
.px-ws-foot-d { margin-top: 4px; color: var(--muted); font-size: 15px; line-height: 1.6; }
.px-ws-foot > a { display: inline-flex; align-items: center; gap: 12px; min-height: 44px; flex: none; color: var(--accent); font-weight: 600; }
.px-ws-foot > a:hover { text-decoration: underline; text-underline-offset: 4px; }
.px-ws-signature { margin-top: 30px; color: var(--muted); font-size: var(--t-xs); }
.px-ws-page :is(a, button):focus-visible { outline: 2px solid var(--accent); outline-offset: 4px; }
@media (max-width: 1100px) {
  .px-ws-facts { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .px-ws-fact:nth-child(odd) { padding-inline-start: 0; border-inline-start: 0; }
  .px-ws-fact:nth-child(n + 3) { padding-top: 18px; border-top: 1px solid var(--line); }
}
@media (max-width: 900px) {
  .px-ws-top { gap: 18px; flex-wrap: wrap; }
  .px-ws-tags { justify-content: flex-start; }
  .px-ws-buttons { width: 100%; }
  .px-ws-buttons .btn { flex: 1; }
  .px-ws-foot { align-items: flex-start; flex-direction: column; gap: 12px; }
}
@media (max-width: 600px) {
  .px-ws-page .px-head { align-items: flex-start; flex-direction: column; margin-bottom: 24px; }
  .px-ws-page .px-head-act { width: 100%; }
  .px-ws-create { width: 100%; }
  .px-ws-top { gap: 14px; padding-block: 22px; }
  .px-ws-top .px-ws-av { width: 56px; height: 56px; font-size: 23px; border-radius: 12px; }
  .px-ws-top .px-ws-av.has-logo { width: 104px; }
  .px-ws-id { flex-basis: calc(100% - 70px); }
  .px-ws-av.has-logo + .px-ws-id { flex-basis: calc(100% - 118px); }
  .px-ws-tags { width: 100%; padding-inline-start: 0; }
  .px-ws-host { font-size: 14px; gap: 2px; }
  .px-ws-facts { gap: 16px; padding: 16px; }
  .px-ws-fact + .px-ws-fact { border-inline-start: 0; padding-inline-start: 0; }
  .px-ws-fact dd { font-size: 18px; }
  .px-ws-note { padding: 10px 12px; }
  .px-ws-act { gap: 16px; padding-block: 18px; }
  .px-ws-links { gap: 8px 20px; }
  .px-ws-buttons { flex-direction: column-reverse; }
  .px-ws-buttons .btn { width: 100%; white-space: normal; }
  .px-ws-assurance { padding: 16px; align-items: flex-start; font-size: 15px; }
  .px-ws-foot { padding: 20px; margin-top: 24px; }
}

/* =====================================================================
   12 · TAMAÑOS PEQUEÑOS, IMPRESIÓN Y MOVIMIENTO REDUCIDO
   ===================================================================== */

/* El velo del cajón no existe en escritorio: antes era un botón nativo de
   16×6 px al pie de la página que entraba en el tabulador. */
.px-scrim { display: none; }

/* --- EL ARMAZÓN EN ≤1000 px ------------------------------------------
   La hoja va a sangre (sin aire, filo ni radio: --px-sheet-gap a 0 y todo
   lo que cuelga de ella se recoloca), la barra lateral pasa a ser un cajón
   con su × y su velo, y la cabecera se queda con lo que cabe: menú, en qué
   entorno estás, dónde, buscar, avisos y cuenta. La campana y el buscador
   se ven a TODAS las anchuras (antes la campana compartía clase con
   «plegar» y desaparecía; un portátil de 1366 px al 150 % cae aquí). */
@media (max-width: 1000px) {
  [data-surface="console"] { --px-sheet-gap: 0px; }
  .px-shell { grid-template-columns: minmax(0, 1fr); }
  .px-side {
    position: fixed;
    inset-block: 0;
    inset-inline-start: 0;
    z-index: var(--z-drawer);
    width: min(300px, 86vw);
    padding: 0 10px 12px;
    background: var(--canvas);
    border-inline-end: 1px solid var(--line-2);
    translate: -101% 0;
    transition: translate var(--dur-3) var(--ease-out), box-shadow var(--dur-3) var(--ease-out);
  }
  :root[dir="rtl"] .px-side { translate: 101% 0; }
  /* La sombra, solo abierto: con el cajón fuera de la pantalla, su --e3
     asomaba unos 35 px por el borde izquierdo de la página. */
  :root.px-side-open .px-side { translate: 0 0; box-shadow: var(--e3); }
  .px-iconbtn.px-side-x { display: inline-grid; margin-inline-start: auto; }
  .px-scrim {
    display: block;
    position: fixed;
    inset: 0;
    z-index: var(--z-scrim);
    padding: 0;
    border: 0;
    background: var(--scrim);
    -webkit-backdrop-filter: blur(var(--scrim-blur));
    backdrop-filter: blur(var(--scrim-blur));
    opacity: 0;
    pointer-events: none;
    transition: opacity var(--dur-3) var(--ease-out);
  }
  :root.px-side-open .px-scrim { opacity: 1; pointer-events: auto; }
  :root.px-side-open body { overflow: hidden; }

  .px-main { margin: 0; border: 0; border-radius: 0; min-height: 100vh; min-height: 100dvh; }
  .px-top { top: 0; margin: 0; padding-inline: 6px 10px; border-width: 0 0 1px; border-radius: 0; }
  .px-burger { display: inline-grid; }
  .px-fold { display: none; }
  /* El cajón está cerrado: la chapa de entorno sale en la cabecera. */
  .px-top .px-env { display: inline-flex; margin-inline: 2px 4px; }
  .px-search { min-width: 200px; }
  .px-body { padding-inline: 14px; }
}

/* Por debajo de 720 px (un móvil, una tableta en vertical) la cabecera
   ya no tiene sitio para todo. */
@media (max-width: 720px) {
  /* El buscador queda en su lupa. El texto no se borra: se esconde a la
     vista y sigue siendo su nombre (y lleva `aria-label` además). */
  .px-search { min-width: 0; width: var(--ctl-sm); margin-inline-end: 0; padding: 0; justify-content: center; border-color: transparent; background: transparent; }
  .px-search-t { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; }
  .px-search .px-kbd { display: none; }
  /* Migas: sin el grupo. En una pantalla de dentro queda «Sección ›
     Título», con la sección de enlace para volver. */
  .px-crumbs li.px-crumbs-group { display: none; }
  .px-crumbs li.px-crumbs-group + li > .px-sep { display: none; }
}

/* En ≤400 px la chapa de entorno de la cabecera se queda en su punto de
   color, como con la barra plegada. Entera no cabía: con el dedo, los
   cuatro botones de la derecha miden 44 y «PRODUCCIÓN» empujaba el avatar
   fuera de la pantalla (a 360 px la página entera se desplazaba de lado).
   El nombre sigue en su texto oculto para el lector y en el globo; en
   producción el punto es ámbar y además está la línea de la barra. */
@media (max-width: 400px) {
  .px-top .px-env { width: 20px; padding: 0; gap: 0; border: 0; background: none; justify-content: center; }
  .px-top .px-env.is-live { color: var(--warn); }
  .px-top .px-env b { display: none; }
  .px-top .px-env-dot { width: 8px; height: 8px; }
}

/* SIN TECLADO NO SE OFRECEN ATAJOS. En una pantalla táctil sin ratón, «/»,
   «Esc» o «Ctrl K» son pistas de algo que no se puede pulsar: fuera las
   pistas, el botón que los enseña y su interruptor (la paleta tampoco
   ofrece «Ver los atajos», panel.js). */
@media (hover: none) and (pointer: coarse) {
  .px-nav-search .px-nav-kbd, .px-search .px-kbd, .px-cmd .px-kbd, .px-cmd-foot,
  .px-side-link[data-px-keys-open],
  .px-menu-pop button:is([data-px-keys-open], [data-px-keys-single]) { display: none; }
}

/* ATAJOS DE UNA TECLA APAGADOS (menú de cuenta): sus pistas no pueden
   seguir anunciando lo que ya no hace nada. */
.px-keys-off :is(.px-nav-search .px-nav-kbd, [data-px-keys-open] .px-kbd, .px-cmd-item .px-kbd) { display: none; }

@media (max-width: 860px) {
  /* En un móvil el aviso de cookies se apila y pasa de 130 px a más de 300:
     con el hueco de escritorio seguía tapando el botón de «Entrar», que es
     exactamente el que se viene a pulsar. */
  body:has([data-cookie-banner]) .px-card-page { padding-bottom: 340px; }
}

@media (max-width: 720px) {
  /* La barra del área de cliente no cabe en un móvil: marca + enlaces +
     nombre de quien ha entrado suman más de 500 px, y como es una fila sin
     `wrap` empujaba el ANCHO DEL DOCUMENTO — la página entera se desplazaba
     de lado, que es el peor fallo de maquetación que hay porque afecta a
     todo lo demás. Se parte en dos filas y el nombre se queda en su avatar,
     que es lo único que hace falta para saber con quién has entrado. */
  .px-appmain { padding-inline: 14px; }

  /* Una tabla densa se DESPLAZA, no se estruja. Sin este mínimo, en 390 px
     el navegador reparte seis columnas entre 360 y el subdominio acaba
     partido letra a letra («demo2026.s / atsm.test»): técnicamente está
     todo, pero no se puede leer ni copiar. Desplazar a lo ancho DENTRO de
     la caja es lo correcto aquí; lo que no puede pasar nunca es que sea la
     página entera la que se desplace, y de eso se encarga `.px-scroll`. */
  .px-scroll > table.data { min-width: 36rem; }
}

@media (max-width: 560px) {
  :root { --px-gap: 14px; }
  .px-history-filters { display: grid; grid-template-columns: repeat(2,minmax(0,1fr)); }
  .px-history-filters .px-history-query { grid-column: 1 / -1; }
  .px-history-filters input, .px-history-filters select { width: 100%; min-width: 0; }
  .px-head { align-items: flex-start; }
  .px-head-act { width: 100%; }
  .px-kpis { grid-template-columns: minmax(0, 1fr); }
  .px-g2, .px-g3, .px-split { grid-template-columns: minmax(0, 1fr); }
  /* La vista previa de la marca se pone encima de sus botones: en 360 px,
     120 px de miniatura más el botón dejan el texto en dos letras. */
  .px-media { grid-template-columns: minmax(0, 1fr); }

  /* La ficha de empresa en 390 px. Las chapas de estado bajan a su propia
     línea —sangradas para que sigan colgando del nombre y no del borde— en
     vez de estrujar el nombre de la tienda hasta partirlo. Y los dos
     botones se reparten el ancho: en un móvil se pulsa con el pulgar. */
  .px-mail-env { margin-inline-start: 0; }
  /* La barra de guardar, a una línea: en 390 px el recordatorio ocupaba dos
     renglones y la barra se comía un tercio de la pantalla justo encima de
     lo que se está editando. El botón dice lo mismo. */
  .px-saver .small { display: none; }
  .px-saver .btn { width: 100%; }
  .px-card { padding: 22px 18px; border-radius: var(--r-lg); }
  /* Ocho casillas en 360 px: encogen ANTES de desbordar. Lo que no puede
     pasar nunca es que la fila empuje el ancho del documento y la página
     entera se desplace de lado. */
  .px-otp-cells { gap: 6px; }
  .px-otp-cell { height: 54px; font-size: 1.25rem; }
  .px-otp-cell[data-gap] { margin-inline-start: 10px; }
  /* Una fila de lista con su bloque de chapas al otro lado NO cabe en 390
     px. Sin esto, el nombre y el correo se comprimen hasta partirse LETRA A
     LETRA en vertical —«a d m i n», «info@mun doph one. com»— y la fila
     mide media pantalla de alto. Que baje a la línea siguiente. */
  .px-list-row { flex-wrap: wrap; }
  /* Lo mismo, y por lo mismo, en la lista de «Sistema» de /ajustes: el
     rótulo no encoge (`flex:none`) y el valor lleva `overflow-wrap:anywhere`,
     así que un servidor de correo largo —«smtp.miproveedor.example.com:587»—
     se parte por donde caiga contra el borde derecho. Al bajar a su línea
     tiene los 360 px enteros, y ahí la alineación a la derecha ya no ayuda a
     leerlo: se queda a la izquierda, debajo de su rótulo. */
  .px-def { flex-wrap: wrap; }
  .px-def dd { text-align: start; }
  .px-toolbar { padding: 10px; }
  .px-toolbar .px-find { min-width: 0; max-width: none; }
  .px-toasts { inset-inline: 10px; max-width: none; }
}

/* El armazón en ≤560 px: los avisos, a lo ancho al pie de la pantalla, y
   las capas de la cabecera, a todo el ancho bajo la barra. Las migas se
   van: en 390 px quedaban en «Cue… › Dem…», y el título de la pantalla está
   justo debajo, en grande; su sitio es para la chapa de entorno. */
@media (max-width: 560px) {
  [data-surface="console"] .px-toasts { bottom: var(--px-toasts-bottom, 8px); inset-inline: 8px; width: auto; }
  .px-crumbs { display: none; }
  .px-top .px-pop,
  .px-top .px-menu-pop,
  .px-top .px-menu-pop.px-me-pop {
    position: fixed;
    top: calc(var(--px-top-h) + 6px);
    inset-inline: 8px;
    width: auto;
    min-width: 0;
    max-width: none;
    max-height: calc(100dvh - var(--px-top-h) - 16px);
    overflow-y: auto;
  }
  .px-cmd { width: calc(100vw - 16px); max-height: calc(100dvh - 16px); margin-top: 8px; }
  .px-cmd-foot { display: none; }
  .px-keys-list > div { grid-template-columns: 96px minmax(0, 1fr); }
}

@media print {
  .px-side, .px-top, .px-toasts, .px-toolbar, .px-row-act, .px-fold, .px-burger, .px-scrim { display: none !important; }
  /* En papel no hay hoja ni lienzo: la pantalla, a sangre. */
  .px-main { margin: 0; border: 0; border-radius: 0; background: none; }
  .px-shell { grid-template-columns: minmax(0, 1fr); }
  .px-body { padding: 0; }
  .px-panel, .px-kpi, .px-tablebox { box-shadow: none; break-inside: avoid; }
  /* Los datos del gráfico se despliegan al imprimir: en papel no hay ratón
     que pasar por encima, así que la tabla es la única forma de leerlos. */
  .px-data { display: block !important; }
  .px-data > summary { display: none; }
  .px-data > table { display: table !important; }
}

/* Lo del armazón no necesita nada aquí: la regla global de pulsar.css ya
   deja en nada sus transiciones y entradas, y no tiene nada infinito. */
@media (prefers-reduced-motion: reduce) {
  .px-meter > i, .px-col-bars > i, .px-funnel-bar > i { transition: none; }
  .px-otp, .px-otp-cell.is-active::after { animation: none; }
}

/* Modo de contraste forzado: los colores se los queda el sistema, así que
   las marcas que solo eran color necesitan un contorno para seguir
   existiendo. (El armazón tiene su bloque al final del fichero.) */
@media (forced-colors: active) {
  .px-kpi, .px-panel, .px-tablebox, .px-card { border: 1px solid CanvasText; }
  .px-col-bars > i, .px-funnel-bar > i, .px-rank-bar > i, .px-meter > i, .px-cal-d { outline: 1px solid CanvasText; }

  /* La tinta transparente del campo del código deja de serlo cuando el
     sistema impone sus colores: el número saldría ENCIMA de las casillas,
     descuadrado y a doble. Se quitan las casillas y queda el campo de
     siempre, que en este modo es lo correcto. */
  .px-otp.is-ready .px-otp-cells { display: none; }
  .px-otp.is-ready .px-code {
    position: static;
    height: auto;
    padding: 12px 14px;
    border: 1px solid CanvasText;
    color: CanvasText;
    caret-color: CanvasText;
    font-size: 1.4rem;
    letter-spacing: .4em;
  }
}

@media (max-width:640px) {
  .px-health-kpis { grid-template-columns:repeat(2,minmax(0,1fr)); gap:10px; }
  .px-health-kpis .px-kpi { padding:14px; min-width:0; }
  .px-health-kpis .px-kpi-v { font-size:28px; }
  .px-health-kpis .px-kpi-k { font-size:11px; line-height:1.4; white-space:normal; }
}
/* Facturas del cliente: filtros y saldos por moneda, dentro del ancho del área privada. */
.px-customer-billing-filters{display:grid;grid-template-columns:minmax(180px,2fr) repeat(4,minmax(130px,1fr));gap:16px;padding:24px;border-bottom:1px solid var(--line)}
.px-customer-billing-filters .field{margin:0;min-width:0}
.px-customer-billing-filters input,.px-customer-billing-filters select{min-width:0;width:100%}
.px-customer-billing-filter-actions{grid-column:1/-1;display:flex;gap:8px;flex-wrap:wrap}
.px-customer-billing-summary{padding:20px 24px;border-bottom:1px solid var(--line)}
.px-customer-billing-totals{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:16px;margin:16px 0 0}
.px-customer-billing-totals dt{color:var(--muted);font-size:13px}
.px-customer-billing-totals dd{font-size:20px;font-weight:600;margin:4px 0 0;overflow-wrap:anywhere}
.px-customer-billing-detail{display:block;margin-top:4px;white-space:normal;min-width:160px}
@media(max-width:1000px){.px-customer-billing-filters{grid-template-columns:repeat(2,minmax(0,1fr))}.px-customer-billing-search{grid-column:1/-1}}
@media(max-width:600px){.px-customer-billing-filters,.px-customer-billing-summary{padding:16px}.px-customer-billing-totals{grid-template-columns:repeat(2,minmax(0,1fr));gap:16px 12px}.px-customer-billing-totals dd{font-size:17px}.px-customer-billing-filters input[type=date]{font-size:13px;padding-inline:8px}}

/* Asistente: pasos visibles y formularios con ancho útil también en móvil. */
/* La configuración personal comparte el ancho del área de cuenta. */
.authenticator-page { max-width: 760px; margin: 32px auto; padding: 0 16px; }
.authenticator-page-wide { max-width: none; margin: 0; padding: 0; }
.authenticator-layout { display: grid; gap: var(--s-6); align-items: start; }
.authenticator-layout > * { min-width: 0; }
.authenticator-primary .px-panel-body > :is(p,ol,form,details) { max-width: 72ch; }
.authenticator-primary :is(input,select) { max-width: 36rem; }
.authenticator-primary details summary { min-height: 44px; cursor: pointer; padding-block: 10px; }
.authenticator-support .px-panel-body { display: grid; gap: var(--s-6); }
.authenticator-support h3 { font-size: var(--t-base); margin-bottom: var(--s-2); }
.authenticator-support p { color: var(--muted); line-height: 1.7; }
@media (min-width: 1100px) {
 .authenticator-page-wide .authenticator-layout { grid-template-columns: minmax(0,1.6fr) minmax(260px,1fr); }
}
@media (max-width: 380px) {
  .px-ws-top .px-ws-av.has-logo { width: 88px; }
  .px-ws-av.has-logo + .px-ws-id { flex-basis: calc(100% - 102px); }
}
@media (max-width: 359px) {
  .px-ws-id, .px-ws-av.has-logo + .px-ws-id { flex-basis: 100%; }
  .px-ws-facts { grid-template-columns: 1fr; }
  .px-ws-fact + .px-ws-fact { padding-top: 16px; border-top: 1px solid var(--line); }
}
.px-onboarding-grid { grid-template-columns: 240px minmax(0,1fr); }
.px-onboarding-grid > * { min-width: 0; }
.px-onboarding-invite { grid-template-columns: minmax(0,2fr) minmax(140px,1fr); gap: var(--s-3); }
@media(max-width:900px) {
 .px-onboarding-grid { grid-template-columns: minmax(0,1fr); }
 .px-onboarding-grid .px-steps ol { position: static; grid-template-columns: repeat(2,minmax(0,1fr)); }
 .px-onboarding-grid .px-steps a { padding: 10px; }
}
@media(max-width:560px) {
 .px-onboarding-grid .px-g2,.px-onboarding-grid .px-g3,.px-onboarding-invite { grid-template-columns: minmax(0,1fr); }
 .px-onboarding-grid .px-steps a { font-size: 12px; gap: 8px; }
 .px-onboarding-grid .px-panel-foot .btn-primary { width: 100%; }
}

/* Crear una empresa: el área es fluida, los campos tienen una medida útil.
   La ayuda comparte el espacio sobrante sin convertir un código en una barra. */
.px-create .px-head p { max-width: 76ch; }
.px-create-layout { display: grid; grid-template-columns: minmax(0, 1fr); gap: 28px; align-items: start; }
.px-create-layout > * { min-width: 0; }
.px-create-form { container-type: inline-size; container-name: company-form; }
.px-create-form .px-panel-body { padding: 28px; display: grid; gap: 28px; }
.px-create-form .px-panel-body > * + * { margin-top: 0; }
.px-create-form .field { min-width: 0; margin: 0; }
.px-create-form :is(input, .input-group) { width: 100%; min-width: 0; }
.px-create-form input { min-height: 48px; }
.px-create-form .input-group input { width: 0; flex: 1; }
.px-create-form .input-group .suffix { flex: none; padding-inline: 12px; }
.px-create-heading { justify-content: flex-start; flex-wrap: nowrap; gap: 14px; padding: 24px 28px; }
.px-create-heading > :first-child { flex: none; }
.px-create-heading > :last-child:not(:first-child) { flex: 1; min-width: 0; }
.px-create-heading h2 { font-size: var(--t-lg); }
.px-create-heading p { font-size: var(--t-sm); line-height: 1.5; margin-top: 6px; }
.px-create-icon { flex: none; width: 44px; height: 44px; display: grid; place-items: center; border-radius: 12px; background: var(--accent-soft); color: var(--accent); }
.px-create-fields { display: grid; grid-template-columns: minmax(0, 1fr); gap: 24px; align-items: start; }
.px-create-invite { padding-bottom: 24px; border-bottom: 1px solid var(--line); }
.px-create-invite input { max-width: 25rem; letter-spacing: .1em; }
.px-create-form .hint { display: block; max-width: 76ch; line-height: 1.6; margin-top: 8px; }
.px-create-form .slug-status:empty { display: none; }
.px-create-note { display: flex; align-items: flex-start; gap: 10px; color: var(--ink-2); padding: 16px; border-radius: var(--r-sm); background: var(--surface-2); line-height: 1.6; }
.px-create-note svg { flex: none; margin-top: 3px; color: var(--accent); }
.px-create-actions { display: flex; align-items: center; justify-content: space-between; gap: 16px; flex-wrap: wrap; padding: 18px 28px; }
.px-create-actions .btn { min-height: 44px; white-space: normal; }
.px-create-help { padding: 28px; border: 1px solid var(--line); border-radius: var(--r-lg); background: var(--surface-2); }
.px-create-help-title { display: flex; align-items: center; gap: 14px; }
.px-create-help h2 { font-size: var(--t-lg); letter-spacing: -.015em; }
.px-create-help h3 { font-size: var(--t-base); line-height: 1.4; }
.px-create-help p { max-width: 68ch; font-size: var(--t-sm); line-height: 1.7; color: var(--muted); margin-top: 6px; }
.px-create-steps { list-style: none; padding: 0; margin: 28px 0; display: grid; gap: 24px; }
.px-create-steps li { display: grid; grid-template-columns: 30px minmax(0, 1fr); gap: 14px; }
.px-create-steps li > span { display: grid; place-items: center; width: 30px; height: 30px; border: 1px solid var(--line-2); border-radius: 50%; background: var(--surface); font-size: var(--t-sm); font-weight: 600; color: var(--accent); }
.px-create-separate { display: flex; align-items: flex-start; gap: 14px; border-top: 1px solid var(--line); padding-top: 24px; }
.px-create-separate > svg { flex: none; margin: 2px 5px; color: var(--accent); }
@media (min-width: 1100px) {
  .px-create-layout { grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr); gap: clamp(24px, 3vw, 56px); }
}
@container company-form (min-width: 700px) {
  .px-create-fields { grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr); }
}
@media (min-width: 1800px) {
  .px-create-layout { grid-template-columns: minmax(0, 64rem) minmax(0, 1fr); }
}
@media (max-width: 600px) {
  .px-create-layout { gap: 20px; }
  .px-create-heading, .px-create-form .px-panel-body, .px-create-help { padding: 20px 18px; }
  .px-create-heading { align-items: flex-start; }
  .px-create-actions { padding: 16px 18px; }
  .px-create-actions .btn-primary { flex: 1 1 100%; }
  .px-create-actions > a { flex: 1 1 100%; }
  .px-create-form .input-group .suffix { padding-inline: 8px; font-size: 12px; }
}

/* La tarjeta de Veri*factu de la ficha de factura del cliente. El QR toma el
   color del texto (currentColor en el SVG), así que sigue al tema sin tener
   dos versiones del dibujo. */
.px-vf{display:flex;gap:20px;align-items:flex-start;flex-wrap:wrap}
.px-vf>div:last-child{flex:1;min-width:200px;display:grid;gap:8px}
.px-vf p{margin:0}
.px-vf code{font-size:13px;overflow-wrap:anywhere}
/* El QR va SIEMPRE oscuro sobre blanco, también en modo oscuro. No es
   decoración: es un código que tiene que leer la cámara de un móvil, y
   muchos lectores no aceptan el contraste invertido. Un QR que sigue el
   tema es bonito y no se escanea. */
.px-vf-qr{flex-shrink:0;line-height:0;color:#0b1220;padding:10px;border:1px solid var(--line);border-radius:12px;background:#fff}
.px-vf-qr svg{display:block;width:132px;height:132px}
@media(max-width:560px){.px-vf{gap:14px}.px-vf-qr{margin-inline:auto}}
/* Estado de la AEAT en la lista de facturas del cliente. */
.px-vf-tag{display:inline-block;font-size:11px;line-height:1.4;padding:3px 8px;border-radius:6px;border:1px solid var(--line);color:var(--muted);white-space:nowrap}
.px-vf-tag.is-registered{color:var(--ok);border-color:color-mix(in srgb,var(--ok) 40%,transparent)}
/* Los dos datos que el resumen por moneda no da: cuándo vence lo próximo y
   cuántas facturas constan ya en la AEAT. En una línea, porque repetir los
   importes en tarjetas grandes era decir dos veces lo mismo. */
.px-customer-billing-extra{margin-top:12px}

/* Mensajes compartidos de los formularios sobre fondo oscuro. */
.px-stage-card .hint { color: rgba(255, 255, 255, .62); }
.px-stage-card .field .error { color: #FFB4B4; }
.px-stage-card .field.has-error input,
.px-stage-card .field.has-error .input-group { border-color: #F26D6D; }

/* La casilla de condiciones: objetivo de dedo, enlaces subrayados en
   blanco (un enlace azul sobre azul no se ve). */
.px-stage-card .check { color: #fff; padding: 4px 0; }
.px-stage-card .check span { font-size: var(--t-sm); line-height: 1.5; }
.px-stage-card .check a { color: #fff; text-decoration: underline; text-underline-offset: 3px; }
.px-stage-card .check a:hover { opacity: .85; }
.px-stage-card .check input { accent-color: #fff; }

/* El campo trampa, fuera de la pantalla. */
.px-hp { position: absolute; left: -9999px; top: 0; width: 1px; height: 1px; overflow: hidden; }

/* La invitación (01/10/2026). El código se lee en mayúsculas y espaciado
   —se dicta y se copia—, aunque se escriba como se quiera: lo normaliza el
   servidor. «Invitación válida» en verde: sobre la tinta del alta, el
   claro; en «Mis empresas», el del tema. */
.px-invite-input { font-family: var(--font-mono); text-transform: uppercase; letter-spacing: .12em; }
.px-invite-input::placeholder { text-transform: none; letter-spacing: normal; font-family: var(--font-sans); }
.px-invite-from { display: flex; align-items: center; gap: 6px; margin-top: 6px; color: var(--ok); font-size: var(--t-sm); font-weight: 600; }
.px-invite-from[hidden] { display: none; }
.px-invite .hint a { text-decoration: underline; text-underline-offset: 3px; }

/* =====================================================================
   MI CUENTA (/cuenta)
   ---------------------------------------------------------------------
   Identidad y seguridad a todo el ancho del área privada. Las tarjetas
   pasan de una a tres columnas sin alargar los campos en pantallas grandes.
   ===================================================================== */

.px-acct { max-width: none; min-width: 0; }
.px-acct .px-head { margin-bottom: 24px; }
.px-acct .px-head-txt { min-width: 0; }
.px-acct .px-head p { max-width: 70ch; }
.px-acct .px-head-act .btn { min-height: 44px; }
/* Un borrado de la cuenta ya programado: arriba, antes que nada. */
.px-acct-deletion { margin-bottom: 24px; }
.px-acct-deletion a { margin-left: 6px; font-weight: 600; text-decoration: underline; text-underline-offset: 3px; }

/* --- Identidad y estado ------------------------------------------------ */
.px-acct-summary { min-width: 0; }
.px-acct-id { display: flex; align-items: center; gap: 18px; padding: 22px 24px; }
.px-acct-avatar {
  flex: none;
  width: 60px;
  height: 60px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: var(--accent-soft);
  color: var(--accent);
  font-family: var(--font-display);
  font-size: 26px;
  font-weight: 700;
}
.px-acct-id-txt { min-width: 0; }
.px-acct-id-txt h2 { font-size: var(--t-xl); letter-spacing: -.02em; line-height: 1.2; overflow-wrap: anywhere; }
.px-acct-mail {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px 10px;
  margin-top: 4px;
  color: var(--ink-2);
  font-size: var(--t-sm);
  overflow-wrap: anywhere;
}
.px-acct-meta { display: flex; flex-wrap: wrap; gap: 4px 18px; margin-top: 8px; font-size: var(--t-sm); color: var(--muted); }
.px-acct-meta a { color: inherit; text-decoration: underline; text-underline-offset: 3px; }
.px-acct-meta a:hover { color: var(--accent); }

.px-acct-status {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  border-top: 1px solid var(--line);
}
.px-acct-status li + li { border-left: 1px solid var(--line); }
.px-acct-status a {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  column-gap: 12px;
  row-gap: 2px;
  align-content: start;
  height: 100%;
  min-height: 76px;
  padding: 16px 20px;
  color: var(--ink);
  text-decoration: none;
  transition: background-color .15s ease;
}
.px-acct-status a:hover { background: var(--surface-2); }
.px-acct-status-ic {
  grid-row: 1 / span 2;
  width: 32px;
  height: 32px;
  border-radius: 10px;
  display: grid;
  place-items: center;
  background: var(--surface-3);
  color: var(--ink-2);
}
.px-acct-status a.is-ok .px-acct-status-ic { background: var(--ok-soft); color: var(--ok); }
.px-acct-status-k { font-size: var(--t-xs); color: var(--muted); line-height: 1.5; }
.px-acct-status-v { font-size: var(--t-sm); font-weight: 600; overflow-wrap: anywhere; }
.px-acct-ip { font-family: var(--font-mono); font-size: 11px; font-weight: 400; color: var(--muted); }
.px-acct-status-v .px-acct-ip { display: block; margin-top: 1px; }

/* Índice de enlaces reales: funciona sin JS y respeta los fragmentos de
   retorno de los formularios. No hay una segunda barra fija tapando el foco. */
.px-acct-nav { display: flex; flex-wrap: wrap; gap: 8px; margin: 24px 0; }
.px-acct-nav a {
  display: flex; align-items: center; gap: 9px; min-height: 44px;
  padding: 10px 14px; border: 1px solid var(--line-2); border-radius: var(--r-sm);
  background: var(--surface); color: var(--ink-2); font-size: var(--t-sm);
  font-weight: 600; line-height: 1.4; text-decoration: none;
  transition: background-color .15s ease, border-color .15s ease;
}
.px-acct-nav a svg { flex: none; color: var(--muted); }
.px-acct-nav a:hover { background: var(--accent-soft); border-color: var(--accent); color: var(--accent); }
.px-acct:has(#datos:target) .px-acct-nav a[href="#datos"],
.px-acct:has(#contrasena:target) .px-acct-nav a[href="#contrasena"],
.px-acct:has(#doble-factor:target) .px-acct-nav a[href="#doble-factor"],
.px-acct:has(#equipos:target) .px-acct-nav a[href="#equipos"],
.px-acct:has(#sesiones:target) .px-acct-nav a[href="#sesiones"],
.px-acct:has(#actividad:target) .px-acct-nav a[href="#actividad"],
.px-acct:has(#privacidad:target) .px-acct-nav a[href="#privacidad"] {
  background: var(--accent-soft); border-color: var(--accent); color: var(--accent);
}

/* --- Tarjetas ------------------------------------------------------------ */
.px-acct-grid { display: grid; grid-template-columns: minmax(0, 1fr); gap: 24px; align-items: stretch; }
.px-acct-row {
  display: flex; flex-direction: column; min-width: 0;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-lg); box-shadow: var(--px-e1);
  scroll-margin-top: 96px;
}
.px-acct-aside { padding: 22px 24px 18px; border-bottom: 1px solid var(--line); }
.px-acct-aside h2 { display: flex; align-items: center; gap: 10px; font-size: var(--t-lg); letter-spacing: -.015em; line-height: 1.3; }
.px-acct-aside h2 svg { flex: none; color: var(--accent); }
.px-acct-aside p { margin-top: 10px; font-size: var(--t-sm); line-height: 1.6; color: var(--muted); max-width: 76ch; }
.px-acct-row:target { box-shadow: 0 0 0 3px var(--accent-soft), var(--px-e1); border-color: var(--accent); }
.px-acct-row:focus { outline: none; }
.px-acct-row:focus-visible { outline: 2px solid var(--accent); outline-offset: 4px; }

.px-acct-card { min-width: 0; flex: 1; display: flex; flex-direction: column; container-type: inline-size; container-name: account-card; }
.px-acct-row > .px-acct-card { border: 0; box-shadow: none; border-radius: 0 0 var(--r-lg) var(--r-lg); margin: 0; }
.px-acct-card .px-panel-body { padding: 22px 24px; flex: 1; }
.px-acct-card .field { margin-bottom: 0; }
.px-acct-fields { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 18px 20px; }
.px-acct-fields > *, .px-acct-state > div { min-width: 0; }
.px-acct-card :is(input, select) { min-width: 0; width: 100%; }
.px-acct-card .btn { min-height: 44px; white-space: normal; }
.px-acct-narrow { max-width: 26rem; }
.px-acct-alert { margin: 0; }
.px-acct-alert svg { flex: none; margin-top: 2px; }
.px-acct-alert p + p, .px-acct-alert p + a { display: block; margin-top: 4px; }

.px-acct-foot {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  flex-wrap: wrap;
  gap: 12px 20px;
  padding: 14px 24px;
}
.px-acct-foot-note { flex: 1 1 18rem; display: flex; align-items: flex-start; gap: 8px; line-height: 1.5; }
.px-acct-foot-note svg { flex: none; margin-top: 2px; }
.px-acct-foot .btn { flex: none; }

/* El correo como dato, no como un campo apagado que parece editable. */
.px-acct-static dt { font-weight: 600; font-size: var(--t-sm); margin-bottom: 6px; color: var(--ink); }
.px-acct-static dd {
  margin: 0;
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 46px;
  padding: 10px 14px;
  border-radius: var(--r-sm);
  border: 1px dashed var(--line-2);
  background: var(--surface-3);
  color: var(--ink);
  overflow-wrap: anywhere;
}
.px-acct-static dd svg { flex: none; color: var(--muted); }
.px-acct-static dd span { min-width: 0; }
.px-acct-hint { font-size: var(--t-xs); color: var(--muted); margin-top: 6px; }

/* --- Verificación en dos pasos ------------------------------------------ */
.px-acct-state { display: flex; align-items: flex-start; gap: 14px; }
.px-acct-state-ic {
  flex: none;
  width: 40px;
  height: 40px;
  border-radius: 12px;
  display: grid;
  place-items: center;
  background: var(--surface-3);
  color: var(--ink-2);
}
.px-acct-state.is-ok .px-acct-state-ic { background: var(--ok-soft); color: var(--ok); }
.px-acct-state h3 { font-size: var(--t-base); line-height: 1.35; }
.px-acct-state p { margin-top: 4px; font-size: var(--t-sm); color: var(--ink-2); line-height: 1.55; overflow-wrap: anywhere; }
.px-acct-advice {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 12px 14px;
  border-radius: var(--r-md);
  background: var(--accent-soft);
  color: var(--ink-2);
  font-size: var(--t-sm);
  line-height: 1.5;
}
.px-acct-advice svg { flex: none; margin-top: 3px; color: var(--accent); }

/* --- Listas: equipos y enlaces ------------------------------------------ */
.px-acct-list { list-style: none; margin: 0; padding: 0; }
.px-acct-list > li + li { border-top: 1px solid var(--line); }
.px-acct-item {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: 14px;
  padding: 16px 24px;
}
.px-acct-item.is-current { background: color-mix(in srgb, var(--ok-soft) 55%, transparent); }
.px-acct-item > form { margin: 0; }
.px-acct-item-ic {
  flex: none;
  width: 36px;
  height: 36px;
  border-radius: 10px;
  display: grid;
  place-items: center;
  background: var(--surface-3);
  color: var(--ink-2);
}
.px-acct-item-txt, .px-acct-log-txt { min-width: 0; overflow-wrap: anywhere; }
.px-acct-item-title { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px; font-size: var(--t-sm); }
.px-acct-item-meta { display: flex; flex-wrap: wrap; gap: 2px 16px; margin-top: 4px; font-size: var(--t-xs); color: var(--muted); }

.px-acct-empty { padding: 32px 24px; text-align: center; }
.px-acct-empty-ic {
  display: inline-grid;
  place-items: center;
  width: 44px;
  height: 44px;
  margin-bottom: 12px;
  border-radius: 50%;
  background: var(--surface-3);
  color: var(--ink-2);
}
.px-acct-empty p { max-width: 48ch; margin-inline: auto; font-size: var(--t-sm); color: var(--ink-2); }
.px-acct-empty p + p { margin-top: 6px; color: var(--muted); }

.px-acct-go {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: 14px;
  min-height: 64px;
  padding: 16px 24px;
  color: var(--ink);
  text-decoration: none;
  transition: background-color .15s ease;
}
.px-acct-go:hover { background: var(--surface-2); }
.px-acct-go > svg:last-child { color: var(--muted); transition: transform .15s ease, color .15s ease; }
.px-acct-go:hover > svg:last-child { color: var(--accent); transform: translateX(2px); }
/* Borrar la cuenta: en rojo, para que no se confunda con los otros dos. */
.px-acct-go.is-danger .px-acct-item-ic { background: var(--danger-soft); color: var(--danger); }
.px-acct-go.is-danger strong { color: var(--danger); }
.px-acct-go-txt { min-width: 0; }
.px-acct-go-txt strong { display: block; font-size: var(--t-sm); }
.px-acct-go-txt span { display: block; margin-top: 2px; font-size: var(--t-xs); line-height: 1.5; color: var(--muted); }
.px-acct-privacy { grid-column: 1 / -1; }
.px-acct-privacy .px-acct-go { height: 100%; }

/* Dentro de un panel con overflow:hidden, el contorno de foco por fuera se
   recortaba: aquí va por dentro. */
.px-acct-status a:focus-visible, .px-acct-go:focus-visible { outline: 2px solid var(--accent); outline-offset: -3px; }

/* --- Sesiones ------------------------------------------------------------ */
.px-acct-list-lead { font-size: var(--t-sm); font-weight: 600; }
.px-acct-bullets {
  display: grid;
  gap: 4px;
  margin: 8px 0 0;
  padding-left: 1.2em;
  font-size: var(--t-sm);
  line-height: 1.55;
  color: var(--ink-2);
}

/* --- Actividad ----------------------------------------------------------- */
.px-acct-log { list-style: none; margin: 0; padding: 6px 24px; }
.px-acct-log-item { display: grid; grid-template-columns: 16px minmax(0, 1fr); gap: 14px; padding: 12px 0; }
.px-acct-log-item + .px-acct-log-item { border-top: 1px solid var(--line); }
.px-acct-log-mark { display: grid; place-items: center; height: 20px; }
.px-acct-log-mark i { width: 8px; height: 8px; border-radius: 50%; background: var(--line-strong); }
.px-acct-log-item.is-ok .px-acct-log-mark i { background: var(--ok); }
.px-acct-log-item.is-warn .px-acct-log-mark { color: var(--warn); }
.px-acct-log-title { font-size: var(--t-sm); font-weight: 600; color: var(--ink); line-height: 1.4; }
.px-acct-log-meta { display: flex; flex-wrap: wrap; gap: 2px 16px; margin-top: 2px; font-size: var(--t-xs); color: var(--muted); }

@media (prefers-reduced-motion: reduce) {
  .px-acct-status a, .px-acct-go, .px-acct-go > svg:last-child, .px-acct-nav a { transition: none; }
}

@media (min-width: 1100px) {
  .px-acct-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .px-acct-privacy .px-acct-list { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .px-acct-privacy .px-acct-list > li + li { border-top: 0; border-inline-start: 1px solid var(--line); }
}
@media (min-width: 1600px) {
  .px-acct-summary { display: grid; grid-template-columns: minmax(300px, .8fr) minmax(0, 1.6fr); align-items: stretch; }
  .px-acct-status { border-top: 0; border-inline-start: 1px solid var(--line); align-items: stretch; }
  .px-acct-status a { align-content: center; }
}
@media (min-width: 1900px) {
  .px-acct-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
/* El ancho de la tarjeta manda también en una pantalla de tres columnas. */
@container account-card (max-width: 480px) {
  .px-acct-fields { grid-template-columns: minmax(0, 1fr); }
  .px-acct-foot { gap: 12px; }
  .px-acct-foot .btn { width: 100%; }
  .px-acct-item { grid-template-columns: auto minmax(0, 1fr); }
  .px-acct-item > form { grid-column: 2; }
}

@media (max-width: 1080px) {
  .px-acct-status { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .px-acct-status li:nth-child(3) { border-left: 0; }
  .px-acct-status li:nth-child(n+3) { border-top: 1px solid var(--line); }
}

@media (max-width: 600px) {
  .px-acct-grid { gap: 18px; }
  .px-acct-aside { padding: 18px; }
  .px-acct-nav { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; margin-block: 20px; }
  .px-acct-nav a { padding: 10px; font-size: 13px; overflow-wrap: anywhere; }
  .px-acct .px-head-act .btn { width: 100%; }
  .px-acct-id { align-items: flex-start; gap: 14px; padding: 18px; }
  .px-acct-avatar { width: 48px; height: 48px; font-size: 20px; }
  .px-acct-status a { padding: 14px 16px; column-gap: 10px; }
  .px-acct-fields { grid-template-columns: minmax(0, 1fr); }
  .px-acct-card .px-panel-body { padding: 18px; }
  .px-acct-foot { padding: 14px 18px; }
  .px-acct-foot .btn { width: 100%; }
  .px-acct-item { grid-template-columns: auto minmax(0, 1fr); padding: 14px 18px; }
  .px-acct-item > form { grid-column: 2; }
  .px-acct-item .btn-sm { min-height: 44px; padding-inline: 18px; }
  .px-acct-log { padding: 4px 18px; }
  .px-acct-go { padding: 14px 18px; }
}

@media (max-width: 380px) {
  .px-acct-id { flex-wrap: wrap; }
  .px-acct-id-txt { flex-basis: 100%; }
  .px-acct-status { grid-template-columns: minmax(0, 1fr); }
  .px-acct-status li + li { border-left: 0; border-top: 1px solid var(--line); }
}

/* ---------------------------------------------------------------------
   EL CENTRO DE AVISOS Y LOS MENSAJES (cabecera, 28/09/2026)
   ---------------------------------------------------------------------
   Dos botones de icono —Mensajes y Avisos— con su panel flotante
   (partials/console-inbox.php). La superficie, la sombra, la entrada y el
   sitio en el móvil los pone `.px-pop` (Capas flotantes); aquí solo lo
   suyo. Sustituye a la campana de antes, que solo enseñaba peticiones de
   plan y llevaba a un ancla que no existía.

   Decisiones:
     · LA PASTILLA DICE DOS COSAS, CADA UNA POR SU CANAL. El número es lo
       PENDIENTE: no baja por mirarlo, baja al resolverlo. El color dice si
       hay algo NUEVO desde la última mirada: acento si lo hay, neutra si no
       (lo decide panel.js, 2b). Antes era cian siempre, y un aviso que
       grita siempre enseña a no mirarlo.
     · NO TAPA EL ICONO. Sale por la esquina con un filo del color de la
       cabecera que la recorta: la campana se sigue leyendo (la de antes se
       comía casi todo el dibujo de 16 px).
     · EL PANEL NO SE DESPLAZA ENTERO. Cabecera y pie se quedan quietos y
       solo corre la lista, con alto máximo propio: «Marcar como visto» y
       «Ver todas» siguen a mano también a 1280 px al 150 %.
     · CADA ELEMENTO ES UN ENLACE ENTERO, con el anillo de foco por DENTRO:
       en una lista que se desplaza, uno por fuera se cortaría.
   --------------------------------------------------------------------- */
/* Un poco de aire a cada lado: la pastilla sale por la esquina y no puede
   pisar el botón de al lado. */
.px-inbox { position: relative; margin-inline: 2px; }

/* La pastilla: 16 px en la esquina de arriba del botón, cifras tabulares
   («9+» y «3» no bailan). Neutra por defecto; `is-new`, en acento. Tan
   fuera como cabe: con 18 px y más adentro se comía media campana. */
.px-inbox-n {
  position: absolute;
  top: -4px;
  inset-inline-end: -6px;
  min-width: 16px;
  height: 16px;
  padding: 0 4px;
  border-radius: var(--r-full);
  background: var(--surface-3);
  color: var(--ink-2);
  font-size: var(--t-2xs);
  font-weight: 700;
  line-height: 16px;
  letter-spacing: 0;
  text-align: center;
  font-variant-numeric: tabular-nums;
  box-shadow: 0 0 0 2px var(--bg), inset 0 0 0 1px var(--line-2);
  pointer-events: none;
  transition: background-color var(--dur-2) var(--ease-out), color var(--dur-2) var(--ease-out);
}
.px-inbox-n.is-new { background: var(--accent); color: var(--on-accent); box-shadow: 0 0 0 2px var(--bg); }
/* Nada pendiente pero novedades en «En curso»: un punto, sin número. */
.px-inbox-n.is-dot { top: 3px; inset-inline-end: 3px; min-width: 0; width: 9px; height: 9px; padding: 0; }

/* El panel: 400 px, alto máximo y solo la lista con barra propia. */
.px-pop.px-inbox-pop {
  display: flex;
  flex-direction: column;
  width: 400px;
  max-width: calc(100vw - 16px);
  max-height: min(600px, calc(100vh - var(--px-top) - 24px));
  max-height: min(600px, calc(100dvh - var(--px-top) - 24px));
  padding: 0;
  overflow: hidden;
}

.px-inbox-head {
  flex: none;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px 8px;
  min-height: 52px;
  padding-block: 10px;
  padding-inline: 22px 10px;
  border-bottom: 1px solid var(--line);
}
.px-inbox-t {
  margin: 0;
  color: var(--ink);
  font-family: var(--font-display);
  font-size: .9375rem;
  font-weight: 650;
  line-height: 1.3;
  letter-spacing: -.01em;
}
.px-inbox-t:focus { outline: none; }
.px-inbox-t:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 4px; }
/* Las chapas neutras del panel van sobre una VELADURA y no sobre
   --surface-3: encima de --surface-overlay ese color es casi el mismo y la
   chapa desaparecía (quedaba un «13» suelto). */
.px-inbox-count {
  display: inline-grid;
  place-items: center;
  height: 20px;
  padding: 0 8px;
  border-radius: var(--r-full);
  background: var(--surface-pressed);
  color: var(--ink-2);
  font-size: var(--t-2xs);
  font-weight: 600;
  line-height: 1;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
/* «Marcar como visto» y «Abrir la bandeja»: fantasma pequeño en acento. */
.px-inbox-hbtn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: var(--ctl-xs);
  margin-inline-start: auto;
  padding: 0 8px;
  border: 0;
  border-radius: var(--r-ctl);
  background: transparent;
  color: var(--accent);
  font: inherit;
  font-size: .78125rem;
  font-weight: 600;
  line-height: 1;
  white-space: nowrap;
  text-decoration: none;
  cursor: pointer;
  transition: background-color var(--dur-1) var(--ease-out), color var(--dur-1) var(--ease-out);
}
.px-inbox-hbtn:hover { background: var(--accent-soft); color: var(--accent-hover); }
.px-inbox-hbtn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.px-inbox-hbtn svg { width: 14px; height: 14px; max-width: none; flex: none; }

.px-inbox-body {
  flex: 1 1 auto;
  min-height: 0;
  padding: 2px 6px 6px;
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: thin;
}
.px-inbox-group + .px-inbox-group { margin-top: 4px; }
.px-inbox-cap {
  margin: 0;
  padding-block: 12px 6px;
  padding-inline: 16px 10px;
  color: var(--muted);
  font-family: var(--font-sans);
  font-size: var(--t-2xs);
  font-weight: 600;
  line-height: 1.3;
  letter-spacing: .06em;
  text-transform: uppercase;
}
.px-inbox-note { margin-block: -2px 6px; margin-inline: 16px 10px; color: var(--muted); font-size: var(--t-2xs); line-height: 1.4; }
.px-inbox-list { display: grid; gap: 1px; margin: 0; padding: 0; list-style: none; }

/* El elemento: baldosa · texto · cuándo y qué hacer. */
.px-inbox-item {
  position: relative;
  display: grid;
  grid-template-columns: 28px minmax(0, 1fr) auto;
  align-items: start;
  column-gap: 12px;
  padding-block: 10px;
  padding-inline: 16px 10px;
  border-radius: var(--r-ctl);
  color: var(--ink);
  text-decoration: none;
  transition: background-color var(--dur-1) var(--ease-out);
}
.px-inbox-item:hover { background: var(--surface-hover); color: var(--ink); }
.px-inbox-item:focus-visible { background: var(--surface-hover); outline: 2px solid var(--accent); outline-offset: -2px; }

/* «Nuevo desde tu última mirada»: un punto en el margen, en la misma
   columna para todos (se ve de un vistazo cuáles son), con su palabra para
   el lector de pantalla. Lo enciende panel.js: sin él no se sabe qué se ha
   visto, así que no hay punto. */
.px-inbox-dot { display: none; }
.px-inbox-item.is-new .px-inbox-dot {
  display: block;
  position: absolute;
  top: 21px;
  inset-inline-start: 5px;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--accent);
}

/* La baldosa (el icono de la fuente, tintado por lo que corre) y el avatar
   de quien escribe: el mismo hueco de 28 px. */
.px-inbox-tile,
.px-inbox-av {
  display: grid;
  place-items: center;
  width: 28px;
  height: 28px;
  background: var(--surface-pressed);
  color: var(--muted);
}
.px-inbox-tile { border-radius: 8px; }
.px-inbox-av { border-radius: var(--r-full); color: var(--ink-2); font-size: var(--t-2xs); font-weight: 700; letter-spacing: .02em; }
.px-inbox-tile svg, .px-inbox-av svg { width: 16px; height: 16px; max-width: none; }
.px-inbox-tile.is-accent, .px-inbox-av.is-accent { background: var(--accent-soft); color: var(--accent); }
.px-inbox-tile.is-danger { background: var(--danger-soft); color: var(--danger); }
.px-inbox-tile.is-warn { background: var(--warn-soft); color: var(--warn); }
.px-inbox-tile.is-info, .px-inbox-av.is-info { background: var(--info-soft); color: var(--info); }
.px-inbox-av.is-ok { background: var(--ok-soft); color: var(--ok); }

.px-inbox-txt { display: grid; gap: 2px; min-width: 0; }
.px-inbox-title { color: var(--ink); font-size: var(--t-ui); font-weight: 600; line-height: 1.35; overflow-wrap: anywhere; }
.px-inbox-text {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  overflow: hidden;
  color: var(--muted);
  font-size: .78125rem;
  line-height: 1.45;
}
.px-inbox-meta { display: grid; justify-items: end; align-content: start; gap: 6px; padding-top: 1px; }
.px-inbox-meta time { color: var(--muted); font-size: var(--t-2xs); line-height: 1.5; white-space: nowrap; font-variant-numeric: tabular-nums; }
.px-inbox-num {
  display: inline-grid;
  place-items: center;
  min-width: 24px;
  height: 20px;
  padding: 0 7px;
  border-radius: var(--r-full);
  background: var(--surface-pressed);
  color: var(--ink);
  font-size: var(--t-2xs);
  font-weight: 700;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}
/* «Revisar», «Ver»: parece un botón pequeño y es parte del enlace. */
.px-inbox-act {
  display: inline-flex;
  align-items: center;
  height: 22px;
  padding: 0 8px;
  /* --line-strong (3,57:1 sobre --surface-overlay): es la pieza más
     pequeña de la capa y necesita el filo más claro; --border-control da
     3,15:1 desde que subió a #60739A. */
  border: 1px solid var(--line-strong);
  border-radius: 6px;
  background: var(--surface-raised);
  color: var(--ink-2);
  font-size: var(--t-2xs);
  font-weight: 600;
  line-height: 1;
  white-space: nowrap;
  transition: border-color var(--dur-1) var(--ease-out), color var(--dur-1) var(--ease-out);
}
.px-inbox-item:hover .px-inbox-act,
.px-inbox-item:focus-visible .px-inbox-act { border-color: var(--border-hover); color: var(--ink); }

/* Un mensaje: quién (y de qué empresa) con su tipo, y una línea de lo que
   dice. */
.px-inbox-from { display: flex; align-items: center; gap: 6px; min-width: 0; }
.px-inbox-from .px-inbox-title { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; overflow-wrap: normal; }
.px-inbox-co { flex: 0 1 auto; min-width: 0; overflow: hidden; color: var(--muted); font-size: .78125rem; text-overflow: ellipsis; white-space: nowrap; }
.px-inbox-co::before { content: "· "; content: "· " / ""; }
.px-inbox-kind {
  flex: none;
  display: inline-grid;
  place-items: center;
  height: 18px;
  padding: 0 6px;
  border: 1px solid var(--line-2);
  border-radius: var(--r-full);
  color: var(--muted);
  font-size: var(--t-2xs);
  font-weight: 600;
  line-height: 1;
  white-space: nowrap;
}
.px-inbox-snip { overflow: hidden; color: var(--muted); font-size: .78125rem; line-height: 1.45; text-overflow: ellipsis; white-space: nowrap; }

/* Vacío: una baldosa, una frase y para qué sirve el panel. */
.px-inbox-empty { display: grid; justify-items: center; gap: 4px; padding: 36px 24px 40px; text-align: center; }
.px-inbox-empty-ic { display: grid; place-items: center; width: 40px; height: 40px; margin-bottom: 8px; border-radius: 12px; background: var(--ok-soft); color: var(--ok); }
.px-inbox-empty-ic.is-neutral { background: var(--surface-pressed); color: var(--muted); }
.px-inbox-empty-ic svg { width: 20px; height: 20px; max-width: none; }
.px-inbox-empty b { color: var(--ink); font-size: var(--t-sm); font-weight: 600; }
.px-inbox-empty p { max-width: 32ch; margin: 0; color: var(--muted); font-size: .78125rem; line-height: 1.5; }
.px-inbox-empty.is-compact { grid-template-columns: auto minmax(0, 1fr); justify-items: start; align-items: center; column-gap: 12px; row-gap: 0; padding-block: 14px 6px; padding-inline: 22px 16px; text-align: start; }
.px-inbox-empty.is-compact .px-inbox-empty-ic { grid-row: span 2; width: 28px; height: 28px; margin: 0; border-radius: 8px; }
.px-inbox-empty.is-compact .px-inbox-empty-ic svg { width: 16px; height: 16px; }
.px-inbox-empty.is-compact p { max-width: none; }

.px-inbox-foot { flex: none; padding: 6px; border-top: 1px solid var(--line); }
.px-inbox-more {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  min-height: 36px;
  padding: 0 12px;
  border-radius: var(--r-ctl);
  color: var(--accent);
  font-size: var(--t-ui);
  font-weight: 600;
  text-decoration: none;
  transition: background-color var(--dur-1) var(--ease-out), color var(--dur-1) var(--ease-out);
}
.px-inbox-more:hover { background: var(--surface-hover); color: var(--accent-hover); }
.px-inbox-more:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.px-inbox-more svg { width: 14px; height: 14px; max-width: none; flex: none; }
:root[dir="rtl"] .px-inbox-more svg { scale: -1 1; }

/* En el móvil el panel es del ancho de la pantalla, bajo la cabecera (lo
   coloca «Capas flotantes»); aquí se deshacen los 400 px y se mantiene que
   solo corra la lista. Más específico a propósito: esta hoja va después.
   Con el dedo, sus botones suben a 44 en «Con el dedo», justo debajo. */
@media (max-width: 560px) {
  .px-top .px-pop.px-inbox-pop {
    width: auto;
    max-width: none;
    max-height: calc(100vh - var(--px-top-h) - 16px);
    max-height: calc(100dvh - var(--px-top-h) - 16px);
    overflow: hidden;
  }
}

/* ---------------------------------------------------------------------
   CON EL DEDO (armazón y centro de avisos)
   ---------------------------------------------------------------------
   44 px para todo lo que se pulsa, a CUALQUIER anchura: una tableta de
   1180 px se quedaba en 26–34 px cuando esto solo valía en ≤1000. Y 16 px
   en el filtro del menú, o el iPhone amplía la página al enfocarlo. Las
   pestañas van aquí porque las usa también el área de cliente (en la
   Consola ya las sube 9b).

   VA AL FINAL A PROPÓSITO: pesa lo mismo que las reglas base de lo que
   agranda, y delante del centro de avisos perdía contra ellas («Abrir la
   bandeja» y «Marcar como visto» volvían a 28 px, y «Ver los N mensajes»,
   a 36). El hueco de la estrella en la fila NO va aquí: ver «Con el dedo
   la estrella mide 44», junto a la barra plegada.
   --------------------------------------------------------------------- */
@media (pointer: coarse) {
  .px-nav a, .px-nav-section > summary, .px-side-link, .px-cmd-item,
  .px-menu-pop a:not(.btn), .px-menu-pop button:not(.btn),
  .px-tabs a, .px-tabs button { min-height: 44px; }
  .px-iconbtn, .px-menu > .px-me-btn, .px-search, .px-nav-pin { width: 44px; height: 44px; }
  .px-side .px-brand { min-width: 44px; min-height: 44px; }
  /* Las migas siguen cortándose con «…»: se crece por la altura de línea. */
  .px-crumbs a { line-height: 36px; }
  .px-nav-search { height: 44px; }
  .px-nav-search #px-nav-q { font-size: 16px; }
  .px-inbox-hbtn { height: 44px; padding-inline: 12px; }
  .px-inbox-more { min-height: 44px; }
  [data-surface="console"] .px-toast-x { width: 44px; height: 44px; margin-block: -8px; }
}
/* La barra plegada en una tableta táctil: 44 × 44 cada icono sin moverlo de
   su sitio. Con 6 px de margen a cada lado en vez de 8, los 44 caben en los
   60 de la barra, y el centro de cada icono se queda donde estaba. El
   flotante de un grupo crece solo de alto: su ancho es el de sus nombres. */
@media (pointer: coarse) and (min-width: 1001px) {
  :root.px-rail-off .px-side { padding-inline: 6px; }
  :root.px-rail-off .px-nav a,
  :root.px-rail-off .px-nav-section > summary,
  :root.px-rail-off .px-nav-tile,
  :root.px-rail-off .px-side-link,
  :root.px-rail-off .px-nav-search .px-nav-find { width: 44px; height: 44px; min-height: 44px; }
  :root.px-rail-off .px-nav .px-nav-flyout a { min-height: 44px; }
}

/* ---------------------------------------------------------------------
   EL ARMAZÓN CON CONTRASTE FORZADO (27/09/2026)
   ---------------------------------------------------------------------
   Con los colores del sistema, lo que se distinguía solo por su fondo —la
   hoja, las capas flotantes, la entrada activa, el interruptor, el punto
   de un contador, lo nuevo del centro de avisos— deja de distinguirse:
   necesita filo propio. Y los focos van con `outline`, que sí se pinta en
   este modo (un `box-shadow`, no).

   LO ACTUAL NO SE DIBUJA COMO EL FOCO. La pantalla en la que estás y la
   opción activa de la paleta llevaban el mismo contorno de 2 px que el
   foco, y con el foco en el panel de Avisos se veían dos cosas
   «enfocadas» a la vez. Llevan una barra de 3 px a su principio; el
   contorno queda solo para el foco.

   Sin movimiento no hace falta nada: la regla global de pulsar.css deja en
   nada las transiciones y entradas del armazón, y no tiene nada infinito. */
@media (forced-colors: active) {
  .px-main, .px-top, .px-pop, .px-menu-pop, .px-cmd, .px-keys, .px-toast { border: 1px solid CanvasText; }
  .px-nav-search:focus-within { outline: 2px solid Highlight; outline-offset: 1px; }
  .px-nav-tile, .px-env, .px-nav-caption-n, .px-nav .px-n, .px-me-role, .px-switch,
  .px-inbox-n, .px-inbox-count, .px-inbox-num, .px-inbox-act, .px-inbox-kind { border: 1px solid CanvasText; }
  .px-nav-flyout > .px-nav-entries { border: 1px solid CanvasText; background: Canvas; }
  .px-nav-hit { outline: 1px solid Highlight; }
  .px-cmd-item.is-on { position: relative; }
  .px-nav a[aria-current="page"]::before,
  .px-cmd-item.is-on::before {
    content: "";
    position: absolute;
    inset-block: 6px;
    inset-inline-start: 0;
    width: 3px;
    border-radius: 2px;
    background: Highlight;
    forced-color-adjust: none;
  }
  [aria-checked="true"] > .px-switch { background: Highlight; }
  [aria-checked="true"] > .px-switch::after { background: HighlightText; }
  /* Lo nuevo solo se distinguía por el color: aquí, con el del sistema. */
  .px-inbox-n.is-new,
  .px-inbox-item.is-new .px-inbox-dot { forced-color-adjust: none; background: Highlight; color: HighlightText; }
  .px-toast-bar { background: CanvasText; }
  /* EL ENTORNO TIENE QUE SEGUIR VIÉNDOSE. En ≤400 px la chapa de la
     cabecera queda en su punto, y en este modo el sistema pinta el punto
     del color del fondo y no pinta la línea ámbar (es una sombra): la
     cabecera de producción no decía nada. El punto toma un color del
     sistema y, en producción, la raya de abajo engorda. */
  .px-top .px-env-dot { forced-color-adjust: none; background: CanvasText; }
  .px-top .px-env.is-live .px-env-dot { background: Mark; }
  .px-top.is-live { border-bottom-width: 3px; }
}
