/* =============================================================================
   Utiliobox — sistema de diseño compartido / shared design system
   Un único archivo. Todas las páginas y todas las herramientas futuras
   heredan de aquí. NUNCA escribas un color o un tamaño a mano en una página.
   ============================================================================= */

/* =============================================================================
   1. TOKENS
   ============================================================================= */
/* =============================================================================
   0. RESPALDO TIPOGRÁFICO
   -----------------------------------------------------------------------------
   Inter llega de fuera y tarda. Mientras, el navegador pinta con la fuente del
   sistema, que MEDIDA es un 11 % más estrecha: el texto reparte en menos
   líneas y, cuando Inter llega, todo el contenido se recoloca de golpe. Ese
   reflow es el que el informe atribuía a #content, #contenido y #herramienta,
   los contenedores enteros.

   `size-adjust` estira el respaldo hasta que ocupa lo mismo que Inter, así que
   el cambio de fuente ya no mueve nada. El 106,8 % sale de medir: Arial es el
   93,61 % del ancho de Inter, y 100 / 93,61 = 106,8.
   ============================================================================= */
@font-face {
  font-family: "Inter respaldo";
  src: local("Arial"), local("Helvetica"), local("Liberation Sans");
  size-adjust: 106.8%;
  font-display: swap;
}

:root {
  /* --- Escala de grises (modo claro) --- */
  --g-0:  #ffffff;
  --g-25: #fbfcfd;
  --g-50: #f5f7f9;
  --g-100:#eceff3;
  --g-200:#dfe3e9;
  --g-300:#c7ced8;
  --g-400:#98a2b3;
  /* #6b7686 dejaba el texto secundario en 4,48:1 sobre el fondo de página y
     en 4,13 sobre las superficies hundidas: por debajo de la AA en los dos
     casos, y salía en el pie, en las pestañas, en el selector de idioma y en
     media docena de sitios más. Con #636c77 el peor caso es 4,62 (sobre
     --surface-sunken) y sigue siendo un gris claramente más suave que
     --ink-soft, así que la jerarquía visual no cambia. */
  --g-500:#636c77;
  --g-600:#4d5765;
  --g-700:#39424e;
  --g-800:#242c36;
  --g-900:#141a21;
  --g-950:#0b0f14;

  /* --- Color de acento (uno solo, y nada más) --- */
  --accent:        #0f62fe;
  --accent-hover:  #0043ce;
  /* Sobre #e8f0ff, el propio --accent se queda en 4,37:1 — y ese par sale en
     el número de cada paso, en los botones activos y en los <code> de los
     ejemplos. Un tono más claro lo sube a 4,58 sin dejar de leerse como un
     lavado azul. */
  --accent-soft:   #f0f5ff;
  --accent-border: #b9d0ff;
  --accent-ink:    #ffffff;

  /* --- Semánticos --- */
  --ok:      #0e7c4a;
  --ok-soft: #e6f5ee;
  --warn:      #9a6200;
  --warn-soft: #fdf3e2;
  --danger:      #c02626;
  --danger-hover:#9d1c1c;
  --danger-soft: #fdecec;

  /* --- Roles de superficie --- */
  --bg:          var(--g-25);
  --bg-alt:      var(--g-50);
  --surface:     var(--g-0);
  --surface-alt: var(--g-50);
  --surface-sunken: var(--g-100);
  --border:       var(--g-200);
  --border-strong:var(--g-300);
  --ink:      var(--g-900);
  --ink-soft: var(--g-600);
  --ink-mute: var(--g-500);
  --ink-invert: var(--g-0);

  /* --- Tipografía --- */
  --sans: "Inter", "Inter respaldo", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --mono: "JetBrains Mono", ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;

  --fs-2xs: 0.6875rem;  /* 11px */
  --fs-xs:  0.75rem;    /* 12px */
  --fs-sm:  0.8125rem;  /* 13px */
  --fs-base:0.9375rem;  /* 15px */
  --fs-md:  1rem;
  --fs-lg:  1.125rem;
  --fs-xl:  1.375rem;
  --fs-2xl: clamp(1.5rem, 1.2rem + 1.4vw, 1.9rem);
  --fs-3xl: clamp(1.85rem, 1.4rem + 2.2vw, 2.6rem);
  --fs-4xl: clamp(2.1rem, 1.5rem + 3vw, 3.1rem);

  --fw-normal: 400;
  --fw-medium: 500;
  --fw-semi:   600;
  --fw-bold:   700;

  --lh-tight: 1.15;
  --lh-snug:  1.35;
  --lh-base:  1.62;

  /* --- Espaciado (escala de 4) --- */
  --s-1: 0.25rem;
  --s-2: 0.5rem;
  --s-3: 0.75rem;
  --s-4: 1rem;
  --s-5: 1.25rem;
  --s-6: 1.5rem;
  --s-8: 2rem;
  --s-10:2.5rem;
  --s-12:3rem;
  --s-16:4rem;
  --s-20:5rem;

  /* --- Radios --- */
  --r-xs: 4px;
  --r-sm: 6px;
  --r-md: 9px;
  --r-lg: 13px;
  --r-xl: 18px;
  --r-full: 999px;

  /* --- Sombras --- */
  --sh-xs: 0 1px 2px rgba(11, 15, 20, .05);
  --sh-sm: 0 1px 3px rgba(11, 15, 20, .07), 0 1px 2px rgba(11, 15, 20, .04);
  --sh-md: 0 4px 12px rgba(11, 15, 20, .08), 0 1px 3px rgba(11, 15, 20, .04);
  --sh-lg: 0 12px 34px rgba(11, 15, 20, .12), 0 2px 8px rgba(11, 15, 20, .05);
  --sh-focus: 0 0 0 3px var(--accent-soft);

  /* --- Layout --- */
  --wrap: 1140px;
  --wrap-narrow: 760px;
  --header-h: 60px;

  /* --- Movimiento --- */
  --ease-out: cubic-bezier(.16, 1, .3, 1);
  --dur-fast: .12s;
  --dur: .2s;

  --z-header: 100;
  --z-dropdown: 200;
  --z-toast: 300;
  --z-dialog: 400;
  --z-consent: 500;

  color-scheme: light;
}

/* --- Modo oscuro: por preferencia del sistema… --- */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) { color-scheme: dark; }
}
/* …y conmutable a mano (data-theme gana siempre). Los roles se redefinen,
   la escala de grises se invierte. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --g-0:  #0b0f14;
    --g-25: #0e1319;
    --g-50: #12181f;
    --g-100:#182029;
    --g-200:#232d38;
    --g-300:#33404e;
    --g-400:#5c6b7c;
    --g-500:#8b98a8;
    --g-600:#a9b5c2;
    --g-700:#c6cfd9;
    --g-800:#e0e6ec;
    --g-900:#f2f5f8;
    --g-950:#ffffff;

    --accent:        #4d8bff;
    --accent-hover:  #7aa7ff;
    --accent-soft:   #14243d;
    --accent-border: #2a4a7d;
    --accent-ink:    #06101f;

    --ok:      #4ade9c;
    --ok-soft: #0e2a1e;
    --warn:      #e2b45c;
    --warn-soft: #2a2013;
    --danger:      #ff7b72;
    --danger-hover:#ff9d96;
    --danger-soft: #2c1616;

    --bg:          var(--g-25);
    --bg-alt:      var(--g-0);
    --surface:     var(--g-50);
    --surface-alt: var(--g-100);
    --surface-sunken: var(--g-100);
    --border:       var(--g-200);
    --border-strong:var(--g-300);
    --ink:      var(--g-900);
    --ink-soft: var(--g-600);
    --ink-mute: var(--g-500);
    --ink-invert: var(--g-0);

    --sh-xs: 0 1px 2px rgba(0, 0, 0, .4);
    --sh-sm: 0 1px 3px rgba(0, 0, 0, .45);
    --sh-md: 0 4px 12px rgba(0, 0, 0, .5);
    --sh-lg: 0 12px 34px rgba(0, 0, 0, .6);
    --sh-focus: 0 0 0 3px rgba(77, 139, 255, .28);
  }
}
:root[data-theme="dark"] {
  color-scheme: dark;
  --g-0:  #0b0f14;
  --g-25: #0e1319;
  --g-50: #12181f;
  --g-100:#182029;
  --g-200:#232d38;
  --g-300:#33404e;
  --g-400:#5c6b7c;
  --g-500:#8b98a8;
  --g-600:#a9b5c2;
  --g-700:#c6cfd9;
  --g-800:#e0e6ec;
  --g-900:#f2f5f8;
  --g-950:#ffffff;

  --accent:        #4d8bff;
  --accent-hover:  #7aa7ff;
  --accent-soft:   #14243d;
  --accent-border: #2a4a7d;
  --accent-ink:    #06101f;

  --ok:      #4ade9c;
  --ok-soft: #0e2a1e;
  --warn:      #e2b45c;
  --warn-soft: #2a2013;
  --danger:      #ff7b72;
  --danger-hover:#ff9d96;
  --danger-soft: #2c1616;

  --bg:          var(--g-25);
  --bg-alt:      var(--g-0);
  --surface:     var(--g-50);
  --surface-alt: var(--g-100);
  --surface-sunken: var(--g-100);
  --border:       var(--g-200);
  --border-strong:var(--g-300);
  --ink:      var(--g-900);
  --ink-soft: var(--g-600);
  --ink-mute: var(--g-500);
  --ink-invert: var(--g-0);

  --sh-xs: 0 1px 2px rgba(0, 0, 0, .4);
  --sh-sm: 0 1px 3px rgba(0, 0, 0, .45);
  --sh-md: 0 4px 12px rgba(0, 0, 0, .5);
  --sh-lg: 0 12px 34px rgba(0, 0, 0, .6);
  --sh-focus: 0 0 0 3px rgba(77, 139, 255, .28);
}

/* =============================================================================
   2. RESET Y BASE
   ============================================================================= */
