/* =============================================================================
   Vault Solutions — Sistema de diseño
   Una sola fuente de verdad. Tokens OKLCH verificados con contraste WCAG AA.
   Estructura: tokens · reset · tipografía · layout · componentes · utilidades
   ============================================================================= */

/* ---------------------------------------------------------------- Tokens --- */
:root {
  /* Marca (oro Vault #D4AF37 = oklch(0.767 0.139 91)).
     El oro es claro: encima va SIEMPRE el navy de marca, nunca blanco.
     --brand-ink es la única versión oscura, y existe solo para texto en color
     de marca sobre fondo blanco (el oro puro no llega a AA sobre blanco). */
  --brand: oklch(0.767 0.139 91);
  --brand-strong: oklch(0.72 0.135 91);
  --brand-strong-hover: oklch(0.66 0.13 91);
  --brand-ink: oklch(0.50 0.11 91);
  --brand-50: oklch(0.968 0.028 91);
  --brand-100: oklch(0.93 0.055 91);
  --on-brand: #0B0B0D;

  /* Tinta (navy) */
  --ink: oklch(0.24 0 0 );
  --ink-strong: oklch(0.30 0 0 );
  --ink-body: oklch(0.40 0 0 );
  --ink-muted: oklch(0.50 0 0 );
  --ink-faint: oklch(0.55 0 0 );

  /* Superficies */
  --bg: #ffffff;
  --bg-subtle: oklch(0.985 0 0 );
  --surface: #ffffff;
  --surface-2: oklch(0.978 0 0 );
  --surface-raised: #ffffff;
  --border: oklch(0.922 0 0 );
  --border-strong: oklch(0.87 0 0 );
  --logo-tile: #0B0B0D;

  /* Semánticos */
  --success: var(--brand);
  --success-50: var(--brand-50);
  --success-ink: var(--brand-ink);
  --warn: oklch(0.72 0.15 70);
  --warn-50: oklch(0.96 0.04 75);
  --warn-ink: oklch(0.50 0.11 60);
  --danger: oklch(0.58 0.19 25);
  --danger-50: oklch(0.96 0.03 25);
  --danger-ink: oklch(0.52 0.18 25);
  --info: oklch(0.58 0.13 245);
  --info-50: oklch(0.96 0.025 245);
  --info-ink: oklch(0.50 0.13 245);

  /* Tipografía — Manrope en todo (la misma de la referencia arisuperfoodpe.com);
     mono para claves. Display y cuerpo comparten familia, cambia el peso. */
  /* 11-ago-2026: la tipografía pasa de Manrope a INTER por decisión del dueño
     («esa letra no puedes usarla»). Se cambia SOLO aquí, en los dos tokens: no
     hay una sola regla del sitio que nombre una fuente a mano, así que volver
     atrás es deshacer estas dos líneas. Manrope se queda de respaldo por si
     Inter no llegara a cargar. */
  /* 12-ago-2026 · REVERTIDO A INTER
     Se probó FRAUNCES en los titulares como sustituta libre de la comercial
     «Groupe — Modern Vintage Luxury Elegant Tech» (que es de pago y exige
     licencia web). Al dueño no le gustó: «está fea la tipografía que has
     añadido, reviértelo». Vuelve a mandar Inter en todo.

     Si algún día se busca otra vez una display distinta, el cambio sigue
     siendo esta única línea —ninguna regla del sitio nombra una fuente a
     mano—, pero hay que recordar el motivo por el que Fraunces iba solo en
     titulares: la portada fuerza `-webkit-font-smoothing: antialiased`, que
     sobre negro ADELGAZA el trazo (documentado en portada.css). Una serif de
     contraste alto en cuerpo pequeño y sobre negro se rompe por ahí. */
  --font-display: "Inter", "Manrope", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --font-sans: "Inter", "Manrope", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --font-mono: "JetBrains Mono", ui-monospace, "SFMono-Regular", "Cascadia Code", Consolas, monospace;

  /* Radios */
  --r-xs: 6px;
  --r-sm: 9px;
  --r: 13px;
  --r-md: 15px;
  --r-lg: 18px;
  --r-xl: 26px;
  --r-pill: 999px;

  /* Sombras (tintadas hacia navy, nunca negro puro) */
  --shadow-xs: 0 1px 2px oklch(0.24 0 0 / 0.06);
  --shadow-sm: 0 1px 2px oklch(0.24 0 0 / 0.05), 0 2px 6px oklch(0.24 0 0 / 0.05);
  --shadow-md: 0 4px 10px oklch(0.24 0 0 / 0.06), 0 10px 24px oklch(0.24 0 0 / 0.07);
  --shadow-lg: 0 12px 28px oklch(0.24 0 0 / 0.10), 0 28px 60px oklch(0.24 0 0 / 0.10);
  --shadow-brand: 0 8px 22px oklch(0.52 0.15 91 / 0.28);
  --ring: 0 0 0 3px oklch(0.69 0.16 91 / 0.32);

  /* Layout */
  --container: 1520px;
  --container-wide: 1720px;
  --gutter: clamp(1.25rem, 4vw, 3rem);

  /* Brillo de los botones (una sola fuente de verdad para toda la web).
     --gloss-face  = la luz de arriba y la sombra de abajo, lo que da el bombeo
     --gloss-sweep = el reflejo diagonal que cruza al pasar el cursor
     --gloss-rim   = filo claro arriba y oscuro abajo, el canto del botón
     Las variantes claras usan las versiones "soft", más discretas. */
  --gloss-face: linear-gradient(180deg,
      rgb(255 255 255 / 0.26) 0%,
      rgb(255 255 255 / 0.08) 40%,
      rgb(255 255 255 / 0) 58%,
      rgb(0 0 0 / 0.09) 100%);
  --gloss-face-soft: linear-gradient(180deg,
      rgb(255 255 255 / 0.75) 0%,
      rgb(255 255 255 / 0.15) 45%,
      rgb(0 0 0 / 0.02) 70%,
      rgb(0 0 0 / 0.05) 100%);
  --gloss-sweep: linear-gradient(112deg,
      transparent 34%,
      rgb(255 255 255 / 0.28) 46%,
      transparent 58%);
  --gloss-sweep-soft: linear-gradient(112deg,
      transparent 34%,
      rgb(255 255 255 / 0.9) 46%,
      transparent 58%);
  --gloss-rim: inset 0 1px 0 rgb(255 255 255 / 0.32), inset 0 -1px 0 rgb(0 0 0 / 0.18);
  --gloss-rim-soft: inset 0 1px 0 rgb(255 255 255 / 0.9), inset 0 -1px 0 rgb(0 0 0 / 0.05);
  --gloss-press: inset 0 2px 5px rgb(0 0 0 / 0.26);
  --gloss-press-soft: inset 0 2px 4px rgb(0 0 0 / 0.10);

  /* Movimiento */
  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
  --ease-out-soft: cubic-bezier(0.33, 1, 0.68, 1);
  --t-fast: 130ms;
  --t: 190ms;
  --t-slow: 320ms;

  /* Entrada del contenido (apertura de página y paso por cada apartado).
     Valores calcados de apple.com/la/mac (27-jul-2026): el contenido nace
     30px abajo y sin opacidad, y entra con opacidad .4s + desplazamiento .5s
     sobre la curva cubic-bezier(0,0,.2,1). El escalonado entre elementos lo
     pone cinematic.js con --in-step. */
  --in-ease: cubic-bezier(0, 0, 0.2, 1);
  --in-shift: 30px;
  --in-fade: 0.4s;
  --in-move: 0.5s;
  --in-step: 90ms;

  /* z-index semántico */
  --z-dropdown: 100;
  --z-sticky: 200;
  --z-backdrop: 300;
  --z-drawer: 310;
  --z-modal: 400;
  --z-toast: 500;

  color-scheme: light;
}

