/* ============================================================
   Utilazo — hoja de estilos unica, organizada por secciones.
   Sin preprocesador ni paso de compilacion.

   Direccion visual: bloques. Papel crema, tinta negra, bordes
   gruesos y sombras duras (sin difuminar). El caracter esta en el
   contorno y en el color plano, no en degradados ni en brillos.
   ============================================================ */

/* --- 0. Tipografia --------------------------------------
   Space Grotesk servida desde aqui, NO desde fonts.googleapis.com.

   Dos motivos. El primero es el invariante del proyecto: nada de CDN en
   tiempo de ejecucion. La fuente era la unica excepcion que quedaba, y
   ademas era la unica peticion a un tercero en todo el sitio.

   El segundo es de privacidad: pedirla a Google transmite la IP de cada
   visitante antes de que haya consentido nada. Un juzgado de Munich lo
   considero infraccion del RGPD en enero de 2022. Es primera instancia
   alemana, no jurisprudencia europea, pero el sitio se dirige a Espana y
   presume de no rastrear a nadie: sostener eso con una peticion a Google en
   cada carga era contradictorio.

   Es una fuente VARIABLE: un solo archivo cubre de 300 a 700, asi que pesa
   menos que los tres pesos estaticos que se pedian antes. Los unicode-range
   son los mismos que sirve Google, para que el navegador solo baje el
   subconjunto que necesite. El vietnamita no se incluye.

   Licencia: SIL Open Font License 1.1, que permite alojarla.
   --------------------------------------------------------- */