*, *::before, *::after { box-sizing: border-box; margin: 0; }
html {
  -webkit-text-size-adjust: 100%;
  tab-size: 2;
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--header-h) + var(--s-4));
}
body {
  font-family: var(--sans);
  font-size: var(--fs-base);
  line-height: var(--lh-base);
  color: var(--ink);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: clip;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}
[hidden] { display: none !important; }   /* gana a los display:flex de los componentes */
img, svg, video, canvas { display: block; max-width: 100%; }
img { height: auto; }
button { font: inherit; color: inherit; cursor: pointer; border: 0; background: none; }
a { color: inherit; text-decoration: none; }
p { text-wrap: pretty; }
h1, h2, h3, h4 { text-wrap: balance; line-height: var(--lh-tight); letter-spacing: -0.021em; font-weight: var(--fw-semi); }
h1 { font-size: var(--fs-3xl); letter-spacing: -0.03em; }
h2 { font-size: var(--fs-2xl); }
h3 { font-size: var(--fs-xl); }
h4 { font-size: var(--fs-lg); }
ul, ol { padding-left: var(--s-5); }
li + li { margin-top: var(--s-1); }
code, kbd, samp, pre { font-family: var(--mono); font-size: 0.92em; }
code { background: var(--surface-sunken); border-radius: var(--r-xs); padding: .1em .35em; }
hr { border: 0; border-top: 1px solid var(--border); margin: var(--s-8) 0; }
::selection { background: var(--accent); color: var(--accent-ink); }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: var(--r-xs); }
:target { scroll-margin-top: calc(var(--header-h) + var(--s-6)); }

/* =============================================================================
   3. UTILIDADES
   ============================================================================= */
.wrap { width: 100%; max-width: var(--wrap); margin-inline: auto; padding-inline: var(--s-4); }
.wrap--narrow { max-width: var(--wrap-narrow); }
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0;
}
/* La cabecera la pinta site.js sobre un <header> vacío. Sin reservar su alto,
   al entrar empuja hacia abajo TODA la página: es el salto que más molesta,
   porque mueve justo lo que el visitante está mirando. Con conexión rápida no
   se nota —el JS entra antes de pintar— y por eso no salía en las pruebas
   locales; con conexión lenta se nota siempre. */
/* +1px es el borde inferior: --header-h son los 60 del contenido y la cabecera
   mide 61 en pantalla. Un píxel no arregla nada por sí solo, pero reservar de
   menos deja siempre un salto residual, y cuadrarlo no cuesta nada. */
#site-header { display: block; min-height: calc(var(--header-h) + 1px); }

.skip-link {
  position: fixed; top: -100px; left: var(--s-4); z-index: 9999;
  padding: var(--s-2) var(--s-4); background: var(--accent); color: var(--accent-ink);
  border-radius: var(--r-sm); font-weight: var(--fw-medium);
}
.skip-link:focus { top: var(--s-3); }
.eyebrow {
  font-family: var(--mono); font-size: var(--fs-2xs); font-weight: var(--fw-medium);
  letter-spacing: .12em; text-transform: uppercase; color: var(--ink-mute);
}
.lede { font-size: var(--fs-lg); line-height: var(--lh-snug); color: var(--ink-soft); }
.muted { color: var(--ink-mute); }
.mono { font-family: var(--mono); }
.nowrap { white-space: nowrap; }
.stack > * + * { margin-top: var(--s-4); }
.section { padding-block: var(--s-12); }
.section + .section { padding-top: 0; }
.hide { display: none !important; }
main { flex: 1 0 auto; }

/* Prosa: bloques de texto SEO / legales */
.prose { max-width: 68ch; }
.prose h2 { margin-top: var(--s-10); margin-bottom: var(--s-3); }
.prose h3 { margin-top: var(--s-6); margin-bottom: var(--s-2); font-size: var(--fs-lg); }
.prose p, .prose ul, .prose ol { margin-bottom: var(--s-4); color: var(--ink-soft); }
.prose strong { color: var(--ink); font-weight: var(--fw-semi); }
.prose a { color: var(--accent); text-decoration: underline; text-underline-offset: 2px; }
.prose a:hover { color: var(--accent-hover); }
.prose > :first-child { margin-top: 0; }

/* =============================================================================
   4. CABECERA
   ============================================================================= */
.site-header {
  position: sticky; top: 0; z-index: var(--z-header);
  background: color-mix(in srgb, var(--bg) 88%, transparent);
  backdrop-filter: saturate(1.4) blur(10px);
  border-bottom: 1px solid var(--border);
}
.site-header__inner {
  height: var(--header-h);
  display: flex; align-items: center; gap: var(--s-3);
}
.logo { display: inline-flex; align-items: center; gap: var(--s-2); font-weight: var(--fw-semi); letter-spacing: -0.02em; font-size: var(--fs-md); }
.logo__mark {
  width: 26px; height: 26px; border-radius: var(--r-sm); flex: none;
  background: var(--accent); color: var(--accent-ink);
  display: grid; place-items: center;
}
.logo__mark svg { width: 15px; height: 15px; }
.logo__text b { font-weight: var(--fw-bold); }
.logo__text span { color: var(--ink-mute); font-weight: var(--fw-normal); }

.header-nav { margin-left: auto; display: flex; align-items: center; gap: var(--s-1); }

/* Botón genérico de cabecera */
.hbtn {
  display: inline-flex; align-items: center; gap: var(--s-2);
  height: 36px; padding-inline: var(--s-3);
  border-radius: var(--r-sm); border: 1px solid transparent;
  font-size: var(--fs-sm); font-weight: var(--fw-medium); color: var(--ink-soft);
  transition: background var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out), border-color var(--dur-fast) var(--ease-out);
}
.hbtn:hover { background: var(--surface-sunken); color: var(--ink); }
.hbtn[aria-expanded="true"] { background: var(--surface-sunken); color: var(--ink); border-color: var(--border); }
.hbtn svg { width: 15px; height: 15px; flex: none; }
.hbtn__chev { transition: transform var(--dur) var(--ease-out); }
.hbtn[aria-expanded="true"] .hbtn__chev { transform: rotate(180deg); }