[data-theme="dark"] {
  /* Sobre el navy el oro puede ir a su luminosidad real: aquí sí es el
     #D4AF37 del manual, sin apagarlo. */
  --brand: oklch(0.80 0.145 91);
  --brand-strong: oklch(0.767 0.139 91);
  --brand-strong-hover: oklch(0.83 0.14 91);
  --brand-ink: oklch(0.86 0.13 91);
  --brand-50: oklch(0.27 0.055 91);
  --brand-100: oklch(0.34 0.075 91);
  --on-brand: #0B0B0D;

  --ink: oklch(0.98 0 0 );
  --ink-strong: oklch(0.91 0 0 );
  --ink-body: oklch(0.80 0 0 );
  /* 13-ago-2026 · LOS DOS GRISES MÁS FLOJOS SUBEN.
     Al pasar TODA la web a negro se midió el contraste real de cada texto en
     cada página, y el único que fallaba —en todas— era --ink-faint: daba entre
     4,36 y 4,49 sobre el fondo, por debajo del 4,5 que se considera legible.
     Es el gris del pie de página, de las fechas, de los rótulos «Nombre
     comercial / Domicilio» del libro de reclamaciones y del precio tachado.
     Justo lo que el dueño pidió que no se perdiera.

     0.62 medido sobre las CINCO superficies de la casa, no solo sobre el fondo:
       --bg 5.60 · --bg-subtle 5.37 · --surface 5.10 · raised 4.97 · surface-2 4.68
     El caso peor es una tarjeta clara, y aun ahí pasa.

     --ink-muted sube con él (0.66 → 0.70) por una razón de diseño, no de
     medida: ese ya cumplía de sobra, pero con el flojo en 0.62 los dos escalones
     quedaban a 0.04 uno del otro y la jerarquía dejaba de leerse. */
  --ink-muted: oklch(0.70 0 0 );
  --ink-faint: oklch(0.62 0 0 );

  /* NEGRO NEUTRO, SIN UNA GOTA DE AZUL (11-ago-2026, decisión del dueño).
     Todo esto era navy: el lienzo y las cuatro superficies llevaban croma en el
     tono 265, y en pantalla las tarjetas del acordeón y la píldora de moneda se
     leían azuladas sobre el negro de la página. Ahora la escalera es gris puro
     —croma cero— y arranca más abajo, para que el fondo sea negro de verdad y
     las tarjetas sigan despegándose de él. Lo único con color en la casa es el
     oro de la marca. */
  --bg: oklch(0.115 0 0);
  --bg-subtle: oklch(0.155 0 0);
  --surface: oklch(0.185 0 0);
  --surface-2: oklch(0.225 0 0);
  --surface-raised: oklch(0.20 0 0);
  --border: oklch(0.29 0 0);
  --border-strong: oklch(0.38 0 0);
  --logo-tile: #0B0B0D;

  --warn: oklch(0.78 0.14 75);
  --warn-50: oklch(0.32 0.06 70);
  --warn-ink: oklch(0.85 0.12 80);
  --danger: oklch(0.64 0.19 25);
  --danger-50: oklch(0.30 0.08 25);
  --danger-ink: oklch(0.80 0.14 25);
  --info: oklch(0.68 0.13 245);
  --info-50: oklch(0.30 0.06 245);
  --info-ink: oklch(0.82 0.10 245);

  /* Sombras profundas con un halo de oro de marca para el aire "premium" */
  --shadow-xs: 0 1px 2px oklch(0 0 0 / 0.4);
  --shadow-sm: 0 1px 2px oklch(0 0 0 / 0.42), 0 2px 8px oklch(0 0 0 / 0.4);
  --shadow-md: 0 6px 16px oklch(0 0 0 / 0.5), 0 16px 36px oklch(0 0 0 / 0.46);
  --shadow-lg: 0 22px 60px oklch(0 0 0 / 0.6), 0 4px 18px oklch(0.6 0.16 91 / 0.1);
  --shadow-brand: 0 8px 26px oklch(0.6 0.18 91 / 0.45), 0 2px 8px oklch(0.6 0.18 91 / 0.3);
  --ring: 0 0 0 3px oklch(0.76 0.18 91 / 0.45);

  color-scheme: dark;
}

/* ----------------------------------------------- Luces ambientales (fondo) ---
   Capa fija detrás de todo el contenido: halos dorados de marca sobre el negro.
   Da el aire "premium" sin teñir el texto. Solo en oscuro; respeta reduced-motion. */
body {
  position: relative;
  isolation: isolate;
}

[data-theme="dark"] body::before {
  content: "";
  position: fixed;
  inset: -10vmax;
  z-index: -2;
  pointer-events: none;
  background:
    radial-gradient(38vmax 30vmax at 8% -4%, oklch(0.72 0.17 91 / 0.20), transparent 60%),
    radial-gradient(34vmax 30vmax at 104% 6%, oklch(0.7 0.16 91 / 0.13), transparent 62%),
    radial-gradient(46vmax 38vmax at 52% 116%, oklch(0.6 0.15 91 / 0.16), transparent 66%);
  animation: ambient-drift 22s var(--ease-out-soft) infinite alternate;
}