@font-face {
  font-family: "Space Grotesk";
  font-style: normal;
  font-weight: 300 700;
  font-display: swap;   /* texto visible desde el primer momento */
  src: url("lib/fonts/space-grotesk-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6,
    U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122,
    U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Space Grotesk";
  font-style: normal;
  font-weight: 300 700;
  font-display: swap;
  src: url("lib/fonts/space-grotesk-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7,
    U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F,
    U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F,
    U+A720-A7FF;
}

/* --- 1. Tokens ------------------------------------------- */
:root {
  --bg: #FFFCF2;          /* papel crema */
  --bg-alt: #F7F2E4;
  --surface: #FFFCF2;
  --paper: #FFFFFF;       /* campos y zonas de entrada */
  --ink: #1B1B1B;
  --text: #1B1B1B;
  --text-soft: #4A463E;
  --text-mute: #8C8779;

  --accent: #E4572E;      /* naranja de marca */
  --accent-hover: #C6431D;
  --yellow: #FFD447;
  --ok: #1E7A47;
  --warn: #B45309;
  --err: #C42B1C;

  --border: var(--ink);
  --border-strong: var(--ink);
  --bw: 2px;              /* grosor estandar */
  --bw-lg: 3px;           /* estructura: cabecera, secciones */

  /* Sombra dura: el sello de esta direccion. Nunca difuminada. */
  --shadow: 4px 4px 0 var(--ink);
  --shadow-sm: 3px 3px 0 var(--ink);
  --shadow-lg: 6px 6px 0 var(--ink);

  /* Un color por categoria: rellenos planos, siempre con tinta encima. */
  --c-imagen: #C7E9F1;
  --c-documentos: #FFD447;
  --c-calculadoras: #FFC9B5;
  --c-generadores: #E7D3F5;
  --c-internet: #CDEBC5;

  /* Texto que va ENCIMA de un relleno de categoria o del amarillo. Los
     rellenos siguen siendo claros tambien en modo oscuro, asi que su texto
     es siempre tinta oscura: usar var(--ink) los volveria ilegibles al
     invertir el tema. */
  --on-c: #1B1B1B;

  --radius: 0px;          /* los bloques no tienen esquinas redondeadas */
  --radius-sm: 0px;
  --maxw: 980px;
  --font: "Space Grotesk", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
}

/* --- 1b. Modo oscuro -------------------------------------
   No es el tema claro invertido: es el mismo lenguaje con los papeles
   cambiados. La tinta pasa a ser crema, asi que los bordes y las sombras
   duras se vuelven claros automaticamente (estan definidos con var(--ink))
   y siguen leyendose como bloques recortados sobre el fondo.

   Los rellenos de categoria NO se oscurecen: siguen siendo pastillas claras
   sobre fondo oscuro, que es lo que mantiene reconocible el sitio. Su texto
   lo fija --on-c, que no cambia con el tema.
   --------------------------------------------------------- */
/* El tema se decide asi, por orden:
     1. Lo que el visitante haya elegido (atributo data-tema en <html>, que
        guarda main.js en localStorage y aplica un script del <head> antes de
        pintar, para que no haya parpadeo).
     2. Si no ha elegido nada, lo que pida su sistema.
   Por eso cada bloque oscuro se declara DOS veces: una para el sistema
   (excluyendo a quien ha forzado claro) y otra para la eleccion explicita. */
@media (prefers-color-scheme: dark) {
  :root:not([data-tema="claro"]) {
    --bg: #15140F;        /* negro calido, no gris azulado: es el mismo papel */
    --bg-alt: #1D1B14;
    --surface: #15140F;
    --paper: #201E17;
    --ink: #FFFCF2;       /* la tinta ahora es crema: bordes y sombras claros */
    --text: #FFFCF2;
    --text-soft: #C4BDAC;
    --text-mute: #8C8779;

    --accent: #FF7A4D;    /* el naranja de marca se aclara para el fondo oscuro */
    --accent-hover: #FF9670;
    --ok: #4ADE80;
    --warn: #FBBF24;
    --err: #FF6B5A;
  }
}
:root[data-tema="oscuro"] {
    --bg: #15140F;        /* negro calido, no gris azulado: es el mismo papel */
    --bg-alt: #1D1B14;
    --surface: #15140F;
    --paper: #201E17;
    --ink: #FFFCF2;       /* la tinta ahora es crema: bordes y sombras claros */
    --text: #FFFCF2;
    --text-soft: #C4BDAC;
    --text-mute: #8C8779;

    --accent: #FF7A4D;    /* el naranja de marca se aclara para el fondo oscuro */
    --accent-hover: #FF9670;
    --ok: #4ADE80;
    --warn: #FBBF24;
    --err: #FF6B5A;
}

/* --- 2. Base --------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: smooth; -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  overflow-x: hidden;   /* nada desplaza la pagina en horizontal */
  font-family: var(--font);
  font-size: 16px;
  line-height: 1.55;
  color: var(--text);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
}
img { max-width: 100%; display: block; }
a { color: var(--ink); text-underline-offset: 3px; }
a:hover { color: var(--accent); }
h1, h2, h3 { line-height: 1.05; letter-spacing: -.035em; margin: 0 0 .5em; font-weight: 700; }

/* El titulo de pagina va en MAYUSCULAS apretadas: es lo que da caracter a la
   direccion, y sin esto las paginas de herramienta parecian de otro sitio que
   la portada. Los h2 se quedan en caja normal a proposito: los titulares SEO
   son largos y una pared de mayusculas se lee mucho peor. */
h1 {
  font-size: clamp(1.75rem, 4.8vw, 2.7rem);
  text-transform: uppercase; letter-spacing: -.045em;
}
h2 { font-size: clamp(1.4rem, 3.2vw, 1.9rem); margin-top: 2em; }
h3 { font-size: 1.12rem; letter-spacing: -.02em; }
p { margin: 0 0 1em; }
.wrap { max-width: var(--maxw); margin: 0 auto; padding: 0 22px; }
.muted { color: var(--text-soft); }
.small { font-size: .9rem; }

/* --- 3. Cabecera / pie ----------------------------------- */
.site-header {
  border-bottom: var(--bw-lg) solid var(--ink);
  background: var(--bg);
  position: sticky; top: 0; z-index: 50;
}
.site-header .wrap {
  display: flex; align-items: center; justify-content: space-between;
  gap: 16px; height: 62px;
}
.logo {
  font-weight: 700; font-size: 1.32rem; letter-spacing: -.045em;
  text-transform: uppercase; text-decoration: none;
  color: var(--ink); display: flex; align-items: center; gap: 10px;
}
.logo-mark {
  width: 30px; height: 30px;
  border: var(--bw) solid var(--ink); background: var(--yellow);
  display: grid; place-items: center; color: var(--on-c);
  font-size: .95rem; font-weight: 700; letter-spacing: 0;
}
.tema-btn {
  display: inline-flex; align-items: center; gap: 7px; cursor: pointer;
  font: inherit; font-size: .78rem; font-weight: 700;
  letter-spacing: .03em; text-transform: uppercase;
  color: var(--ink); background: var(--bg);
  border: var(--bw) solid var(--ink); padding: 8px 12px;
  transition: transform .1s, box-shadow .1s, background .12s;
}
.tema-btn:hover { background: var(--yellow); color: var(--on-c); box-shadow: var(--shadow-sm); transform: translate(-1px, -1px); }
.tema-btn svg { width: 16px; height: 16px; flex: 0 0 auto; }
@media (max-width: 520px) { .tema-txt { display: none; } .tema-btn { padding: 8px 10px; } }

.nav-tools {
  font-size: .82rem; font-weight: 700; letter-spacing: .03em;
  text-transform: uppercase; text-decoration: none;
  color: var(--bg); background: var(--ink);
  padding: 9px 16px; border: var(--bw) solid var(--ink);
  transition: transform .1s, box-shadow .1s;
}
.nav-tools:hover {
  color: var(--bg); background: var(--accent); border-color: var(--ink);
  box-shadow: var(--shadow-sm); transform: translate(-1px, -1px);
}

.site-footer {
  margin-top: 60px; border-top: var(--bw-lg) solid var(--ink);
  background: var(--bg); padding: 26px 0; font-size: .85rem;
  font-weight: 500; color: var(--text-soft);
}
.site-footer .wrap { display: flex; flex-wrap: wrap; gap: 10px 22px; justify-content: space-between; }
.site-footer a { color: var(--ink); text-decoration: none; }
.site-footer a:hover { color: var(--accent); }

/* Barra de categorias: se desplaza en horizontal en el movil en lugar de
   partirse en varias filas y comerse media pantalla. */
.cat-bar { border-bottom: var(--bw-lg) solid var(--ink); background: var(--bg-alt); }
.cat-bar .wrap {
  display: flex; gap: 0; align-items: stretch;
  overflow-x: auto; scrollbar-width: none;
}
.cat-bar .wrap::-webkit-scrollbar { display: none; }
.cat-item { position: relative; flex: 0 0 auto; }
/* Cada boton lleva SU color de relleno, no un fondo neutro: la barra es la
   primera muestra de que este sitio va de bloques de color, y con todo en
   crema no se distinguia de cualquier otra web de herramientas. */
.cat-link {
  display: inline-flex; align-items: center; gap: 8px; height: 100%;
  white-space: nowrap; text-decoration: none; cursor: pointer;
  font: inherit; font-size: .84rem; font-weight: 700; letter-spacing: -.01em;
  color: var(--on-c); padding: 11px 18px;
  background: var(--c, var(--yellow)); border: 0;
  border-right: var(--bw) solid var(--ink);
  transition: background .12s, color .12s;
}
.cat-item:first-child .cat-link { border-left: var(--bw) solid var(--ink); }

/* Nombre largo en pantalla ancha, corto en movil. Los cinco largos suman
   841 px: en un movil de 390 no caben ni encogiendolos, y la barra se cortaba
   por la derecha con aspecto de rota. Con los cortos y menos relleno entra
   casi todo y el ultimo asoma, que es lo que se lee como "hay mas, desliza". */
.cat-corto { display: none; }
@media (max-width: 640px) {
  .cat-largo { display: none; }
  .cat-corto { display: inline; }
  .cat-link { padding: 11px 12px; font-size: .8rem; gap: 6px; }
  .cat-chevron { display: none; }   /* 12 px que se ganan por cada categoria */
  .cat-ico svg { width: 16px; height: 16px; }
}

/* Al pasar por encima y al estar abierta o activa se invierte a tinta: es el
   contraste mas fuerte disponible y no depende del color de la categoria. */
.cat-link:hover { background: var(--ink); color: var(--bg); }

/* Cada categoria tiene su relleno plano. */
[data-cat="imagen"]        { --c: var(--c-imagen); }
[data-cat="documentos"]    { --c: var(--c-documentos); }
[data-cat="calculadoras"]  { --c: var(--c-calculadoras); }
[data-cat="generadores"]   { --c: var(--c-generadores); }
[data-cat="internet"]      { --c: var(--c-internet); }

.cat-link.is-activa,
.cat-link[aria-expanded="true"] { background: var(--c, var(--yellow)); }
.cat-ico { display: inline-flex; }
.cat-ico svg { width: 17px; height: 17px; }
.cat-chevron { width: 12px; height: 12px; transition: transform .15s; }
.cat-link[aria-expanded="true"] .cat-chevron { transform: rotate(180deg); }

/* Panel desplegable de cada categoria.

   position: FIXED, no absolute. La barra usa overflow-x:auto para deslizarse
   en movil, y un contenedor con overflow recorta a sus hijos posicionados:
   el panel salia cortado a los pocos pixeles. Con position:fixed escapa del
   recorte, y main.js le calcula la posicion a partir del boton. */
.cat-menu {
  position: fixed; z-index: 60;
  min-width: 300px; max-width: min(360px, calc(100vw - 24px));
  /* Fondo neutro con una franja del color arriba, en vez del relleno entero:
     un panel relleno de color obliga a texto oscuro, y en modo oscuro el
     resto de la interfaz usa texto claro. Asi el panel funciona en los dos. */
  background: var(--paper);
  border: var(--bw-lg) solid var(--ink);
  border-top: 10px solid var(--c, var(--yellow));
  box-shadow: var(--shadow-lg); padding: 8px;
}
.cat-menu a {
  display: flex; gap: 11px; align-items: flex-start;
  padding: 10px 11px; text-decoration: none; color: var(--ink);
  white-space: normal; border: var(--bw) solid transparent;
}
.cat-menu a:hover { background: var(--paper); border-color: var(--ink); box-shadow: var(--shadow-sm); }
.cat-menu .cat-ico { padding-top: 1px; }
.cat-menu .cat-ico svg { width: 19px; height: 19px; }
.cat-menu strong { display: block; font-size: .93rem; font-weight: 700; }
.cat-menu em {
  display: block; font-style: normal; font-size: .81rem;
  color: var(--text-soft); line-height: 1.4; margin-top: 1px;
}
.cat-todas {
  margin-top: 6px; border-top: var(--bw) solid var(--ink) !important;
  border-radius: 0; font-size: .8rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: .03em; justify-content: center;
}

@media (max-width: 600px) {
  .cat-menu { left: 12px !important; right: 12px; max-width: none; min-width: 0; }
}

/* Titulos de categoria en el indice */
.cat-titulo {
  display: flex; align-items: center; gap: 12px; scroll-margin-top: 130px;
  text-transform: uppercase;
}
.cat-titulo svg {
  width: 36px; height: 36px; flex: 0 0 auto; padding: 6px;
  color: var(--on-c); background: var(--c, var(--yellow));
  border: var(--bw) solid var(--ink);
}
.cat-cuenta {
  font-size: .78rem; font-weight: 700; letter-spacing: 0;
  color: var(--ink); background: var(--paper);
  border: var(--bw) solid var(--ink); padding: 2px 10px;
}

/* --- 4. Portada ------------------------------------------ */
.hero { padding: 40px 0 30px; }
.hero h1 { text-wrap: balance; margin-bottom: 14px; }
.hero p.sub { font-size: 1.05rem; color: var(--text-soft); max-width: 620px; margin: 0; }
.hero-inicio { border-bottom: var(--bw-lg) solid var(--ink); }

.hero-badge {
  display: inline-block; background: var(--yellow);
  border: var(--bw) solid var(--ink); box-shadow: var(--shadow);
  padding: 5px 13px; margin-bottom: 20px; color: var(--on-c);
  font-weight: 700; font-size: .78rem; letter-spacing: .05em; text-transform: uppercase;
}
/* Crema sobre el naranja de marca da 3,6:1. Cumple porque esto SOLO se usa en
   el H1 de portada, que es texto grande (32-50 px en negrita, donde el minimo
   es 3:1). Si alguna vez se reutiliza en texto normal, hay que oscurecer el
   fondo a var(--accent-hover), que sube a 4,9:1. */
.hero-marca { background: var(--accent); color: var(--bg); padding: 0 11px; display: inline-block; }

/* Buscador */
.buscador {
  display: flex; max-width: 680px; margin-top: 26px;
  border: var(--bw-lg) solid var(--ink); background: var(--paper);
  box-shadow: var(--shadow-lg);
}
.buscador svg { width: 21px; height: 21px; flex: 0 0 auto; }
.buscador input {
  font: inherit; font-size: 1.02rem; font-weight: 500;
  border: 0; background: transparent; color: var(--ink);
  padding: 15px 14px; flex-grow: 1; min-width: 0; outline: none;
}
.buscador input::placeholder { color: var(--text-mute); }
.buscador label { display: flex; align-items: center; padding-left: 16px; }
.buscador-btn {
  font: inherit; font-weight: 700; font-size: .88rem;
  letter-spacing: .04em; text-transform: uppercase; cursor: pointer;
  background: var(--ink); color: var(--bg); border: 0;
  padding: 0 24px; white-space: nowrap;
}
.buscador-btn:hover { background: var(--accent); }

.atajos { display: flex; flex-wrap: wrap; gap: 9px; margin-top: 18px; }
.atajo {
  font: inherit; font-size: .84rem; font-weight: 500; cursor: pointer;
  background: var(--bg); color: var(--ink);
  border: var(--bw) solid var(--ink); box-shadow: var(--shadow-sm);
  padding: 6px 12px; transition: transform .1s;
}
.atajo:hover { background: var(--yellow); color: var(--on-c); transform: translate(-1px, -1px); }

/* Resultados de la busqueda */
.resultados { margin: 26px 0 0; }
.res-vacio {
  border: var(--bw) solid var(--ink); background: var(--bg-alt);
  padding: 18px 20px; font-weight: 500;
}

/* --- 5. Tarjeta de herramienta --------------------------- */
.tool-card {
  background: var(--paper);
  border: var(--bw-lg) solid var(--ink);
  box-shadow: var(--shadow-lg);
  padding: 26px;
  margin: 24px 0 16px;
}
.dropzone {
  display: grid; place-items: center; gap: 10px; position: relative;
  padding: 44px 20px; text-align: center; cursor: pointer;
  border: var(--bw-lg) dashed var(--ink);
  background: var(--bg); transition: background .14s;
}
/* El hover SOLO donde hay puntero de verdad. En un movil, iOS deja pegado el
   estado :hover despues de tocar, y la zona se quedaba amarilla para siempre
   con el texto secundario gris encima, ilegible. */
@media (hover: hover) {
  .dropzone:hover { background: var(--yellow); color: var(--on-c); }
}
.dropzone.is-over { background: var(--yellow); color: var(--on-c); }
/* Sobre amarillo, el gris apagado no se lee: el texto secundario hereda. */
.dropzone.is-over .muted { color: inherit; }
@media (hover: hover) { .dropzone:hover .muted { color: inherit; } }
.dropzone svg { width: 40px; height: 40px; color: currentColor; }
.dropzone strong { font-size: 1.05rem; font-weight: 700; }
/* NUNCA display:none en un input de archivo: iOS Safari se salta la activacion
   de un input que no esta en el flujo y la foto no llega nunca al change. Se
   esconde a la vista pero se queda en la caja. */
.dropzone input[type=file], .file-oculto {
  position: absolute; width: 1px; height: 1px; opacity: 0;
  pointer-events: none; clip-path: inset(50%); overflow: hidden;
  border: 0; padding: 0; margin: -1px;
}

/* maquina de estados */
.tool-card [data-when] { display: none; }
.tool-card[data-state="idle"]    [data-when~="idle"],
.tool-card[data-state="engine"]  [data-when~="engine"],
.tool-card[data-state="working"] [data-when~="working"],
.tool-card[data-state="done"]    [data-when~="done"],
.tool-card[data-state="error"]   [data-when~="error"] { display: block; }

/* --- 6. Controles ---------------------------------------- */
.controls { display: flex; flex-wrap: wrap; gap: 16px; margin-top: 18px; align-items: flex-end; }
.field { display: flex; flex-direction: column; gap: 6px; flex: 1 1 170px; }
.field label {
  font-size: .78rem; font-weight: 700; letter-spacing: .03em;
  text-transform: uppercase; color: var(--text-soft);
}
select, input[type=number], input[type=text], input[type=date], textarea {
  font: inherit; font-size: .95rem; font-weight: 500; padding: 10px 12px;
  border: var(--bw) solid var(--ink); background: var(--paper);
  color: var(--ink); width: 100%; border-radius: 0;
}
select:focus, input:focus, textarea:focus { outline: 2px solid var(--accent); outline-offset: 1px; }
input[type=range] { width: 100%; accent-color: var(--accent); }
input[type=color] { border: var(--bw) solid var(--ink); background: var(--paper); }

.btn {
  font: inherit; font-weight: 700; font-size: .92rem;
  letter-spacing: .03em; text-transform: uppercase; cursor: pointer;
  padding: 13px 24px; border: var(--bw) solid var(--ink); border-radius: 0;
  background: var(--ink); color: var(--bg);
  display: inline-flex; align-items: center; justify-content: center; gap: 9px;
  text-decoration: none; transition: transform .1s, box-shadow .1s, background .12s;
}
.btn:hover { background: var(--accent); box-shadow: var(--shadow); transform: translate(-2px, -2px); }
.btn:active { box-shadow: none; transform: none; }
.btn:disabled { opacity: .45; cursor: not-allowed; box-shadow: none; transform: none; background: var(--ink); }
.btn-lg { width: 100%; padding: 16px; font-size: 1rem; }
.btn-ghost { background: var(--bg); color: var(--ink); }
.btn-ghost:hover { background: var(--yellow); color: var(--on-c); }
.link-reset {
  display: inline-block; margin-top: 14px; font-size: .88rem; font-weight: 600;
  color: var(--text-soft); background: none; border: 0; cursor: pointer;
  text-decoration: underline; font-family: inherit;
}
.link-reset:hover { color: var(--accent); }

/* --- 7. Progreso / estados ------------------------------- */
.progress {
  height: 14px; background: var(--paper); overflow: hidden;
  border: var(--bw) solid var(--ink); margin: 14px 0 8px;
}
.progress > i { display: block; height: 100%; width: 0; background: var(--accent); transition: width .25s; }
.state-msg { text-align: center; color: var(--text-soft); font-size: .94rem; font-weight: 500; }
.error-box {
  border: var(--bw) solid var(--ink); background: #FBE3E0;
  color: var(--on-c); padding: 14px 16px; font-size: .94rem; font-weight: 500;
  box-shadow: var(--shadow-sm);
}

/* --- 8. Resultados --------------------------------------- */
.file-row {
  display: flex; align-items: center; gap: 14px; padding: 13px 0;
  border-bottom: var(--bw) solid var(--ink);
}
.file-row:last-child { border-bottom: 0; }
.file-thumb {
  width: 52px; height: 52px; object-fit: cover;
  border: var(--bw) solid var(--ink); background: var(--bg-alt); flex: 0 0 auto;
}
.file-meta { flex: 1 1 auto; min-width: 0; }
.file-name {
  font-weight: 700; font-size: .95rem; white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis;
}
.file-sizes { font-size: .87rem; color: var(--text-soft); font-weight: 500; }
.saved { color: var(--ok); font-weight: 700; }
.btn-dl {
  font: inherit; font-size: .82rem; font-weight: 700;
  letter-spacing: .03em; text-transform: uppercase; text-decoration: none;
  background: var(--ink); color: var(--bg); padding: 9px 15px;
  border: var(--bw) solid var(--ink); cursor: pointer; white-space: nowrap;
  transition: transform .1s, box-shadow .1s, background .12s;
}
.btn-dl:hover { background: var(--accent); box-shadow: var(--shadow-sm); transform: translate(-1px, -1px); }

/* --- 9. Privacidad + limites ----------------------------- */
.privacy-ico { color: var(--on-c); flex: 0 0 auto; line-height: 0; padding-top: 1px; }
.privacy-ico svg { width: 20px; height: 20px; }
.privacy {
  display: flex; align-items: flex-start; gap: 11px;
  font-size: .92rem; font-weight: 500; color: var(--on-c);
  background: var(--yellow); border: var(--bw) solid var(--ink);
  box-shadow: var(--shadow-sm); padding: 14px 16px; margin-bottom: 10px;
}
.limits { font-size: .85rem; color: var(--text-soft); margin-bottom: 8px; font-weight: 500; }

/* --- 10. Huecos de anuncio (placeholders — invariante 8) - */
.ad-slot {
  min-height: 100px; margin: 34px 0; display: grid; place-items: center;
  border: var(--bw) dashed var(--ink); background: var(--bg-alt);
  color: var(--text-mute); font-size: .74rem; font-weight: 700;
  letter-spacing: .12em; text-transform: uppercase;
}
@media (min-width: 760px) { .ad-slot { min-height: 120px; } }

/* --- 11. Contenido: pasos, FAQ, rejilla ------------------ */
.steps { display: grid; gap: 14px; grid-template-columns: 1fr; margin: 20px 0; padding: 0; list-style: none; }
@media (min-width: 700px) { .steps { grid-template-columns: repeat(3, 1fr); } }
.steps li {
  background: var(--paper); border: var(--bw) solid var(--ink);
  box-shadow: var(--shadow); padding: 20px;
}
.steps svg { width: 26px; height: 26px; color: var(--accent); margin-bottom: 8px; }
.steps strong { display: block; margin-bottom: 4px; font-weight: 700; }
.steps span { font-size: .92rem; color: var(--text-soft); }

.faq details {
  border: var(--bw) solid var(--ink); padding: 14px 18px;
  margin-bottom: 10px; background: var(--paper);
}
.faq details[open] { box-shadow: var(--shadow-sm); }
.faq summary { cursor: pointer; font-weight: 700; }
.faq details[open] summary { margin-bottom: 8px; }
.faq p { margin: 0; color: var(--text-soft); font-size: .94rem; }

.tool-grid { display: grid; gap: 14px; grid-template-columns: 1fr; padding: 0; list-style: none; }
@media (min-width: 640px) { .tool-grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 900px) { .tool-grid { grid-template-columns: repeat(3, 1fr); } }
.tool-grid a {
  display: block; height: 100%; text-decoration: none; color: var(--ink);
  background: var(--paper); border: var(--bw) solid var(--ink);
  box-shadow: var(--shadow); padding: 18px; transition: transform .1s, box-shadow .1s, background .12s;
}
.tool-grid a:hover {
  background: var(--c, var(--yellow)); color: var(--on-c);
  box-shadow: var(--shadow-lg); transform: translate(-2px, -2px);
}
.tool-grid .t-icon {
  color: var(--on-c); width: 42px; height: 42px; margin-bottom: 12px;
  display: grid; place-items: center;
  background: var(--c, var(--yellow)); border: var(--bw) solid var(--ink);
}
.tool-grid a:hover .t-icon { background: var(--paper); color: var(--ink); }
.tool-grid .t-icon svg { width: 22px; height: 22px; }
.tool-grid strong { display: block; font-size: 1rem; font-weight: 700; margin-bottom: 4px; letter-spacing: -.015em; }
.tool-grid span { font-size: .88rem; color: var(--text-soft); }
.tool-grid a:hover span { color: var(--on-c); }

/* --- 12. Paginas legales --------------------------------- */
.prose { max-width: 720px; margin: 30px auto; }
.prose h2 { margin-top: 1.8em; }
.todo {
  background: var(--yellow); border: var(--bw) solid var(--ink);
  color: var(--on-c); padding: 2px 8px; font-size: .85rem; font-weight: 700;
}

/* --- 13. Recorte / redes --------------------------------- */
.crop-stage {
  position: relative; width: 100%; max-width: 520px; margin: 18px auto 0;
  background: var(--bg-alt); border: var(--bw) solid var(--ink);
  overflow: hidden; touch-action: none; cursor: grab;
}
.crop-stage.is-drag { cursor: grabbing; }
.crop-stage canvas { display: block; width: 100%; height: auto; }

/* --- 13b. Rejilla de iconos del QR ----------------------- */
.emoji-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(44px, 1fr)); gap: 6px; }
.emoji-op {
  font-size: 1.25rem; line-height: 1; padding: 8px 0; cursor: pointer;
  background: var(--paper); color: inherit;
  border: var(--bw) solid var(--ink); transition: background .12s;
}
.emoji-op:hover { background: var(--yellow); color: var(--on-c); }