/* Desplegable de herramientas */
.menu { position: relative; }
.menu__panel {
  /* Anclado a la VENTANA y no al botón. Colgándolo del botón —que está pegado
     al borde derecho, con el tema y el idioma detrás— un panel de 860 px se
     salía por la izquierda en cuanto la pantalla bajaba de 1100: medido, −101
     píxeles a 900 de ancho. Anclado al margen de la página no se sale nunca.

     Y la anchura es EXPLÍCITA: con solo min/max el panel se ajusta a su
     contenido y las columnas de `minmax(0, 1fr)` se aplastan; salían las
     cuatro metidas en 300 px y 2036 de alto, o sea la lista larga de siempre. */
  position: fixed; top: calc(var(--header-h) + 6px); z-index: var(--z-dropdown);
  right: max(var(--s-4), calc((100vw - var(--wrap)) / 2 + var(--s-4)));
  width: min(860px, calc(100vw - var(--s-8)));
  max-height: min(78vh, 640px); overflow-y: auto;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--r-lg); box-shadow: var(--sh-lg);
  padding: var(--s-2);
  opacity: 0; visibility: hidden; transform: translateY(-6px);
  transition: opacity var(--dur) var(--ease-out), transform var(--dur) var(--ease-out), visibility var(--dur);
}
.menu[data-open="true"] .menu__panel { opacity: 1; visibility: visible; transform: none; }
.menu__label { padding: var(--s-2) var(--s-3) var(--s-1); }
/* -----------------------------------------------------------------------------
   El desplegable, en columnas por categoría. Con más de veinte herramientas,
   una lista seguida obliga a desplazarse y no se encuentra nada.
   ----------------------------------------------------------------------------- */
.menu__cols {
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--s-1) var(--s-2);
  padding: 0 var(--s-1) var(--s-1);
}
.menu__col { min-width: 0; }
/* Detrás de la regla base, no delante: con la misma especificidad gana la
   última, y puestas antes no hacían nada —a 780 px seguían saliendo cuatro
   columnas—. */
@media (max-width: 1040px) { .menu__cols { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 820px)  { .menu__cols { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 460px)  { .menu__cols { grid-template-columns: 1fr; } }
.menu__cat {
  margin: 0; padding: var(--s-2) var(--s-2) var(--s-1);
  font-size: var(--fs-2xs); font-weight: var(--fw-semi); color: var(--ink-soft);
  text-transform: uppercase; letter-spacing: .06em;
  border-bottom: 1px solid var(--border); margin-bottom: var(--s-1);
}
.menu__todas {
  display: block; margin: var(--s-1) var(--s-1) 0;
  padding: var(--s-2) var(--s-3); border-top: 1px solid var(--border);
  font-size: var(--fs-xs); font-weight: var(--fw-medium); color: var(--accent);
  text-align: center; border-radius: 0 0 var(--r-md) var(--r-md);
}
.menu__todas:hover { background: var(--accent-soft); }

.menu__item {
  display: flex; gap: var(--s-2); align-items: center;
  padding: var(--s-2); border-radius: var(--r-sm);
  transition: background var(--dur-fast) var(--ease-out);
}
.menu__item:hover { background: var(--surface-sunken); }
.menu__item[aria-current="page"] { background: var(--accent-soft); }
.menu__ico { width: 26px; height: 26px; flex: none; border-radius: var(--r-sm); background: var(--surface-sunken); color: var(--accent); display: grid; place-items: center; }
.menu__ico svg { width: 16px; height: 16px; }
.menu__item[aria-current="page"] .menu__ico { background: var(--surface); }
.menu__name {
  display: block; font-size: var(--fs-xs); font-weight: var(--fw-medium); color: var(--ink);
  line-height: 1.3; min-width: 0; overflow-wrap: anywhere;
}
.menu__desc { display: block; font-size: var(--fs-xs); color: var(--ink-mute); line-height: 1.4; }
.menu__empty { padding: var(--s-3); font-size: var(--fs-xs); color: var(--ink-mute); }

/* Selector de idioma */
.lang { display: inline-flex; padding: 2px; gap: 2px; background: var(--surface-sunken); border-radius: var(--r-sm); }
.lang a {
  font-family: var(--mono); font-size: var(--fs-2xs); font-weight: var(--fw-medium);
  text-transform: uppercase; letter-spacing: .06em;
  padding: 5px var(--s-2); border-radius: var(--r-xs); color: var(--ink-mute);
  transition: background var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out);
}
.lang a:hover { color: var(--ink); }
.lang a[aria-current="true"] { background: var(--surface); color: var(--ink); box-shadow: var(--sh-xs); }

/* =============================================================================
   5. MIGAS DE PAN
   ============================================================================= */
.crumbs { padding-block: var(--s-4) 0; }
.crumbs ol { list-style: none; padding: 0; margin: 0; display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-1); font-size: var(--fs-xs); color: var(--ink-mute); }
.crumbs li { display: inline-flex; align-items: center; gap: var(--s-1); margin: 0; }
.crumbs li + li::before { content: "/"; color: var(--border-strong); margin-right: var(--s-1); }
.crumbs a { color: var(--ink-mute); }
.crumbs a:hover { color: var(--accent); text-decoration: underline; text-underline-offset: 2px; }
.crumbs [aria-current="page"] { color: var(--ink-soft); }

/* =============================================================================
   6. BOTONES
   ============================================================================= */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--s-2);
  min-height: 40px; padding: var(--s-2) var(--s-4);
  border-radius: var(--r-sm); border: 1px solid transparent;
  font-size: var(--fs-sm); font-weight: var(--fw-medium); letter-spacing: -0.005em;
  text-align: center; white-space: nowrap;
  transition: background var(--dur-fast) var(--ease-out), border-color var(--dur-fast) var(--ease-out),
              color var(--dur-fast) var(--ease-out), box-shadow var(--dur-fast) var(--ease-out), transform var(--dur-fast) var(--ease-out);
}
.btn svg { width: 16px; height: 16px; flex: none; }
.btn:active { transform: translateY(1px); }
.btn:disabled, .btn[aria-disabled="true"] { opacity: .5; pointer-events: none; }

.btn--primary { background: var(--accent); color: var(--accent-ink); box-shadow: var(--sh-xs); }
.btn--primary:hover { background: var(--accent-hover); }
.btn--secondary { background: var(--surface); color: var(--ink); border-color: var(--border-strong); }
.btn--secondary:hover { background: var(--surface-sunken); border-color: var(--g-400); }
.btn--danger { background: var(--danger-soft); color: var(--danger); border-color: color-mix(in srgb, var(--danger) 30%, transparent); }
.btn--danger:hover { background: var(--danger); color: var(--g-0); border-color: var(--danger); }
.btn--ghost { color: var(--ink-soft); }
.btn--ghost:hover { background: var(--surface-sunken); color: var(--ink); }
.btn--lg { min-height: 50px; padding-inline: var(--s-6); font-size: var(--fs-md); border-radius: var(--r-md); }
.btn--sm { min-height: 32px; padding: var(--s-1) var(--s-3); font-size: var(--fs-xs); }
.btn--block { display: flex; width: 100%; }
.btn--link { padding: 0; min-height: 0; color: var(--accent); text-decoration: underline; text-underline-offset: 2px; }
.btn--link:hover { color: var(--accent-hover); }

.btn-row { display: flex; flex-wrap: wrap; gap: var(--s-2); }

/* =============================================================================
   7. CAMPOS DE FORMULARIO
   ============================================================================= */
.field { display: flex; flex-direction: column; gap: var(--s-2); min-width: 0; }
.field__label { font-size: var(--fs-xs); font-weight: var(--fw-medium); color: var(--ink-soft); display: flex; align-items: baseline; justify-content: space-between; gap: var(--s-2); }
.field__hint { font-size: var(--fs-xs); color: var(--ink-mute); }
.field__value { font-family: var(--mono); font-size: var(--fs-xs); color: var(--accent); font-weight: var(--fw-medium); }

