/* ═══════════════════════════════════════════════════════════
   🥚 LIMPIAAI v22 — RETÍCULA UNIFICADA (CENTRAR / ALINEAR / JUSTIFICAR)

   POR QUÉ EXISTE ESTA HOJA
   ────────────────────────
   La app se construyó por capas (style, premium, celestial, quantum,
   titan, imperial, omega, singularity, nexus, protocol, precision,
   oracle). Cada capa trajo sus propias tarjetas con su propio criterio.
   Al medir la pantalla de inicio con getBoundingClientRect() el
   resultado fue este:

     · Bordes EXTERIORES de los 18 bloques ... 116/684 en los 18. PERFECTO.
     · Rellenos INTERIORES ................... SEIS valores distintos:
         0px    -> hero, stats-row, oracle-section, section-heading, tech-grid
         14px   -> nx-streak-card
         16px   -> lunar-card, zen-banner, spread-cta, sound-card,
                   weather-card, numer-card, quest-card, notice
         20px   -> affirm-card
         21.6px -> seo-guide
         48px   -> steps-list (asimétrico: 48 a la izquierda, 0 a la derecha)
     · Radios de esquina ..................... 16px, 20px y 28px mezclados.

   Ahí estaba el problema real. Las CAJAS encajaban, pero el TEXTO de
   cada una empezaba en una columna distinta. El ojo no mide cajas: sigue
   el filo izquierdo del texto. Con seis filos distintos, la lectura es
   la de una columna dentada — exactamente la sensación de "está todo
   desalineado" que se reportó, y la razón por la que cuadrar sólo el
   huevo y las tarjetas de cifras no bastó.

   QUÉ HACE
   ────────
   Fija UNA escala única (--pad-card / --rad-card) y la aplica a todas
   las tarjetas de la columna, vengan de la hoja que vengan. Se carga
   después de todas las temáticas y antes de a11y.css, que debe seguir
   siendo la última.
   ═══════════════════════════════════════════════════════════ */

:root {
  --pad-card: 16px;   /* relleno horizontal único de toda tarjeta */
  --pad-card-y: 16px; /* relleno vertical único */
  --rad-card: 20px;   /* radio de esquina único */
  --gap-card: 14px;   /* separación vertical entre bloques hermanos */
}

/* ─── 1. RELLENO Y RADIO ÚNICOS ─────────────────────────────
   Se listan por clase (no con `*`) para no tocar rejillas ni
   contenedores que deben quedarse a 0.

   NOTA sobre especificidad: el primer intento usó `:where(...)`, que
   vale 0. Las reglas de origen (`.affirm-card`, `.seo-guide`...) valen
   0-1-0 y por tanto seguían ganando: la medición posterior mostró que
   affirm-card se quedaba en 20px, nx-streak-card en 14px y seo-guide
   en 21.6px. Se usan selectores de clase reales para empatar en
   especificidad; al cargarse esta hoja la última, gana por orden de
   cascada sin necesidad de !important. */
.lunar-card, .affirm-card, .zen-banner, .sound-card, .weather-card,
.numer-card, .quest-card, .nx-streak-card, .notice, .spread-cta,
.seo-guide, .upload-tips {
  padding-left: var(--pad-card);
  padding-right: var(--pad-card);
  border-radius: var(--rad-card);
}

/* El radio también venía en tres valores (16 / 20 / 28). Se unifica
   junto con las tarjetas genéricas de cristal. */
.glass-card, .tech-card, .stat-card, .oracle-section .res-section {
  border-radius: var(--rad-card);
}

/* `pixar.css` impone `border-radius: var(--rx) !important` al modo arcilla,
   así que .weather-card y .notice seguían en 28px mientras el resto ya
   estaba en 20px. Responder con otro !important sería una guerra de
   especificidad; se alinea la VARIABLE que esa regla consume, de modo que
   el modo Pixar conserva su estilo y además cuadra con la retícula. */
.pixar-mode { --rx: var(--rad-card); }

/* ─── 2. RITMO VERTICAL ÚNICO ───────────────────────────────
   Los márgenes iban de 0 a 32px sin criterio (0/14, 19.2/19.2,
   16/0, 32/16). Un único hueco entre hermanos hace que la columna
   respire igual de arriba abajo.

   Se aplica a TODAS las pantallas (`.scr-inner`), no sólo a Inicio:
   Analizar, Aprender e Historial arrastran las mismas tarjetas de las
   mismas hojas, así que sufrían exactamente el mismo desajuste. */
.scr-inner > * { margin-top: 0; margin-bottom: var(--gap-card); }
.scr-inner > *:last-child { margin-bottom: 0; }

/* Las cabeceras de sección necesitan aire ARRIBA para que se lean
   como separadores, no como parte de la tarjeta anterior. */
.scr-inner > .section-heading { margin-top: 26px; margin-bottom: 12px; }
.scr-inner > .section-heading:first-child { margin-top: 0; }