/* --- 13c. Escaner: acciones de pagina y editor de bordes -- */
.pag-acciones { display: flex; flex-wrap: wrap; gap: 6px; flex: 0 0 auto; justify-content: flex-end; }
/* En movil los seis botones no caben al lado de la miniatura: la fila exigia
   mas ancho que la pantalla y empujaba la PAGINA ENTERA en horizontal, con la
   cabecera cortada y el texto exprimido en una columna de dos palabras. Aqui
   la botonera baja a su propia linea. */
@media (max-width: 640px) {
  .file-row { flex-wrap: wrap; }
  .file-meta { flex: 1 1 120px; }
  .pag-acciones { flex: 1 1 100%; justify-content: flex-start; }
  /* Sin crecer: con `1 1 auto` el ultimo boton de cada linea se estiraba a
     todo el ancho y la papelera acababa siendo una barra de 290 px. */
  .btn-mini { flex: 0 0 auto; }
}
.btn-mini {
  font: inherit; font-size: .78rem; font-weight: 700;
  letter-spacing: .03em; text-transform: uppercase; cursor: pointer;
  padding: 7px 11px; border: var(--bw) solid var(--ink); border-radius: 0;
  background: var(--bg); color: var(--ink); transition: background .12s;
}
.btn-mini:hover:not(:disabled) { background: var(--yellow); color: var(--on-c); }
.btn-mini:disabled { opacity: .38; cursor: not-allowed; }

