/* =====================================================================
   satsm · PÚLSAR — sistema de diseño de la plataforma
   ---------------------------------------------------------------------
   Superficies:
     [data-surface="web"]      web comercial, registro, asistente  (claro, azul)
     [data-surface="console"]  administración de la plataforma     (oscuro, cian)
   El ERP de cada empresa conserva su tema oscuro propio.
   ===================================================================== */

/* ---- Tipografía ---------------------------------------------------- */
@font-face { font-family: 'satsm-fallback'; src: local('Segoe UI'), local('Helvetica Neue'), local('Arial'); }

:root {
  --font-display: 'Schibsted Grotesk', 'Segoe UI', system-ui, sans-serif;
  --font-sans: 'Albert Sans', 'Segoe UI', system-ui, sans-serif;
  --font-mono: 'DM Mono', ui-monospace, 'Cascadia Mono', Consolas, monospace;
  --font-cjk: 'Noto Sans SC', var(--font-sans);

  /* Escala tipográfica */
  --t-xs: .75rem;  --t-sm: .875rem; --t-base: 1rem; --t-lg: 1.125rem;
  --t-xl: 1.375rem; --t-2xl: 1.75rem; --t-3xl: 2.25rem; --t-4xl: 3rem; --t-5xl: 3.75rem;

  /* Espaciado */
  --s-1: .25rem; --s-2: .5rem; --s-3: .75rem; --s-4: 1rem; --s-5: 1.5rem;
  --s-6: 2rem; --s-7: 2.5rem; --s-8: 3rem; --s-9: 4rem; --s-10: 5.5rem;

  /* Radios */
  --r-sm: 8px; --r-md: 12px; --r-lg: 16px; --r-xl: 20px; --r-full: 999px;

  /* Semánticos (claro) */
  --ok: #0E7A43; --ok-soft: #E7F7EE;
  --warn: #B45309; --warn-soft: #FFF7ED;
  --danger: #D92D20; --danger-soft: #FEF3F2;
  --info: #1570EF; --info-soft: #EFF6FF;

  --sh-sm: 0 1px 2px rgba(11,21,38,.05), 0 1px 3px rgba(11,21,38,.06);
  --sh-md: 0 4px 12px -2px rgba(11,21,38,.08), 0 2px 6px -2px rgba(11,21,38,.05);
  --sh-lg: 0 24px 60px -24px rgba(11,21,38,.22), 0 4px 12px rgba(11,21,38,.06);
  --ring: 0 0 0 3px rgba(46,91,255,.45);

  /* EL ANCHO DE LA PÁGINA — A PANTALLA COMPLETA, PERO CON MEDIDA.
     Estaba clavado en 1160 px. En un monitor de 1920 eso deja 380 px de
     campo vacío a cada lado: la web se veía como una tira estrecha en
     medio de la pantalla, y encima la maqueta del TPV —que es lo que hay
     que MIRAR— salía en miniatura.
     Ahora crece con la pantalla: nunca por debajo de los 1160 de antes,
     93 % de lo que haya, y tope en 1640 porque una fila de texto de dos
     metros no se lee, se barre con la cabeza. Las columnas de lectura
     (`.wrap-sm`, `.section-head`, el titular) conservan su medida: lo
     que se ensancha es la PÁGINA, no el renglón. */
  --wrap: clamp(1160px, 93vw, 1640px);
  /* El aire lateral también crece: con 24 px fijos, a 1640 px de ancho el
     contenido quedaba pegado al borde de la pantalla. */
  --wrap-pad: clamp(1rem, 2.2vw, 2.5rem);
}

/* ---- A · Superficie WEB (claro) ------------------------------------ */
:root, [data-surface="web"] {
  --bg: #F7F9FC; --surface: #FFFFFF; --surface-2: #FBFCFE; --surface-3: #F1F5FB;
  --ink: #0B1526; --ink-2: #31415C; --muted: #5A6B85; --line: #E3E9F2; --line-2: #D5DEEC;
  /* Contorno de los CONTROLES (campos, botones, casillas). Separado de --line
     a propósito: --line vale para una raya decorativa, pero con 1,16:1 sobre
     el fondo un botón secundario no tenía borde visible y un campo no tenía
     contorno. WCAG pide 3:1 para lo que se maneja; este da 3,48:1 sobre
     tarjeta y 3,30:1 sobre el fondo (tools/check-contraste.php). */
  --line-strong: #7E8AA1;
  --accent: #2E5BFF; --accent-dark: #1E3FCC; --accent-soft: #EBF0FF; --on-accent: #FFFFFF;
}

/* ---- C · Superficie CONSOLA (oscuro, cian) ------------------------- */
[data-surface="console"] {
  --bg: #0B1526; --surface: #101C33; --surface-2: #0E1830; --surface-3: #16233C;
  --ink: #E7ECF4; --ink-2: #C3CCDC; --muted: #8C9AB5; --line: #22304E; --line-2: #2C3C60;
  /* Mismo papel que en la superficie clara: el contorno de lo que se maneja
     tiene que verse. Sobre el fondo oscuro hay que ACLARAR, no oscurecer. */
  --line-strong: #6B7C9E;
  --accent: #22D3EE; --accent-dark: #0EA5C4; --accent-soft: #0E2A38; --on-accent: #062229;
  --ok: #4ADE80; --ok-soft: #10291C;
  --warn: #F0B34E; --warn-soft: #2A2210;
  --danger: #F26D6D; --danger-soft: #2B1414;
  /* En oscuro el rojo es CLARO, así que su texto tiene que ser oscuro. Con
     `color:#fff` clavado, el botón de borrar de la consola se quedaba en
     2,92:1 y se leía mal justo en la acción que más conviene leer bien. */
  --on-danger: #2B1414;
  --info: #6C8CFF; --info-soft: #141F3D;
  --sh-sm: 0 1px 2px rgba(0,0,0,.3);
  --sh-md: 0 6px 16px -4px rgba(0,0,0,.4);
  --sh-lg: 0 24px 60px -24px rgba(0,0,0,.6);
  --ring: 0 0 0 3px rgba(34,211,238,.3);

  /* ---- LA CONSOLA RENOVADA (27/09/2026) -------------------------------
     Tokens que usa el armazón y los componentes rediseñados. Solo se
     AÑADEN: los de arriba siguen valiendo para lo que ya los usa.

     Superficies EN ORDEN DE ELEVACIÓN. Antes --surface-2 era más oscura que
     --surface (el nombre decía lo contrario) y un menú desplegable se pintaba
     del mismo color que el panel de debajo: la capa solo se separaba por una
     raya de 1,56:1. Ahora cada capa aclara un paso sobre la anterior.
       canvas  #070E1B  lo que queda detrás de la hoja: barra lateral
       bg      #0B1526  la hoja donde vive la pantalla (6,81:1 muted/canvas)
       surface #101C33  paneles
       raised  #15233F  barras de herramientas, botón secundario, cabecera de tabla
       overlay #172741  menús, campana, mensajes, diálogos, avisos (ink 12,62:1;
                        muted 5,28:1)
     Contornos: --border-control 3,57:1 sobre panel, 3,84:1 sobre la hoja y
     3,15:1 sobre una capa flotante, el caso más justo (WCAG 1.4.11 pide 3:1
     para lo que se maneja). Con el #5B6D92 de antes, un campo o un botón
     secundario dentro de un diálogo o de una barra de guardar se quedaba en
     2,88:1, y ahí el borde es lo único que dibuja el control. --line queda
     para rayas decorativas. */
  --canvas: #070E1B;
  --surface-sunken: #0C172B;
  --surface-raised: #15233F;
  --surface-overlay: #172741;
  --surface-hover: rgba(148, 163, 184, .07);
  --surface-selected: rgba(34, 211, 238, .10);
  --border-control: #60739A;
  --border-hover: #7486AA;
  --placeholder: #7D8DAA;
  /* El primario ACLARA al pasar el ratón: en oscuro, oscurecer un botón
     brillante parece que se apaga (11,42:1 con su texto). */
  --accent-hover: #67E8F9;
  --accent-active: #0EA5C4;
  --accent-border: rgba(34, 211, 238, .42);
  --danger-hover: #F58A8A;
  --danger-border: rgba(242, 109, 109, .45);
  --warn-border: rgba(240, 179, 78, .45);
  --ok-border: rgba(74, 222, 128, .40);
  /* Foco en DOS anillos: uno del color de la hoja que separa y otro del
     acento (10,11:1). El anillo único al 30 % daba 2,01:1 y no se veía. */
  --focus-ring: 0 0 0 2px var(--bg), 0 0 0 4px var(--accent);
  --scrim: rgba(3, 8, 16, .62);
  --scrim-blur: 4px;

  /* Una sola escala de alturas para botón, campo, select y filtro. Antes
     convivían 36, 40, 41, 44, 45, 48, 49 y 52 px, y en cada barra de
     filtros el campo sobresalía 13 px del botón de al lado. */
  --ctl-xs: 28px;
  --ctl-sm: 32px;
  --ctl-md: 38px;
  --ctl-lg: 44px;
  --r-ctl: 8px;
  --r-pop: 12px;
  /* Radio de PANEL (tarjeta, caja de tabla, bandeja). Las hojas de cada
     pantalla escribían 12, 14, 16, 18 y 20 px a mano para lo mismo; con un
     nombre, el panel de Facturación y el de Planes dejan de discrepar. */
  --r-panel: 14px;

  /* Letra de interfaz: ningún rótulo baja de 11 px (había de 9 y 10). */
  --t-2xs: .6875rem;
  --t-ui: .8125rem;

  /* Elevación para oscuro: sombra + filo claro. Sustituye a la mezcla de
     --sh-* y --px-e* en lo que se rediseña. */
  --e1: inset 0 1px 0 rgba(255, 255, 255, .03), 0 1px 2px rgba(0, 0, 0, .35);
  --e2: 0 0 0 1px rgba(255, 255, 255, .04), 0 10px 28px -8px rgba(0, 0, 0, .6);
  --e3: 0 0 0 1px rgba(255, 255, 255, .05), 0 24px 64px -12px rgba(0, 0, 0, .72);

  /* Movimiento: color rápido, menús un poco más, cajón y diálogo lo que más. */
  --dur-1: 120ms;
  --dur-2: 180ms;
  --dur-3: 260ms;
  --ease-out: cubic-bezier(.22, .61, .36, 1);
  --ease-spring: cubic-bezier(.34, 1.56, .64, 1);

  /* Capas: una escala, no quince números sueltos. */
  --z-sticky: 20;
  --z-topbar: 40;
  --z-pop: 60;
  --z-flyout: 70;
  --z-scrim: 80;
  --z-drawer: 90;
  --z-toast: 140;
  --z-tooltip: 150;

  /* El armazón: alto de la barra superior y aire alrededor de la hoja. */
  --px-top-h: 56px;
  --px-sheet-gap: 8px;

  /* Los PASOS de lo que se pulsa (parcela de componentes). Un botón
     secundario vive en --surface-raised: al pasar el ratón aclara un paso
     (11,53:1 con su texto) y al pulsarlo se hunde un paso, sin moverse. En
     oscuro, oscurecer al pasar parece que el botón se apaga. El pulsado de
     lo transparente (fantasma, pestaña, chip) es una veladura, no un color:
     vale sobre panel, sobre barra y sobre la hoja. */
  --surface-raised-hover: #1D2D4D;
  --surface-raised-active: #111D36;
  --surface-pressed: rgba(148, 163, 184, .12);
  --danger-active: #E25D5D;       /* su texto encima: 4,91:1 */
  --info-border: rgba(108, 140, 255, .45);
}

/* ---- Reset --------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}
body {
  margin: 0; background: var(--bg); color: var(--ink);
  font-family: var(--font-sans); font-size: var(--t-base); line-height: 1.65;
  -webkit-font-smoothing: antialiased;
}
html[lang="zh-Hans"] body { font-family: var(--font-cjk); }
img, svg, video { max-width: 100%; height: auto; }
a { color: var(--accent); text-decoration: none; }
a:hover { color: var(--accent-dark); }
h1, h2, h3, h4 { font-family: var(--font-display); font-weight: 700; line-height: 1.12; letter-spacing: -.02em; margin: 0; text-wrap: balance; }
p { margin: 0; }
ul, ol { margin: 0; padding: 0; }
button { font: inherit; color: inherit; }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* EL RADIO DEL FOCO NO PISA EL DE NADIE. Estaba en la misma regla, y un
   `:focus-visible` (0,1,0) le gana a `select` o a `textarea` (0,0,1): al
   tabular, un desplegable de esquina redondeada pasaba a 4 px de golpe.
   Dentro de `:where()` no suma nada, así que solo redondea lo que no trae
   radio propio (un enlace suelto) y todo lo demás conserva el suyo. */
:where(:focus-visible) { border-radius: 4px; }

/* Saltar al contenido: primer elemento tabulable de cada página */
.skip { position: absolute; left: -9999px; top: 0; z-index: 200; background: var(--accent); color: var(--on-accent); padding: 12px 20px; border-radius: 0 0 var(--r-md) 0; font-weight: 600; }
.skip:focus { left: 0; color: var(--on-accent); }

/* ---- Utilidades ---------------------------------------------------- */
.wrap { max-width: var(--wrap); margin-inline: auto; padding-inline: var(--wrap-pad); }
/* La columna de LECTURA no se ensancha: 760 px son unos 90 caracteres, que es
   donde el ojo deja de perder el renglón. Las páginas legales y la ayuda
   siguen aquí aunque la web entera haya crecido. */
.wrap-sm { max-width: 760px; margin-inline: auto; padding-inline: var(--wrap-pad); }
.stack > * + * { margin-top: var(--s-4); }
.row { display: flex; gap: var(--s-3); align-items: center; flex-wrap: wrap; }
.row-between { display: flex; gap: var(--s-4); align-items: center; justify-content: space-between; flex-wrap: wrap; }
.grid { display: grid; gap: var(--s-4); }
.g2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.g3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.g4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.muted { color: var(--muted); }
.small { font-size: var(--t-sm); }
.xs { font-size: var(--t-xs); }
.mono { font-family: var(--font-mono); }
.center { text-align: center; }
.nowrap { white-space: nowrap; }
.tnum { font-variant-numeric: tabular-nums; }
.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0; }
.hidden { display: none !important; }

/* El atributo `hidden` del HTML gana a cualquier `display` de una clase.
   Sin esta línea, poner `hidden` a algo que además es .field, .row o .known
   no lo esconde: el `display:block` de la clase pisa el `display:none` que
   trae el navegador por defecto, y el elemento sigue ahí. Pasó con el chip de
   «te conozco de este navegador», que salía vacío en cada visita nueva. */