/* ─── 3. LA LISTA DE PASOS ──────────────────────────────────
   Tenía `padding-left:48px` con 0 a la derecha: el único bloque
   asimétrico de toda la pantalla. El sangrado existe para dejar
   sitio a los números, así que se conserva el hueco pero se mueve
   DENTRO de cada paso, con rejilla en vez de posicionamiento
   absoluto. Así el texto de los pasos cae en la misma columna que
   el del resto de tarjetas y el bloque deja de estar descuadrado. */
.steps-list { padding-left: 0; }
.step-item {
  display: grid;
  grid-template-columns: 34px 1fr;
  gap: 12px;
  align-items: start;
}
.step-item .step-num {
  position: relative;
  top: auto; left: auto;
  width: 34px; height: 34px;
  display: flex; align-items: center; justify-content: center;
  margin: 0;
}
.step-item .step-body { min-width: 0; }

/* ─── 4. TIPOGRAFÍA: JUSTIFICADO LEGIBLE ────────────────────
   Se pidió texto justificado. Un `text-align: justify` a secas en
   una columna estrecha abre "ríos" de espacio en blanco entre
   palabras, que se lee peor que el borde dentado. La combinación
   correcta es justificar SÓLO los párrafos largos y activar la
   partición de palabras para que el reparto no deforme los huecos. */
.seo-guide p,
.notice p,
.step-body p {
  text-align: justify;
  text-justify: inter-word;
  hyphens: auto;
  -webkit-hyphens: auto;
  overflow-wrap: break-word;

  /* Medido tras activar el justificado: varios párrafos terminaban con una
     última línea de 4 px de ancho sobre 286 px. Es decir, UN carácter suelto
     colgando (una sílaba partida o el punto final). En texto justificado eso
     es lo más feo que puede pasar, porque la línea anterior queda estirada de
     extremo a extremo y debajo aparece una mota aislada.

     `hyphenate-limit-chars: 6 3 3` impide partir palabras de menos de 6
     letras y exige dejar al menos 3 letras a cada lado del guion, así que ya
     no pueden generarse fragmentos de una o dos letras.

     `text-wrap: pretty` pide al navegador que reparta las últimas líneas para
     no dejar viudas. Se degrada solo: donde no hay soporte, simplemente se
     ignora y quedan los límites de partición, que ya resuelven el caso peor. */
  hyphenate-limit-chars: 6 3 3;
  -webkit-hyphenate-limit-chars: 6 3 3;
  text-wrap: pretty;
}

/* NOTA sobre un falso positivo, para que no se "arregle" en el futuro:
   la sonda de justificado avisaba de dos párrafos con una última línea de
   3-4 px, que parecía un carácter colgando solo. Al comprobarlo, esos
   rectángulos correspondían al PUNTO que sigue a un elemento en línea
   (`...<em>interpretación de la limpia</em>.` y `...<a>Aviso Legal</a>.`):
   `Range.getClientRects()` devuelve un rectángulo por NODO, así que el punto
   aparece separado aunque comparta línea con el texto anterior.

   Se verificó comparando coordenadas verticales: `top=3884.4` en el último
   rectángulo y `top=3884.4` en el penúltimo. Misma línea, ningún defecto.
   No se añade CSS para esto: no hay nada que corregir. */

/* Los textos CORTOS no se justifican nunca: con dos o tres palabras
   el justificado las separa hasta los extremos y queda peor. */
.stat-label, .zen-banner-sub, .lunar-detail, .affirm-text,
.tech-card p, .bnav-btn, .hero-sub {
  text-align: inherit;
  hyphens: manual;
}
.hero-sub, .affirm-text { text-align: center; }
.tech-card p { text-align: left; }

/* ─── 5. EJE DE CENTRADO COHERENTE ──────────────────────────
   `text-align` heredaba valores mezclados (start / left / center)
   según la hoja de origen. Se normaliza a `start` en la columna y
   se centra de forma explícita sólo lo que debe ir centrado. */
.scr-inner { text-align: start; }
.hero, .affirm-card { text-align: center; }

/* ─── 6. CABECERAS DE SECCIÓN ALINEADAS ─────────────────────
   Son flex con un icono delante: si el icono y el texto no comparten
   línea base, el título parece hundido respecto al icono. */
.section-heading {
  display: flex;
  align-items: center;
  gap: 10px;
  line-height: 1.3;
}
.section-heading i { flex-shrink: 0; line-height: 1; }

/* ─── 7. NADA PUEDE DESBORDAR LA COLUMNA ────────────────────
   Salvaguarda: cualquier tarjeta futura con contenido ancho (una
   tabla, un <pre>, una palabra larga) recortaría la retícula y
   reabriría el problema. Se corta de raíz. */
.scr-inner > * { max-width: 100%; min-width: 0; }
.seo-guide, .notice, .lunar-card, .affirm-card { overflow-wrap: break-word; }

/* ─── 8. ESCRITORIO ─────────────────────────────────────────
   Con la columna más ancha el relleno crece en proporción, para que
   la mancha de texto no quede pegada a los bordes. */