.input, .select, .textarea {
  width: 100%; min-height: 40px; padding: var(--s-2) var(--s-3);
  background: var(--surface); color: var(--ink);
  border: 1px solid var(--border-strong); border-radius: var(--r-sm);
  font-size: var(--fs-sm); font-family: inherit;
  transition: border-color var(--dur-fast) var(--ease-out), box-shadow var(--dur-fast) var(--ease-out);
}
.input::placeholder, .textarea::placeholder { color: var(--ink-mute); }
.input:focus, .select:focus, .textarea:focus { outline: none; border-color: var(--accent); box-shadow: var(--sh-focus); }
.input--mono { font-family: var(--mono); }
.textarea { min-height: 84px; resize: vertical; line-height: 1.5; }
.select {
  appearance: none; padding-right: var(--s-8); cursor: pointer;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%236b7686' stroke-width='1.6' stroke-linecap='round'%3E%3Cpath d='M4 6.5 8 10.5 12 6.5'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right var(--s-3) center; background-size: 14px;
}

/* Etiqueta y control en la misma linea, para barras de herramientas */
.inline-field { display: inline-flex; align-items: center; gap: var(--s-2); }
.inline-field__label { font-size: var(--fs-xs); color: var(--ink-mute); white-space: nowrap; }

/* Variantes compactas, para barras de herramientas dentro de una herramienta */
.select--sm { width: auto; min-height: 32px; padding: var(--s-1) var(--s-6) var(--s-1) var(--s-2); font-size: var(--fs-xs); }
.input--sm { min-height: 32px; padding: var(--s-1) var(--s-2); font-size: var(--fs-xs); }

/* Deslizador */
.slider { -webkit-appearance: none; appearance: none; width: 100%; height: 22px; background: transparent; cursor: pointer; }
.slider::-webkit-slider-runnable-track { height: 5px; border-radius: var(--r-full); background: var(--surface-sunken); border: 1px solid var(--border); }
.slider::-moz-range-track { height: 5px; border-radius: var(--r-full); background: var(--surface-sunken); border: 1px solid var(--border); }
.slider::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none; width: 18px; height: 18px; margin-top: -7px;
  border-radius: var(--r-full); background: var(--accent); border: 2px solid var(--surface); box-shadow: var(--sh-sm);
  transition: transform var(--dur-fast) var(--ease-out);
}
.slider::-moz-range-thumb { width: 18px; height: 18px; border-radius: var(--r-full); background: var(--accent); border: 2px solid var(--surface); box-shadow: var(--sh-sm); }
.slider:hover::-webkit-slider-thumb { transform: scale(1.12); }
.slider:focus-visible::-webkit-slider-thumb { box-shadow: var(--sh-focus); }

/* Casillas y opciones */
.check { display: flex; align-items: center; gap: var(--s-2); font-size: var(--fs-sm); color: var(--ink-soft); cursor: pointer; }
.check input { width: 16px; height: 16px; accent-color: var(--accent); cursor: pointer; flex: none; }

.segmented { display: inline-flex; padding: 3px; gap: 3px; background: var(--surface-sunken); border: 1px solid var(--border); border-radius: var(--r-sm); flex-wrap: wrap; }
.segmented label { position: relative; }
.segmented input { position: absolute; opacity: 0; width: 0; height: 0; }
.segmented span {
  display: block; padding: var(--s-1) var(--s-3); border-radius: var(--r-xs);
  font-size: var(--fs-xs); font-weight: var(--fw-medium); color: var(--ink-mute); cursor: pointer;
  transition: background var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out);
}
.segmented input:checked + span { background: var(--surface); color: var(--ink); box-shadow: var(--sh-xs); }
.segmented input:focus-visible + span { outline: 2px solid var(--accent); outline-offset: 1px; }

/* =============================================================================
   8. PESTAÑAS
   ============================================================================= */
.tabs { display: flex; gap: var(--s-1); border-bottom: 1px solid var(--border); overflow-x: auto; scrollbar-width: none; -webkit-overflow-scrolling: touch; }
.tabs::-webkit-scrollbar { display: none; }
.tab {
  position: relative; display: inline-flex; align-items: center; gap: var(--s-2);
  padding: var(--s-3) var(--s-3); white-space: nowrap;
  font-size: var(--fs-sm); font-weight: var(--fw-medium); color: var(--ink-mute);
  border-bottom: 2px solid transparent; margin-bottom: -1px;
  transition: color var(--dur-fast) var(--ease-out), border-color var(--dur-fast) var(--ease-out);
}
.tab svg { width: 15px; height: 15px; }
.tab:hover { color: var(--ink); }
.tab[aria-selected="true"] { color: var(--accent); border-bottom-color: var(--accent); }
.tabpanel { padding-top: var(--s-5); }
.tabpanel[hidden] { display: none; }

/* =============================================================================
   9. TARJETAS
   ============================================================================= */
.card {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--r-lg); box-shadow: var(--sh-sm);
}
.card__body { padding: var(--s-5); }
.card__head { padding: var(--s-4) var(--s-5); border-bottom: 1px solid var(--border); display: flex; align-items: center; justify-content: space-between; gap: var(--s-3); flex-wrap: wrap; }
.card__title { font-size: var(--fs-md); font-weight: var(--fw-semi); }

/* Tarjeta de herramienta (índice + relacionadas) */
.tool-grid { display: grid; gap: var(--s-4); grid-template-columns: repeat(auto-fill, minmax(min(100%, 280px), 1fr)); }
.tool-card {
  display: flex; flex-direction: column; gap: var(--s-2);
  padding: var(--s-5); background: var(--surface);
  border: 1px solid var(--border); border-radius: var(--r-lg);
  box-shadow: var(--sh-xs);
  transition: border-color var(--dur) var(--ease-out), box-shadow var(--dur) var(--ease-out), transform var(--dur) var(--ease-out);
}
a.tool-card:hover { border-color: var(--accent-border); box-shadow: var(--sh-md); transform: translateY(-2px); }
.tool-card__ico {
  width: 38px; height: 38px; border-radius: var(--r-md); flex: none;
  background: var(--accent-soft); color: var(--accent);
  display: grid; place-items: center; margin-bottom: var(--s-1);
}
.tool-card__ico svg { width: 19px; height: 19px; }
.tool-card__name { font-size: var(--fs-md); font-weight: var(--fw-semi); color: var(--ink); display: flex; align-items: center; gap: var(--s-2); }
.tool-card__desc { font-size: var(--fs-sm); color: var(--ink-mute); line-height: 1.5; }
.tool-card__more { margin-top: auto; padding-top: var(--s-3); font-size: var(--fs-xs); font-weight: var(--fw-medium); color: var(--accent); display: inline-flex; align-items: center; gap: var(--s-1); }
a.tool-card:hover .tool-card__more svg { transform: translateX(3px); }
.tool-card__more svg { width: 13px; height: 13px; transition: transform var(--dur) var(--ease-out); }
.tool-card--soon { border-style: dashed; box-shadow: none; background: transparent; }
.tool-card--soon .tool-card__ico { background: var(--surface-sunken); color: var(--ink-mute); }

/* Subpáginas de un hub, bajo su tarjeta del índice.
   Van FUERA de la tarjeta porque la tarjeta entera ya es un enlace y un <a>
   dentro de otro <a> no es HTML válido: el navegador lo deshace por su cuenta
   y los enlaces de dentro dejan de existir.
   El color es --ink-soft y no --ink-mute a propósito: sobre el fondo de la
   página, el mute se queda en 4,48:1 y no llega al 4,5 que pide la AA. */
.tool-cell { display: flex; flex-direction: column; }
.tool-cell > .tool-card { flex: 1 1 auto; }
.tool-subs {
  display: flex; flex-wrap: wrap; align-items: baseline;
  gap: var(--s-1) var(--s-3);
  margin: var(--s-2) 0 0; padding: 0 var(--s-2);
  font-size: var(--fs-xs); line-height: 1.6;
}
.tool-subs__label { color: var(--ink-soft); font-weight: var(--fw-semi); }
.tool-subs__link {
  color: var(--ink-soft); text-decoration: none;
  border-bottom: 1px solid var(--border-strong);
  transition: color var(--dur) var(--ease-out), border-color var(--dur) var(--ease-out);
}
.tool-subs__link:hover { color: var(--accent); border-bottom-color: var(--accent); }