/* El editor tapa la pagina entera a proposito: ajustar cuatro esquinas con el
   dedo necesita toda la pantalla del movil, que es de donde viene el trafico. */
.editor-bordes {
  position: fixed; inset: 0; z-index: 120; display: flex;
  align-items: center; justify-content: center; padding: 14px;
  background: rgba(0, 0, 0, .62);
}
.editor-caja {
  background: var(--surface); border: var(--bw-lg) solid var(--border);
  box-shadow: var(--shadow-lg); padding: 18px;
  width: 100%; max-width: 640px; max-height: 94vh; overflow: auto;
}
.editor-titulo { font-size: 1.05rem; margin: 0 0 4px; }
.editor-lienzo {
  position: relative; margin: 14px 0; line-height: 0;
  touch-action: none; -webkit-user-select: none; user-select: none;
}
/* Solo la foto, NO la lupa. Con `.editor-lienzo canvas` a secas esta regla
   tambien alcanzaba a la lupa: le imponia width:100% -mas especifica que
   .editor-lupa, asi que ganaba- y ademas display:block, que anula el atributo
   hidden. Resultado: la lupa siempre visible y estirada a todo el ancho,
   tapando la foto con un zoom gigante. */
.editor-lienzo > canvas:not(.editor-lupa) {
  display: block; width: 100%; height: auto;
  border: var(--bw) solid var(--ink);
}
.editor-svg { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }
.editor-svg polygon { fill: rgba(228, 87, 46, .16); stroke: var(--accent); stroke-width: 3; }
/* Cuadrados, no circulos: aqui no se redondea nada, y un cuadrado amarillo
   sobre borde de tinta se ve igual de bien contra una foto clara u oscura. */