/* Grid tecnológico de puntos (casi imperceptible) + viñeta para dar profundidad */
[data-theme="dark"] body::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background-image:
    radial-gradient(oklch(0.78 0.16 91 / 0.05) 1px, transparent 1.5px),
    radial-gradient(120% 92% at 50% -4%, transparent 56%, oklch(0 0 0 / 0.6) 100%);
  background-size: 38px 38px, 100% 100%;
  background-position: 0 0, 0 0;
}

@keyframes ambient-drift {
  0% {
    transform: translate3d(0, 0, 0) scale(1);
  }

  50% {
    transform: translate3d(2.5%, 1.5%, 0) scale(1.06);
  }

  100% {
    transform: translate3d(-2%, -1%, 0) scale(1.02);
  }
}

@media (prefers-reduced-motion: reduce) {
  [data-theme="dark"] body::before {
    animation: none;
  }
}

/* Botón primario: en oscuro respira un halo dorado al posar el cursor */
[data-theme="dark"] .btn--primary {
  box-shadow: var(--shadow-brand);
}

[data-theme="dark"] .btn--primary:hover {
  box-shadow: 0 10px 32px oklch(0.62 0.18 91 / 0.55), 0 0 0 1px oklch(0.7 0.16 91 / 0.4);
}

[data-theme="dark"] .btn--secondary {
  background: oklch(1 0 0 / 0.04);
  border-color: oklch(1 0 0 / 0.1);
}

[data-theme="dark"] .btn--secondary:hover {
  border-color: oklch(0.7 0.16 91 / 0.5);
  background: oklch(0.7 0.16 91 / 0.08);
}

/* Tarjetas y categorías: borde dorado suave + glow controlado al pasar el cursor */
[data-theme="dark"] .card--interactive:hover,
[data-theme="dark"] .cat-tile:hover {
  border-color: oklch(0.7 0.16 91 / 0.5);
  box-shadow: var(--shadow-md), 0 0 0 1px oklch(0.72 0.16 91 / 0.16), 0 14px 34px oklch(0.55 0.15 91 / 0.14);
}

/* ----------------------------------------------------------------- Reset --- */
*,
*::before,
*::after {
  box-sizing: border-box;
}

* {
  margin: 0;
}

html {
  -webkit-text-size-adjust: 100%;
  tab-size: 4;
  scroll-behavior: smooth;
  /* Red de seguridad contra el desplazamiento lateral (28-jul-2026).
     `clip` y NO `hidden`: hidden convertiría la página en un contenedor de
     scroll y rompería la cabecera pegajosa y el hero fijado. Con clip, si algún
     bloque se pasa de ancho en un celular angosto —o con la letra del sistema
     en grande— se recorta en vez de empujar toda la web hacia el costado. */
  overflow-x: clip;
}

/* LA MISMA RED, TAMBIÉN EN EL BODY (13-ago-2026).
   No es redundante. El `overflow` puesto en la RAÍZ no se aplica a la raíz: el
   navegador se lo pasa al viewport, y ese traspaso es justo lo que Safari en
   iOS no hace igual que los demás. Resultado: en un iPhone el recorte no
   ocurría y un solo bloque que se pasaba de ancho —el rótulo de las filas de
   productos, ver portada.css— estiraba el documento a 502 px mientras la
   pantalla medía 390. Todo el contenido quedaba pegado a la izquierda con una
   franja muerta a la derecha.

   Puesto en el BODY el recorte sí es suyo y se aplica de verdad. Y sigue sin
   romper nada: `clip` no crea un contenedor de scroll, así que la cabecera
   pegajosa aguanta; y los elementos `fixed` —los cajones, el botón de WhatsApp,
   el fondo— no cuelgan del body, así que no los recorta.

   Esto es una RED, no el arreglo. El bloque que se salía está corregido en su
   sitio. Esto es para el siguiente que se salga. */
body {
  overflow-x: clip;
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
}

body {
  font-family: var(--font-sans);
  background: var(--bg);
  color: var(--ink-body);
  line-height: 1.6;
  font-size: 1rem;
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  font-feature-settings: "ss01", "cv01", "ss03";
  min-height: 100vh;
  transition: background-color var(--t) var(--ease-out), color var(--t) var(--ease-out);
}

img,
svg,
video,
canvas {
  display: block;
  max-width: 100%;
}

img {
  height: auto;
}

/* Tamaño base de icono (lo sobrescriben los contenedores: .btn svg, .icon-tile svg, etc.) */
.si-ico {
  width: 1.25em;
  height: 1.25em;
  flex: none;
}

/* Logo de WhatsApp (PNG real) usado como ícono */
.wa-img {
  width: 1.25em;
  height: 1.25em;
  object-fit: contain;
  vertical-align: middle;
}

.btn .wa-img {
  width: 1.2em;
  height: 1.2em;
}

input,
button,
textarea,
select {
  font: inherit;
  color: inherit;
}

button {
  background: none;
  border: none;
  cursor: pointer;
}

a {
  color: inherit;
  text-decoration: none;
}

ul,
ol {
  list-style: none;
  padding: 0;
}

:focus-visible {
  outline: 2px solid transparent;
  box-shadow: var(--ring);
  border-radius: var(--r-xs);
}

::selection {
  background: oklch(0.69 0.16 91 / 0.22);
}

hr {
  border: none;
  border-top: 1px solid var(--border);
}

/* ------------------------------------------------------------ Tipografía --- */
/* Semibold en todos los niveles: el 800/700 se sentía demasiado pesado */
h1,
h2,
h3,
h4,
h5 {
  color: var(--ink);
  line-height: 1.12;
  font-weight: 600;
  letter-spacing: -0.022em;
  text-wrap: balance;
}

h1,
h2,
h3,
h4 {
  font-family: var(--font-display);
}

h1 {
  font-size: clamp(1.95rem, 1.05rem + 3.6vw, 4rem);
  line-height: 1.06;
  letter-spacing: -0.032em;
}

h2 {
  font-size: clamp(1.8rem, 1.2rem + 2.4vw, 2.75rem);
  letter-spacing: -0.028em;
}

h3 {
  font-size: clamp(1.3rem, 1.05rem + 1.1vw, 1.7rem);
  font-weight: 600;
}

h4 {
  font-size: 1.15rem;
  font-weight: 600;
  letter-spacing: -0.015em;
}

h5 {
  font-size: 1rem;
  font-weight: 600;
}

p {
  text-wrap: pretty;
}

strong,
b {
  font-weight: 700;
  color: var(--ink-strong);
}

small {
  font-size: 0.82rem;
}