.badge {
  display: inline-flex; align-items: center; gap: var(--s-1);
  padding: 2px var(--s-2); border-radius: var(--r-full);
  font-family: var(--mono); font-size: var(--fs-2xs); font-weight: var(--fw-medium);
  letter-spacing: .04em; text-transform: uppercase;
  background: var(--surface-sunken); color: var(--ink-mute); border: 1px solid var(--border);
}
.badge--new { background: var(--accent-soft); color: var(--accent); border-color: var(--accent-border); }
.badge--ok { background: var(--ok-soft); color: var(--ok); border-color: color-mix(in srgb, var(--ok) 25%, transparent); }

/* Estructura lista para «herramientas relacionadas» aunque esté vacía */
.related__empty {
  padding: var(--s-6); text-align: center; font-size: var(--fs-sm); color: var(--ink-mute);
  border: 1px dashed var(--border-strong); border-radius: var(--r-lg);
}

/* =============================================================================
   10. BLOQUE DE PRIVACIDAD (reutilizable en toda herramienta de archivos)
   ============================================================================= */
.privacy-note {
  display: flex; gap: var(--s-3); align-items: flex-start;
  padding: var(--s-4); border-radius: var(--r-md);
  background: var(--ok-soft); border: 1px solid color-mix(in srgb, var(--ok) 22%, transparent);
}
.privacy-note__ico { width: 26px; height: 26px; flex: none; border-radius: var(--r-sm); background: var(--ok); color: var(--g-0); display: grid; place-items: center; }
:root[data-theme="dark"] .privacy-note__ico, :root:not([data-theme="light"]) .privacy-note__ico { color: var(--g-0); }
.privacy-note__ico svg { width: 15px; height: 15px; }
.privacy-note__title { display: block; font-size: var(--fs-sm); font-weight: var(--fw-semi); color: var(--ink); }
.privacy-note__text { display: block; font-size: var(--fs-xs); color: var(--ink-soft); line-height: 1.55; margin-top: 4px; }
.privacy-note--hero { background: var(--surface); border-color: var(--border); box-shadow: var(--sh-xs); }

/* =============================================================================
   11. ZONA DE ARRASTRAR Y SOLTAR
   ============================================================================= */
.dropzone {
  position: relative; display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: var(--s-3); text-align: center;
  min-height: 210px; padding: var(--s-6) var(--s-4);
  border: 2px dashed var(--border-strong); border-radius: var(--r-lg);
  background: var(--surface-alt); cursor: pointer;
  transition: border-color var(--dur) var(--ease-out), background var(--dur) var(--ease-out), transform var(--dur) var(--ease-out);
}
.dropzone:hover { border-color: var(--accent-border); background: var(--surface); }
.dropzone input[type="file"] { position: absolute; inset: 0; opacity: 0; width: 100%; height: 100%; cursor: pointer; }
.dropzone__ico { width: 46px; height: 46px; border-radius: var(--r-md); background: var(--accent-soft); color: var(--accent); display: grid; place-items: center; }
.dropzone__ico svg { width: 22px; height: 22px; }
.dropzone__title { font-size: var(--fs-md); font-weight: var(--fw-semi); color: var(--ink); }
.dropzone__hint { font-size: var(--fs-xs); color: var(--ink-mute); }
.dropzone__hint code { font-size: var(--fs-2xs); }

.dropzone[data-state="over"] { border-color: var(--accent); background: var(--accent-soft); transform: scale(1.006); }
.dropzone[data-state="over"] .dropzone__ico { background: var(--accent); color: var(--accent-ink); }
.dropzone[data-state="busy"] { border-style: solid; border-color: var(--accent-border); background: var(--surface); cursor: progress; }
.dropzone[data-state="busy"] input[type="file"] { pointer-events: none; }
.dropzone[data-state="busy"] .dropzone__ico { background: var(--accent-soft); color: var(--accent); animation: ub-pulse 1.4s var(--ease-out) infinite; }
.dropzone[data-state="error"] { border-color: var(--danger); background: var(--danger-soft); }
.dropzone[data-state="error"] .dropzone__ico { background: var(--danger); color: var(--g-0); }
.dropzone--compact { min-height: 120px; padding: var(--s-4); }

@keyframes ub-pulse { 0%,100% { opacity: 1; } 50% { opacity: .45; } }

/* =============================================================================
   12. BARRA DE PROGRESO
   ============================================================================= */
.progress { display: flex; flex-direction: column; gap: var(--s-2); width: 100%; }
.progress__bar { height: 6px; border-radius: var(--r-full); background: var(--surface-sunken); overflow: hidden; border: 1px solid var(--border); }
.progress__fill { height: 100%; width: 0%; background: var(--accent); border-radius: var(--r-full); transition: width var(--dur) var(--ease-out); }
.progress[data-indeterminate="true"] .progress__fill { width: 35%; animation: ub-slide 1.1s var(--ease-out) infinite; }
.progress__meta { display: flex; justify-content: space-between; gap: var(--s-3); font-size: var(--fs-xs); color: var(--ink-mute); }
.progress__meta b { font-family: var(--mono); font-weight: var(--fw-medium); color: var(--ink-soft); }
@keyframes ub-slide { 0% { margin-left: -35%; } 100% { margin-left: 100%; } }

/* =============================================================================
   13. AVISO DE ESTADO
   ============================================================================= */
.notice {
  display: flex; gap: var(--s-3); align-items: flex-start;
  padding: var(--s-3) var(--s-4); border-radius: var(--r-md);
  border: 1px solid var(--border); background: var(--surface-alt);
  font-size: var(--fs-sm); color: var(--ink-soft);
}
.notice__ico { width: 18px; height: 18px; flex: none; margin-top: 2px; color: var(--ink-mute); }
.notice__ico svg { width: 100%; height: 100%; }
.notice b { color: var(--ink); font-weight: var(--fw-semi); }
.notice--info    { background: var(--accent-soft); border-color: var(--accent-border); }
.notice--info .notice__ico { color: var(--accent); }
.notice--ok      { background: var(--ok-soft); border-color: color-mix(in srgb, var(--ok) 25%, transparent); }
.notice--ok .notice__ico { color: var(--ok); }
.notice--warn    { background: var(--warn-soft); border-color: color-mix(in srgb, var(--warn) 30%, transparent); }
.notice--warn .notice__ico { color: var(--warn); }
.notice--danger  { background: var(--danger-soft); border-color: color-mix(in srgb, var(--danger) 30%, transparent); }
.notice--danger .notice__ico { color: var(--danger); }
.notice__actions { margin-left: auto; display: flex; gap: var(--s-2); flex: none; }

/* =============================================================================
   14. TABLA DE RESULTADOS
   ============================================================================= */
.table-wrap { overflow-x: auto; border: 1px solid var(--border); border-radius: var(--r-md); background: var(--surface); }
.table { width: 100%; border-collapse: collapse; font-size: var(--fs-sm); min-width: 420px; }
.table th, .table td { padding: var(--s-3) var(--s-4); text-align: left; border-bottom: 1px solid var(--border); }
.table th {
  font-family: var(--mono); font-size: var(--fs-2xs); font-weight: var(--fw-medium);
  letter-spacing: .07em; text-transform: uppercase; color: var(--ink-mute);
  background: var(--surface-alt); white-space: nowrap;
}
.table tbody tr:last-child td { border-bottom: 0; }
.table tbody tr:hover { background: var(--surface-alt); }
.table td.num { font-family: var(--mono); font-variant-numeric: tabular-nums; white-space: nowrap; }
.table .delta-down { color: var(--ok); font-weight: var(--fw-medium); }
.table .delta-up { color: var(--warn); font-weight: var(--fw-medium); }

/* =============================================================================
   15. HUECOS DE ANUNCIOS (placeholders — nunca empujan la herramienta)
   ============================================================================= */