.editor-punto {
  position: absolute; width: 30px; height: 30px; margin: -15px 0 0 -15px;
  background: var(--yellow); border: var(--bw) solid #1B1B1B;
  box-shadow: 2px 2px 0 rgba(0, 0, 0, .45);
  cursor: grab; touch-action: none;
}
.editor-punto.is-drag { cursor: grabbing; background: var(--accent); }

/* Tirador de lado: mueve el borde entero, las dos esquinas a la vez. Es plano
   y alargado a proposito, para que no se confunda con una esquina. Se gira
   para alinearse con su lado; en una foto torcida, uno horizontal sobre un
   borde inclinado se lee como que no pertenece a ese borde. */
.editor-lado {
  position: absolute; width: 44px; height: 16px;
  background: var(--bg); border: var(--bw) solid #1B1B1B;
  box-shadow: 2px 2px 0 rgba(0, 0, 0, .45);
  cursor: grab; touch-action: none;
}
.editor-lado.is-drag { cursor: grabbing; background: var(--accent); }

/* Lupa. El dedo tapa justo el punto que hay que colocar: es EL problema de
   ajustar esquinas en una pantalla tactil. Se ancla arriba, en el lado
   contrario al que se arrastra, asi que nunca queda debajo de la mano. */
.editor-lupa {
  position: absolute; top: 8px; left: 8px; width: 132px; height: 132px;
  border: var(--bw-lg) solid #1B1B1B; box-shadow: 3px 3px 0 rgba(0, 0, 0, .45);
  background: #fff; pointer-events: none; z-index: 3;
}
.editor-lupa.a-la-derecha { left: auto; right: 8px; }
.editor-lupa[hidden] { display: none; }