[hidden] { display: none !important; }

/* ---- Botones ------------------------------------------------------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--s-2);
  font-weight: 600; font-size: var(--t-sm); line-height: 1;
  padding: 12px 22px; border-radius: var(--r-md);
  border: 1px solid var(--line-strong); background: var(--surface); color: var(--ink);
  cursor: pointer; transition: transform .14s ease, box-shadow .14s ease, background .14s ease, border-color .14s ease;
  box-shadow: var(--sh-sm); text-align: center;
}
.btn:hover { color: var(--ink); border-color: var(--line-2); transform: translateY(-1px); box-shadow: var(--sh-md); }
.btn:active { transform: translateY(0); }
.btn[disabled], .btn.is-loading { opacity: .82; pointer-events: none; cursor: not-allowed; }
.btn-primary { background: var(--accent); border-color: var(--accent); color: var(--on-accent); box-shadow: 0 8px 20px -8px rgba(46,91,255,.55); }
.btn-primary:hover { background: var(--accent-dark); border-color: var(--accent-dark); color: var(--on-accent); }
.btn-ghost { background: transparent; border-color: transparent; box-shadow: none; }
.btn-ghost:hover { background: var(--surface-3); box-shadow: none; }
.btn-danger { background: var(--danger); border-color: var(--danger); color: var(--on-danger, #fff); }
.btn-danger:hover { background: var(--danger); color: #fff; filter: brightness(.92); }
.btn-lg { padding: 15px 30px; font-size: var(--t-base); }
.btn-sm { padding: 8px 14px; font-size: var(--t-xs); border-radius: var(--r-sm); min-height: 36px; }
.btn-block { width: 100%; }

/* ---- Formularios --------------------------------------------------- */
.field { display: block; margin-bottom: var(--s-4); }
/* `.field-head > label` también: es la misma etiqueta con algo al lado (la
   cuenta atrás del código). Sin esto, en el acceso «Correo» salía en negrita
   pequeña y «Contraseña», justo debajo, en letra normal y más grande. */
.field > label, .field-head > label, .label { display: block; font-weight: 600; font-size: var(--t-sm); margin-bottom: 6px; color: var(--ink); }
.field .hint { display: block; font-size: var(--t-xs); color: var(--muted); margin-top: 6px; }
.input, input[type="text"], input[type="email"], input[type="password"], input[type="tel"],
input[type="url"], input[type="number"], input[type="search"], input[type="date"], input[type="month"], select, textarea {
  width: 100%; font: inherit; font-size: var(--t-sm);
  padding: 12px 14px; border: 1px solid var(--line-strong); border-radius: var(--r-md);
  background: var(--surface); color: var(--ink);
  transition: border-color .14s ease, box-shadow .14s ease;
}
.input:focus, input:focus, select:focus, textarea:focus { outline: none; border-color: var(--accent); box-shadow: var(--ring); }
input::placeholder, textarea::placeholder { color: #8395B0; opacity: 1; }
textarea { min-height: 130px; resize: vertical; line-height: 1.6; }
select { appearance: none; padding-right: 38px;
  background-image: linear-gradient(45deg, transparent 50%, currentColor 50%), linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-position: calc(100% - 18px) calc(50% + 1px), calc(100% - 13px) calc(50% + 1px);
  background-size: 5px 5px, 5px 5px; background-repeat: no-repeat; }
.field.has-error .input, .field.has-error input, .field.has-error select { border-color: var(--danger); }
.field .error { display: block; font-size: var(--t-xs); color: var(--danger); margin-top: 6px; font-weight: 600; }

/* Campo con sufijo fijo (el subdominio) */
.input-group { display: flex; align-items: stretch; border: 1px solid var(--line-2); border-radius: var(--r-md); background: var(--surface); overflow: hidden; }
.input-group:focus-within { border-color: var(--accent); box-shadow: var(--ring); }
.input-group input { border: 0; box-shadow: none !important; flex: 1; min-width: 0; border-radius: 0; }
.input-group input:focus { box-shadow: none; }
.input-group .suffix { display: flex; align-items: center; padding: 0 14px; font-family: var(--font-mono); font-size: var(--t-sm); color: var(--muted); background: var(--surface-3); border-left: 1px solid var(--line); white-space: nowrap; }

.check { display: flex; gap: var(--s-3); align-items: flex-start; cursor: pointer; }
.check input[type="checkbox"], .check input[type="radio"] { width: 18px; height: 18px; margin-top: 3px; accent-color: var(--accent); flex: none; cursor: pointer; }
.check span { font-size: var(--t-sm); }
/* Una casilla DENTRO de un campo (las condiciones del alta): `.field > label`
   pesa más que `.check` y la convertía en bloque y en negrita, con el texto
   metiéndose por debajo de la casilla. */
.field > label.check { display: flex; font-weight: 400; margin-bottom: 0; }

/* ---- Tarjetas ------------------------------------------------------ */
.card { background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-lg); padding: var(--s-5); box-shadow: var(--sh-sm); }
.card-flat { box-shadow: none; }
.card-pad-lg { padding: var(--s-6); }
.card h3 { font-size: var(--t-lg); margin-bottom: var(--s-2); }

/* ---- Avisos -------------------------------------------------------- */
.alert { display: flex; gap: var(--s-3); align-items: flex-start; padding: 14px 18px; border-radius: var(--r-md); border: 1px solid; font-size: var(--t-sm); }
.alert-ok     { background: var(--ok-soft);     border-color: var(--ok);     color: var(--ink); }
.alert-error  { background: var(--danger-soft); border-color: var(--danger); color: var(--ink); }
.alert-warn   { background: var(--warn-soft);   border-color: var(--warn);   color: var(--ink); }
.alert-info   { background: var(--info-soft);   border-color: var(--info);   color: var(--ink); }
.alert strong { font-weight: 700; }

/* ---- Etiquetas ----------------------------------------------------- */
.pill { display: inline-flex; align-items: center; gap: 6px; font-size: var(--t-xs); font-weight: 600;
  padding: 5px 12px; border-radius: var(--r-full); background: var(--accent-soft); color: var(--accent-dark); border: 1px solid transparent; }
.pill-ok     { background: var(--ok-soft);     color: var(--ok); }
.pill-warn   { background: var(--warn-soft);   color: var(--warn); }
.pill-danger { background: var(--danger-soft); color: var(--danger); }
.pill-muted  { background: var(--surface-3);   color: var(--muted); }
.pill-draft  { background: var(--warn-soft); color: var(--warn); border: 1px dashed var(--warn); font-family: var(--font-mono); letter-spacing: .06em; text-transform: uppercase; font-size: 10px; }

.dot { width: 8px; height: 8px; border-radius: 50%; flex: none; background: var(--muted); }
.dot-ok { background: var(--ok); } .dot-warn { background: var(--warn); } .dot-danger { background: var(--danger); }

/* ---- Tablas -------------------------------------------------------- */
.table-wrap { overflow-x: auto; border: 1px solid var(--line); border-radius: var(--r-lg); background: var(--surface); }
table.data { width: 100%; border-collapse: collapse; font-size: var(--t-sm); }
table.data th, table.data td { padding: 12px 16px; text-align: left; border-top: 1px solid var(--line); vertical-align: middle; }
table.data thead th { background: var(--surface-3); border-top: 0; font-size: var(--t-xs); text-transform: uppercase; letter-spacing: .06em; color: var(--muted); font-weight: 700; white-space: nowrap; }
table.data tbody tr:hover { background: var(--surface-2); }
table.data td.num, table.data th.num { text-align: right; font-variant-numeric: tabular-nums; }

/* ---- Estado vacío --------------------------------------------------- */
.empty { text-align: center; padding: var(--s-8) var(--s-5); color: var(--muted); }
.empty .icon { width: 52px; height: 52px; margin: 0 auto var(--s-4); border-radius: var(--r-lg); background: var(--surface-3); display: grid; place-items: center; color: var(--muted); }
.empty h3 { font-size: var(--t-lg); color: var(--ink); margin-bottom: var(--s-2); }

/* Los seis pasos del flujo (portada y Producto).
   Estaban escritos como `style="grid-template-columns:repeat(6,...)"` en la
   propia vista, y un estilo en línea no lo puede desactivar ninguna consulta
   de medios: en un móvil de 390 px cada tarjeta quedaba en 42 px y el texto
   se salía y se solapaba con el de al lado. Con `auto-fit` y un mínimo, la
   rejilla decide sola cuántas columnas caben: seis en el escritorio, tres en
   una tableta, dos en un móvil. */
.flow-6 { grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }
@media (max-width: 420px) { .flow-6 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

/* ---- Cabecera de la web -------------------------------------------- */
.site-head { position: sticky; top: 0; z-index: 60; background: color-mix(in srgb, var(--surface) 92%, transparent); -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px); border-bottom: 1px solid var(--line); }
/* `min-height` y no `height`: con una altura fija y sin permitir que nada
   ceda, en un móvil de 390 px la fila se pasaba del ancho de la pantalla —
   TODA página desplazaba 2 px en horizontal— y los botones se partían en dos
   líneas cortadas por el borde. */
.site-nav { display: flex; align-items: center; gap: var(--s-3); min-height: 68px; }
.brand { display: inline-flex; align-items: center; gap: 10px; font-family: var(--font-display); font-weight: 800; font-size: var(--t-xl); letter-spacing: -.03em; color: var(--ink); margin-right: var(--s-4); flex: none; }
.brand:hover { color: var(--ink); }
/* El logo del producto, subido desde la Consola. Sustituye al símbolo y al
   nombre: un logo ya lleva el nombre dentro. */