.ad-slot {
  position: relative; display: flex; align-items: center; justify-content: center;
  border: 1px dashed var(--border-strong); border-radius: var(--r-md);
  background: repeating-linear-gradient(135deg, var(--surface-alt) 0 10px, var(--surface) 10px 20px);
  color: var(--ink-mute); overflow: hidden;
}
.ad-slot::after {
  content: attr(data-label);
  font-family: var(--mono); font-size: var(--fs-2xs); font-weight: var(--fw-medium);
  letter-spacing: .18em; text-transform: uppercase; color: var(--ink-mute);
}
/* 280 px MEDIDOS, no estimados: es lo que ocupa el bloque responsive de
   AdSense a 360, 480, 768, 1024 y 1280 px de ancho. Reservar 96 dejaba un
   salto de 184 px justo en la primera pantalla, que es de lo que más pesa en
   el CLS. Si algún día el anuncio servido mide otra cosa, hay que volver a
   medir y cambiar este número: es el precio de reservar sitio de verdad. */
.ad-slot--leaderboard { min-height: 280px; margin-block: var(--s-8); }
.ad-slot--incontent   { min-height: 280px; margin-block: var(--s-8); }
.ad-slot--dialog      { min-height: 240px; width: 100%; }
.ad-slot--toast       { min-height: 78px; width: 100%; }
/* Con un anuncio de verdad dentro, el hueco deja de ser un marcador: fuera el
   rayado, el borde de puntos y la etiqueta, que si no se quedan por debajo y
   asomando por los lados del anuncio. */
.ad-slot[data-ad-listo="1"] { border: 0; background: none; display: block; }
.ad-slot[data-ad-listo="1"]::after { content: none; }
.ad-slot ins.adsbygoogle { display: block; width: 100%; }


/* Pop-up de descarga */
.ad-dialog {
  /* margin:auto centra el <dialog> modal; el reset global de margin lo anulaba */
  margin: auto;
  width: min(440px, calc(100vw - 2rem)); padding: 0; border: 1px solid var(--border);
  border-radius: var(--r-lg); background: var(--surface); color: var(--ink); box-shadow: var(--sh-lg);
}
.ad-dialog::backdrop { background: rgba(11, 15, 20, .55); backdrop-filter: blur(2px); }
.ad-dialog__head { display: flex; align-items: center; justify-content: space-between; gap: var(--s-3); padding: var(--s-3) var(--s-4); border-bottom: 1px solid var(--border); }
.ad-dialog__title { font-size: var(--fs-sm); font-weight: var(--fw-semi); display: flex; align-items: center; gap: var(--s-2); }
.ad-dialog__title svg { width: 16px; height: 16px; color: var(--ok); }
.ad-dialog__close { width: 30px; height: 30px; border-radius: var(--r-sm); display: grid; place-items: center; color: var(--ink-mute); transition: background var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out); }
.ad-dialog__close:hover { background: var(--surface-sunken); color: var(--ink); }
.ad-dialog__close svg { width: 16px; height: 16px; }
.ad-dialog__body { padding: var(--s-4); display: flex; flex-direction: column; gap: var(--s-4); }
.ad-dialog__foot { padding: 0 var(--s-4) var(--s-4); }

/* Notificación de esquina */
.ad-toast {
  position: fixed; right: var(--s-4); bottom: var(--s-4); z-index: var(--z-toast);
  width: min(300px, calc(100vw - 2rem));
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-md);
  box-shadow: var(--sh-lg); padding: var(--s-3);
  display: flex; flex-direction: column; gap: var(--s-2);
  opacity: 0; transform: translateY(10px); pointer-events: none;
  transition: opacity var(--dur) var(--ease-out), transform var(--dur) var(--ease-out);
}
.ad-toast[data-open="true"] { opacity: 1; transform: none; pointer-events: auto; }
.ad-toast__head { display: flex; align-items: center; justify-content: space-between; gap: var(--s-2); }
.ad-toast__label { font-family: var(--mono); font-size: var(--fs-2xs); letter-spacing: .14em; text-transform: uppercase; color: var(--ink-mute); }
.ad-toast__close { width: 24px; height: 24px; border-radius: var(--r-xs); display: grid; place-items: center; color: var(--ink-mute); }
.ad-toast__close:hover { background: var(--surface-sunken); color: var(--ink); }
.ad-toast__close svg { width: 14px; height: 14px; }


/* =============================================================================
   17. FAQ Y PASOS
   ============================================================================= */
.faq { display: flex; flex-direction: column; gap: var(--s-2); }
.faq details {
  border: 1px solid var(--border); border-radius: var(--r-md); background: var(--surface);
  transition: border-color var(--dur) var(--ease-out);
}
.faq details[open] { border-color: var(--accent-border); }
.faq summary {
  list-style: none; cursor: pointer; padding: var(--s-4);
  font-size: var(--fs-base); font-weight: var(--fw-medium); color: var(--ink);
  display: flex; align-items: flex-start; justify-content: space-between; gap: var(--s-3);
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after {
  content: ""; flex: none; width: 16px; height: 16px; margin-top: 3px;
  background: currentColor; color: var(--ink-mute);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M7.25 3h1.5v10h-1.5z'/%3E%3Cpath d='M3 7.25h10v1.5H3z'/%3E%3C/svg%3E") center/contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M7.25 3h1.5v10h-1.5z'/%3E%3Cpath d='M3 7.25h10v1.5H3z'/%3E%3C/svg%3E") center/contain no-repeat;
  transition: transform var(--dur) var(--ease-out);
}
.faq details[open] summary::after { transform: rotate(45deg); }
.faq summary:hover { color: var(--accent); }
.faq__answer { padding: 0 var(--s-4) var(--s-4); font-size: var(--fs-sm); color: var(--ink-soft); }
.faq__answer p + p { margin-top: var(--s-3); }
.faq__answer a { color: var(--accent); text-decoration: underline; text-underline-offset: 2px; }

.steps { display: grid; gap: var(--s-4); grid-template-columns: repeat(auto-fit, minmax(min(100%, 240px), 1fr)); counter-reset: step; list-style: none; padding: 0; }
.steps li { margin: 0; padding: var(--s-5); background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-lg); }
.steps li::before {
  counter-increment: step; content: counter(step);
  display: grid; place-items: center; width: 28px; height: 28px; margin-bottom: var(--s-3);
  border-radius: var(--r-sm); background: var(--accent-soft); color: var(--accent);
  font-family: var(--mono); font-size: var(--fs-xs); font-weight: var(--fw-bold);
}
.steps h3 { font-size: var(--fs-base); font-weight: var(--fw-semi); margin-bottom: var(--s-1); }
.steps p { font-size: var(--fs-sm); color: var(--ink-mute); }

.usecases { display: grid; gap: var(--s-3); grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr)); list-style: none; padding: 0; }
.usecases li { margin: 0; display: flex; gap: var(--s-3); padding: var(--s-4); border: 1px solid var(--border); border-radius: var(--r-md); background: var(--surface); font-size: var(--fs-sm); color: var(--ink-soft); }
.usecases svg { width: 17px; height: 17px; flex: none; color: var(--accent); margin-top: 2px; }
.usecases b { display: block; color: var(--ink); font-weight: var(--fw-semi); margin-bottom: 2px; }

/* =============================================================================
   18. HERO Y CABECERAS DE PÁGINA
   ============================================================================= */
.page-head { padding-block: var(--s-6) var(--s-5); }
.page-head h1 { margin-bottom: var(--s-3); }
.page-head .lede { max-width: 62ch; }

.hero { padding-block: var(--s-12) var(--s-8); text-align: center; }
.hero h1 { font-size: var(--fs-4xl); margin-bottom: var(--s-4); }
.hero .lede { max-width: 60ch; margin-inline: auto; }
.hero__points { display: flex; flex-wrap: wrap; gap: var(--s-2); justify-content: center; margin-top: var(--s-6); }
.hero__point {
  display: inline-flex; align-items: center; gap: var(--s-2);
  padding: var(--s-2) var(--s-3); border-radius: var(--r-full);
  border: 1px solid var(--border); background: var(--surface);
  font-size: var(--fs-xs); color: var(--ink-soft); box-shadow: var(--sh-xs);
}
.hero__point svg { width: 14px; height: 14px; color: var(--ok); flex: none; }