/* Vista de la pagina a tamano util. Los selectores van por CLASE y nunca por
   tipo: `.editor-lienzo canvas` a secas ya nos estiro la lupa una vez. */
.vista-caja { max-width: 780px; }
.vista-lienzo {
  margin: 12px 0; padding: 10px; display: flex; justify-content: center;
  background: var(--bg-alt); border: var(--bw) solid var(--ink);
}
/* Se ve la pagina ENTERA, que es lo que hace falta para juzgar el recorte.
   El borde fino la separa del fondo: un folio en blanco y negro sobre papel
   crema, sin borde, parece que flota. */
.vista-img {
  display: block; width: auto; height: auto;
  max-width: 100%; max-height: 58vh;
  border: 1px solid var(--text-mute); background: #fff;
}

@media (max-width: 420px) {
  .editor-lupa { width: 104px; height: 104px; }
}
.editor-botones { margin-top: 4px; }
@media (pointer: coarse) {
  .editor-punto { width: 38px; height: 38px; margin: -19px 0 0 -19px; }
}

/* --- 13d. Extraer audio: ficha y salidas ------------------ */
.meta-panel { border: var(--bw) solid var(--ink); background: var(--paper); }
.meta-fila {
  display: flex; justify-content: space-between; gap: 14px; align-items: baseline;
  padding: 10px 14px; border-bottom: var(--bw) solid var(--ink); font-size: .92rem;
}
.meta-fila:last-child { border-bottom: 0; }
.meta-fila span { color: var(--text-soft); font-weight: 500; }
.meta-fila strong { text-align: right; word-break: break-word; }
/* Una salida por bloque, no botones sueltos: cada formato necesita su nota
   explicando que se gana y que se pierde, y sin ella la gente elige MP3 por
   costumbre cuando el .m4a es mejor en casi todos los casos. */