code,
kbd,
samp {
  font-family: var(--font-mono);
  font-size: 0.9em;
}

.lede {
  font-size: clamp(1.05rem, 0.98rem + 0.5vw, 1.25rem);
  color: var(--ink-muted);
  line-height: 1.6;
  max-width: 60ch;
}

.muted {
  color: var(--ink-muted);
}

.faint {
  color: var(--ink-faint);
}

.brand-text {
  color: var(--brand-ink);
}

.measure {
  max-width: 65ch;
}

.mono {
  font-family: var(--font-mono);
  font-feature-settings: normal;
}

/* Cifras y expresiones destacadas comparten la tipografía de titulares (display) */
.brand-word,
.price__now,
.price--lg .price__now,
.bt-offer__price .now,
.trust-item .v,
.stat-card .v,
.bt-proof__num,
.dsc-price b,
.dsc-sum b,
.flow__num,
.step__n,
.demo-step__n {
  font-family: var(--font-display);
}

/* Eyebrow — usado con intención, no sobre cada sección */
.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.8rem;
  font-weight: 600;
  letter-spacing: 0.01em;
  color: var(--brand-ink);
}

.eyebrow::before {
  content: "";
  width: 1.4rem;
  height: 2px;
  border-radius: 2px;
  background: var(--brand);
}

/* Ceja de sección (estilo Ari): raya + etiqueta verde en versalitas, como el
   "LICENCIAS DIGITALES" del hero. Y la palabra clave del título va en verde. */
.sec-eyebrow {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  margin-bottom: 0.7rem;
  font-size: 0.76rem;
  font-weight: 700;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: oklch(0.55 0.16 87);
}

.sec-eyebrow::before {
  content: "";
  width: 2.2rem;
  height: 1px;
  background: currentColor;
  opacity: 0.7;
  flex: none;
}

/* La palabra destacada del titular va en el oro de marca. Antes era un valor
   escrito a mano (oklch(0.55 0.16 87)), oscuro a propósito para leerse sobre
   blanco; con la portada en negro quedaba casi marrón. --brand-ink ya trae la
   versión correcta de cada tema: bronce en claro, oro vivo en oscuro. */
.sec-head h2 em,
.section-head h2 em,
.page-head h1 em,
.catalog-head h1 em,
.support2__copy h2 em,
.faq-aside h2 em {
  font-style: normal;
  color: var(--brand-ink);
}