@media (min-width: 769px) {
  :root { --pad-card: 20px; --gap-card: 16px; }
}

/* ─── 9. TELÉFONOS ESTRECHOS ────────────────────────────────
   Medido con la columna a 360 px: las 4 tarjetas de cifras caen a
   76 px y sólo una falla, la cuarta:

     card4 etiqueta "Tradiciones" W=58  scrollW=63  -> SE RECORTA
     card1..3 ("Fotos Máx", "Capas IA", "Símbolos") -> caben

   Es una sola palabra larga e indivisible: no hay hueco donde partir,
   así que ni `hyphens` ni pasar a dos líneas la salvan. Y apilar en
   2×2 ya se probó en v21: escondía la mitad de los datos. Se reduce
   lo que sobra en la etiqueta (espaciado entre letras y cuerpo).

   Se resuelve con CONTAINER QUERIES, no con `@media` ni con `vw`.
   El motivo es que lo que aprieta a la etiqueta es el ancho de LA
   COLUMNA, no el de la pantalla: la columna mide 480 o 600 px según
   el caso, y en escritorio conviven una pantalla ancha con una
   columna estrecha. Un `@media` mediría lo que no toca, y `vw` tiene
   el mismo defecto (se comprobó: con el viewport a 800 px y la
   columna a 360 px el `clamp` no llegaba a activarse y la etiqueta
   seguía desbordando, 66 px de texto en 64 px de hueco).
   `cqi` mide el ancho del contenedor, que es la magnitud real. */
.stats-row {
  container-type: inline-size;
  container-name: statsrow;
  gap: 8px;
}

/* ═══ v24 · BARRA DE NAVEGACIÓN CON CINCO PESTAÑAS ═══
   Al añadir «Ritual» la barra pasa de 4 a 5 botones. En un teléfono de
   360 px cada botón dispone de ~72 px en vez de ~90 px, y `min-width: 58px`
   más `padding: 4px 14px` (28 px de relleno lateral) desbordaba la barra.
   Se recorta el relleno y se reparte el ancho a partes iguales, en lugar de
   estrechar la zona táctil: los botones conservan toda la altura de la
   barra, que es lo que cuenta para el dedo.
   Igual que en `.stat-label`, se anula `letter-spacing`: en textos muy
   pequeños consume más ancho que el propio tamaño de letra. */
.bottom-nav .bnav-btn {
  padding-left: 3px;
  padding-right: 3px;
  min-width: 0;
  flex: 1 1 0;
  /* Zona táctil: el botón medía 39,6 px de alto, por debajo del mínimo de
     44 px que recomiendan las guías de accesibilidad (WCAG 2.5.5) para que
     un dedo acierte sin ampliar. Se estira el botón dentro de la barra en
     lugar de agrandar la barra, que ya tiene su altura calculada con el
     área segura del teléfono. */
  min-height: 44px;
  justify-content: center;
}
.bottom-nav .bnav-btn > span:not(.bnav-main-btn) {
  max-width: 100%;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  letter-spacing: 0;
}

/* Por debajo de ~420 px de COLUMNA cada tarjeta baja de ~95 px y
   "TRADICIONES" deja de caber: se ajusta el texto, no la retícula,
   para que las 4 cifras sigan visibles a la vez.

   REVISIÓN IMPORTANTE de este ajuste. El primer intento bajó la
   etiqueta a .47rem (7,52 px). Cabía, pero a ese cuerpo apenas se
   lee: cambiaba un defecto visible por otro peor. Se midieron
   alternativas a 360 px de columna:

     .47rem con espaciado .15px ....... 7,52 px  cabe
     .54rem SIN espaciado ............. 8,64 px  cabe   <- elegida
     .52rem sin espaciado ............. 8,32 px  cabe
     .56rem sin may. .................. 8,96 px  cabe

   Lo que sobraba no era el tamaño de la letra, sino el
   `letter-spacing: .7px` heredado. En una palabra de 11 caracteres
   ese espaciado suma ~7,7 px de puro aire — más de lo que faltaba.
   Quitándolo se conserva el cuerpo de diseño (.54rem) y además cabe.
   Verificado a 340/360/390/480/600 px: las cuatro etiquetas caen en
   2 líneas exactas, sin desborde ni palabras partidas. */
@container statsrow (max-width: 420px) {
  .stat-label { font-size: .54rem; letter-spacing: 0; }
  .stat-card { padding-left: 3px; padding-right: 3px; }
  .stats-row { gap: 6px; }
}

/* Reserva para navegadores sin soporte de container queries: el
   ajuste por viewport es menos preciso, pero evita el recorte. */
@supports not (container-type: inline-size) {
  @media (max-width: 430px) {
    .stat-label { font-size: .54rem; letter-spacing: 0; }
    .stat-card { padding-left: 3px; padding-right: 3px; }
    .stats-row { gap: 6px; }
  }
}