.salidas { display: grid; gap: 14px; margin-top: 18px; }
.salida-op {
  border: var(--bw) solid var(--ink); background: var(--bg-alt); padding: 14px;
}
.salida-op .btn { width: 100%; }
.salida-op p { margin: 9px 0 0; }
.salida-op select { margin-top: 8px; }

/* --- 14. Metadatos --------------------------------------- */
.meta-table { width: 100%; border-collapse: collapse; font-size: .92rem; margin-top: 8px; }
.meta-table th, .meta-table td {
  text-align: left; padding: 9px 10px;
  border-bottom: var(--bw) solid var(--ink); vertical-align: top;
}
.meta-table thead th, .meta-table thead td { background: var(--ink); color: var(--bg); font-weight: 700; }
.meta-table th { font-weight: 700; width: 42%; }
.gps-warn {
  border: var(--bw) solid var(--ink); background: #FFE9C7; color: var(--on-c);
  box-shadow: var(--shadow-sm); padding: 14px 16px; margin-top: 14px;
  font-size: .93rem; font-weight: 500;
}
.gps-warn strong { color: var(--on-c); }
.ico-aviso { width: 17px; height: 17px; vertical-align: -3px; margin-right: 3px; }

.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}

/* --- 15. Franja de prueba (portada) ---------------------- */
.franja {
  background: var(--ink); color: var(--bg);
  padding: 30px 0; border-bottom: var(--bw-lg) solid var(--ink);
}
.franja .wrap { display: flex; align-items: center; gap: 24px; }
.franja-cifra {
  font-size: 3.1rem; font-weight: 700; letter-spacing: -.05em;
  line-height: 1; color: var(--yellow);
}
.franja strong { display: block; font-size: 1.15rem; font-weight: 700; margin-bottom: 2px; }
.franja span { font-size: .92rem; opacity: .75; }