.brand-img { height: 30px; width: auto; max-width: 190px; object-fit: contain; display: block; }
.site-foot .brand-img { height: 26px; }
.brand .mark { width: 30px; height: 30px; border-radius: 9px; background: linear-gradient(135deg, var(--accent), color-mix(in srgb, var(--accent) 60%, #8FA8FF)); display: grid; place-items: center; flex: none; }
.site-nav .links { display: flex; gap: 2px; list-style: none; margin-right: auto; }
.site-nav .links a { display: block; font-size: var(--t-sm); font-weight: 500; color: var(--muted); padding: 9px 14px; border-radius: var(--r-md); }
.site-nav .links a:hover { color: var(--ink); background: var(--surface-3); }
.site-nav .links a[aria-current="page"] { color: var(--accent); background: var(--accent-soft); font-weight: 600; }
.site-nav .actions { display: flex; gap: var(--s-2); align-items: center; flex: none; margin-left: auto; }
/* `flex: none` y medidas explícitas en el icono. Sin lo primero, el botón se
   comprimía a 26 px dentro de la fila; sin lo segundo, el reset
   `svg { max-width:100%; height:auto }` dejaba el icono en 0×0 y el botón de
   menú quedaba como una pastilla VACÍA. Como por debajo de 900 px los enlaces
   se ocultan, en el móvil no había forma de llegar a ninguna sección. */
.nav-toggle { display: none; background: none; border: 1px solid var(--line); border-radius: var(--r-md); padding: 9px 12px; cursor: pointer; flex: none; align-items: center; justify-content: center; min-width: 44px; min-height: 44px; color: var(--ink); }
.nav-toggle svg { width: 18px; height: 18px; max-width: none; flex: none; }
.nav-toggle:hover { border-color: var(--line-2); background: var(--surface-3); }
/* El enlace que SOLO existe dentro del menú desplegable. En una pantalla
   ancha sería un duplicado del botón de la esquina. */
.nav-only-menu { display: none; }

/* Selector de idioma */
.lang { position: relative; }
.lang summary { list-style: none; cursor: pointer; font-family: var(--font-mono); font-size: var(--t-xs); color: var(--muted); border: 1px solid var(--line); border-radius: var(--r-md); padding: 8px 12px; -webkit-user-select: none; user-select: none; display: inline-flex; align-items: center; min-height: 38px; }
.lang summary::-webkit-details-marker { display: none; }
.lang summary:hover { color: var(--ink); border-color: var(--line-2); }
.lang[open] summary { border-color: var(--accent); color: var(--accent); }
.lang menu { position: absolute; right: 0; top: calc(100% + 6px); background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-md); box-shadow: var(--sh-lg); padding: 6px; margin: 0; min-width: 168px; list-style: none; z-index: 70; }
.lang menu a { display: flex; align-items: center; gap: 10px; min-height: 44px; padding: 8px 12px; border-radius: var(--r-sm); font-size: var(--t-sm); color: var(--ink); }
.lang summary { gap: 8px; }
.lang menu a > span { flex: 1; }
.lang .flag { display: block; flex: none; border-radius: 3px; outline: 1px solid var(--line-2); outline-offset: -1px; }
@media (max-width: 480px) { .site-head .lang summary > span { display: none; } .site-head .lang summary { padding-inline: 9px; gap: 6px; } }
.lang menu a:hover { background: var(--surface-3); }
.lang menu a[aria-current="true"] { color: var(--accent); font-weight: 600; }

/* Menú de cuenta compartido por la portada y el área de cliente. */
.site-account { position: relative; flex: none; }
.site-account summary { display: flex; align-items: center; justify-content: center; gap: 6px; min-width: 44px; min-height: 44px; list-style: none; cursor: pointer; color: var(--muted); border-radius: var(--r-full); }
.site-account summary::-webkit-details-marker { display: none; }
.site-avatar { display: grid; place-items: center; width: 36px; height: 36px; border-radius: 50%; background: var(--accent-soft); color: var(--accent); font-size: 16px; font-weight: 700; }
.site-account summary:hover, .site-account[open] summary { background: var(--surface-3); color: var(--accent); }
.site-account-menu { position: absolute; inset-inline-end: 0; top: calc(100% + 8px); width: min(260px, calc(100vw - 32px)); padding: 8px; border: 1px solid var(--line); border-radius: var(--r-md); background: var(--surface); box-shadow: var(--sh-lg); z-index: 70; }
.site-account-name { display: block; padding: 12px; color: var(--muted); font-size: var(--t-sm); font-weight: 600; overflow-wrap: anywhere; border-bottom: 1px solid var(--line); margin-bottom: 4px; }
.site-account-menu a, .site-account-menu button { display: flex; align-items: center; gap: 10px; min-height: 44px; width: 100%; border: 0; padding: 10px 12px; border-radius: var(--r-sm); background: transparent; color: var(--ink); font: inherit; font-size: var(--t-sm); text-align: start; cursor: pointer; }
.site-account-menu :is(a, button):hover { background: var(--surface-3); color: var(--accent); }
.site-account-menu a[aria-current="page"] { background: var(--accent-soft); color: var(--accent); }
.site-account-menu form { margin-top: 4px; padding-top: 4px; border-top: 1px solid var(--line); }
.site-head :is(a, button, summary):focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
.site-head :is(a, button, summary) { touch-action: manipulation; }
.site-head .lang summary { min-height: 44px; }
.site-nav .links.open { max-height: calc(100dvh - 68px); overflow-y: auto; overscroll-behavior: contain; }
@media (max-width: 700px) {
  .site-account summary > svg { display: none; }
}

/* ---- Pie ------------------------------------------------------------ */
.site-foot { border-top: 1px solid var(--line); background: var(--surface); padding-block: var(--s-8) var(--s-5); margin-top: var(--s-9); }
.foot-grid { display: grid; grid-template-columns: 1.5fr repeat(4, minmax(0, 1fr)); gap: var(--s-6); }
.foot-grid h4 { font-size: var(--t-xs); font-weight: 700; text-transform: uppercase; letter-spacing: .08em; color: var(--muted); margin-bottom: var(--s-3); }
.foot-grid ul { list-style: none; display: grid; gap: 2px; }
/* El área que se puede pulsar mide 44 px, aunque el texto siga midiendo lo
   mismo: con 20 px de alto y 9 de separación, en un móvil se acierta el
   enlace de al lado. Se agranda el área, no la letra. */
.foot-grid ul a { font-size: var(--t-sm); color: var(--muted); display: flex; align-items: center; min-height: 44px; }
.foot-grid ul a:hover { color: var(--accent); }
.foot-base { display: flex; justify-content: space-between; gap: var(--s-4); margin-top: var(--s-7); padding-top: var(--s-5); border-top: 1px solid var(--line); font-size: var(--t-xs); color: var(--muted); flex-wrap: wrap; }
.foot-langs { display: flex; flex-wrap: wrap; gap: 4px var(--s-4); }
.foot-langs a { display: inline-flex; align-items: center; gap: 6px; color: inherit; }
.foot-langs a[aria-current] { color: var(--ink); font-weight: 600; }
.foot-langs .flag { display: block; flex: none; border-radius: 2px; outline: 1px solid rgba(0, 0, 0, .12); outline-offset: -1px; }

/* ---- Secciones ------------------------------------------------------ */
.section { padding-block: var(--s-9); }
.section-sm { padding-block: var(--s-7); }
.section-head { max-width: 640px; margin-bottom: var(--s-7); }
.section-head.center { margin-inline: auto; text-align: center; }
/* h1 y h2 con el mismo tamaño aquí: el título de estas páginas era un h2 —
   ninguna tenía encabezado principal, así que un lector de pantalla no
   encontraba nada al pedir «encabezado 1» y los buscadores tampoco. Al pasarlo
   a h1 no debía cambiar nada de lo que se ve. */
.section-head h1, .section-head h2 { font-size: var(--t-3xl); }
.section-head p { color: var(--muted); margin-top: var(--s-3); font-size: var(--t-lg); }
.eyebrow { display: inline-flex; align-items: center; gap: 8px; font-family: var(--font-mono); font-size: var(--t-xs);
  letter-spacing: .08em; text-transform: uppercase; color: var(--accent); background: var(--accent-soft);
  border: 1px solid color-mix(in srgb, var(--accent) 22%, transparent); border-radius: var(--r-full); padding: 6px 14px; margin-bottom: var(--s-4); }

/* ---- Página de entrada (hero) --------------------------------------- */
/* EL RESPLANDOR VA A SANGRE, EL TEXTO NO.
   El degradado estaba dentro de `.hero`, que es un `.wrap`: se cortaba en
   seco en el borde de la columna y dibujaba dos costuras verticales que
   delataban lo estrecha que era la página. Ahora lo pinta la BANDA, que es
   un bloque normal y por tanto ocupa el ancho del cuerpo —sin `100vw`, que
   cuenta la barra de desplazamiento y saca la página 15 px de lado. */
.hero-band { position: relative; overflow: hidden; isolation: isolate; }
.hero-band::before { content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background:
    radial-gradient(1100px 460px at 50% -120px, color-mix(in srgb, var(--accent) 13%, transparent), transparent 70%),
    radial-gradient(680px 320px at 12% 12%, color-mix(in srgb, var(--accent) 7%, transparent), transparent 70%); }
/* La rejilla técnica, muy tenue: da profundidad al campo que antes estaba
   vacío a los lados sin competir con nada de lo que hay que leer. */
.hero-band::after { content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none; opacity: .5;
  background-image:
    linear-gradient(to right, color-mix(in srgb, var(--line) 55%, transparent) 1px, transparent 1px),
    linear-gradient(to bottom, color-mix(in srgb, var(--line) 55%, transparent) 1px, transparent 1px);
  background-size: 56px 56px;
  -webkit-mask-image: radial-gradient(720px 380px at 50% 30%, #000, transparent 75%);
  mask-image: radial-gradient(720px 380px at 50% 30%, #000, transparent 75%); }
.hero { text-align: center; padding-block: var(--s-10) var(--s-7); position: relative; }
.hero > * { position: relative; }
.hero h1 { font-size: clamp(2.2rem, 5.2vw, 3.75rem); max-width: 17ch; margin-inline: auto; }
.hero h1 .hl { color: var(--accent); }
.hero .lead { font-size: var(--t-lg); color: var(--muted); max-width: 44rem; margin: var(--s-5) auto 0; }
.hero .cta { display: flex; gap: var(--s-3); justify-content: center; margin-top: var(--s-6); flex-wrap: wrap; }
.hero .facts { display: flex; gap: var(--s-5); justify-content: center; margin-top: var(--s-5); flex-wrap: wrap; font-size: var(--t-sm); color: var(--muted); }
.hero .facts span { display: inline-flex; align-items: center; gap: 7px; }
.hero .facts svg { color: var(--ok); flex: none; }

/* ---- Maqueta del producto ------------------------------------------- */
.shot { margin-top: var(--s-7); background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-xl); box-shadow: var(--sh-lg); overflow: hidden; text-align: left; }
.shot-bar { display: flex; align-items: center; gap: 10px; border-bottom: 1px solid var(--line); padding: 12px 18px; font-family: var(--font-mono); font-size: var(--t-xs); color: var(--muted); }
.shot-bar .dots { display: flex; gap: 6px; }
.shot-bar .dots i { width: 9px; height: 9px; border-radius: 50%; background: var(--line-2); display: block; }
.shot-bar .url { background: var(--surface-3); border: 1px solid var(--line); border-radius: var(--r-sm); padding: 4px 14px; }
/* «● En línea» en una sola línea: partido en dos, en un móvil parecía un
   fallo de la maqueta que la maqueta está para enseñar. */
.shot-bar .live { margin-left: auto; color: var(--ok); white-space: nowrap; }
/* Las tres columnas del TPV, en PROPORCIÓN.
   Con `200px 1fr 300px` fijos, al ensanchar la página todo el espacio nuevo
   se lo comía el centro: el menú y el ticket quedaban como dos tiras finas
   y la maqueta se veía deformada, no más grande. Y el alto mínimo fijo la
   dejaba en una franja apaisada de 340 px dentro de un marco de 1640. */
.shot-body { display: grid; grid-template-columns: clamp(170px, 13%, 250px) minmax(0, 1fr) clamp(260px, 21%, 370px); min-height: clamp(340px, 24vw, 440px); }
.shot-side { border-right: 1px solid var(--line); padding: 14px 10px; display: flex; flex-direction: column; gap: 2px; background: var(--surface-2); }
.shot-side span { font-size: var(--t-sm); font-weight: 500; color: var(--muted); padding: 9px 12px; border-radius: var(--r-sm); display: flex; gap: 9px; align-items: center; }
.shot-side span.on { background: var(--accent-soft); color: var(--accent); font-weight: 600; }
.shot-main { padding: 16px; }
.shot-search { border: 1px solid var(--line); border-radius: var(--r-md); padding: 9px 14px; font-size: var(--t-sm); color: var(--muted); background: var(--surface); margin-bottom: 14px; display: flex; justify-content: space-between; }
kbd { font-family: var(--font-mono); font-size: 11px; border: 1px solid var(--line-2); border-bottom-width: 2px; border-radius: 5px; padding: 2px 7px; background: var(--surface-3); color: var(--ink-2); }
.prods { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 10px; }
.prod { border: 1px solid var(--line); border-radius: var(--r-md); padding: 12px; font-size: var(--t-xs); background: var(--surface); }
.prod .sw { height: 32px; border-radius: var(--r-sm); background: var(--surface-3); margin-bottom: 8px; }
.prod b { display: block; font-family: var(--font-mono); font-size: var(--t-xs); color: var(--accent); margin-top: 4px; }
.prod.sat { border-color: color-mix(in srgb, var(--accent) 35%, var(--line)); background: var(--surface-2); }
.prod.sat small { font-family: var(--font-mono); font-size: 10px; color: var(--accent); }
/* La fila de más que rellena la maqueta cuando hay sitio. En un portátil
   sobra —alargaría el hero antes de que se lea el titular— y desaparece. */
@media (max-width: 1180px) { .prod-xl { display: none; } }
.shot-cart { border-left: 1px solid var(--line); padding: 16px; display: flex; flex-direction: column; background: var(--surface-2); }
.shot-cart .line { display: flex; justify-content: space-between; font-size: var(--t-sm); padding: 9px 0; border-bottom: 1px solid var(--line); }
.shot-cart .line span:last-child { font-variant-numeric: tabular-nums; font-weight: 600; }
.shot-cart .total { margin-top: auto; padding-top: 14px; }
.shot-cart .total .lbl { font-family: var(--font-mono); font-size: var(--t-xs); color: var(--muted); text-transform: uppercase; letter-spacing: .08em; }
.shot-cart .total .amt { font-family: var(--font-display); font-size: var(--t-2xl); font-weight: 800; letter-spacing: -.03em; font-variant-numeric: tabular-nums; }
.shot-cart .pay { margin-top: 10px; background: var(--accent); color: var(--on-accent); border-radius: var(--r-md); text-align: center; padding: 12px; font-weight: 700; font-size: var(--t-sm); box-shadow: 0 8px 18px -8px rgba(46,91,255,.6); }

/* ---- Rejilla de funciones ------------------------------------------- */
.feats { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--s-4); }
.feat { background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-lg); padding: var(--s-5); box-shadow: var(--sh-sm); transition: transform .15s ease, box-shadow .15s ease; display: block; color: var(--ink); }
.feat:hover { transform: translateY(-3px); box-shadow: var(--sh-lg); color: var(--ink); border-color: var(--line-2); }
.feat .ic { width: 40px; height: 40px; border-radius: 11px; background: var(--accent-soft); color: var(--accent); display: grid; place-items: center; margin-bottom: var(--s-4); }
.feat h3 { font-size: var(--t-lg); margin-bottom: var(--s-2); }
.feat p { font-size: var(--t-sm); color: var(--muted); }
.feat .more { display: inline-flex; align-items: center; gap: 6px; font-size: var(--t-sm); font-weight: 600; color: var(--accent); margin-top: var(--s-3); }

/* ---- Banda oscura (Veri*factu) --------------------------------------- */
.band { background: #0B1526; border-radius: var(--r-xl); color: #fff; padding: var(--s-8); display: grid; grid-template-columns: 1.1fr .9fr; gap: var(--s-7); align-items: center; position: relative; overflow: hidden; }
.band::after { content: ""; position: absolute; right: -120px; top: -120px; width: 380px; height: 380px; border-radius: 50%; background: radial-gradient(circle, rgba(46,91,255,.35), transparent 70%); }
.band > * { position: relative; z-index: 1; }
.band h2 { color: #fff; font-size: var(--t-2xl); }
.band p { color: #9DAAC4; margin-top: var(--s-3); }
.band .dates { display: flex; gap: var(--s-3); margin-top: var(--s-5); flex-wrap: wrap; }
.band .date { border: 1px solid #2A3A5C; border-radius: var(--r-md); padding: 14px 18px; background: rgba(255,255,255,.03); }
.band .date b { font-family: var(--font-display); font-size: var(--t-lg); display: block; color: #8FA8FF; }
.band .date span { font-family: var(--font-mono); font-size: 11px; color: #9DAAC4; letter-spacing: .06em; }
.band .term { background: #101C33; border: 1px solid #22304E; border-radius: var(--r-lg); padding: var(--s-5); font-family: var(--font-mono); font-size: var(--t-sm); line-height: 2; color: #C3CCDC; }
.band .term .ok { color: #4ADE80; }

/* ---- Pasos numerados ------------------------------------------------ */
.steps { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--s-4); counter-reset: step; }
.step { background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-lg); padding: var(--s-6) var(--s-5) var(--s-5); position: relative; }
.step::before { counter-increment: step; content: counter(step); position: absolute; top: -16px; left: var(--s-5);
  width: 32px; height: 32px; border-radius: 50%; background: var(--accent); color: var(--on-accent);
  font-family: var(--font-display); font-weight: 700; display: grid; place-items: center; font-size: var(--t-sm);
  box-shadow: 0 6px 14px -6px rgba(46,91,255,.6); }
.step h3 { font-size: var(--t-base); margin-bottom: var(--s-2); }
.step p { font-size: var(--t-sm); color: var(--muted); }

/* ---- Bloques nuevos de la portada ------------------------------------ */
/* Rejillas que deciden solas cuántas columnas caben. Se usa `auto-fit` y no
   un número: estas secciones no tienen SIEMPRE el mismo número de tarjetas
   —las soluciones y las integraciones salen del catálogo— y una rejilla de
   tres fija deja un hueco feo en cuanto hay cuatro cosas. */
.feats-4 { grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); }

/* Lo que trae de serie: una tira de datos, no tarjetas. Es lo primero que
   se lee después del titular y tiene que leerse de un vistazo. */
.serie { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: var(--s-5);
  border: 1px solid var(--line); border-radius: var(--r-lg); background: var(--surface);
  padding: var(--s-5) var(--s-6); box-shadow: var(--sh-sm); }
.serie > div { min-width: 0; }
.serie b { display: block; font-family: var(--font-display); font-size: var(--t-lg); letter-spacing: -.02em; }
.serie span { display: block; font-size: var(--t-sm); color: var(--muted); margin-top: 2px; }

/* Seguridad: texto corrido en columnas, con una marca de comprobado. */
.sec-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: var(--s-5); }
.sec-item { display: flex; gap: var(--s-3); align-items: flex-start; }
.sec-item .tick { flex: none; width: 26px; height: 26px; border-radius: 8px; background: var(--ok-soft); color: var(--ok); display: grid; place-items: center; margin-top: 2px; }
.sec-item h3 { font-size: var(--t-base); margin-bottom: 4px; }
.sec-item p { font-size: var(--t-sm); color: var(--muted); }

/* Asomo de precios: el plan en una línea, sin repetir la tabla de /precios. */
.peek { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: var(--s-4); }
.peek-plan { border: 1px solid var(--line); border-radius: var(--r-lg); background: var(--surface); padding: var(--s-5); box-shadow: var(--sh-sm); position: relative; }
.peek-plan.on { border-color: var(--accent); box-shadow: var(--sh-md); }
.peek-plan h3 { font-size: var(--t-lg); }
.peek-plan .who { font-size: var(--t-sm); color: var(--muted); margin-top: 2px; min-height: 2.6em; }
.peek-plan .amt { font-family: var(--font-display); font-size: var(--t-2xl); font-weight: 800; letter-spacing: -.03em; margin-top: var(--s-4); }
.peek-plan .amt small { font-family: var(--font-sans); font-size: var(--t-sm); font-weight: 500; color: var(--muted); letter-spacing: 0; }
.peek-plan .amt.tbd { font-size: var(--t-lg); color: var(--muted); font-weight: 600; }
.peek-plan .lim { font-size: var(--t-sm); color: var(--muted); margin-top: var(--s-3); display: grid; gap: 3px; }

/* Integraciones: nombre y ESTADO, que es el dato que importa. Cada una
   enlaza a su página, donde se explica qué le falta para estar operativa. */
/* 340 px de mínimo, y no 230: el estado más largo —«Pendiente de
   credenciales»— partía en dos líneas y dejaba cada fila a una altura
   distinta, que es justo lo que hace que una rejilla parezca rota. */
/* El `min(340px, 100%)` no es adorno: una pista mínima de 340 px es MAYOR
   que la pantalla de un móvil pequeño, y una rejilla cuya pista no cabe
   empuja la página de lado. Con el `min()`, el mínimo nunca supera el
   ancho disponible. */
.integr { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(340px, 100%), 1fr)); gap: var(--s-3); }
.integr a { display: flex; align-items: center; justify-content: space-between; gap: var(--s-3);
  border: 1px solid var(--line); border-radius: var(--r-md); background: var(--surface);
  padding: 12px 16px; color: var(--ink); font-size: var(--t-sm); font-weight: 600; min-height: 56px; }
.integr a:hover { border-color: var(--line-2); background: var(--surface-2); color: var(--ink); }
.integr a .pill { font-weight: 600; white-space: nowrap; flex: none; }

/* Preguntas desplegables. Antes iban con estilos escritos dentro de la
   vista y el signo `+` no cambiaba al abrir: parecía que no había pasado
   nada. Aquí gira 45° y se convierte en una `×`. */
.qa { border: 1px solid var(--line); border-radius: var(--r-md); background: var(--surface); padding: var(--s-4) var(--s-5); }
.qa + .qa { margin-top: var(--s-3); }
.qa summary { cursor: pointer; font-weight: 600; list-style: none; display: flex; justify-content: space-between; align-items: center; gap: var(--s-4); }
.qa summary::-webkit-details-marker { display: none; }
.qa summary::after { content: "+"; color: var(--accent); font-size: var(--t-xl); line-height: 1; flex: none; transition: transform .18s ease; }
.qa[open] summary::after { transform: rotate(45deg); }
.qa p { font-size: var(--t-sm); color: var(--muted); margin-top: var(--s-3); }

/* ---- Planes --------------------------------------------------------- */
.plans { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--s-4); align-items: start; }
.plan { background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-xl); padding: var(--s-6); box-shadow: var(--sh-sm); position: relative; }
.plan.featured { border-color: var(--accent); box-shadow: var(--sh-lg); }
.plan .top-tag { position: absolute; top: -13px; left: 50%; transform: translateX(-50%); background: var(--accent); color: var(--on-accent); font-size: var(--t-xs); font-weight: 700; letter-spacing: .05em; text-transform: uppercase; border-radius: var(--r-full); padding: 5px 16px; white-space: nowrap; }
.plan h3 { font-size: var(--t-xl); }
.plan .who { font-size: var(--t-sm); color: var(--muted); margin-top: 4px; }
.plan .price { font-family: var(--font-display); font-size: var(--t-4xl); font-weight: 800; margin-top: var(--s-4); letter-spacing: -.03em; }
.plan .price small { font-size: var(--t-sm); color: var(--muted); font-weight: 500; font-family: var(--font-sans); letter-spacing: 0; }
.plan ul { list-style: none; margin-top: var(--s-5); display: grid; gap: 11px; font-size: var(--t-sm); }
.plan ul li { display: flex; gap: 10px; align-items: flex-start; }
.plan ul li .ck { color: var(--ok); font-weight: 700; flex: none; }
.plan ul li.off { color: var(--muted); }
.plan ul li.off .ck { color: var(--line-2); }
.plan .btn { width: 100%; margin-top: var(--s-5); }

/* ---- Página de acceso / registro ------------------------------------ */
/* A PANTALLA COMPLETA, PERO CON EL CONTENIDO SUJETO.
   Las dos columnas van a sangre, de borde a borde. Lo que no puede ir a
   sangre es el CONTENIDO: sin un ancho máximo, en un monitor de 3800 px el
   panel oscuro estiraba su texto hasta partirlo y el formulario se quedaba
   flotando en medio de un campo blanco. Cada columna llena la pantalla; lo
   que se lee dentro tiene su medida y se centra. */
.auth {
  display: grid; grid-template-columns: 46% 54%;
  min-height: 100vh; min-height: 100dvh;
  background: var(--surface);
}
.auth-aside {
  background: #0B1526; color: #fff; padding: var(--s-8);
  display: flex; flex-direction: column; justify-content: center;
  align-items: center;
  position: relative; overflow: hidden;
}
/* La medida del panel. `align-items: center` de arriba centra esta columna
   interior en la mitad oscura, ocupe la pantalla lo que ocupe. */
.auth-aside > * { width: 100%; max-width: 34rem; }
.auth-aside::after {
  content: ""; position: absolute; left: -140px; bottom: -180px;
  width: 520px; height: 520px; border-radius: 50%;
  background: radial-gradient(circle, rgba(46,91,255,.34), transparent 70%);
}
/* Una rejilla de 64 px, casi invisible, para que el panel tenga textura y no
   sea un rectángulo plano. Va en ::before para no gastar un div. */
.auth-aside::before {
  content: ""; position: absolute; inset: 0;
  background-image:
    linear-gradient(rgba(255,255,255,.035) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255,255,255,.035) 1px, transparent 1px);
  background-size: 64px 64px;
}
.auth-aside > * { position: relative; z-index: 1; }
/* La marca, en blanco. `.brand` nace con `color: var(--ink)`, que sobre el
   panel oscuro es tinta sobre tinta: el logotipo se veía y el nombre no
   estaba. Aquí, y no en línea en cada vista, que es donde se olvida. */
.auth-aside .brand { color: #fff; }
.auth-aside .brand:hover { color: #fff; }
.auth-aside h2 { color: #fff; font-size: var(--t-3xl); max-width: 13ch; }
.auth-aside p { color: #9DAAC4; margin-top: var(--s-4); max-width: 34ch; }
.auth-aside ol { list-style: none; margin-top: var(--s-6); display: grid; gap: var(--s-4); }
.auth-aside ol li { display: flex; gap: var(--s-3); align-items: flex-start; font-size: var(--t-sm); color: #DDE2EC; }
.auth-aside ol li b { font-family: var(--font-mono); color: #8FA8FF; font-size: var(--t-xs); padding-top: 3px; flex: none; }

/* La columna clara. En columna y no solo centrada: en el móvil, «¿aún no
   tienes cuenta?» baja de la esquina al final, y para eso tiene que estar
   en el flujo. */
.auth-main {
  position: relative; display: flex; flex-direction: column;
  align-items: center; justify-content: center; padding: var(--s-8) var(--s-6);
  background: var(--surface);
}
.auth-form { width: 100%; max-width: 408px; }
.auth-form h1 { font-size: var(--t-3xl); margin-bottom: var(--s-2); }
.auth-form > p.sub { color: var(--muted); margin-bottom: var(--s-6); font-size: var(--t-sm); }
.auth-form .foot { margin-top: var(--s-5); font-size: var(--t-sm); color: var(--muted); text-align: center; }

/* «¿Aún no tienes cuenta?» en la esquina de arriba, no debajo del botón de
   entrar: son dos caminos distintos, y pegado al botón se lee como el
   siguiente paso de este formulario. */
.auth-top {
  position: absolute; top: var(--s-6); inset-inline-end: var(--s-6); margin: 0;
  display: flex; align-items: center; gap: var(--s-3);
  font-size: var(--t-sm); color: var(--muted);
}
.auth-copy {
  position: absolute; bottom: var(--s-6); inset-inline-end: var(--s-6); margin: 0;
  font-family: var(--font-mono); font-size: var(--t-xs); color: #8395B0;
}
/* Lo que de verdad tranquiliza en una pantalla de contraseña, dicho sin
   adornos y sin prometer nada que no sea cierto. */
.auth-trust {
  display: flex; gap: 10px; align-items: center;
  margin-top: var(--s-6); padding: 14px 16px;
  border: 1px solid var(--line); border-radius: var(--r-md); background: var(--surface-2);
  font-size: var(--t-xs); color: var(--muted); line-height: 1.5;
}
.auth-trust svg { flex: none; }

/* --- El lateral del ACCESO -------------------------------------------
   El del registro cuenta los tres pasos del alta (ol). Este cuenta a
   dónde se entra, y reserva el pie para lo que hace falta cuando NO se
   entra: ayuda e idioma. Por eso space-between en vez del center de
   arriba: aquí hay tres bloques, no uno. */
.auth-aside:has(.auth-aside-mid) { justify-content: space-between; gap: var(--s-6); }
.auth-aside-mid, .auth-aside-foot { position: relative; z-index: 1; }

.auth-areas { list-style: none; margin-top: var(--s-6); display: grid; border-top: 1px solid rgba(255,255,255,.10); }
.auth-areas li { display: flex; gap: var(--s-4); align-items: center; padding: var(--s-5) 0; border-bottom: 1px solid rgba(255,255,255,.10); }
.auth-areas .ico {
  flex: none; width: 40px; height: 40px; border-radius: var(--r-md);
  display: grid; place-items: center;
  background: rgba(46,91,255,.16); color: #A8BEFF;
  border: 1px solid rgba(143,168,255,.22);
}
.auth-areas li > span:last-child { display: grid; gap: 3px; }
.auth-areas b { color: #fff; font-size: var(--t-sm); font-weight: 700; }
.auth-areas i { color: #9DAAC4; font-size: var(--t-xs); font-style: normal; line-height: 1.55; }

/* --- La novedad del panel --------------------------------------------
   El hueco de escaparate del acceso. NO es un texto escrito aquí: es la
   última novedad publicada en la Consola, en el idioma de quien mira. Si no
   hay ninguna reciente, este bloque no existe y el panel enseña las tres
   áreas: el hueco nunca se queda con una noticia rancia.
   Toda la tarjeta es UN enlace, para que el objetivo sea la tarjeta entera. */
.auth-promo {
  display: block; margin-top: var(--s-6); overflow: hidden;
  border: 1px solid rgba(255,255,255,.11); border-radius: var(--r-xl);
  background: rgba(255,255,255,.045); color: inherit;
  transition: border-color .14s ease, background .14s ease;
}
.auth-promo:hover { color: inherit; border-color: rgba(143,168,255,.38); background: rgba(255,255,255,.065); }
.auth-promo:focus-visible { outline: 2px solid #8FA8FF; outline-offset: 3px; }
.auth-promo-art {
  display: block; position: relative; height: 112px; overflow: hidden;
  background: linear-gradient(140deg, #16244A, #0E1B33);
  border-bottom: 1px solid rgba(255,255,255,.09);
}
.auth-promo-art::after {
  content: ""; position: absolute; right: -60px; top: -70px;
  width: 220px; height: 220px; border-radius: 50%;
  background: radial-gradient(circle, rgba(46,91,255,.45), transparent 70%);
}
.auth-promo-art svg { position: absolute; inset: 0; width: 100%; height: 100%; opacity: .6; }
.auth-promo-body { padding: var(--s-5) var(--s-5) var(--s-4); display: grid; gap: 10px; }
.auth-promo .tag {
  display: inline-flex; align-items: center; gap: 8px;
  font-family: var(--font-mono); font-size: var(--t-xs);
  letter-spacing: .14em; text-transform: uppercase; color: #8FA8FF;
}
.auth-promo .tag::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: #6E86FF; }
.auth-promo h3 { font-family: var(--font-display); font-size: var(--t-lg); font-weight: 700; color: #fff; margin: 0; letter-spacing: -.02em; line-height: 1.25; }
.auth-promo p { margin: 0; font-size: var(--t-sm); line-height: 1.6; color: #9DAAC4; max-width: none; }
.auth-promo .go { display: inline-flex; align-items: center; gap: 7px; margin-top: 2px; font-size: var(--t-sm); font-weight: 600; color: #A8BEFF; }
.auth-promo:hover .go { color: #fff; }

/* El max-width de .auth-aside p es para el texto de arriba; aquí partía
   «Cómo recuperar el acceso» en dos líneas con el subrayado a medias. */
.auth-aside-foot p { margin: 0 0 var(--s-3); color: #8494AE; max-width: none; }
.auth-aside-foot a { color: #A8BEFF; text-decoration: underline; text-underline-offset: 2px; }
.auth-aside-foot a:hover { color: #fff; }
.auth-langs { display: flex; flex-wrap: wrap; gap: var(--s-4); font-size: var(--t-xs); }
.auth-langs a { color: #8494AE; text-decoration: none; }
.auth-langs a:hover { color: #fff; }
.auth-langs a[aria-current="true"] { color: #fff; font-weight: 700; }

/* Entre 900 y 1200 px las dos columnas siguen cabiendo, pero con el padding
   grande el panel oscuro aprieta el texto contra el borde. */
@media (max-width: 1200px) {
  .auth-aside { padding: var(--s-6); }
  .auth-main { padding: var(--s-7) var(--s-5); }
  .auth-top { top: var(--s-5); inset-inline-end: var(--s-5); }
}

/* PANTALLAS BAJAS, que las hay: un portátil de 1366×768 con la barra del
   navegador deja menos de 600 px útiles. El formulario va centrado, así que
   al acortar la altura sube hacia la esquina y se metía DEBAJO de «crear una
   gratis», que está posicionada. Por debajo de este alto, la esquina vuelve
   al flujo (detrás del formulario) y la firma se retira: es un adorno y no
   puede ganarle el sitio a lo que se usa. */
@media (max-height: 780px) {
  .auth-top { position: static; order: 2; margin-top: var(--s-5); justify-content: center; flex-wrap: wrap; }
  .auth-copy { display: none; }
}

/* --- «Te conozco de este navegador» ---------------------------------
   Nombre y correo guardados en ESTE equipo. Ninguna credencial: lo único
   que ahorra es teclear el correo.

   El saludo va a todo el ancho y, debajo, la cuenta con la que se va a
   entrar. El correo se PARTE si no cabe en vez de cortarse con puntos
   suspensivos: es lo que dice con qué cuenta se entra, y «info@mun…» no lo
   dice (26/09/2026). */
.known { margin-bottom: var(--s-5); }
.known-hi {
  margin: 0 0 var(--s-3);
  font-size: var(--t-lg); font-weight: 700; line-height: 1.3; letter-spacing: -.01em;
  color: var(--ink);
}
.known-id {
  display: flex; align-items: center; gap: var(--s-3);
  padding: 6px 6px 6px 10px;
  border: 1px solid var(--line); border-radius: var(--r-md); background: var(--surface-3);
}
.known-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;
}
.known-mail {
  flex: 1; min-width: 0;
  font-size: var(--t-sm); line-height: 1.35; color: var(--ink);
  overflow-wrap: anywhere;
}
/* Botón de texto, pero con el alto de un botón: 40 px de área de toque. */
.known-switch {
  flex: none; min-height: 40px; padding: 0 12px;
  border: 0; border-radius: var(--r-sm); background: none;
  font: inherit; font-size: var(--t-sm); font-weight: 600; color: var(--accent);
  cursor: pointer;
}
.known-switch:hover { background: var(--surface-2); text-decoration: underline; text-underline-offset: 3px; }
.known-switch:focus-visible { outline: none; box-shadow: var(--ring); }

/* La marca dentro del formulario: solo cuando el panel oscuro no está. */
.auth-brand-sm { display: none; margin-bottom: var(--s-6); color: var(--ink); }

/* ---- El acceso DENTRO del dominio de una tienda ---------------------
   Misma pantalla, otra marca: el nombre, el logo y el color del cliente. El
   color tiñe SOLO el acento; el fondo y el texto no se tocan, porque un color
   de marca cualquiera puesto detrás del texto lo deja ilegible y aquí no se
   puede permitir que la gente no vea lo que escribe.

   `--brand` lo pone la vista en línea, sacado de la cuenta. Si no hay marca
   —en satsm.test— nada de esto se aplica y la pantalla es la del producto. */
.auth-tienda { --accent: var(--brand, var(--accent)); }
.brand-tienda { cursor: default; }
/* `max-width` además de la altura: un logo apaisado de 2000 px de ancho
   empujaba el panel entero y sacaba el formulario de la pantalla. */
.px-brand .brand-logo { height: 40px; width: auto; max-width: 220px; object-fit: contain; display: block; }
/* Sin logo, las iniciales. Es lo honesto mientras la empresa no suba el suyo:
   dice de quién es esto en vez de enseñar el logotipo del fabricante. */
.mark-iniciales {
  width: 40px; height: 40px; border-radius: 11px;
  background: var(--brand, var(--accent)); color: #fff;
  display: grid; place-items: center; flex: none;
  font-family: var(--font-display); font-weight: 800; font-size: 15px;
  letter-spacing: -.02em;
}

/* Etiqueta con un enlace a la derecha (contraseña / olvidada) */
.field-head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--s-3); }
.field-head > label { margin-bottom: 6px; }

/* ---------------------------------------------------------------------------
   «¿Olvidaste la contraseña?»: DEBAJO del campo, a la derecha
   ---------------------------------------------------------------------------
   Aquí no hay nada que recolocar: el enlace está en el HTML donde se ve, y se
   ve donde se tabula. Estuvo arriba, en la línea de la etiqueta, y hubo que
   bajarlo por el TECLADO — el foco saltaba del ojo hacia ARRIBA hasta el
   enlace y volvía a bajar, un zigzag que desconcierta a quien mira dónde está
   el cursor. Con el enlace aquí, el recorrido siempre desciende.

   Objetivo táctil: el enlace es pequeño y se pulsa con el dedo, así que el
   área de toque se estira con padding, no con tamaño de letra.
--------------------------------------------------------------------------- */
.field-forgot {
  display: block;
  width: fit-content;
  margin: 8px 0 0 auto;        /* a la derecha, sin sacarlo del flujo */
  padding: 6px 2px;            /* área de toque, no tamaño de letra */
}
.field-head > a { color: var(--muted); text-decoration: none; }
.field-head > a:hover { color: var(--accent); text-decoration: underline; }

/* --- Campo de contraseña con ojo ------------------------------------- */
.input-reveal { position: relative; display: flex; }
.input-reveal input { padding-right: 46px; }
.input-reveal .reveal {
  position: absolute; inset-block: 0; inset-inline-end: 0; width: 44px;
  display: grid; place-items: center;
  background: none; border: 0; cursor: pointer; color: var(--muted);
  border-radius: 0 var(--r-md) var(--r-md) 0;
}
.input-reveal .reveal:hover { color: var(--ink); }
.input-reveal .reveal:focus-visible { outline: none; box-shadow: var(--ring); }
.input-reveal .reveal .eye-off { display: none; }
.input-reveal .reveal[aria-pressed="true"] .eye-on { display: none; }
.input-reveal .reveal[aria-pressed="true"] .eye-off { display: block; }

/* --- Avisos vivos de la contraseña ----------------------------------- */
.pw-hints { display: grid; gap: 6px; }
/* Solo con un aviso A LA VISTA. `:not(:empty)` no servía: los dos avisos
   están siempre en el HTML (ocultos), así que el hueco salía siempre. */
.pw-hints:has(> :not([hidden])) { margin-top: 8px; }
.hint-warn {
  display: flex; gap: 7px; align-items: flex-start; margin: 0;
  font-size: var(--t-xs); line-height: 1.5; color: var(--warn); font-weight: 600;
}
.hint-warn svg { flex: none; margin-top: 2px; }

/* Botón ocupado: el ancho no cambia al cambiar el texto, que si no la
   pantalla da un salto justo al pulsar. */
.btn[data-busy] { pointer-events: none; opacity: .72; }
.divider { display: flex; align-items: center; gap: var(--s-3); font-size: var(--t-xs); color: var(--muted); margin-block: var(--s-5); text-transform: uppercase; letter-spacing: .06em; }
.divider::before, .divider::after { content: ""; flex: 1; height: 1px; background: var(--line); }

/* Fuerza de la contraseña */
.pw-meter { display: flex; gap: 4px; margin-top: 8px; }
.pw-meter i { height: 4px; flex: 1; border-radius: 2px; background: var(--line-2); transition: background .2s; }
.pw-meter.s1 i:nth-child(1) { background: var(--danger); }
.pw-meter.s2 i:nth-child(-n+2) { background: var(--warn); }
.pw-meter.s3 i:nth-child(-n+3) { background: var(--info); }
.pw-meter.s4 i { background: var(--ok); }

/* Disponibilidad del subdominio */
.slug-status { display: flex; align-items: center; gap: 7px; font-size: var(--t-xs); margin-top: 7px; min-height: 18px; font-weight: 600; }
.slug-status.free { color: var(--ok); }
.slug-status.taken { color: var(--danger); }
.slug-status.checking { color: var(--muted); font-weight: 500; }

/* =====================================================================
   COOKIES · banner, interruptores, preferencias y política
   ---------------------------------------------------------------------
   Tres reglas mandan sobre la estética:

   1. Aceptar y rechazar son EL MISMO BOTÓN. No es una opinión de diseño: un
      «rechazar» más apagado que el «aceptar» invalida el consentimiento. Antes
      aceptar era azul sólido (5,18:1) y rechazar un borde de 1,22:1 sobre
      blanco — o sea, invisible.
   2. El banner no puede tapar el pie ni el contenido: reserva su sitio.
   3. Todo lo que se pulsa mide 44 px en pantalla táctil y tiene foco visible.
   ===================================================================== */

.ck {
  position: fixed; inset-inline: 0; bottom: 0; z-index: 120;
  /* La barra de gestos del móvil se come lo que haya pegado al borde de
     abajo, y aquí lo que hay pegado abajo son los dos botones de la decisión.
     `env()` vale 0 en los equipos que no tienen muesca, así que no estorba. */
  padding: var(--s-4);
  padding-bottom: calc(var(--s-4) + env(safe-area-inset-bottom, 0px));
  padding-inline: calc(var(--s-4) + env(safe-area-inset-left, 0px)) calc(var(--s-4) + env(safe-area-inset-right, 0px));
  /* El contenedor ocupa todo el ancho para centrar la tarjeta, pero no debe
     robar los clics de la página que hay detrás. */
  pointer-events: none;
}
.ck-card {
  pointer-events: auto;
  max-width: 980px; margin-inline: auto;
  /* OPACO, sin vidrio esmerilado y sin filo de color arriba.
     El vidrio quedaba bonito sobre una sección lisa y sucio sobre cualquier
     otra cosa: encima de la captura de pantalla del producto, de una tabla o
     de una imagen, el texto legal se leía sobre lo que hubiera detrás. Y un
     banner translúcido recortado se ve gris, porque deja pasar el fondo.
     Esta pieza tiene que leerse igual de bien esté donde esté: color sólido,
     un borde fino y la sombra haciendo la separación. */
  background: var(--surface);
  border: 1px solid var(--line-2);
  border-radius: var(--r-xl);
  box-shadow: 0 32px 64px -28px rgba(11, 21, 38, .35), 0 6px 16px -6px rgba(11, 21, 38, .12);
  padding: var(--s-5);
  display: flex; flex-direction: column; gap: var(--s-4);
  position: relative;
  /* Nunca más alto que la pantalla: lo que sobre lo absorbe la lista de
     categorías con su propio scroll, y los botones de decidir se quedan
     siempre a la vista. `dvh` y no `vh`: en el móvil la barra del navegador
     aparece y desaparece, y `vh` mide como si nunca estuviera. */
  max-height: calc(100dvh - 2 * var(--s-4));
  animation: ck-in .42s cubic-bezier(.2, .8, .25, 1) both;
}
/* La barra: texto a la izquierda, decisiones a la derecha. No se encoge. */
.ck-bar {
  flex: none;
  display: flex; gap: var(--s-5); align-items: center; justify-content: space-between;
  flex-wrap: wrap;
}
@keyframes ck-in { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .ck-card { animation: none; } }

/* El texto ocupa lo que sobra DESPUÉS de los botones, y solo baja de línea
   cuando ya no cabe. Con una base fija se empujaban entre ellos: o el texto se
   quedaba en una columna estrecha de tres líneas, o se estiraba tanto que
   mandaba los botones a una segunda fila él solo. */
.ck-head { display: flex; gap: var(--s-4); align-items: flex-start; min-width: 0; flex: 1 1 360px; }
.ck-ico {
  flex: none; width: 42px; height: 42px; border-radius: var(--r-md);
  display: grid; place-items: center;
  background: var(--accent-soft); color: var(--accent);
}
.ck-copy { min-width: 0; }
.ck-copy h2 { font-size: var(--t-lg); margin-bottom: 4px; }
.ck-copy p { font-size: var(--t-sm); color: var(--muted); text-wrap: pretty; }
/* «Leer la política» se partía por la mitad al final del párrafo y quedaba una
   «Leer» suelta colgando de una línea. Es el enlace que lleva a la página que
   explica todo esto: merece leerse de una pieza. */
.ck-copy a { font-weight: 600; text-decoration: underline; text-underline-offset: 3px; white-space: nowrap; }
.ck-again {
  margin-top: 8px !important; font-size: var(--t-xs) !important;
  color: var(--ink-2) !important; background: var(--info-soft);
  border-radius: var(--r-sm); padding: 6px 10px; display: inline-block;
}

.ck-acts { display: flex; gap: var(--s-2); align-items: center; flex-wrap: wrap; justify-content: flex-end; flex: 0 0 auto; }
/* `manipulation` quita el retardo de 300 ms que el navegador táctil se guarda
   por si viene un segundo toque. En un botón de «aceptar» ese cuarto de
   segundo se siente como que no ha pasado nada, y la gente vuelve a pulsar. */
.ck-acts .btn, .ck-acts .ck-more, .ck-save, .ckp-quick-acts .btn, .sw {
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}
/* Los botones van cada uno dentro de su <form> (llevan su ficha), así que el
   elemento que la fila coloca sería el formulario y no el botón: sin esto, el
   `flex: 1` del móvil estiraba «Elegir» y dejaba los otros dos en su ancho
   mínimo. */
.ck-acts form { display: contents; }
.ck-choice {
  min-width: 148px;
  border: 2px solid var(--accent); color: var(--accent); background: transparent;
  font-weight: 700; box-shadow: none;
}
.ck-choice:hover { background: var(--accent-soft); color: var(--accent-dark); border-color: var(--accent-dark); }
.ck-more {
  color: var(--muted); font-weight: 600; font-size: var(--t-sm);
  padding: 10px 12px; border-radius: var(--r-sm); cursor: pointer;
  border: 0; background: none; text-decoration: underline; text-underline-offset: 3px;
}
.ck-more:hover { color: var(--ink); background: var(--surface-3); }

/* El detalle cae debajo, ocupando las dos columnas.
   Y con scroll propio, porque si no se come la pantalla: en un móvil EN
   HORIZONTAL (390 px de alto) el banner desplegado medía 551 px y, como está
   anclado abajo, crecía hacia arriba hasta sacar de la pantalla «Aceptar
   todas» y «Rechazar todas». Desplegar las opciones te dejaba sin los dos
   botones que sirven para decidir. */
.ck-detail {
  border-top: 1px solid var(--line); padding-top: var(--s-4);
  min-height: 0; display: flex; flex-direction: column;
}
.ck-detail[hidden] { display: none; }
.ck-detail form { display: flex; flex-direction: column; min-height: 0; }

/* El scroll va en la LISTA, no en el bloque entero: así «Guardar mi elección»
   queda fuera del área que se desplaza y se ve siempre. Metido dentro, en una
   pantalla baja había que adivinar que existía y bajar a buscarlo. */
.ck-detail .ck-cats {
  overflow-y: auto; overscroll-behavior: contain; min-height: 0;
  padding-inline-end: 2px;                 /* que el foco no toque la barra */
}
.ck-save { margin-top: var(--s-4); flex: none; align-self: flex-start; }

/* El banner es fijo: el pie tiene que poder verse entero por debajo, y sus
   enlaces reciben el foco al tabular.
   El hueco es la ALTURA REAL del banner, que el JavaScript escribe en
   `--ck-alto` y vuelve a medir cada vez que cambia. Con un número fijo no
   puede salir bien: el banner mide 143 px cerrado en un portátil y 439 px con
   las opciones desplegadas, así que cualquier valor que se elija tapa el pie
   en un caso o deja un agujero en el otro. El 190 px del respaldo solo actúa
   mientras el JavaScript no haya medido (o si no lo hay). */
body:has(.ck) .site-foot { padding-bottom: calc(var(--ck-alto, 190px) + var(--s-5)); }

/* Confirmación corta: aparece abajo, se lee en un vistazo y se va sola a los
   tres segundos. No pide que la cierres. */
.ck-toast {
  position: fixed; z-index: 130; inset-inline: var(--s-4);
  bottom: calc(var(--s-5) + env(safe-area-inset-bottom, 0px));
  margin-inline: auto; max-width: 420px;
  background: var(--ink); color: var(--surface);
  padding: 12px var(--s-5); border-radius: var(--r-full);
  font-size: var(--t-sm); font-weight: 600; text-align: center;
  box-shadow: var(--sh-lg);
  animation: ck-in .28s cubic-bezier(.2, .8, .25, 1) both;
}
.ck-toast.is-out { opacity: 0; transform: translateY(10px); transition: opacity .3s ease, transform .3s ease; }

/* ---- Interruptores de categoría (banner y preferencias) -------------- */
.ck-cats { list-style: none; display: grid; gap: var(--s-3); }
.ck-cat { min-width: 0; }
.sw { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: var(--s-3); align-items: start; cursor: pointer; }
.sw input {
  /* Enfocable de verdad, pero sin dibujar: lo dibuja `.sw-track`. */
  position: absolute; opacity: 0; width: 1px; height: 1px; margin: 0;
}
.sw-track {
  flex: none; width: 44px; height: 26px; border-radius: var(--r-full);
  background: var(--surface-3); border: 1px solid var(--line-strong);
  position: relative; transition: background .18s ease, border-color .18s ease;
  margin-top: 2px;
}
.sw-dot {
  position: absolute; top: 3px; inset-inline-start: 3px;
  width: 18px; height: 18px; border-radius: 50%;
  background: var(--surface); box-shadow: var(--sh-sm);
  transition: transform .18s cubic-bezier(.2, .8, .25, 1);
}
.sw input:checked + .sw-track { background: var(--accent); border-color: var(--accent); }
.sw input:checked + .sw-track .sw-dot { transform: translateX(18px); }
[dir="rtl"] .sw input:checked + .sw-track .sw-dot { transform: translateX(-18px); }
.sw input:focus-visible + .sw-track { outline: 2px solid var(--accent); outline-offset: 2px; }
.sw input:disabled + .sw-track { opacity: .65; }
.sw:has(input:disabled) { cursor: default; }
.sw-name { font-weight: 700; display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.sw-hint { display: block; font-size: var(--t-sm); color: var(--muted); margin-top: 2px; }
.sw-none { color: var(--ink-2); font-style: italic; }

/* ---- Página de preferencias ----------------------------------------- */
.ckp-state {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-lg); padding: var(--s-4) var(--s-5);
  box-shadow: var(--sh-sm); margin-top: var(--s-5);
}
.ckp-state-main { display: flex; gap: var(--s-4); align-items: center; flex-wrap: wrap; justify-content: space-between; }
.ckp-state-label { font-weight: 700; font-size: var(--t-sm); }
.ckp-pills { display: flex; gap: var(--s-2); flex-wrap: wrap; }
.ckp-pills .pill { display: inline-flex; align-items: center; gap: 7px; }
.ckp-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--ok); flex: none; }
.ckp-dot.is-off { background: var(--line-strong); }
.ckp-state-meta { margin-top: var(--s-3); padding-top: var(--s-3); border-top: 1px solid var(--line); }

.ckp-form {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-lg); padding: var(--s-5);
  box-shadow: var(--sh-sm); margin-top: var(--s-4);
}
.ckp-cats { gap: 0; }
.ckp-cats .ck-cat + .ck-cat { border-top: 1px solid var(--line); margin-top: var(--s-4); padding-top: var(--s-4); }
.ckp-save { display: flex; gap: var(--s-4); align-items: center; flex-wrap: wrap; margin-top: var(--s-5); padding-top: var(--s-4); border-top: 1px solid var(--line); }
.ckp-save .xs { flex: 1 1 260px; }

.ckp-quick { display: flex; gap: var(--s-4); align-items: center; flex-wrap: wrap; justify-content: space-between; margin-top: var(--s-4); }
.ckp-quick-label { text-transform: uppercase; letter-spacing: .1em; font-weight: 700; }
.ckp-quick-acts { display: flex; gap: var(--s-2); flex-wrap: wrap; }
.ckp-quick-acts form { display: contents; }

.ckp-withdraw {
  display: flex; gap: var(--s-4); align-items: center; justify-content: space-between; flex-wrap: wrap;
  margin-top: var(--s-6); padding: var(--s-4) var(--s-5);
  border: 1px dashed var(--line-2); border-radius: var(--r-lg); background: var(--surface-2);
}
/* Retirar es una acción seria pero no un castigo: se ve, tiene su contorno y
   no grita. Antes era un `.btn-ghost`, o sea, sin fondo NI borde: parecía
   texto suelto y no se distinguía de la explicación de al lado. */
.ckp-withdraw-btn {
  border: 1px solid var(--line-strong); background: var(--surface);
  color: var(--ink-2); font-weight: 600; box-shadow: none; flex: none;
}
.ckp-withdraw-btn:hover { border-color: var(--danger); color: var(--danger); background: var(--danger-soft); }

.ckp-policy { margin-top: var(--s-6); }
.ckp-policy a { display: inline-flex; align-items: center; gap: 6px; font-weight: 600; }

/* ---- Página de la política ------------------------------------------ */
.ckl-version { margin-top: var(--s-3); }
.ckl-toc {
  margin-top: var(--s-6); padding: var(--s-4) var(--s-5);
  background: var(--surface-2); border: 1px solid var(--line); border-radius: var(--r-lg);
}
.ckl-toc-label { font-size: var(--t-xs); text-transform: uppercase; letter-spacing: .1em; font-weight: 700; color: var(--muted); }
.ckl-toc ol { margin-top: var(--s-3); padding-inline-start: var(--s-5); display: grid; gap: 6px; font-size: var(--t-sm); }
.ckl-toc ol li::marker { color: var(--muted); font-variant-numeric: tabular-nums; }

.ckl-sec { margin-top: var(--s-7); scroll-margin-top: 90px; }
.ckl-sec h2 { font-size: var(--t-xl); }
.ckl-sec h2 + p { margin-top: var(--s-3); }
.ckl-sub { font-size: var(--t-lg); margin-top: var(--s-6); }
.ckl-sub + p { margin-top: var(--s-2); }
.ckl-table { margin-top: var(--s-4); }
.ckl-name { white-space: nowrap; }
.ckl-cats { list-style: none; display: grid; gap: var(--s-3); margin-top: var(--s-4); }
.ckl-cats li { display: flex; gap: var(--s-3); align-items: baseline; flex-wrap: wrap; }
.ckl-cats .pill { flex: none; }
.ckl-browsers { list-style: none; display: flex; gap: var(--s-2); flex-wrap: wrap; margin-top: var(--s-4); }
.ckl-browsers a {
  display: inline-flex; align-items: center; min-height: 40px; padding: 0 var(--s-4);
  border: 1px solid var(--line-strong); border-radius: var(--r-full);
  font-size: var(--t-sm); font-weight: 600; color: var(--ink-2); background: var(--surface);
}
.ckl-browsers a:hover { border-color: var(--accent); color: var(--accent); background: var(--accent-soft); }
.ckl-cta {
  display: flex; gap: var(--s-4); align-items: center; justify-content: space-between; flex-wrap: wrap;
  margin-top: var(--s-5); padding: var(--s-5);
  background: var(--accent-soft); border-radius: var(--r-lg);
}

/* En el móvil la tabla se deshace en fichas.
   Cuatro columnas no caben en 390 px: quedaba una tabla que había que
   arrastrar de lado, y ésta es una página para leer, no para pelearse con
   ella. Cada fila pasa a ser una ficha y cada dato lleva encima el nombre de
   su columna (el `data-label` de la vista). */
@media (max-width: 720px) {
  .ckl-table { overflow-x: visible; }
  .ckl-table table, .ckl-table tbody, .ckl-table tr, .ckl-table td { display: block; width: auto; }
  .ckl-table thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
  .ckl-table tr {
    border: 1px solid var(--line); border-radius: var(--r-md);
    padding: var(--s-4); margin-bottom: var(--s-3); background: var(--surface);
  }
  .ckl-table td { border: 0; padding: 0; }
  .ckl-table td + td { margin-top: var(--s-3); }
  .ckl-table td::before {
    content: attr(data-label);
    display: block; font-size: var(--t-xs); font-weight: 700;
    text-transform: uppercase; letter-spacing: .08em; color: var(--muted);
    margin-bottom: 3px;
  }
  .ckl-name { white-space: normal; overflow-wrap: anywhere; }
}

/* AQUÍ ESTABAN LAS PIEZAS DE LA CONSOLA DE ANTES (28/09/2026): su armazón
   (.console, .console-side…), las cifras partidas, las barras de altas y
   bajas, el selector de tramo, el embudo, las casillas de migración, el
   medidor de uso y las tarjetas de cifra. La Consola las pinta hoy con las
   `px-` de panel.css y ninguna vista las usaba ya: eran casi cien líneas que
   se descargaban en cada página de la web y de la Consola para nada. */

/* ---- Asistente inicial ----------------------------------------------- */
.wizard { display: grid; grid-template-columns: 260px 1fr; gap: var(--s-7); align-items: start; }
.wizard-steps { list-style: none; display: grid; gap: 2px; position: sticky; top: 88px; }
.wizard-steps li a { display: flex; gap: 12px; align-items: center; padding: 11px 14px; border-radius: var(--r-md); font-size: var(--t-sm); color: var(--muted); }
.wizard-steps li a:hover { background: var(--surface-3); color: var(--ink); }
.wizard-steps li a .n { width: 24px; height: 24px; border-radius: 50%; border: 1.5px solid var(--line-2); display: grid; place-items: center; font-size: var(--t-xs); font-weight: 700; flex: none; }
.wizard-steps li.done a .n { background: var(--ok); border-color: var(--ok); color: #fff; }
.wizard-steps li.current a { background: var(--accent-soft); color: var(--accent); font-weight: 600; }
.wizard-steps li.current a .n { border-color: var(--accent); color: var(--accent); }
.progress { height: 6px; border-radius: 3px; background: var(--line); overflow: hidden; margin-bottom: var(--s-5); }
.progress i { display: block; height: 100%; background: var(--accent); border-radius: 3px; transition: width .3s ease; }

/* ---- Responsive ------------------------------------------------------ */
@media (max-width: 1040px) {
  .foot-grid { grid-template-columns: 1fr 1fr; }
}
@media (max-width: 900px) {
  .site-nav .links { display: none; }
  .site-nav .links.open { display: flex; position: absolute; inset-inline: 0; top: 68px; flex-direction: column; background: var(--surface); border-bottom: 1px solid var(--line); padding: var(--s-3); box-shadow: var(--sh-lg); }
  .nav-toggle { display: inline-flex; }
  .feats, .steps, .plans, .g3, .g4 { grid-template-columns: 1fr; }
  /* Las rejillas que se cuentan solas siguen contándose solas: en una
     tableta de 800 px caben dos soluciones por fila, y bajar a una sola
     columna alargaría la portada sin ganar nada. Va DESPUÉS de la línea de
     arriba a propósito, que si no se la lleva por delante. */
  .feats-4 { grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); }
  .band, .auth, .wizard { grid-template-columns: 1fr; }
  .auth-aside { display: none; }
  .auth-brand-sm { display: inline-flex; }
  .auth-main { padding-block: var(--s-7); }
  /* De la esquina al final de la columna, centrado y detrás del formulario. */
  .auth-top { position: static; order: 2; margin-top: var(--s-6); justify-content: center; flex-wrap: wrap; }
  .auth-copy { display: none; }
  .shot-body { grid-template-columns: 1fr; }
  .shot-side { flex-direction: row; overflow-x: auto; border-right: 0; border-bottom: 1px solid var(--line); }
  .shot-cart { border-left: 0; border-top: 1px solid var(--line); }
  .prods { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  /* En estrecho, las acciones ocupan una fila entera y SÍ se encogen: en
     ancho fijo (`flex: 0 0 auto`) no cabían y se salían por la derecha. */
  .ck-acts { justify-content: stretch; flex: 1 1 100%; min-width: 0; }
  .ck-choice { flex: 1 1 auto; min-width: 0; }
  .ck-more { flex: 1 1 100%; text-align: center; }
  /* 44 px por ANCHO de pantalla, no solo por puntero grueso.
     La regla general de tacto pide `pointer: coarse`, y hay pantallas
     estrechas que no lo declaran —un móvil con ratón bluetooth, un navegador
     emulando— donde estos tres botones se quedaban en 42 px. En cualquier
     otro sitio serían dos píxeles; aquí es el único control que la persona
     tiene sobre sus datos, y fallar el dedo significa aceptar sin querer. */
  .ck-choice, .ck-more, .ck-acts .btn { min-height: 44px; }
  .ckp-quick-acts .ck-choice { min-height: 44px; }
  .ckp-quick { flex-direction: column; align-items: stretch; }
  .ckp-quick-acts .ck-choice { flex: 1 1 auto; }
}
/* ---- La cabecera en un móvil ----------------------------------------
   TODA la web se desplazaba de lado, no solo la portada: a 390 px el
   documento medía 522 porque la fila de la cabecera —logo, botón de menú,
   idioma, «Entrar» y «Empezar gratis»— sumaba más que la pantalla. Se
   arregla donde se rompe: el logo se achica, los huecos se estrechan y
   «Entrar» se muda al menú desplegable (`.nav-only-menu` en el layout).
   Nada desaparece; cambia de sitio. */
@media (max-width: 700px) {
  .site-nav { gap: var(--s-2); }
  .brand { margin-right: var(--s-2); font-size: var(--t-lg); }
  .brand-img { height: 26px; max-width: 124px; }
  .site-nav .actions { gap: 6px; }
  .site-nav .links .nav-only-menu { display: block; }
  .nav-hide-sm { display: none; }
}
/* Y en los móviles pequeños de verdad —360 px sigue siendo muy común— hay
   que apretar otro poco: con el logo a 124 px y el botón a 22 px de aire
   por lado aún sobraban 22 px. Se recortan del LOGO y del relleno del
   botón, no de su altura: el objetivo táctil sigue midiendo 36 px. */
@media (max-width: 420px) {
  .brand-img { max-width: 104px; }
  .site-nav .actions .btn-sm { padding-inline: 11px; }
}

@media (max-width: 560px) {
  :root { --s-9: 3rem; --s-10: 3.5rem; }
  .g2 { grid-template-columns: 1fr; }
  .foot-grid { grid-template-columns: 1fr; }
  .hero .facts { gap: var(--s-3); }
}

/* ---- Impresión -------------------------------------------------------- */
@media print {
  .site-head, .site-foot, .ck, .btn { display: none !important; }
  body { background: #fff; color: #000; }
}


/* =====================================================================
   LA CONSOLA RENOVADA · CONTROLES (27/09/2026)
   ---------------------------------------------------------------------
   Botones, campos, chapas, avisos en línea y tablas de la superficie
   oscura, hechos con las fichas del bloque «LA CONSOLA RENOVADA» de
   arriba.

   TODO VA DETRÁS DE `:where([data-surface="console"])`, y el `:where` es
   la decisión. Acota a la Consola SIN sumar especificidad: `.btn` sigue
   pesando 0,1,0, así que una hoja de pantalla que venga detrás (planes,
   facturación, copias) lo sigue pudiendo ajustar igual que antes. Con el
   atributo a pelo pesaría 0,2,0 y pisaría en silencio docenas de reglas
   suyas, que es justo lo que le pasaba a `.pill`: el cian de la Consola
   le ganaba a ok/warn/danger, y «Suspendida», «En prueba» y «Cancelada»
   salían del mismo color. La web clara, el acceso y el área de cliente no
   llevan `data-surface="console"`: no ven nada de esto.

   Los campos, las chapas de las tablas y las tablas se acotan además a
   `.px-body` (el contenido): el buscador del menú y la paleta de comandos
   son piezas del armazón y se dibujan solas.

   Va al final de la hoja y antes de los bloques de tacto, a propósito:
   gana por orden a las reglas base de arriba, y los 44 px del dedo, que
   vienen detrás, le siguen ganando a él.
   ===================================================================== */

/* ---- Botones ---------------------------------------------------------
   UNA ESCALA: 32 (`.btn-sm`), 38 (normal) y 44 (`.btn-lg`), la misma que
   la de los campos, para que en una barra de filtros el botón y el campo
   de al lado midan lo mismo; antes convivían 36, 40, 41, 44, 45, 48, 49 y
   52. Radio 8 en las tres tallas (antes 12 el normal y 8 el pequeño).

   Sin halo y sin levantarse al pasar el ratón: eso es un gesto de web
   comercial, y en un panel denso lo que se mueve es el color, no la caja.
   El color del texto va en `--btn-fg` para que el indicador de «cargando»
   lo pueda usar aunque el texto se vuelva transparente. */
:where([data-surface="console"]) .btn {
  --btn-h: var(--ctl-md);
  --btn-fg: var(--ink);
  position: relative;
  min-height: var(--btn-h);
  padding: 0 14px;
  gap: 8px;
  border: 1px solid var(--border-control);
  border-radius: var(--r-ctl);
  background-color: var(--surface-raised);
  color: var(--btn-fg);
  font-size: var(--t-sm);
  font-weight: 600;
  line-height: 1.25;
  letter-spacing: -.005em;
  text-decoration: none;
  box-shadow: none;
  transform: none;
  transition: background-color var(--dur-1) var(--ease-out), border-color var(--dur-1) var(--ease-out),
              color var(--dur-1) var(--ease-out), box-shadow var(--dur-1) var(--ease-out);
  -webkit-tap-highlight-color: transparent;
}
:where([data-surface="console"]) .btn > svg { flex: none; max-width: none; }

/* Lo apagado no reacciona al ratón. El `:where(:not(…))` no pesa nada: las
   hojas de pantalla pueden seguir retocando `.btn:hover` como siempre. */
:where([data-surface="console"]) .btn:where(:not(:disabled, [aria-disabled="true"])):hover {
  background-color: var(--surface-raised-hover);
  border-color: var(--border-hover);
  color: var(--btn-fg);
  transform: none;
  box-shadow: none;
}
/* Pulsado: el fondo se hunde un paso. Nada se desplaza. */
:where([data-surface="console"]) .btn:where(:not(:disabled, [aria-disabled="true"])):active {
  background-color: var(--surface-raised-active);
  transform: none;
}

/* `.btn-secondary` se usaba en /planes sin estar definido en ninguna hoja.
   Es el mismo botón que `.btn` a secas: ahora existe con nombre. */
:where([data-surface="console"]) .btn-secondary {
  --btn-fg: var(--ink);
  background-color: var(--surface-raised);
  border-color: var(--border-control);
}

/* Primario: plano. Aclara al pasar (en oscuro, oscurecer un botón
   brillante parece que se apaga) y se hunde al pulsar. Uno por zona. */
:where([data-surface="console"]) .btn-primary {
  --btn-fg: var(--on-accent);
  background-color: var(--accent);
  border-color: var(--accent);
  box-shadow: none;
}
:where([data-surface="console"]) .btn-primary:where(:not(:disabled, [aria-disabled="true"])):hover {
  background-color: var(--accent-hover);
  border-color: var(--accent-hover);
}
:where([data-surface="console"]) .btn-primary:where(:not(:disabled, [aria-disabled="true"])):active {
  background-color: var(--accent-active);
  border-color: var(--accent-active);
}

/* Fantasma: sin caja hasta que el ratón pasa. Para «Limpiar», «Copiar» y
   lo que acompaña sin competir. */
:where([data-surface="console"]) .btn-ghost {
  --btn-fg: var(--ink-2);
  background-color: transparent;
  border-color: transparent;
  box-shadow: none;
}
:where([data-surface="console"]) .btn-ghost:where(:not(:disabled, [aria-disabled="true"])):hover {
  --btn-fg: var(--ink);
  background-color: var(--surface-hover);
  border-color: transparent;
}
:where([data-surface="console"]) .btn-ghost:where(:not(:disabled, [aria-disabled="true"])):active {
  background-color: var(--surface-pressed);
}

/* Borrar, relleno: para CONFIRMAR, no para empezar. Al pasar el ratón el
   texto seguía en blanco sobre el rojo oscurecido y se quedaba en 3,42:1;
   ahora el rojo aclara y el texto sigue oscuro (7,33:1). */
:where([data-surface="console"]) .btn-danger {
  --btn-fg: var(--on-danger);
  background-color: var(--danger);
  border-color: var(--danger);
  filter: none;
}
:where([data-surface="console"]) .btn-danger:where(:not(:disabled, [aria-disabled="true"])):hover {
  background-color: var(--danger-hover);
  border-color: var(--danger-hover);
  color: var(--btn-fg);
  filter: none;
}
:where([data-surface="console"]) .btn-danger:where(:not(:disabled, [aria-disabled="true"])):active {
  background-color: var(--danger-active);
  border-color: var(--danger-active);
}

/* Borrar, contorneado: la PUERTA de lo destructivo («Suspender», «Borrar»
   antes de confirmar). Un rojo relleno en la cabecera de una ficha pesaba
   más que la acción principal de la pantalla. */
:where([data-surface="console"]) .btn-danger-soft {
  --btn-fg: var(--danger);
  background-color: transparent;
  border-color: var(--danger-border);
}
:where([data-surface="console"]) .btn-danger-soft:where(:not(:disabled, [aria-disabled="true"])):hover {
  background-color: var(--danger-soft);
  border-color: var(--danger);
}
:where([data-surface="console"]) .btn-danger-soft:where(:not(:disabled, [aria-disabled="true"])):active {
  background-color: color-mix(in srgb, var(--danger-soft), var(--danger) 12%);
}

/* Tallas: `--btn-h` manda en el alto. */
:where([data-surface="console"]) .btn-sm {
  --btn-h: var(--ctl-sm);
  min-height: var(--btn-h);
  padding: 0 12px;
  gap: 6px;
  border-radius: var(--r-ctl);
  font-size: var(--t-ui);
}
:where([data-surface="console"]) .btn-lg {
  --btn-h: var(--ctl-lg);
  padding: 0 20px;
  font-size: var(--t-sm);
}
/* Un botón pequeño PEGADO a un campo (el «Aplicar» de un desplegable) toma
   el alto del campo: 38 y 32 en la misma fila se ven escalonados. En las
   barras de filtros manda su propia regla (panel.css), que deja a los dos
   en 32. Los ocultos no cuentan: casi todo formulario empieza por uno. */
:where([data-surface="console"] .px-body) :where(input:not([type="hidden"], [type="checkbox"], [type="radio"]), select) + .btn-sm {
  --btn-h: var(--ctl-md);
}

/* Apagado: se nota (antes .82, casi igual que encendido) y el cursor lo
   dice. Sin `pointer-events:none`, que se comía el `not-allowed`; un enlace
   no se puede apagar de otra forma, así que ahí sí se queda. */
:where([data-surface="console"]) .btn:is(:disabled, [aria-disabled="true"]) {
  opacity: .45;
  cursor: not-allowed;
  pointer-events: auto;
  box-shadow: none;
}
:where([data-surface="console"]) a.btn[aria-disabled="true"] { pointer-events: none; }

/* CARGANDO. platform.js pone `data-busy` e `is-loading` al enviar; otros
   guiones, `aria-busy`. El botón no se atenúa: lo dice el indicador.
   Con `data-busy-label` el propio guion cambia el texto («Guardando…») y
   fija el ancho de antes: el indicador va delante del texto nuevo. Sin él,
   el texto de siempre se queda —reserva el ancho, así que el botón no da un
   salto— pero se vuelve transparente y el indicador va encima, centrado. */
:where([data-surface="console"]) .btn:is(.is-loading, [data-busy], [aria-busy="true"]) {
  opacity: 1;
  cursor: progress;
  pointer-events: none;
}
:where([data-surface="console"]) .btn:is(.is-loading, [data-busy], [aria-busy="true"])::before {
  content: "";
  flex: none;
  box-sizing: border-box;
  width: 14px;
  height: 14px;
  border: 2px solid var(--btn-fg);
  border-inline-end-color: transparent;
  border-radius: 50%;
  animation: px-spin .7s linear infinite;
}
:where([data-surface="console"]) .btn:is(.is-loading, [data-busy], [aria-busy="true"]):not([data-busy-label]) { color: transparent; }
:where([data-surface="console"]) .btn:is(.is-loading, [data-busy], [aria-busy="true"]):not([data-busy-label])::before {
  position: absolute;
  inset: 0;
  margin: auto;
}
@keyframes px-spin { to { transform: rotate(360deg); } }

/* ---- Campos ----------------------------------------------------------
   Medían 49 px: el relleno de 12 más el interlineado de 1,65 que heredan
   del cuerpo. Ahora el alto se FIJA (38, el del botón normal) y el texto se
   centra solo. Fondo hundido: un campo es un hueco donde se escribe, no
   una tarjeta más. `color-scheme` para que el calendario y las flechas del
   navegador salgan en claro sobre el oscuro.

   CADA SELECTOR PESA LO MISMO QUE SU REGLA BASE, ni un gramo más: los
   `input[type=…]` 0,1,1, `select` y `textarea` 0,0,1, `.input` 0,1,0. Si
   `select` subiera a 0,1,1 (lo que pasaría metiéndolo en el mismo `:is()`
   que los `input`), cualquier `.algo-select` de una hoja de pantalla que
   hoy manda dejaría de mandar. Y el alto va aparte y sin peso ninguno: la
   regla base nunca lo fijó, así que una pantalla que lo fija a su manera
   lo sigue fijando. */
:where([data-surface="console"] .px-body) :is(input:not([type]), input[type="text"], input[type="email"],
  input[type="password"], input[type="tel"], input[type="url"], input[type="number"], input[type="search"],
  input[type="date"], input[type="month"], input[type="time"], input[type="datetime-local"]),
:where([data-surface="console"] .px-body) select,
:where([data-surface="console"] .px-body) textarea,
:where([data-surface="console"] .px-body) .input {
  padding: 0 12px;
  border: 1px solid var(--border-control);
  border-radius: var(--r-ctl);
  background-color: var(--surface-sunken);
  color: var(--ink);
  line-height: 1.4;
  color-scheme: dark;
  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);
}
:where([data-surface="console"] .px-body) :where(.input:not(textarea), input:not([type]), input[type="text"],
  input[type="email"], input[type="password"], input[type="tel"], input[type="url"], input[type="number"],
  input[type="search"], input[type="date"], input[type="month"], input[type="time"], input[type="datetime-local"],
  select:not([multiple], [size])) {
  height: var(--ctl-md);
}
/* Un <input> sin `type` es de texto, pero la regla base solo le daba el ancho
   a `input[type="text"]` (29/09/2026): sin él se quedaba en sus ~20 caracteres,
   estrecho al lado de un `select` o un número a todo lo ancho (Versión y Mínima
   requerida en /agentes, la IP del bloqueo, la referencia de un pago…). El
   mismo peso que esa base, 0,1,1, para que una hoja de pantalla siga mandando. */
:where([data-surface="console"] .px-body) input:not([type]) { width: 100%; }
:where([data-surface="console"] .px-body) select { padding-inline-end: 34px; }
:where([data-surface="console"] .px-body) select:is([multiple], [size]) { padding-block: 6px; }
:where([data-surface="console"] .px-body) textarea { padding: 9px 12px; line-height: 1.55; }
:where([data-surface="console"] .px-body) :is(input, textarea)::placeholder { color: var(--placeholder); opacity: 1; }
/* El selector de archivo sacaba el botón gris del sistema, de esquinas vivas
   y con su letra, en medio de la pantalla oscura (/agentes, Veri*factu). Su
   botón pasa a ser un secundario pequeño y el nombre del archivo, texto
   atenuado al lado. A lo ancho de su campo: con el ancho propio del control,
   el botón nuevo, más holgado, recortaba el nombre («Ningún archi…»). */
:where([data-surface="console"] .px-body) input[type="file"] { width: 100%; font: inherit; font-size: var(--t-ui); color: var(--muted); }
:where([data-surface="console"] .px-body) input[type="file"]::file-selector-button {
  height: var(--ctl-sm);
  margin-inline-end: 10px;
  padding: 0 12px;
  border: 1px solid var(--border-control);
  border-radius: var(--r-ctl);
  background-color: var(--surface-raised);
  color: var(--ink);
  font: inherit;
  font-weight: 600;
  cursor: pointer;
  transition: background-color var(--dur-1) var(--ease-out), border-color var(--dur-1) var(--ease-out);
}
:where([data-surface="console"] .px-body) input[type="file"]::file-selector-button:hover { background-color: var(--surface-raised-hover); border-color: var(--border-hover); }

/* Los estados, solo en lo que se escribe o se elige: una casilla o un
   selector de archivo no llevan anillo de campo ni borde de acento. */

:where([data-surface="console"] .px-body) :is(.input, input:not([type="checkbox"], [type="radio"], [type="file"], [type="color"], [type="range"], [type="submit"], [type="button"], [type="reset"], [type="image"]), select, textarea):where(:not(:focus, :disabled, [readonly])):hover {
  border-color: var(--border-hover);
}
/* Solo lectura: se ve que está, pero no invita a escribir. Apagado: más
   todavía, y el cursor lo dice. Antes no tenían estilo en ninguna hoja. */
:where([data-surface="console"] .px-body) :is(.input, input:not([type="checkbox"], [type="radio"], [type="file"], [type="color"], [type="range"], [type="submit"], [type="button"], [type="reset"], [type="image"]), select, textarea)[readonly] {
  background-color: transparent;
  border-color: var(--line-2);
  color: var(--ink-2);
}
:where([data-surface="console"] .px-body) :is(.input, input:not([type="checkbox"], [type="radio"], [type="file"], [type="color"], [type="range"], [type="submit"], [type="button"], [type="reset"], [type="image"]), select, textarea):disabled {
  background-color: transparent;
  border-color: var(--line-2);
  color: var(--muted);
  cursor: not-allowed;
  opacity: 1;
}
/* Foco: borde de acento y el anillo doble (10,11:1). El contorno
   transparente no se ve… salvo en contraste forzado de Windows, donde el
   sistema lo pinta y la sombra desaparece: sin él, allí no habría foco. */
:where([data-surface="console"] .px-body) :is(.input, input:not([type="checkbox"], [type="radio"], [type="file"], [type="color"], [type="range"], [type="submit"], [type="button"], [type="reset"], [type="image"]), select, textarea):focus {
  outline: 2px solid transparent;
  outline-offset: 2px;
  border-color: var(--accent);
  box-shadow: var(--focus-ring);
}
:where([data-surface="console"] .px-body) :is(.input, input:not([type="checkbox"], [type="radio"], [type="file"], [type="color"], [type="range"], [type="submit"], [type="button"], [type="reset"], [type="image"]), select, textarea):is([aria-invalid="true"], :user-invalid),
:where([data-surface="console"] .px-body) .field.has-error :is(.input, input:not([type="checkbox"], [type="radio"], [type="file"], [type="color"], [type="range"], [type="submit"], [type="button"], [type="reset"], [type="image"]), select, textarea) {
  border-color: var(--danger);
}
:where([data-surface="console"] .px-body) :is(.input, input:not([type="checkbox"], [type="radio"], [type="file"], [type="color"], [type="range"], [type="submit"], [type="button"], [type="reset"], [type="image"]), select, textarea):is([aria-invalid="true"], :user-invalid):focus {
  box-shadow: 0 0 0 2px var(--bg), 0 0 0 4px var(--danger);
}
/* El autorrelleno de Chrome pinta el campo de celeste con letra negra. */
:where([data-surface="console"] .px-body) input:-webkit-autofill {
  -webkit-text-fill-color: var(--ink);
  caret-color: var(--ink);
  box-shadow: 0 0 0 1000px var(--surface-sunken) inset;
}
:where([data-surface="console"] .px-body) input:-webkit-autofill:focus {
  box-shadow: 0 0 0 1000px var(--surface-sunken) inset, var(--focus-ring);
}

/* Etiquetas. Las de los filtros van dentro del propio <label>, en un <span>
   (`<label class="field"><span>Estado</span><select>`), y salían a 16 px y
   sin peso: en una fila de filtros parecían texto suelto. */
:where([data-surface="console"] .px-body) :is(.field > label, .field-head > label, .label),
:where([data-surface="console"] .px-body) label.field > span:first-child:not(.sr-only, .label) {
  display: block;
  margin-bottom: 6px;
  font-size: var(--t-ui);
  font-weight: 600;
  line-height: 1.35;
  color: var(--ink-2);
}
/* La pista también va fuera de `.field` (en una tarjeta que se elige, en la
   de una imagen de marca) y ahí no tenía estilo: salía a 16 px, más grande
   que la etiqueta a la que acompaña. */
:where([data-surface="console"] .px-body) .hint { font-size: var(--t-xs); line-height: 1.45; color: var(--muted); }
:where([data-surface="console"] .px-body) .field .hint { margin-top: 6px; }
:where([data-surface="console"] .px-body) .field .error { font-size: var(--t-xs); line-height: 1.45; }

/* ---- Chapas ----------------------------------------------------------
   22 px de alto, en pastilla, con su tono de fondo y un filo del mismo
   tono. El tono va en dos variables y las variantes SOLO las cambian: así
   el `.pill` de la Consola ya no puede pisarles el color (era el fallo). */
:where([data-surface="console"]) .pill {
  --pill-fg: var(--accent);
  --pill-bg: var(--accent-soft);
  gap: 6px;
  height: 22px;
  padding: 0 9px;
  border: 1px solid color-mix(in srgb, var(--pill-fg) 26%, transparent);
  border-radius: var(--r-full);
  background: var(--pill-bg);
  color: var(--pill-fg);
  font-family: var(--font-sans);
  font-size: var(--t-xs);
  font-weight: 600;
  line-height: 1;
  letter-spacing: .01em;
  white-space: nowrap;
  vertical-align: middle;
}
:where([data-surface="console"]) .pill > svg { flex: none; max-width: none; }
:where([data-surface="console"]) .pill-ok     { --pill-fg: var(--ok);     --pill-bg: var(--ok-soft); }
:where([data-surface="console"]) .pill-warn   { --pill-fg: var(--warn);   --pill-bg: var(--warn-soft); }
:where([data-surface="console"]) .pill-danger { --pill-fg: var(--danger); --pill-bg: var(--danger-soft); }
:where([data-surface="console"]) .pill-info   { --pill-fg: var(--info);   --pill-bg: var(--info-soft); }
:where([data-surface="console"]) .pill-muted  { --pill-fg: var(--muted);  --pill-bg: var(--surface-3); }
:where([data-surface="console"]) .pill-draft {
  --pill-fg: var(--warn);
  --pill-bg: var(--warn-soft);
  border-style: dashed;
  border-color: color-mix(in srgb, var(--warn) 55%, transparent);
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: var(--t-2xs);
  letter-spacing: .06em;
  text-transform: uppercase;
}
/* El punto delante: lo pone `statusPill()`. Refuerza el estado sin
   depender solo del texto ni solo del color. */
:where([data-surface="console"]) .pill-dot::before {
  content: "";
  flex: none;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: currentColor;
}

/* ---- Avisos en línea -------------------------------------------------
   Fondo suave del tono y un filo del mismo tono al 45 %: con el tono a pelo
   el borde gritaba más que el texto. El icono va del color del tono y
   alineado con la primera línea, no con el centro del bloque. */
:where([data-surface="console"]) .alert {
  --alert-fg: var(--info);
  --alert-bg: var(--info-soft);
  --alert-bd: var(--info-border);
  gap: 10px;
  padding: 12px 14px;
  border: 1px solid var(--alert-bd);
  border-radius: 10px;
  background: var(--alert-bg);
  color: var(--ink);
  font-size: var(--t-sm);
  line-height: 1.5;
}
:where([data-surface="console"]) .alert > svg:first-child { flex: none; max-width: none; margin-top: 2px; color: var(--alert-fg); }
:where([data-surface="console"]) .alert .small { color: var(--ink-2); }
:where([data-surface="console"]) .alert-ok    { --alert-fg: var(--ok);     --alert-bg: var(--ok-soft);     --alert-bd: var(--ok-border); }
:where([data-surface="console"]) .alert-warn  { --alert-fg: var(--warn);   --alert-bg: var(--warn-soft);   --alert-bd: var(--warn-border); }
:where([data-surface="console"]) .alert-error { --alert-fg: var(--danger); --alert-bg: var(--danger-soft); --alert-bd: var(--danger-border); }
:where([data-surface="console"]) .alert-info  { --alert-fg: var(--info);   --alert-bg: var(--info-soft);   --alert-bd: var(--info-border); }

/* ---- Tablas ----------------------------------------------------------
   Cabecera en la superficie de las barras con rótulo de 11 px en
   mayúsculas; filas algo más bajas (10 px arriba y abajo, antes 12) y un
   hover que se ve: el de antes iba a 1,04:1 sobre el panel. */
:where([data-surface="console"] .px-body) table.data :is(th, td) { padding: 10px 14px; border-top: 1px solid var(--line); }
:where([data-surface="console"] .px-body) table.data thead th {
  padding-block: 8px;
  border-top: 0;
  border-bottom: 1px solid var(--line);
  background: var(--surface-raised);
  font-size: var(--t-2xs);
  font-weight: 600;
  letter-spacing: .06em;
  line-height: 1.4;
  color: var(--muted);
}
:where([data-surface="console"] .px-body) table.data tbody tr { transition: background-color var(--dur-1) var(--ease-out); }
/* La caja que desplaza una tabla contiene lo absoluto de dentro (el
   `.sr-only` de una cabecera): si no, se escapa y estira la página en un
   móvil. Lo mismo que `.px-scroll` en panel.css. */
:where([data-surface="console"] .px-body) .table-wrap { position: relative; }
:where([data-surface="console"] .px-body) table.data tbody tr:hover { background: var(--surface-hover); }

@media (prefers-reduced-motion: reduce) {
  /* El indicador de «cargando» gira sin fin: la regla general solo le
     acorta la duración, y girando a 0,01 ms parpadea. Se queda quieto; el
     anillo, el cursor y —si lo lleva— el «Guardando…» siguen diciendo que
     está ocupado. Con el MISMO selector que el indicador: con uno más corto
     (`.btn::before`) pesaba menos que él y el giro seguía. */
  :where([data-surface="console"]) .btn:is(.is-loading, [data-busy], [aria-busy="true"])::before { animation: none; }
}

/* En pantalla táctil nada baja de 44 px, tampoco en una tableta ancha (los
   bloques de abajo solo lo hacen hasta 900 px). `!important` porque es un
   SUELO: los botones de fila o de barra de filtros bajan su talla con una
   regla más específica, y con el dedo esa talla no puede valer. La letra
   de los campos a 16 px por lo mismo que abajo: el zoom de iOS. */
@media (pointer: coarse) {
  :where([data-surface="console"]) .btn { min-height: 44px !important; }
  :where([data-surface="console"] .px-body) input[type="file"]::file-selector-button { height: 44px; }
  :where([data-surface="console"] .px-body) :is(.input:not(textarea), input:not([type]), input[type="text"],
    input[type="email"], input[type="password"], input[type="tel"], input[type="url"], input[type="number"],
    input[type="search"], input[type="date"], input[type="month"], input[type="time"], select:not([multiple], [size])) {
    min-height: 44px !important;
    font-size: 16px !important;
  }
}


/* ---- Tacto en pantallas pequeñas ------------------------------------- */
@media (max-width: 900px) and (pointer: coarse) {
  /* 44 px es la medida que recomiendan las guías de accesibilidad para algo
     que se pulsa con el dedo. Se aplica solo en pantallas táctiles pequeñas:
     con ratón, un objetivo de 44 px desperdicia espacio. */
  .btn, .btn-sm, .lang summary, .nav-toggle { min-height: 44px; }
  /* El enlace de recuperar la contraseña se pulsa con el dedo como todo lo
     demás: el área crece con padding, no con tamaño de letra. */
  .field-forgot { min-height: 44px; display: flex; align-items: center; }
  /* La casilla: el hit target es TODO el <label>, y con una sola línea de
     texto se quedaba en 24 px. No se toca `align-items: flex-start`, que está
     puesto para que el cuadrito no se centre cuando el texto ocupa dos líneas. */
  .check { min-height: 44px; }
  .site-nav .links a { min-height: 44px; display: flex; align-items: center; }
  .foot-base a { min-height: 44px; display: inline-flex; align-items: center; }
}

/* ---------------------------------------------------------------------------
   ⚠️ CAMPOS A 16 px DONDE SE ESCRIBE CON EL DEDO
   ---------------------------------------------------------------------------
   Los campos se dibujan a `--t-sm` (14 px), que es la densidad correcta con
   ratón. Pero **iOS hace ZOOM automático al enfocar cualquier campo con letra
   por debajo de 16 px**: tocas el correo en la pantalla de acceso y la página
   pega un salto, se sale de encuadre y hay que volver a colocarla a mano. Pasa
   en TODOS los formularios de la plataforma, porque esto es la regla base.

   La condición es `pointer: coarse` y no un ancho: lo que decide el zoom es que
   se escriba con el dedo, no cuánto mide la pantalla — un iPad en horizontal
   pasa de 900 px y hace zoom igual.

   Solo sube la letra. Ni el alto ni el espaciado cambian, así que el diseño de
   escritorio se queda exactamente como está.
--------------------------------------------------------------------------- */
@media (pointer: coarse) {
  .input,
  input[type="text"], input[type="email"], input[type="password"],
  input[type="tel"], input[type="url"], input[type="number"],
  input[type="search"], input[type="date"], input[type="month"],
  select, textarea { font-size: 16px; }
}