/* ---------------------------------------------------------------- Layout --- */
.container {
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.container--wide {
  max-width: var(--container-wide);
}

.section {
  padding-block: clamp(3.5rem, 2rem + 6vw, 6.5rem);
}

.section--tight {
  padding-block: clamp(2.5rem, 1.5rem + 4vw, 4rem);
}

.section--alt {
  background: var(--bg-subtle);
}

.section-head {
  max-width: 60ch;
  margin-bottom: clamp(2rem, 1rem + 3vw, 3.25rem);
}

/* Móvil compacto: menos aire vertical entre secciones (petición del dueño) */
@media (max-width: 640px) {
  .section {
    padding-block: 2.75rem;
  }

  .section--tight {
    padding-block: 2rem;
  }

  .section-head {
    margin-bottom: 1.5rem;
  }
}

.section-head--center {
  margin-inline: auto;
  text-align: center;
}

.section-head h2+p {
  margin-top: 0.85rem;
}

.stack {
  display: flex;
  flex-direction: column;
}

.row {
  display: flex;
  align-items: center;
}

.wrap {
  flex-wrap: wrap;
}

.gap-1 {
  gap: 0.5rem;
}

.gap-2 {
  gap: 0.75rem;
}

.gap-3 {
  gap: 1rem;
}

.gap-4 {
  gap: 1.5rem;
}

.gap-5 {
  gap: 2rem;
}

.grid {
  display: grid;
  gap: clamp(1rem, 0.6rem + 1.4vw, 1.5rem);
}

.auto-grid {
  display: grid;
  gap: clamp(1rem, 0.6rem + 1.4vw, 1.5rem);
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
}

.between {
  justify-content: space-between;
}

.center {
  justify-content: center;
}

.items-start {
  align-items: flex-start;
}

.flex-1 {
  flex: 1;
}

.hide {
  display: none !important;
}

/* ---------------------------------------------------------------- Botón --- */
.btn {
  --btn-bg: transparent;
  --btn-fg: var(--ink-strong);
  --btn-bd: transparent;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.55rem;
  font-weight: 600;
  font-size: 0.95rem;
  line-height: 1;
  padding: 0.72rem 1.15rem;
  border-radius: var(--r-sm);
  background: var(--btn-bg);
  color: var(--btn-fg);
  border: 1px solid var(--btn-bd);
  cursor: pointer;
  white-space: nowrap;
  position: relative;
  /* Ningún botón puede ser más ancho que lo que lo contiene: con la letra del
     sistema en grande los rótulos crecen y antes empujaban la fila entera fuera
     de la pantalla (el botón del carrito de la tarjeta se salía del celular). */
  max-width: 100%;
  transition: transform var(--t-fast) var(--ease-out), background-color var(--t) var(--ease-out),
    border-color var(--t) var(--ease-out), box-shadow var(--t) var(--ease-out), color var(--t) var(--ease-out);
}

.btn:active {
  transform: translateY(1px) scale(0.99);
}

/* ---- Acabado brillante compartido -----------------------------------------
   Va en el background-image del propio botón (no en un ::before) para que el
   reflejo quede DEBAJO del texto y del icono, y para no chocar con el ::after
   que usa .btn--loading para su ruedita.
   El reflejo diagonal empieza fuera del botón y lo cruza al pasar el cursor. */
.btn--primary,
.btn--danger,
.btn--secondary,
.btn--soft,
.btn--danger-soft {
  background-image: var(--gloss-sweep), var(--gloss-face);
  /* 180% de ancho y estos dos extremos dejan el reflejo fuera del botón en
     reposo y lo hacen recorrerlo casi entero al pasar el cursor. En `linear`
     a propósito: con una curva ease el reflejo cruzaba en 100 ms y no se veía. */
  background-size: 180% 100%, auto;
  background-position: 140% 0, 0 0;
  background-repeat: no-repeat;
  transition: transform var(--t-fast) var(--ease-out), background-color var(--t) var(--ease-out),
    border-color var(--t) var(--ease-out), box-shadow var(--t) var(--ease-out), color var(--t) var(--ease-out),
    background-position 0.85s linear;
}

.btn--primary:hover,
.btn--danger:hover,
.btn--secondary:hover,
.btn--soft:hover,
.btn--danger-soft:hover {
  background-position: -80% 0, 0 0;
}

/* Sin cursor (celular) el reflejo no aporta y el cambio de posición al tocar
   se vería como un parpadeo: ahí queda solo el brillo fijo. */
@media (hover: none) {

  .btn--primary,
  .btn--danger,
  .btn--secondary,
  .btn--soft,
  .btn--danger-soft {
    background-image: var(--gloss-face);
    transition: transform var(--t-fast) var(--ease-out), background-color var(--t) var(--ease-out),
      border-color var(--t) var(--ease-out), box-shadow var(--t) var(--ease-out), color var(--t) var(--ease-out);
  }

  .btn--secondary,
  .btn--soft,
  .btn--danger-soft {
    background-image: var(--gloss-face-soft);
  }
}

/* Botones claros: el mismo lenguaje, pero el brillo apenas se insinúa */
.btn--secondary,
.btn--soft,
.btn--danger-soft {
  background-image: var(--gloss-sweep-soft), var(--gloss-face-soft);
}

/* Relleno oscuro: filo marcado y una pizca de sombra en el texto */
.btn--primary,
.btn--danger {
  text-shadow: 0 1px 0 rgb(0 0 0 / 0.18);
}

/* Al presionar, el botón se hunde de verdad */
.btn--primary:active,
.btn--danger:active {
  box-shadow: var(--gloss-press);
}

.btn--secondary:active,
.btn--soft:active,
.btn--danger-soft:active {
  box-shadow: var(--gloss-press-soft);
}

/* En modo oscuro el reflejo blanco se baja: si no, los botones "lechosean" */
[data-theme="dark"] {
  --gloss-face: linear-gradient(180deg,
      rgb(255 255 255 / 0.16) 0%,
      rgb(255 255 255 / 0.05) 40%,
      rgb(255 255 255 / 0) 58%,
      rgb(0 0 0 / 0.16) 100%);
  --gloss-face-soft: linear-gradient(180deg,
      rgb(255 255 255 / 0.12) 0%,
      rgb(255 255 255 / 0.03) 45%,
      rgb(0 0 0 / 0.06) 100%);
  --gloss-sweep-soft: linear-gradient(112deg,
      transparent 34%,
      rgb(255 255 255 / 0.16) 46%,
      transparent 58%);
  --gloss-rim-soft: inset 0 1px 0 rgb(255 255 255 / 0.12), inset 0 -1px 0 rgb(0 0 0 / 0.25);
}

.btn svg {
  width: 1.15em;
  height: 1.15em;
  flex: none;
}

.btn:disabled,
.btn[aria-disabled="true"] {
  opacity: 0.55;
  pointer-events: none;
}

.btn--primary {
  --btn-bg: var(--brand-strong);
  --btn-fg: var(--on-brand);
  --btn-bd: var(--brand-strong);
  box-shadow: var(--shadow-brand), var(--gloss-rim);
}

.btn--primary:hover {
  --btn-bg: var(--brand-strong-hover);
  --btn-bd: var(--brand-strong-hover);
  transform: translateY(-1px);
  box-shadow: var(--shadow-brand), var(--gloss-rim);
}

.btn--secondary {
  --btn-bg: var(--surface);
  --btn-fg: var(--ink-strong);
  --btn-bd: var(--border-strong);
  box-shadow: var(--shadow-xs), var(--gloss-rim-soft);
}

.btn--secondary:hover {
  --btn-bd: var(--ink-faint);
  /* background-color y no el atajo `background`: el atajo borraría el brillo */
  background-color: var(--surface-2);
  transform: translateY(-1px);
  box-shadow: var(--shadow-sm), var(--gloss-rim-soft);
}

.btn--ghost {
  --btn-fg: var(--ink-body);
}

.btn--ghost:hover {
  background-color: var(--surface-2);
  --btn-fg: var(--ink);
}

.btn--soft {
  --btn-bg: var(--brand-50);
  --btn-fg: var(--brand-ink);
  box-shadow: var(--gloss-rim-soft);
}

.btn--soft:hover {
  filter: brightness(0.98);
  --btn-bg: var(--brand-100);
}

.btn--danger {
  --btn-bg: var(--danger);
  --btn-fg: #fff;
  --btn-bd: var(--danger);
  box-shadow: 0 6px 16px oklch(0.58 0.19 25 / 0.28), var(--gloss-rim);
}

.btn--danger-soft {
  --btn-bg: var(--danger-50);
  --btn-fg: var(--danger-ink);
  box-shadow: var(--gloss-rim-soft);
}

.btn--lg {
  padding: 0.92rem 1.5rem;
  font-size: 1.02rem;
  border-radius: var(--r);
}

.btn--sm {
  padding: 0.5rem 0.8rem;
  font-size: 0.85rem;
}

.btn--icon {
  padding: 0.6rem;
  aspect-ratio: 1;
}

/* Botón a lo ancho: su rótulo PARTE LÍNEA antes que salirse de la caja.
   El `white-space: nowrap` de .btn está pensado para botones cortos en fila; en
   uno que ocupa todo el ancho (y suele llevar una frase entera, como "Pude
   instalar todo correctamente") lo único que conseguía era desbordar la tarjeta
   que lo contiene — se veía el botón dorado más ancho que la tarjeta blanca. */
.btn--block {
  width: 100%;
  min-width: 0;
  white-space: normal;
  line-height: 1.2;
  text-align: center;
}

/* ---- Tamaño mínimo para el dedo (30-jul-2026) -----------------------------
   Los botones pequeños medían unos 32-37px de alto: con el pulgar, en un
   celular, acertarlos era cuestión de suerte (el de cantidad del carrito ya se
   había arreglado así el 29-jul). Solo se aplica en pantallas TÁCTILES, así que
   en el escritorio con ratón todo se ve igual de compacto que antes. */
@media (pointer: coarse) {

  .btn--sm,
  .btn--icon,
  .chip {
    min-height: 44px;
  }

  .btn--icon {
    min-width: 44px;
  }
}

.btn--pill {
  border-radius: var(--r-pill);
}

/* --- Pantallas angostas: ningún rótulo puede desbordar su caja ---------------
   `.btn` lleva white-space: nowrap porque la mayoría de los botones son cortos
   y en una fila quedan mejor de una línea. Pero en un celular —y más aún con la
   letra del sistema en grande— una frase como "Pude instalar todo correctamente"
   o "Comprar por WhatsApp" no cabe, y en vez de partir se salía por los lados de
   la tarjeta que la contiene. Aquí se le permite partir: los botones cortos no
   cambian y los largos dejan de romper el diseño. (28-jul-2026) */
@media (max-width: 640px) {
  .btn {
    white-space: normal;
    line-height: 1.2;
    min-width: 0;
    text-align: center;
  }
}

.btn--loading {
  color: transparent !important;
  pointer-events: none;
}

.btn--loading::after {
  content: "";
  position: absolute;
  width: 1.05em;
  height: 1.05em;
  border-radius: 50%;
  border: 2px solid currentColor;
  border-top-color: transparent;
  color: var(--on-brand);
  animation: spin 0.7s linear infinite;
}

.btn-link {
  color: var(--brand-ink);
  font-weight: 600;
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
}

.btn-link svg {
  width: 1em;
  height: 1em;
  transition: transform var(--t) var(--ease-out);
}

.btn-link:hover svg {
  transform: translateX(3px);
}

@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}