/* =============================================================================
   19. PIE DE PÁGINA
   ============================================================================= */
.site-footer { margin-top: var(--s-16); border-top: 1px solid var(--border); background: var(--bg-alt); padding-block: var(--s-10) var(--s-8); }
.footer-grid { display: grid; gap: var(--s-8); grid-template-columns: repeat(auto-fit, minmax(min(100%, 200px), 1fr)); }
.footer-brand { max-width: 34ch; }
.footer-brand p { font-size: var(--fs-xs); color: var(--ink-mute); margin-top: var(--s-3); line-height: 1.6; }
.footer-col h3 { font-family: var(--mono); font-size: var(--fs-2xs); font-weight: var(--fw-medium); letter-spacing: .12em; text-transform: uppercase; color: var(--ink-mute); margin-bottom: var(--s-3); }
.footer-col ul { list-style: none; padding: 0; display: flex; flex-direction: column; gap: var(--s-2); }
.footer-col li { margin: 0; }
.footer-col a { font-size: var(--fs-sm); color: var(--ink-soft); }
.footer-col a:hover { color: var(--accent); }
.footer-bottom {
  margin-top: var(--s-8); padding-top: var(--s-5); border-top: 1px solid var(--border);
  display: flex; flex-wrap: wrap; gap: var(--s-3); align-items: center; justify-content: space-between;
  font-size: var(--fs-xs); color: var(--ink-mute);
}
.footer-bottom a { color: var(--ink-soft); }
.footer-bottom a:hover { color: var(--accent); }

/* =============================================================================
   20. RESPONSIVE
   ============================================================================= */
@media (max-width: 539px) {
  :root { --header-h: 56px; }
  .hbtn__text { display: none; }
  .hbtn { padding-inline: var(--s-2); }
  .menu__panel { position: fixed; left: var(--s-3); right: var(--s-3); top: calc(var(--header-h) + 6px); width: auto; min-width: 0; max-width: none; max-height: 70vh; overflow-y: auto; }
  .menu__cols { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .card__body { padding: var(--s-4); }
  .ad-toast { left: var(--s-3); right: var(--s-3); bottom: var(--s-3); width: auto; }
}
@media (min-width: 720px) {
  .wrap { padding-inline: var(--s-6); }
}

/* =============================================================================
   21. MOVIMIENTO REDUCIDO (solo lo intrusivo)
   ============================================================================= */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .dropzone[data-state="busy"] .dropzone__ico { animation: none; }
  .progress[data-indeterminate="true"] .progress__fill { animation: none; width: 100%; opacity: .6; }
}

/* =============================================================================
   22. SIN JAVASCRIPT
   ============================================================================= */
.no-js-note { display: none; }
html.no-js .no-js-note { display: flex; }
/* La herramienta la monta su propio JavaScript dentro de una tarjeta vacía que
   está EN LA PRIMERA PANTALLA. Sin alto reservado, al montarse empuja todo lo
   que hay debajo. Cada herramienta declara el suyo —medido, uno a uno— en su
   propio archivo de estilos; este es el de reserva para las que no lo hagan. */
[data-needs-js] { min-height: var(--alto-herramienta, 320px); }
/* Base64 no tiene hoja propia: su alto va aquí. */
#b64-tool { --alto-herramienta: 459px; }
/* Ojo con lo que NO está aquí: antes había un `html.no-js [data-needs-js]
   { display: none }`. Parecía inocente y era el origen del salto: la clase
   `no-js` la quita el propio site.js, así que la tarjeta estaba oculta hasta
   que entraba el JavaScript y entonces aparecía de golpe, empujando la página
   entera. Reservarle alto no arreglaba nada, porque un elemento oculto no
   ocupa el alto que se le reserve.
   Ahora la tarjeta ocupa su sitio desde el primer pintado, y quien tenga el
   JavaScript desactivado la esconde con el <noscript> de la cabecera. */

/* =============================================================================
   23. UTILIDADES DE SECCIÓN (para no escribir estilos dentro de las páginas)
   ============================================================================= */
.section__lede { margin-bottom: var(--s-6); }
.section__title { margin-bottom: var(--s-5); }
.section__intro { margin-bottom: var(--s-8); }
.noscript-nav { padding-block: var(--s-8); font-size: var(--fs-sm); }
.noscript-nav a { color: var(--accent); text-decoration: underline; text-underline-offset: 2px; }

/* --- Móvil: la herramienta tiene que verse sin bajar la página --- */
@media (max-width: 719px) {
  .page-head { padding-block: var(--s-4) var(--s-3); }
  .page-head h1 { font-size: clamp(1.6rem, 1.1rem + 3.6vw, 2rem); margin-bottom: var(--s-2); }
  .page-head .lede { font-size: var(--fs-base); }
  .crumbs { padding-block: var(--s-3) 0; }
  .section { padding-block: var(--s-8); }
}

/* =============================================================================
   24. BLOQUES DE PÁGINA DE HERRAMIENTA (compartidos por todas las herramientas)
   ============================================================================= */
.tool-limits { font-size: var(--fs-xs); color: var(--ink-mute); }

/* --- Promesa de privacidad sobre la herramienta (toda herramienta) --- */
.tool-claim { display: grid; gap: var(--s-4); margin-bottom: var(--s-5); }
.tool-claim__badge {
  display: inline-flex; align-items: center; gap: var(--s-2); align-self: start; justify-self: start;
  padding: var(--s-2) var(--s-3); border-radius: var(--r-full);
  background: var(--ok-soft); color: var(--ok);
  border: 1px solid color-mix(in srgb, var(--ok) 30%, transparent);
  font-family: var(--mono); font-size: var(--fs-2xs); font-weight: var(--fw-medium);
  letter-spacing: .08em; text-transform: uppercase;
}
.tool-claim__badge svg { width: 14px; height: 14px; }
.tool-claim__why { font-size: var(--fs-sm); color: var(--ink-soft); max-width: 70ch; }
.tool-claim__why strong { color: var(--ink); font-weight: var(--fw-semi); }

/* --- El argumento largo va DEBAJO de la herramienta --- */
.tool-why { display: grid; gap: var(--s-5); }
.tool-why__text h2 { font-size: var(--fs-xl); margin-top: 0; margin-bottom: var(--s-3); }
@media (min-width: 960px) {
  .tool-why { grid-template-columns: 1fr 1fr; align-items: start; gap: var(--s-8); }
}

/* =============================================================================
   25. PÁGINA RAÍZ (la portada bilingüe de utiliobox.com/)
   -----------------------------------------------------------------------------
   La raíz ya no es un trampolín que redirige: es una página de verdad, en los
   dos idiomas, indexable, y con los 24 enlaces de cada idioma dentro del HTML.
   Su cabecera y su pie son estáticos, no los pinta site.js: aquí no hay un
   idioma «actual» del que sacar los textos del menú, y de paso la raíz no
   arrastra ni el registro ni los diccionarios.
   ============================================================================= */

/* --- Cabecera propia, sin menú de herramientas --- */
.root-header { border-bottom: 1px solid var(--border); background: var(--bg); }
.root-header__inner { height: var(--header-h); display: flex; align-items: center; gap: var(--s-3); }
.root-header__nav { margin-left: auto; display: flex; align-items: center; gap: var(--s-2); }
.root-header__nav a {
  display: inline-flex; align-items: center; height: 34px; padding-inline: var(--s-3);
  border: 1px solid var(--border); border-radius: var(--r-sm);
  font-size: var(--fs-sm); font-weight: var(--fw-medium); color: var(--ink-soft);
  transition: border-color var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out);
}
.root-header__nav a:hover { border-color: var(--accent-border); color: var(--accent); }

/* --- Sugerencia de idioma (solo la primera visita; NUNCA redirige) ---
   Nace con `hidden` y solo la enseña el guión de la raíz. Reserva su alto en
   cuanto aparece porque va bajo la cabecera y sobre el titular: si empujara
   el h1 sería exactamente el salto de maquetación que costó arreglar. */