@media (max-width: 560px) {
  .franja .wrap { flex-direction: column; align-items: flex-start; gap: 12px; }
  .buscador { flex-wrap: wrap; }
  .buscador-btn { width: 100%; padding: 13px; border-top: var(--bw) solid var(--ink); }
}


/* --- 16. Ajustes de componente en modo oscuro ------------
   Van AL FINAL a proposito. Los tokens de :root pueden declararse arriba
   porque var() se resuelve al calcular el valor, pero una anulacion de
   componente con la misma especificidad solo gana si va DESPUES de la regla
   que corrige. Puesta arriba, la franja seguia saliendo crema.
   --------------------------------------------------------- */
@media (prefers-color-scheme: dark) {
  /* Fondos claros fijos, suavizados para que no deslumbren sobre oscuro */
  :root:not([data-tema="claro"]) .error-box { background: #F6C9C2; }
  :root:not([data-tema="claro"]) .gps-warn { background: #F5DDB4; }

  /* En claro es un bloque negro sobre crema; invertirlo daria un bloque
     crema cegador a media pagina. Aqui se queda oscuro. */
  :root:not([data-tema="claro"]) .franja { background: var(--bg-alt); color: var(--text); }
  :root:not([data-tema="claro"]) .franja span { opacity: .78; }

  /* El lienzo de firma es blanco SIEMPRE (se firma sobre un PDF, que es
     blanco). Solo se ajusta lo que lo rodea. */
  :root:not([data-tema="claro"]) .crop-stage { background: var(--paper); }

  /* El boton invertido pasa a crema con texto oscuro; su hover naranja
     necesita texto oscuro para seguir legible. */
  :root:not([data-tema="claro"]) .btn:hover, :root:not([data-tema="claro"]) .btn-dl:hover, :root:not([data-tema="claro"]) .nav-tools:hover { color: var(--on-c); }
}

  /* Fondos claros fijos, suavizados para que no deslumbren sobre oscuro */
:root[data-tema="oscuro"] .error-box { background: #F6C9C2; }
:root[data-tema="oscuro"] .gps-warn { background: #F5DDB4; }

/* En claro es un bloque negro sobre crema; invertirlo daria un bloque
   crema cegador a media pagina. Aqui se queda oscuro. */
:root[data-tema="oscuro"] .franja { background: var(--bg-alt); color: var(--text); }
:root[data-tema="oscuro"] .franja span { opacity: .78; }

/* El lienzo de firma es blanco SIEMPRE (se firma sobre un PDF, que es
   blanco). Solo se ajusta lo que lo rodea. */
:root[data-tema="oscuro"] .crop-stage { background: var(--paper); }

/* El boton invertido pasa a crema con texto oscuro; su hover naranja
   necesita texto oscuro para seguir legible. */
:root[data-tema="oscuro"] .btn:hover, :root[data-tema="oscuro"] .btn-dl:hover, :root[data-tema="oscuro"] .nav-tools:hover { color: var(--on-c); }


/* --- 17. Objetivos tactiles ------------------------------
   Solo en dispositivos de dedo (pointer: coarse). Un raton apunta con
   precision de pixel y no necesita 44 px; el dedo si, y los atajos de la
   portada se quedaban en 36. El minimo de 44x44 es el estandar de Apple y
   el criterio 2.5.5 de WCAG.

   Va al final para ganar por orden a las reglas de cada componente. */
@media (pointer: coarse) {
  .atajo, .tema-btn, .nav-tools, .btn-ghost, .btn-dl, .emoji-op {
    min-height: 44px;
  }
  .atajo, .tema-btn, .nav-tools {
    display: inline-flex; align-items: center;
  }
  /* Los enlaces del pie eran de 18 px: se les da area sin moverlos de sitio */
  .site-footer a {
    display: inline-block; padding: 12px 0; margin: -12px 0;
  }
  .logo { padding: 6px 0; }
}