/* --------------------------------------------------------------- Badges --- */
.badge {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  font-size: 0.78rem;
  font-weight: 600;
  line-height: 1;
  white-space: nowrap;
  padding: 0.34rem 0.6rem;
  border-radius: var(--r-pill);
  background: var(--surface-2);
  color: var(--ink-muted);
  border: 1px solid var(--border);
}

.badge .dot {
  width: 0.46rem;
  height: 0.46rem;
  border-radius: 50%;
  background: currentColor;
  flex: none;
}

.badge--success {
  background: var(--success-50);
  color: var(--success-ink);
  border-color: transparent;
}

.badge--warn {
  background: var(--warn-50);
  color: var(--warn-ink);
  border-color: transparent;
}

.badge--danger {
  background: var(--danger-50);
  color: var(--danger-ink);
  border-color: transparent;
}

.badge--info {
  background: var(--info-50);
  color: var(--info-ink);
  border-color: transparent;
}

.badge--solid {
  background: var(--brand-strong);
  color: var(--on-brand);
  border-color: transparent;
}

.badge--lg {
  font-size: 0.85rem;
  padding: 0.45rem 0.8rem;
}

.chip {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  padding: 0.5rem 0.9rem;
  border-radius: var(--r-pill);
  background: var(--surface);
  border: 1px solid var(--border);
  color: var(--ink-body);
  font-size: 0.9rem;
  font-weight: 500;
  cursor: pointer;
  transition: border-color var(--t), background-color var(--t), color var(--t);
}

.chip:hover {
  border-color: var(--border-strong);
}

.chip[aria-pressed="true"],
.chip.is-active {
  background: var(--brand-50);
  border-color: transparent;
  color: var(--brand-ink);
  font-weight: 600;
}

/* --------------------------------------------------------------- Tarjeta --- */
.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-xs);
}

.card--pad {
  padding: clamp(1.25rem, 1rem + 1vw, 1.6rem);
}

.card--interactive {
  transition: transform var(--t) var(--ease-out), box-shadow var(--t) var(--ease-out), border-color var(--t) var(--ease-out);
}

.card--interactive:hover {
  transform: translateY(-3px);
  box-shadow: var(--shadow-md);
  border-color: var(--border-strong);
}

/* Contenedor de icono propio (uso medido, no sobre cada título) */
.icon-tile {
  display: inline-grid;
  place-items: center;
  flex: none;
  width: 2.9rem;
  height: 2.9rem;
  border-radius: var(--r);
  background: linear-gradient(150deg, color-mix(in oklch, var(--brand) 24%, var(--surface)), var(--brand-50) 72%);
  color: var(--brand-ink);
  border: 1px solid color-mix(in oklch, var(--brand) 22%, transparent);
  box-shadow: inset 0 1px 0 oklch(1 0 0 / 0.22), var(--shadow-xs);
  transition: transform var(--t) var(--ease-out), box-shadow var(--t) var(--ease-out);
}

.icon-tile svg {
  width: 1.45rem;
  height: 1.45rem;
}

.icon-tile--lg {
  width: 3.4rem;
  height: 3.4rem;
}

.icon-tile--ghost {
  background: var(--surface-2);
  color: var(--ink-body);
  border-color: var(--border);
}

/* Glifo de marca de software (placeholder) */
.brand-glyph {
  display: inline-grid;
  place-items: center;
  border-radius: 24%;
  flex: none;
  overflow: hidden;
  box-shadow: inset 0 0 0 1px oklch(0.24 0 0 / 0.07);
}

.brand-glyph svg {
  display: block;
}

/* Icono genérico del respaldo (marca sin glifo propio): el <svg> de SI.icon()
   trae su propio tamaño en em, así que se encierra en una caja con medida fija
   para que ocupe siempre la misma proporción del cuadrito. */
.brand-glyph__ic {
  display: grid;
  place-items: center;
  color: var(--ink-muted);
}

.brand-glyph__ic svg {
  width: 100%;
  height: 100%;
}

[data-theme="dark"] .brand-glyph {
  box-shadow: inset 0 0 0 1px oklch(1 0 0 / 0.08);
}

/* Foto real del producto en listas compactas (buscador, carrito); mismo
   encuadre que .brand-glyph para que ambos convivan alineados */
.p-thumb {
  flex: none;
  border-radius: 24%;
  object-fit: cover;
  background: #fff;
  box-shadow: inset 0 0 0 1px oklch(0.24 0 0 / 0.07);
}

[data-theme="dark"] .p-thumb {
  box-shadow: inset 0 0 0 1px oklch(1 0 0 / 0.08);
}

/* ---------------------------------------------------------------- Forms --- */
.field {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}

.label {
  font-size: 0.88rem;
  font-weight: 600;
  color: var(--ink-strong);
}

.hint {
  font-size: 0.82rem;
  color: var(--ink-muted);
}

.input,
.select,
.textarea {
  width: 100%;
  padding: 0.72rem 0.85rem;
  font-size: 0.95rem;
  background: var(--surface);
  color: var(--ink);
  border: 1px solid var(--border-strong);
  border-radius: var(--r-sm);
  transition: border-color var(--t), box-shadow var(--t), background-color var(--t);
}

/* Campos a 16px en el celular: por debajo de ese tamaño, Safari en iPhone hace
   zoom solo al tocar el campo y NO vuelve — el visitante se queda con la web
   desplazada a medio formulario (login, registro, libro de reclamaciones y el
   pago como invitado). El panel de WhatsApp ya lo resolvía así (wa.css); al
   formulario del cliente le faltaba. (29-jul-2026) */
@media (max-width: 640px) {
  .input,
  .select,
  .textarea {
    font-size: 16px;
  }
}