.lang-hint {
  border-bottom: 1px solid var(--accent-border); background: var(--accent-soft);
}
.lang-hint__inner {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-3);
  padding-block: var(--s-3); font-size: var(--fs-sm); color: var(--ink-soft);
}
.lang-hint__go { font-weight: var(--fw-semi); color: var(--accent); text-decoration: underline; text-underline-offset: 3px; }
.lang-hint__go:hover { color: var(--accent-hover); }
.lang-hint__close { margin-left: auto; color: var(--ink-mute); display: inline-flex; padding: var(--s-1); }
.lang-hint__close svg { width: 14px; height: 14px; }
.lang-hint__close:hover { color: var(--ink); }

/* --- Titular bilingüe --- */
.root-hero { padding-block: var(--s-12) var(--s-8); text-align: center; }
.root-hero h1 { font-size: var(--fs-4xl); margin-bottom: var(--s-4); }
.root-hero__lede { font-size: var(--fs-lg); line-height: var(--lh-snug); color: var(--ink-soft); max-width: 60ch; margin-inline: auto; }
.root-hero__lede + .root-hero__lede { margin-top: var(--s-3); }
.root-hero__lede[lang="es"] { color: var(--ink-mute); }

/* --- Las dos puertas de idioma --- */
.lang-pick {
  display: grid; gap: var(--s-4); margin-top: var(--s-8);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr));
  text-align: left;
}
.lang-pick__card {
  display: flex; flex-direction: column; gap: var(--s-2);
  padding: var(--s-5); border: 1px solid var(--border); border-radius: var(--r-md);
  background: var(--surface); box-shadow: var(--sh-xs);
  transition: border-color var(--dur) var(--ease-out), transform var(--dur) var(--ease-out), box-shadow var(--dur) var(--ease-out);
}
.lang-pick__card:hover { border-color: var(--accent-border); transform: translateY(-2px); box-shadow: var(--sh-sm); }
.lang-pick__code {
  align-self: start; padding: var(--s-1) var(--s-2); border-radius: var(--r-xs);
  background: var(--accent-soft); color: var(--accent); border: 1px solid var(--accent-border);
  font-family: var(--mono); font-size: var(--fs-2xs); font-weight: var(--fw-medium); letter-spacing: .1em;
}
.lang-pick__name { font-size: var(--fs-xl); font-weight: var(--fw-semi); color: var(--ink); letter-spacing: -0.02em; }
.lang-pick__desc { font-size: var(--fs-sm); color: var(--ink-mute); line-height: 1.5; }
.lang-pick__go {
  margin-top: auto; padding-top: var(--s-3);
  font-size: var(--fs-sm); font-weight: var(--fw-medium); color: var(--accent);
  display: inline-flex; align-items: center; gap: var(--s-1);
}
.lang-pick__go svg { width: 14px; height: 14px; transition: transform var(--dur) var(--ease-out); }
.lang-pick__card:hover .lang-pick__go svg { transform: translateX(3px); }

/* --- Listado de herramientas: una tarjeta por herramienta, dos idiomas ---
   No se reutiliza .tool-card porque aquí la tarjeta NO es un enlace: lleva
   dos, uno por idioma, y un <a> dentro de otro <a> no es HTML válido. */
.dual-grid { display: grid; gap: var(--s-4); grid-template-columns: repeat(auto-fill, minmax(min(100%, 330px), 1fr)); }
.dual {
  display: flex; flex-direction: column; gap: var(--s-3);
  padding: var(--s-4) var(--s-5) var(--s-5);
  border: 1px solid var(--border); border-radius: var(--r-md);
  background: var(--surface); box-shadow: var(--sh-xs);
}
.dual__ico {
  width: 34px; height: 34px; border-radius: var(--r-sm); flex: none;
  display: grid; place-items: center;
  background: var(--accent-soft); color: var(--accent); border: 1px solid var(--accent-border);
}
.dual__ico svg { width: 19px; height: 19px; }
.dual__row { display: flex; flex-direction: column; gap: var(--s-1); }
.dual__row + .dual__row { padding-top: var(--s-3); border-top: 1px dashed var(--border); }
.dual__link {
  display: inline-flex; align-items: baseline; gap: var(--s-2);
  font-size: var(--fs-md); font-weight: var(--fw-semi); color: var(--ink); letter-spacing: -0.01em;
}
.dual__link:hover { color: var(--accent); }
.dual__link:hover .dual__code { border-color: var(--accent-border); color: var(--accent); }
.dual__code {
  flex: none; padding: 1px var(--s-2); border-radius: var(--r-xs);
  border: 1px solid var(--border-strong); background: var(--surface-alt); color: var(--ink-mute);
  font-family: var(--mono); font-size: var(--fs-2xs); font-weight: var(--fw-medium); letter-spacing: .08em;
  transition: border-color var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out);
}
.dual__desc { font-size: var(--fs-sm); color: var(--ink-mute); line-height: 1.5; }

/* --- Prosa a dos columnas: el mismo argumento en los dos idiomas --- */
.root-prose { display: grid; gap: var(--s-8); }
.root-prose h2 { font-size: var(--fs-xl); margin-bottom: var(--s-3); }
.root-prose p { color: var(--ink-soft); margin-bottom: var(--s-4); }
.root-prose p:last-child { margin-bottom: 0; }
.root-prose a { color: var(--accent); text-decoration: underline; text-underline-offset: 2px; }
@media (min-width: 860px) {
  .root-prose { grid-template-columns: 1fr 1fr; gap: var(--s-10); align-items: start; }
}

/* --- Pie propio, también estático --- */
.root-footer { margin-top: var(--s-16); border-top: 1px solid var(--border); background: var(--bg-alt); padding-block: var(--s-10) var(--s-8); }
.root-footer__cols { display: grid; gap: var(--s-8); grid-template-columns: repeat(auto-fit, minmax(min(100%, 200px), 1fr)); }
.root-footer h2 { font-family: var(--mono); font-size: var(--fs-2xs); font-weight: var(--fw-medium); letter-spacing: .12em; text-transform: uppercase; color: var(--ink-mute); margin-bottom: var(--s-3); }
.root-footer ul { list-style: none; padding: 0; display: flex; flex-direction: column; gap: var(--s-2); }
.root-footer li { margin: 0; }
.root-footer a { font-size: var(--fs-sm); color: var(--ink-soft); }
.root-footer a:hover { color: var(--accent); }
.root-footer__bottom {
  margin-top: var(--s-8); padding-top: var(--s-5); border-top: 1px solid var(--border);
  font-size: var(--fs-xs); color: var(--ink-mute);
}

/* =============================================================================
   GUÍAS Y FECHAS DE REVISIÓN
   ============================================================================= */
/* La caja de la herramienta abre y cierra cada guía: quien llega desde el
   buscador con el problema delante tiene la solución a un clic sin leer todo. */
.guide-meta { margin-top: var(--s-3); font-size: var(--fs-sm); }
.guide-tool {
  margin: var(--s-6) 0; padding: var(--s-5);
  background: var(--accent-soft); border: 1px solid var(--accent-border);
  border-radius: var(--r-lg);
}
.prose .guide-tool p { margin-bottom: var(--s-2); }
.prose .guide-tool__label { margin-bottom: var(--s-1); }
.prose .guide-tool__name { font-size: var(--fs-md); font-weight: var(--fw-semi); color: var(--ink); }
.prose .guide-tool__text { margin-bottom: var(--s-4); }
.prose .guide-tool a.btn { color: var(--accent-ink); text-decoration: none; }
.prose.guide > .guide-tool:first-child { margin-top: 0; }
.prose .notice { margin-bottom: var(--s-5); }
.prose .notice p:last-child { margin-bottom: 0; }
.prose .table-wrap { margin-bottom: var(--s-5); }
.page-revised { font-size: var(--fs-sm); padding-bottom: var(--s-6); }
/* Una cadena WIFI:… o un INSERT seguido no tiene por dónde partir y arrastra
   la página entera a lo ancho en el móvil. */
.prose.guide code { overflow-wrap: anywhere; }