.input::placeholder,
.textarea::placeholder {
  color: var(--ink-faint);
}

.input:focus,
.select:focus,
.textarea:focus {
  outline: none;
  border-color: var(--brand);
  box-shadow: var(--ring);
}

.input:disabled,
.select:disabled {
  background: var(--surface-2);
  color: var(--ink-faint);
  cursor: not-allowed;
}

.field--error .input,
.field--error .select {
  border-color: var(--danger);
}

.field--error .hint {
  color: var(--danger-ink);
}

.textarea {
  resize: vertical;
  min-height: 7rem;
  line-height: 1.55;
}

.select {
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 24 24' fill='none' stroke='%235b6470' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 0.7rem center;
  padding-right: 2.4rem;
}

/* Selector de categorías MÚLTIPLE (checkboxes tipo chip) — editor de productos */
.label-hint { font-weight: 500; color: var(--ink-muted); font-size: 0.8rem; }
.cat-picker {
  display: flex; flex-wrap: wrap; gap: 0.5rem;
  padding: 0.6rem; background: var(--surface);
  border: 1px solid var(--border-strong); border-radius: var(--r-sm);
}
.cat-pick {
  display: inline-flex; align-items: center; gap: 0.45rem;
  padding: 0.4rem 0.7rem; border-radius: 999px; cursor: pointer;
  background: var(--surface-2); border: 1px solid var(--border);
  font-size: 0.9rem; color: var(--ink); user-select: none;
  transition: background-color var(--t), border-color var(--t), color var(--t);
}
.cat-pick:hover { border-color: var(--brand); }
.cat-pick input { accent-color: var(--brand); width: 15px; height: 15px; margin: 0; cursor: pointer; }
.cat-pick:has(input:checked) {
  background: color-mix(in oklch, var(--brand) 14%, transparent);
  border-color: var(--brand); color: var(--ink-strong); font-weight: 600;
}

.input-group {
  position: relative;
  display: flex;
  align-items: center;
}

.input-group>svg {
  position: absolute;
  left: 0.85rem;
  width: 1.15rem;
  height: 1.15rem;
  color: var(--ink-faint);
  pointer-events: none;
}

.input-group .input {
  padding-left: 2.6rem;
}

/* Switch (toggle tema, estados) */
.switch {
  position: relative;
  display: inline-flex;
  align-items: center;
  width: 2.8rem;
  height: 1.6rem;
}

.switch input {
  position: absolute;
  opacity: 0;
  inset: 0;
  cursor: pointer;
}

.switch .track {
  width: 100%;
  height: 100%;
  border-radius: var(--r-pill);
  background: var(--border-strong);
  transition: background-color var(--t);
}

.switch .thumb {
  position: absolute;
  top: 0.2rem;
  left: 0.2rem;
  width: 1.2rem;
  height: 1.2rem;
  border-radius: 50%;
  background: #fff;
  box-shadow: var(--shadow-sm);
  transition: transform var(--t) var(--ease-out);
}

.switch input:checked~.track {
  background: var(--brand-strong);
}

.switch input:checked~.thumb {
  transform: translateX(1.2rem);
}

.switch input:focus-visible~.track {
  box-shadow: var(--ring);
}

/* Segmented control */
.segmented {
  display: inline-flex;
  padding: 0.25rem;
  gap: 0.2rem;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--r);
}

.segmented button {
  padding: 0.5rem 0.9rem;
  border-radius: var(--r-xs);
  font-size: 0.88rem;
  font-weight: 600;
  color: var(--ink-muted);
  transition: background-color var(--t), color var(--t);
}

.segmented button.is-active {
  background: var(--surface-raised);
  color: var(--ink);
  box-shadow: var(--shadow-xs);
}

/* ----------------------------------------------------------------- Tabla --- */
.table-wrap {
  overflow-x: auto;
  min-width: 0;
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  background: var(--surface);
}

table.data {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.92rem;
  min-width: 640px;
}

table.data th {
  text-align: left;
  font-weight: 600;
  color: var(--ink-muted);
  font-size: 0.8rem;
  letter-spacing: 0.01em;
  padding: 0.85rem 1rem;
  border-bottom: 1px solid var(--border);
  background: var(--surface-2);
}

table.data td {
  padding: 0.9rem 1rem;
  border-bottom: 1px solid var(--border);
  color: var(--ink-body);
  vertical-align: middle;
}

table.data tbody tr:last-child td {
  border-bottom: none;
}

table.data tbody tr {
  transition: background-color var(--t);
}

table.data tbody tr:hover {
  background: var(--surface-2);
}

/* --------------------------------------------------------------- Progreso --- */
.progress {
  height: 0.5rem;
  border-radius: var(--r-pill);
  background: var(--surface-2);
  overflow: hidden;
  border: 1px solid var(--border);
}

.progress>span {
  display: block;
  height: 100%;
  border-radius: inherit;
  background: var(--brand);
  transition: width var(--t-slow) var(--ease-out);
}

.progress.is-warn>span {
  background: var(--warn);
}

.progress.is-danger>span {
  background: var(--danger);
}

/* ---------------------------------------------------------------- Avatar --- */
.avatar {
  display: inline-grid;
  place-items: center;
  width: 2.4rem;
  height: 2.4rem;
  border-radius: 50%;
  background: var(--brand-50);
  color: var(--brand-ink);
  font-weight: 700;
  font-size: 0.9rem;
  flex: none;
  overflow: hidden;
}

.avatar img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: inherit;
  display: block;
}

.avatar--xl {
  width: 4.5rem;
  height: 4.5rem;
  font-size: 1.5rem;
  border: 1px solid var(--border);
}

/* Fila de foto de perfil (cuenta → Configuración) */
.profile-photo {
  display: flex;
  align-items: center;
  gap: 1rem;
}

.profile-photo__actions {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  flex-wrap: wrap;
}

.profile-photo__actions .hint {
  flex-basis: 100%;
}

/* -------------------------------------------------------------- Skeleton --- */
.skeleton {
  background: linear-gradient(100deg, var(--surface-2) 30%, var(--border) 50%, var(--surface-2) 70%);
  background-size: 200% 100%;
  border-radius: var(--r-sm);
  animation: shimmer 1.3s infinite linear;
}

@keyframes shimmer {
  to {
    background-position: -200% 0;
  }
}

/* ---------------------------------------------------------------- Drawer --- */
.backdrop {
  position: fixed;
  inset: 0;
  background: oklch(0.18 0 0 / 0.5);
  backdrop-filter: blur(2px);
  z-index: var(--z-backdrop);
  opacity: 0;
  visibility: hidden;
  transition: opacity var(--t), visibility var(--t);
}

.backdrop.is-open {
  opacity: 1;
  visibility: visible;
}

.drawer {
  position: fixed;
  top: 0;
  right: 0;
  height: 100dvh;
  width: min(420px, 92vw);
  background: var(--surface);
  border-left: 1px solid var(--border);
  box-shadow: var(--shadow-lg);
  z-index: var(--z-drawer);
  transform: translateX(100%);
  transition: transform var(--t-slow) var(--ease-out);
  display: flex;
  flex-direction: column;
}

.drawer.is-open {
  transform: translateX(0);
}

.drawer__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 1.15rem 1.35rem;
  border-bottom: 1px solid var(--border);
}

.drawer__body {
  flex: 1;
  overflow-y: auto;
  padding: 1.35rem;
}

.drawer__foot {
  padding: 1.35rem;
  border-top: 1px solid var(--border);
  background: var(--surface-2);
}

/* ----------------------------------------------------------------- Toast --- */
/* Sube por encima de los botones flotantes (WhatsApp y carrito, chrome.css):
   caían en la misma esquina y el aviso "Agregado al carrito" tapaba el botón de
   WhatsApp justo después de agregar, que es cuando más gente pregunta.
   En el celular ocupa el ancho disponible y se apoya sobre esos botones.
   (29-jul-2026) */
.toast-area {
  position: fixed;
  bottom: calc(clamp(1.1rem, 3.5vh, 2rem) + 4rem);
  right: clamp(1rem, 2.5vw, 2rem);
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  z-index: var(--z-toast);
}

@media (max-width: 560px) {
  /* Con el carrito flotante visible hay dos botones apilados: el aviso se pone
     encima de los dos y se estira para que el texto no quede en una columna. */
  .toast-area {
    left: clamp(1rem, 2.5vw, 2rem);
    bottom: calc(clamp(1.1rem, 3.5vh, 2rem) + 7.6rem);
    align-items: stretch;
  }
}

.toast {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  padding: 0.85rem 1.1rem;
  background: var(--surface-raised);
  border: 1px solid var(--border);
  border-radius: var(--r);
  box-shadow: var(--shadow-lg);
  font-size: 0.92rem;
  color: var(--ink-strong);
  animation: toast-in var(--t-slow) var(--ease-out);
}

.toast svg {
  width: 1.2rem;
  height: 1.2rem;
  color: var(--brand);
  flex: none;
}

@keyframes toast-in {
  from {
    opacity: 0;
    transform: translateY(12px);
  }
}

/* ----------------------------------------------------------------- Modal --- */
.modal {
  position: fixed;
  inset: 0;
  z-index: var(--z-modal);
  display: grid;
  place-items: center;
  padding: 1.25rem;
  /* Overlay SÓLIDO (sin backdrop-filter): un blur a pantalla completa sobre una
     página pesada —como la tabla de productos del admin— se recalcula en cada
     frame y hace que el modal abra con tirones. Un velo opaco rinde igual de bien
     visualmente y es instantáneo. */
  background: oklch(0.12 0 0 / 0.82);
  opacity: 0;
  visibility: hidden;
  transition: opacity var(--t), visibility var(--t);
}

.modal.is-open {
  opacity: 1;
  visibility: visible;
}

.modal__panel {
  width: min(560px, 100%);
  max-height: 90dvh;
  overflow-y: auto;
  background: var(--surface-raised);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-lg);
  transform: translateY(12px) scale(0.99);
  transition: transform var(--t-slow) var(--ease-out);
}

.modal.is-open .modal__panel {
  transform: none;
}

.modal__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 1.15rem 1.4rem;
  border-bottom: 1px solid var(--border);
}

.modal__head h3 {
  font-size: 1.15rem;
}

.modal__body {
  padding: 1.4rem;
  display: grid;
  gap: 1.1rem;
}

.modal__foot {
  padding: 1.1rem 1.4rem;
  border-top: 1px solid var(--border);
  display: flex;
  justify-content: flex-end;
  gap: 0.6rem;
  background: var(--surface-2);
}

.form-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1rem;
}

.form-grid .col-span {
  grid-column: 1 / -1;
}

@media (max-width: 520px) {
  .form-grid {
    grid-template-columns: 1fr;
  }
}

/* ------------------------------------------------------------- Breadcrumb --- */
.breadcrumb {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.86rem;
  color: var(--ink-muted);
  flex-wrap: wrap;
}

.breadcrumb a {
  transition: color var(--t);
}

.breadcrumb a:hover {
  color: var(--brand-ink);
}

.breadcrumb svg {
  width: 1rem;
  height: 1rem;
  color: var(--ink-faint);
}

.breadcrumb .current {
  color: var(--ink);
  font-weight: 600;
}

/* ------------------------------------------------------------------ Tabs --- */
.tabs {
  display: flex;
  gap: 0.25rem;
  border-bottom: 1px solid var(--border);
  overflow-x: auto;
}

.tabs button {
  padding: 0.75rem 1.05rem;
  font-weight: 600;
  font-size: 0.95rem;
  color: var(--ink-muted);
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  white-space: nowrap;
  transition: color var(--t), border-color var(--t);
}

.tabs button:hover {
  color: var(--ink);
}

.tabs button.is-active {
  color: var(--ink);
  border-bottom-color: var(--brand);
}

.tab-panel {
  display: none;
}

.tab-panel.is-active {
  display: block;
  animation: tab-enter .16s cubic-bezier(.2, .8, .2, 1);
}

@keyframes tab-enter {
  from {
    transform: translateX(16px);
  }

  to {
    transform: none;
  }
}

/* Bloque de clave de licencia (mono + copiar) */
.license-key {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.7rem 0.85rem;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  font-family: var(--font-mono);
  font-size: 0.88rem;
  color: var(--ink-strong);
  letter-spacing: 0.02em;
}

.license-key code {
  flex: 1;
  overflow-x: auto;
  white-space: nowrap;
}

.license-key button {
  color: var(--ink-muted);
  display: inline-grid;
  place-items: center;
  transition: color var(--t);
}

.license-key button:hover {
  color: var(--brand-ink);
}

/* --------------------------------------------------------------- Divider --- */
.dot-sep {
  width: 3px;
  height: 3px;
  border-radius: 50%;
  background: var(--ink-faint);
  display: inline-block;
}

/* ------------------------------------------------------- prefers-reduced --- */
@media (prefers-reduced-motion: reduce) {

  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
}