/* ============================================================
   GP · Gastos Personales — Rediseño completo (Orden Maestra v5)
   Fase 9 — Fundamentos: tokens de color, tipografía, navegación,
   modo claro/oscuro alternable.

   Sistema de color extraído de las 33 imágenes aprobadas:
   - Logo/ícono de la app: degradado naranja (#FF8A00→#FF5A00) sobre
     fondo negro (variante 4.1, ver bitácora).
   - Interfaz: la mayoría de las pantallas usa un degradado azul→morado
     para encabezados/hero y morado como color de acento principal en
     botones/estados activos, con un sistema de colores semánticos por
     función (verde=ingresos/éxito, rojo=gastos/peligro, azul=info/
     seguridad, naranja=alertas, morado=personalización, teal=respaldo,
     rosado=metas) usado consistentemente en los círculos de ícono de
     cada fila de lista en todas las imágenes.
   ============================================================ */

:root{
  color-scheme: dark;
  --font: 'Inter', system-ui, -apple-system, 'Segoe UI', sans-serif;

  /* Marca / acento principal — azul vívido, extraído con pipeta del botón
     "INICIAR SESIÓN" de Imagen_01.png (pipeta #254EEE, ajustado a un valor
     de sistema #2A4DEE que coincide con el resplandor del hero). Reemplaza
     el morado inventado en la primera pasada: ningún mockup de Login/Crear
     cuenta usa morado como acento primario de marca (ver bitácora — el
     selector de "color de fondo" de Imagen_06/07 con 9 acentos, incluido
     el morado, fue eliminado por orden explícita del usuario: toda
     personalización vive únicamente en "Diseño de la aplicación", y esa
     pantalla — Imagen_33 — no incluye selector de color de acento). */
  --accent: #2A4DEE;
  --accent-2: #1E3FAE;
  --accent-soft: #2A4DEE26;

  /* Degradado "hero" usado en Login/Crear cuenta — pipeta sobre Imagen_01/02
     (marino oscuro arriba-izquierda → azul vívido abajo-derecha, ver
     tools/color-notes.md). Corrige el degradado azul→morado inventado en
     la primera pasada. */
  --hero-grad: linear-gradient(160deg, #081A4D 0%, #0B2C7A 45%, #1E3FAE 75%, #2A4DEE 100%);
  --hero-grad-purple: linear-gradient(160deg, #0b0a2e 0%, #241259 40%, #5b21b6 75%, #9333ea 100%);

  /* Degradado propio de Inicio (Figura 3/image4.png, pipeta aproximada —
     ver nota extensa junto a .hero-home en la sección de tarjetas más
     abajo): a diferencia de Login/Crear cuenta, esta referencia SÍ se
     inclina a violeta en la esquina inferior derecha. No se sampleó con
     la misma pipeta 3x3 de tools/sample.py por una caída temporal de la
     herramienta durante esta sesión — se estimó visualmente sobre la
     imagen a resolución nativa y se ajustó a tonos ya usados en el
     sistema (--accent #2A4DEE, morados ya definidos arriba en
     --hero-grad-purple) para no inventar colores nuevos sin relación con
     la paleta existente. Pendiente: re-verificar con pipeta exacta en
     cuanto la herramienta esté disponible (ver tools/color-notes.md). */
  --hero-grad-home: linear-gradient(160deg, #060B22 0%, #0F1E52 22%, #17308A 42%, #2A4DEE 64%, #5B21B6 86%, #7C3AED 100%);

  /* Colores semánticos (círculos de íconos, estados) */
  --blue: #3b82f6;
  --green: #22c55e;
  --red: #ef4444;
  --orange: #f97316;
  --amber: #f59e0b;
  --purple: #8b5cf6;
  --pink: #ec4899;
  --teal: #14b8a6;
  --gray: #94a3b8;

  /* Logo (siempre igual, no cambia con el tema) — variante 4.1 confirmada,
     valores impresos en Imagen_29.png "VERSIÓN 4.1" + verificados con
     pipeta (ver tools/color-notes.md). */
  --logo-orange: #FF8A00;
  --logo-orange-2: #FF5A00;
  --logo-bg: #0D0D0D;
  --logo-bg-2: #1A1A1A;

  /* Superficies — modo oscuro (predeterminado) */
  --bg: #0a0e1f;
  --bg-elevated: #0f1530;
  --surface: #151c34;
  --surface-2: #1b2340;
  --surface-hover: #212a4a;
  --border: #2a3355;
  --ink: #f4f6fb;
  --ink-soft: #c3cae0;
  --muted: #8b92b3;
  --muted-2: #6b7299;
  --card-on-hero: #ffffff;
  --card-on-hero-ink: #16192b;
  --card-on-hero-muted: #6b7280;
  --shadow: 0 18px 42px #00000055;
}

/* ---- Modo claro ---- */
[data-mode="light"]{
  color-scheme: light;
  --bg: #f3f4f9;
  --bg-elevated: #ffffff;
  --surface: #ffffff;
  --surface-2: #f6f7fb;
  --surface-hover: #eef0f9;
  --border: #e2e5f1;
  --ink: #16192b;
  --ink-soft: #3c4257;
  --muted: #6b7280;
  --muted-2: #8891ab;
  --card-on-hero: #ffffff;
  --card-on-hero-ink: #16192b;
  --card-on-hero-muted: #6b7280;
  --shadow: 0 12px 32px #16192b1a;
}

/* ORDEN CORRECTIVA — Manual Oficial, decisión 013 (§4.1 Registro de
   decisiones oficiales): "La paleta de colores vuelve a formar parte de
   Apariencia." Esto REVIERTE la orden de la ronda anterior, que había
   eliminado por completo el selector de 9 acentos (Imagen_06/07) — ver
   la nota que existía aquí antes (conservada en el historial de git/
   bitácora) y el aviso explícito sobre esta reversión en la respuesta al
   usuario y en bitacora-v5.md. Valores de los 9 acentos verificados con
   pipeta sobre image10.png del Manual (Figura 6, "APARIENCIA — COLOR DE
   FONDO"), ver tools/color-notes.md. El acento de marca por defecto
   (--accent azul arriba) se mantiene como estado inicial "morado" ya
   definido en storage.js — al elegir un acento, estas reglas
   sobreescriben --accent/--accent-2/--accent-soft en toda la app. */
[data-accent="morado"]{--accent:#803FDB;--accent-2:#5B21B6;--accent-soft:#803FDB26}
/* "azul" se unifica con el --accent de marca ya verificado con pipeta
   sobre Imagen_01 (#2A4DEE, ver arriba) en vez del valor crudo de la
   pipeta sobre image10.png del Manual (~#0257EE) — evita tener dos
   "azules" distintos conviviendo en el sistema y mantiene el aspecto
   por defecto de la app idéntico al ya verificado/aprobado. */
[data-accent="azul"]{--accent:#2A4DEE;--accent-2:#1E3FAE;--accent-soft:#2A4DEE26}
[data-accent="verde"]{--accent:#04B543;--accent-2:#0E7A34;--accent-soft:#04B54326}
[data-accent="rojo"]{--accent:#F13D3C;--accent-2:#B91C1C;--accent-soft:#F13D3C26}
[data-accent="rosado"]{--accent:#EF3F82;--accent-2:#BE185D;--accent-soft:#EF3F8226}
[data-accent="amarillo"]{--accent:#FBB723;--accent-2:#D97706;--accent-soft:#FBB72326}
[data-accent="naranja"]{--accent:#FC7F06;--accent-2:#C2570A;--accent-soft:#FC7F0626}
[data-accent="turquesa"]{--accent:#1FB7BC;--accent-2:#0E7C80;--accent-soft:#1FB7BC26}
[data-accent="gris"]{--accent:#868FA0;--accent-2:#5B6478;--accent-soft:#868FA026}
/* FASE 10 (Punto 4, "Estilo de fondo"): 2 tonos nuevos que agrega la
   imagen de referencia de esta fase (índigo/pizarra) + arcoíris (usa un
   violeta representativo para --accent/--accent-2 de botones y estados,
   ya que un control sólido no puede ser literalmente multicolor -- el
   degradado --hero-grad de arcoíris SÍ es multicolor real, ver
   FONDO_COLOR_STOPS.arcoiris en render.js). */
[data-accent="indigo"]{--accent:#4F46E5;--accent-2:#3730A3;--accent-soft:#4F46E526}
[data-accent="pizarra"]{--accent:#5B6B85;--accent-2:#3F4A5E;--accent-soft:#5B6B8526}
[data-accent="arcoiris"]{--accent:#8B5CF6;--accent-2:#6D28D9;--accent-soft:#8B5CF626}

/* FASE 10 (Punto 4, "Unificar completamente: Fondo + Paleta de colores
   bajo un único apartado"): los FONDOS A-E (Manual §3.8, Figura 30) que
   antes gobernaban --hero-grad/--hero-grad-home por su cuenta quedan
   RETIRADOS -- ver bitácora. El degradado hero ahora nace del mismo
   color elegido arriba en "Estilo de fondo" (ver buildFondoGradient() y
   el setProperty('--hero-grad',...) en render(), js/render.js), no de
   un atributo [data-fondo] independiente. Se conserva el campo
   settings.fondo en storage.js solo por compatibilidad de datos ya
   guardados (ver comentario ahí), pero ninguna regla CSS lo usa ya. */

/* Ver también: Fase 11 más abajo — 5 estilos reales de ícono SVG. */

*{box-sizing:border-box;-webkit-tap-highlight-color:transparent}
/* Tamaño base de los íconos SVG reales (sprite js/icons.js). Un <svg>
   sin width/height explícito se renderiza a 300x150px por defecto según
   el spec HTML — sin esta regla, cada ícono aparecía gigante. Los
   contextos que necesitan otro tamaño lo sobreescriben puntualmente
   (.row-icon .icon, .auth-social .icon, etc). */
.icon{width:20px;height:20px;flex:none;display:inline-block;vertical-align:middle}
html,body{margin:0;padding:0}
body{
  font-family:var(--font);
  background:var(--bg);
  color:var(--ink);
  min-height:100vh;
}
button,input,select,textarea{font:inherit;color:inherit}
button{border:0;background:none;cursor:pointer}
a{color:var(--accent);text-decoration:none}
::selection{background:var(--accent-soft)}

/* FASE 13 (Punto 5, "Evitar selección accidental"): por defecto NADA de
   texto/ícono/botón/tarjeta/título es seleccionable -- solo se
   reactiva explícitamente en los campos de texto editables (input/
   textarea/[contenteditable]) y en la información puntual que la app
   marca a propósito como copiable (.copyable-value, ver
   #screen-profileInfo/#screen-about-info y el botón .row-copy-btn en
   events.js/render.js). -webkit-touch-callout:none evita además el menú
   de "Copiar/Compartir" que iOS abre con una pulsación prolongada sobre
   texto no editable. No afecta el arrastre del selector de color
   (.color-wheel-thumb) ni ningún otro gesto táctil -- user-select solo
   bloquea SELECCIÓN de texto, nunca eventos de puntero/touch. */
body{-webkit-user-select:none;user-select:none;-webkit-touch-callout:none}
input,textarea,[contenteditable="true"]{-webkit-user-select:text;user-select:text;-webkit-touch-callout:default}
.copyable-value{-webkit-user-select:text;user-select:text;-webkit-touch-callout:default}

.app{
  width:min(100%,520px);
  min-height:100vh;
  margin:auto;
  background:var(--bg);
  position:relative;
  overflow-x:hidden;
}

/* ============================================================
   Pantallas / navegación por pila (screen stack)
   ============================================================ */
.screen{display:none}
.screen.active{display:block;animation:screenIn .18s ease}
@keyframes screenIn{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}
@media(prefers-reduced-motion:reduce){.screen.active{animation:none}}

.topbar{
  display:flex;align-items:center;gap:10px;
  /* ORDEN CORRECTIVA — Fidelidad visual y Safe Area: la flecha de
     regreso vivía a una distancia fija en píxeles del borde superior,
     así que en iPhone con notch/Dynamic Island terminaba debajo del
     área del sistema (o demasiado cerca de ella). env(safe-area-inset-
     top) devuelve 0 en dispositivos sin recorte (Android normal,
     navegador de escritorio), así que sumarlo siempre es seguro — nunca
     reduce el espacio ya existente, solo lo aumenta donde el sistema
     realmente lo necesita. Mismo patrón que ya se usaba abajo con
     safe-area-inset-bottom en la barra inferior y la hoja modal. */
  /* AUDITORÍA COMPLETA DEL MODO HORIZONTAL (revisión post-iPhone real):
     el padding lateral de la flecha de regreso se protege con
     safe-area-inset-left/right en TODA orientación, no solo en
     horizontal -- en un iPhone actual con Dynamic Island, el recorte
     lateral solo existe girado, así que en vertical estos dos valores
     son 0 y no cambian nada (verificado); se agregan aquí igual, de
     forma incondicional, para que la protección no dependa de qué
     media query esté activa en cada momento, pedido explícito de esta
     auditoría ("verifica que la flecha respete los márgenes seguros...
     en vertical y en horizontal"). */
  padding:calc(18px + env(safe-area-inset-top)) calc(16px + env(safe-area-inset-right)) 10px calc(16px + env(safe-area-inset-left));
  position:sticky;top:0;z-index:5;
  background:var(--bg);
}
.topbar h1,.topbar h2{margin:0;font-size:1.15rem;flex:1;text-align:center;padding-right:44px}
.topbar.no-back h1,.topbar.no-back h2{padding-right:0}
/* Área táctil mínima de 44x44 (mínimo recomendado por Apple HIG /
   Material Design) aunque el ícono visual siga siendo pequeño — antes
   era 34x34, por debajo del mínimo accesible. */
.back-btn{
  width:44px;height:44px;border-radius:12px;
  display:grid;place-items:center;
  background:var(--surface-2);color:var(--ink);
  font-size:1.1rem;flex:none;
}
.topbar-action{
  width:44px;height:44px;border-radius:12px;
  display:grid;place-items:center;
  background:var(--surface-2);color:var(--ink);flex:none;
}
/* FASE 13 (Punto 5): botón pequeño "copiar" junto a un valor de solo
   lectura que la app marca a propósito como copiable (correo, versión
   de la app, etc.) -- el ÍCONO/BOTÓN en sí sigue sin ser seleccionable
   como texto (hereda user-select:none de body), pero es tocable/
   clicable con normalidad y copia .copyable-value al portapapeles
   (ver events.js). */
.row-copy-btn{
  width:32px;height:32px;border-radius:9px;flex:none;
  display:grid;place-items:center;background:var(--surface-2);color:var(--muted);
}
.row-copy-btn[data-copied="true"]{background:var(--green);color:#fff}
.row-copy-btn svg{width:16px;height:16px}

/* FASE 13 (Punto 2): tarjetas de "Frecuencia de copia" (imagen aprobada,
   Panel 13.1) -- mismo componente conceptual que .mode-grid/.mode-card
   (Modo Claro/Oscuro) pero con varias columnas en vez de 2 y una
   insignia de check en la esquina en vez de un punto central, para
   igualar el mockup con la mayor fidelidad posible.
   CORRECCIÓN PUNTUAL (Fase 13, "solo frecuencia de copia"): con la nueva
   opción "Quincenal" ya son 5 tarjetas -- 4 columnas fijas dejaría la
   5ta sola en una segunda fila estirada a todo el ancho (tamaño
   inconsistente con las demás). Se baja a 3 columnas (en vez de 4) para
   que las 5 quepan en dos filas (3+2) SIN reducir el ancho de cada
   tarjeta -- de hecho quedan un poco más anchas que antes, nunca más
   angostas, así el texto no se corta ni se desborda. El tamaño/estilo de
   cada tarjeta (.freq-card: borde, radio, padding, tipografía, ícono,
   estado seleccionado) no se tocó, solo el número de columnas de la
   rejilla que las contiene. */
.freq-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:8px}
.freq-card{
  border:2px solid var(--border);border-radius:14px;padding:10px 3px 8px;
  display:grid;justify-items:center;gap:4px;background:var(--surface-2);
  position:relative;text-align:center;
}
.freq-card svg{width:22px;height:22px;color:var(--amber)}
.freq-card strong{font-size:.72rem;line-height:1.15}
.freq-card span{font-size:.6rem;color:var(--muted);line-height:1.2}
.freq-card[aria-pressed="true"]{border-color:var(--accent)}
.freq-card[aria-pressed="true"]::after{
  content:'✓';position:absolute;right:-6px;bottom:-6px;width:18px;height:18px;border-radius:50%;
  background:var(--accent);color:#fff;font-size:.62rem;font-weight:900;display:grid;place-items:center;
  box-shadow:0 1px 3px #00000040;
}

/* Oculta visualmente una etiqueta pero la deja disponible para lectores
   de pantalla -- usado en Enviar sugerencia/Reportar problemas (Punto
   3/4): la imagen aprobada no muestra un <label> de texto visible sobre
   el área de escritura (el hero ya explica qué escribir), pero el campo
   sigue necesitando una etiqueta accesible real. */
.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}

/* FASE 13 (Punto 3/4): fila "Adjuntar archivo (opcional)" -- mismo
   componente visual que .list-row (ícono + texto + chevron) pero como
   <button> de ancho completo fuera de un .list-card, igual que en la
   imagen aprobada (recuadro propio, no dentro de una lista). */
.attach-row{
  display:flex;align-items:center;gap:12px;width:100%;
  border:1px solid var(--border);border-radius:16px;background:var(--surface);
  padding:12px 14px;text-align:left;margin-top:4px;
}
.attach-row:active{background:var(--surface-hover)}
/* Lista de archivos ya adjuntados (vista previa local, ver renderAttachList
   en render.js) -- cada fila reutiliza .list-row dentro de un .list-card
   compacto, con un botón × para quitar el archivo antes de enviar. */
.attach-list:not(:empty){margin-top:8px;border:1px solid var(--border);border-radius:16px;overflow:hidden;background:var(--surface)}
.attach-list .list-row{padding:10px 14px}
.attach-limits{font-size:.74rem;margin:4px 0 0}
.attach-limits + .attach-limits{margin-top:2px}

.hero{
  background:var(--hero-grad);
  padding:26px 20px 30px;
  position:relative;overflow:hidden;
  color:#fff;
}
/* ORDEN DE CORRECCIÓN (Fase 10, ajuste puntual, Punto 2 "fondo de la
   parte superior de Ajustes"): EXCLUSIVO de #screen-more (no toca
   .hero en sí ni ninguna otra pantalla que también use .hero -- Login,
   Inicio, etc. siguen exactamente igual). Antes, debajo de .hero,
   <main> no tenía ningún fondo propio, así que los espacios alrededor
   de la primera .list-card (los "gutters" de padding:16px de <main>)
   mostraban el gris/blanco plano de --bg, cortando en seco el
   degradado justo donde termina .hero -- se veía como si la tarjeta
   flotara sobre el color "por defecto" de la app en vez de sobre una
   vista previa real del Estilo de fondo elegido. Se pinta el MISMO
   var(--hero-grad) (el que ya alimenta buildFondoGradient() en
   render.js -- NO es un color fijo, cambia con el Estilo de fondo
   elegido en Apariencia) como fondo de #screen-more, limitado con
   background-size a una franja fija desde arriba (h ≈ hero + gran
   parte de la primera tarjeta, mismo criterio de "cabecera / sección
   superior" que pide la orden) -- por debajo de esa franja no hay
   imagen de fondo, así que se ve el --bg normal de la pantalla, sin
   invadir "Otros"/Reportes más abajo. <main> sigue sin fondo propio
   (transparente) para que esto se note en sus huecos; .list-card sigue
   opaca (var(--surface)) así que el degradado NUNCA entra dentro de
   las tarjetas. Envuelto en [data-mode="light"] a propósito -- la
   orden pide conservar "el diseño en modo claro" explícitamente, así
   que el modo oscuro de Ajustes queda intacto, sin este tratamiento. */
[data-mode="light"] #screen-more{
  /* Dos capas: la de encima difumina el último tramo de la franja a
     transparente-a-var(--bg) para que el corte con el fondo normal de
     la pantalla sea un degradado suave, no una línea recta visible; la
     de abajo es el propio var(--hero-grad) sin cambios. */
  background-image:
    linear-gradient(to bottom, transparent 0%, transparent 68%, var(--bg) 100%),
    var(--hero-grad);
  background-repeat:no-repeat,no-repeat;
  background-position:top,top;
  background-size:100% 700px,100% 700px;
}
.hero::before{
  content:'';position:absolute;inset:0;
  background:radial-gradient(circle at 85% 10%, #ffffff22, transparent 45%);
  pointer-events:none;
}
.hero-logo{display:flex;flex-direction:column;align-items:center;gap:10px;text-align:center;position:relative}
.hero-logo img{width:84px;height:84px;border-radius:22px;box-shadow:0 12px 30px #00000055}

/* FASE 10 (Punto 1, cabecera de Ajustes: "mantener la tuerca más
   llamativa con apariencia 3D"): mismo tratamiento visual que el estilo
   de ícono "3D" ya aprobado para el resto de la app (superficie clara en
   degradado + sombra en relieve + sombra interior, ver
   [data-iconstyle="3d"] .row-icon más abajo) para que la tuerca decorativa
   del hero de Ajustes deje de ser un simple trazo de color plano flotando
   sobre el degradado y pase a leerse como una placa/insignia con volumen
   real, EN VEZ de cambiar su tamaño o posición (eso sí se mantiene igual
   que antes -- ver el <span> en gastos_personales_app.html). */
.settings-gear-badge{
  width:56px;height:56px;border-radius:16px;flex:none;
  display:grid;place-items:center;
  background:linear-gradient(160deg,#ffffff,#eef1f8);
  color:var(--accent);
  box-shadow:0 4px 0 #00000018, 0 10px 22px #00000040, inset 0 -3px 6px #00000014, inset 0 2px 2px #ffffff;
}
.settings-gear-badge .icon{width:30px;height:30px}

/* ORDEN DE CORRECCIÓN (post-Tanda 5, "logo sin cuadro blanco"): antes
   había aquí un anillo de rescate de contraste (.is-low-contrast) que se
   agregaba/quitaba desde applyLogoContrastGuard() en render.js. Se
   retiró por completo -- el usuario pidió explícitamente eliminar
   cualquier "cuadro/bloc blanco, borde, tarjeta, contenedor blanco, halo
   o fondo... alrededor del logo", y un anillo de rescate (claro u
   oscuro) es exactamente ese tipo de contenedor. El logo (icons/
   logo-mark.png) ahora es un PNG con transparencia real -- solo la
   billetera, sin ningún fondo ni caja -- y en su lugar de un anillo se
   usa un filter:drop-shadow(), que sigue el contorno real (alfa) de la
   ilustración en vez de dibujar un rectángulo/aro alrededor: da
   profundidad y ayuda a que "resalte" sobre cualquier fondo (como pide
   la corrección) sin crear ningún contenedor visible. Ver la nota
   extensa en render.js junto a applyLogoContrastGuard() (conservada como
   no-operación) y el reporte de esta corrección para la validación
   visual real que reemplaza al cálculo WCAG de un solo color. */
.logo-guard{filter:drop-shadow(0 10px 20px rgba(0,0,0,.45))}
.hero-logo h1{margin:4px 0 0;font-size:1.7rem;font-weight:800}
.hero-logo p{margin:0;color:#dbe0ff;font-size:.92rem}

/* grid-template-columns:minmax(0,1fr) en vez de la columna implícita
   "auto" por defecto: sin esto, un hijo con contenido flex que no puede
   encogerse (ej. montos largos "45.000,00 DOP" en 3 columnas, ver
   .stat-col) fuerza el ancho de la ÚNICA columna del grid más allá del
   viewport, y como .app tiene overflow-x:hidden (necesario para el fix
   de position:sticky, ver más abajo), el excedente se recorta en seco —
   afecta a TODAS las tarjetas de la pantalla, no solo a la que originó
   el desborde. Detectado en Inicio (resumen financiero de 3 columnas)
   durante la reconstrucción de la Orden Correctiva; el fix es genérico
   así que se aplica a "main" globalmente, no solo a Inicio. */
/* align-content:start evita que las filas de la grilla se "estiren" para
   rellenar el alto sobrante cuando el contenido de la pantalla es corto
   (p. ej. Idioma con pocas opciones): sin esto, "normal" se computa como
   "stretch" en un contenedor grid con alto definido (main es flex:1 dentro
   de .screen.active), inflando .section-label y .list-card muy por encima
   de su tamaño natural y dejando huecos vacíos entre ellos. Detectado en
   Tarea #84 (Idioma) mediante inspección de layout con Playwright. */
/* grid-auto-rows:max-content (auditoría horizontal v2): sin esto, cuando
   una fila implícita de "main" contiene un hijo que es a su vez un grid
   (p. ej. .list-card en horizontal, que se vuelve display:grid de 2
   columnas) Y ese hijo tiene overflow:hidden, el navegador puede calcular
   mal el alto de la fila del grid EXTERNO (se detectó, p. ej., una fila de
   155px calculada para una .list-card cuyo alto real correcto era 341px),
   dejando que el siguiente elemento (p. ej. un .section-label como
   "Otros") se dibuje encimado sobre el contenido de la fila anterior en
   vez de debajo. Es una segunda manifestación, a nivel del contenedor
   externo, de la misma familia de bug ya documentada más abajo en
   ".list-card" (tamaño automático mal calculado con overflow≠visible
   dentro de un grid) — aquí el defecto está en el cálculo del alto de la
   FILA del grid externo, no en el elemento mismo. Forzar
   grid-auto-rows:max-content hace que cada fila implícita se mida según
   el contenido real de su hijo más alto, evitando el encimado. Se aplica
   en la regla base de "main" (afecta TODAS las pantallas, ambas
   orientaciones) porque el problema no es exclusivo de una pantalla ni de
   una orientación. */
main{padding:16px;display:grid;grid-template-columns:minmax(0,1fr);grid-auto-rows:max-content;gap:14px;align-content:start}

.card{
  background:var(--surface);
  border:1px solid var(--border);
  border-radius:16px;
  padding:16px;
}
.card-hero{
  background:var(--card-on-hero);
  color:var(--card-on-hero-ink);
  border-radius:18px;
  padding:20px;
  box-shadow:var(--shadow);
}
.card-hero .muted,.card-hero small{color:var(--card-on-hero-muted)}
/* .card-hero es SIEMPRE blanca (--card-on-hero, ver :root arriba) sin
   importar modo claro/oscuro — pero .section-label/.row-right heredan
   por defecto --muted-2/--muted de PÁGINA (pensadas para .card, que sí
   cambia con el tema). Necesario ahora que Límites/Categorías de Inicio
   usan .card-hero (blancas en la Figura 3) en vez de .card. */
.card-hero .section-label,.card-hero .row-right{color:var(--card-on-hero-muted)}

/* ============================================================
   ORDEN CORRECTIVA — Fidelidad visual de Inicio (Manual §3.3,
   Figura 3 / image4.png, "referencia visual prioritaria del
   proyecto"). Reconstrucción completa de encabezado, resumen
   financiero, accesos rápidos, límites (semanal+mensual) y
   gastos por categoría contra la imagen oficial.

   Nota de fidelidad (logotipo): la Figura 3 muestra un isotipo
   circular multicolor "GP" distinto del logo 4.1 (naranja sobre
   fondo negro) reafirmado en el Manual §3.18/Figura 29 y usado en
   TODA la app por decisión explícita y ya verificada del usuario
   (ver bitácora, Fase 9). Es un conflicto real entre dos fuentes
   oficiales del propio Manual. Se resuelve manteniendo el logo 4.1
   (fuente más específica y ya confirmada por el usuario para la
   identidad de marca) en la posición/tamaño que indica esta imagen,
   en vez de introducir un segundo isotipo distinto no aprobado
   como variante de marca. Documentado también en la respuesta al
   usuario y en la bitácora — no es una resolución silenciosa.

   Nota de fidelidad (degradado): esta imagen (Figura 3) muestra un
   degradado que se inclina a violeta en la esquina inferior derecha,
   distinto del degradado azul puro ya verificado con pipeta para
   Login/Crear cuenta (Imagen_01/02, ver tools/color-notes.md — esa
   corrección fue explícitamente "sin violeta" pero basada SOLO en
   las imágenes de Login, no en esta). Como Inicio nunca se había
   muestreado con la misma pipeta (quedaba "pendiente" en
   color-notes.md) y tiene su propia imagen oficial distinta a la de
   Login, se le da su propio degradado --hero-grad-home en vez de
   alterar el ya verificado de Login/Crear cuenta. */
/* Tanda 1 - Punto 5 (área segura superior): padding-top propio con
   env(safe-area-inset-top), mismo patrón ya usado en .topbar (ver más
   arriba). env() devuelve 0 en dispositivos sin notch/isla dinámica, así
   que esto nunca reduce el espacio ya existente en pantallas normales --
   solo lo aumenta donde el sistema realmente lo necesita, para que el
   logo/perfil/campana queden completamente visibles y pulsables sin
   manipular el teléfono. Se define aquí (después de .hero en el archivo)
   para que gane por orden de cascada sobre el padding-top corto de
   .hero, sin tocar esa regla general (usada también por Login/Crear
   cuenta, fuera del alcance de esta tanda). */
.hero-home{
  background:var(--hero-grad-home,var(--hero-grad));
  padding-top:calc(26px + env(safe-area-inset-top));
  /* Tanda 4 (Punto 4): antes vivía como style="padding-bottom:22px" en
     el HTML -- movido aquí (mismo valor) para que la media query de
     orientación horizontal más abajo pueda reducirlo sin !important. */
  padding-bottom:22px;
}
/* FASE 10 (corrección puntual, "Extender el estilo de fondo en Inicio"):
   antes el Estilo de fondo (--hero-grad-home) solo vivía en .hero-home
   (el bloque superior) -- en cuanto <main> empezaba a dibujar "Límites
   de gasto"/"Gastos por categoría", el fondo volvía de golpe al --bg
   plano y neutro de toda la app (gris en modo claro / azul oscuro en
   modo oscuro), dejando una franja/corte visible alrededor y detrás de
   esas tarjetas y hacia abajo, hasta la zona de la barra de navegación.
   Se aplica el MISMO degradado (misma variable ya calculada en render()
   sobre <html>, ver js/render.js) directamente al contenedor de la
   pantalla -- SOLO #screen-home, ninguna otra pantalla (Más incluida)
   se toca -- y se le da min-height:100dvh para que el color cubra de
   verdad hasta el borde inferior real del viewport, incluso cuando el
   contenido de Inicio es más corto que la pantalla (ahí es donde antes
   quedaba expuesto el --bg plano justo encima de la barra inferior).
   .hero-home conserva su propio background sin cambios (mismo valor,
   cero costo de la redundancia). Las tarjetas (.card-hero/.card) siguen
   pintando su propio fondo blanco/superficie por encima sin cambios,
   así que el degradado nunca se ve DENTRO de ellas -- solo detrás y
   alrededor. La barra de navegación (.tabs) tampoco se toca: conserva
   su propio fondo sólido var(--bg-elevated) encima de este degradado,
   sin depender de él ni exponerlo dentro de la barra. Responde de forma
   dinámica a cualquier Estilo de fondo (sólido, degradado, arcoíris) y a
   modo claro/oscuro porque reutiliza la misma fuente de verdad
   (--hero-grad-home/--hero-grad) que ya gobierna toda la app -- no hay
   ningún color fijo nuevo aquí. */
#screen-home{
  background:var(--hero-grad-home,var(--hero-grad));
  min-height:100vh;
  min-height:100dvh;
}
/* Tanda 4 (Punto 4): antes style="display:flex;flex-direction:column;
   gap:14px;margin-top:20px" en línea en el HTML -- mismos valores,
   movidos a clase para poder comprimir gap/margin-top solo en
   horizontal (ver media query) sin tocar el valor por defecto (vertical). */
.home-hero-stack{display:flex;flex-direction:column;gap:14px;margin-top:20px}
/* Tanda 4 (Punto 8): título compartido entre "Límites de gasto" y
   "Gastos por categoría" en Inicio -- antes solo el primero llevaba
   este refuerzo (font-size/weight) en línea, heredado de la Tanda 1
   (Punto 8: "título con más peso"), y el segundo se quedaba en el
   tamaño/peso base de .section-label (.72rem/800), viéndose más débil.
   Se sube el más débil al nivel del que ya estaba aprobado -- no se
   reduce ninguno -- y se centraliza en una sola clase para que ambos
   títulos no puedan volver a desalinearse por separado. */
/* Selector combinado (.section-label.home-block-title, no solo
   .home-block-title) a propósito: ambas clases conviven en el mismo
   <span> en el HTML, y .section-label se define MÁS ABAJO en este mismo
   archivo con la misma especificidad (una sola clase) -- sin combinar
   ambas clases aquí, la regla de .section-label que aparece después en
   la cascada terminaría ganando y el título volvería a quedar en .72rem/
   800 en vez de .82rem/900. Verificado con Playwright que esto se
   corrigió (antes: font-size computado 11.52px/peso 800 pese a esta
   regla; después: 13.12px/900 en ambos títulos). */
.section-label.home-block-title{font-size:.82rem;font-weight:900;padding:0}
/* Tanda 4 (Punto 4): paddings de las tarjetas de Inicio (Límites,
   Categorías, Mis bancos) -- antes en línea (style="padding:14px 18px
   4px" / style="padding:22px" x2), mismos valores movidos a clase para
   poder comprimirlos solo en horizontal. */
.home-limits-card{padding:14px 18px 4px}
.home-section-card{padding:22px}

.home-header{display:flex;align-items:flex-start;justify-content:space-between;gap:8px;position:relative}
.home-header-side{display:flex;flex:none;width:48px}
.home-header-side.is-right{justify-content:flex-end}
.home-header-center{flex:1;display:flex;flex-direction:column;align-items:center;text-align:center;gap:2px;min-width:0}
/* ORDEN DE CORRECCIÓN (Punto 1, "logo en Inicio más grande y con más
   presencia"): +38% adicional sobre el tamaño ya aumentado en la Tanda 5
   (45px). border-radius/box-shadow de "tarjeta" se quitan (ya no hay
   fondo cuadrado que redondear -- ver logo-mark.png); el realce visual
   ahora lo da el filter:drop-shadow de .logo-guard, que sigue el
   contorno real de la billetera. */
.home-header-center img{width:62px;height:62px;margin-bottom:2px}
.home-header-center h1{margin:0;font-size:1.15rem;font-weight:800}
.home-header-center p{margin:0;color:#dbe0ff;font-size:.82rem}
/* Tanda 1 - Punto 6: la opción de usuario (acceso a Perfil) se ve un
   poco más grande que el ".avatar" genérico (48px vs 44px) y con un
   halo/sombra propios para "sobresalir mejor" sobre el degradado del
   hero, sin tocar ".avatar" en sí (compartida con Perfil/Editar perfil,
   fuera de alcance de esta tanda). Sigue siendo el mismo <button> con
   data-nav="profile", pulsable igual que antes. */
.avatar-home{
  width:48px;height:48px;
  box-shadow:0 4px 14px #00000055,0 0 0 2px #ffffff40;
}
.avatar-home .icon{width:24px;height:24px}
/* Tanda 1 - Punto 7: se quita el fondo circular de ".icon-btn" -- la
   campana ya no se ve "encerrada en un círculo". Conserva un área táctil
   de 44x44 (mínimo accesible) y un ícono más grande que antes (26px vs
   20px) para seguir siendo claramente pulsable y no confundirse con un
   adorno decorativo; "position:relative" se mantiene para anclar el
   indicador de notificaciones pendientes. No cambia la funcionalidad de
   notificaciones ya aprobada (Tarea #97), solo la presentación. */
.home-bell-wrap{
  position:relative;width:44px;height:44px;flex:none;
  display:grid;place-items:center;
  background:transparent;border:none;color:#fff;
  filter:drop-shadow(0 2px 6px #00000055);
}
.home-bell-wrap .icon{width:26px;height:26px}
.home-bell-badge{
  position:absolute;top:2px;right:2px;min-width:17px;height:17px;padding:0 4px;
  border-radius:99px;background:var(--red);color:#fff;font-size:.65rem;font-weight:800;
  display:grid;place-items:center;border:2px solid var(--bg,#0a0e1f);line-height:1;
}

/* Tarjeta oscura translúcida "flotando" sobre el degradado del hero
   (Resumen de este mes, Agregar ingreso/gasto) — distinta de
   .card-hero (siempre blanca, ver arriba) que se reserva para las
   tarjetas Límites/Categorías que SÍ son blancas en la referencia. */
.card-on-hero-dark{
  background:#0a1230ee;border:1px solid #ffffff1f;border-radius:18px;
  padding:16px;color:#fff;backdrop-filter:blur(2px);
}
.card-on-hero-dark .muted{color:#c6cdec}

.stat-col{flex:1;min-width:0;text-align:center;display:flex;flex-direction:column;align-items:center;gap:7px}
.stat-col + .stat-col{border-left:1px solid #ffffff26}
.stat-label{font-size:.62rem;font-weight:800;letter-spacing:.04em;text-transform:uppercase}
.stat-amount{font-size:.8rem;font-weight:800;max-width:100%;overflow-wrap:break-word}
.stat-icon{
  width:34px;height:34px;border-radius:50%;flex:none;
  display:grid;place-items:center;color:#fff;
}
.stat-icon .icon{width:17px;height:17px}
.text-blue{color:var(--blue)}

.quick-action-row{display:flex;gap:8px}
.quick-action-card{
  flex:1;min-width:0;display:flex;align-items:center;gap:6px;
  background:#0a1230ee;border:1px solid #ffffff1f;border-radius:16px;
  padding:10px;color:#fff;text-align:left;
}
.quick-action-card.is-income{border-color:#2dd4bf73}
.quick-action-card strong{font-size:.76rem;font-weight:700;display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.quick-action-card .stat-icon{width:30px;height:30px;flex:none}
.quick-action-card .stat-icon .icon{width:18px;height:18px}

/* Límites de gasto — semanal + mensual (Figura 3). Cada fila reutiliza
   .progress-track/.progress-fill ya existentes (ver más abajo) para no
   duplicar el sistema de barras de progreso. */
.limit-row{display:flex;flex-direction:column;gap:6px}
.limit-row + .limit-row{margin-top:16px}
.limit-row-head{display:flex;align-items:center;gap:10px}
.limit-row-head strong{flex:1;font-size:.9rem}
.limit-row-pct{font-weight:800;font-size:.95rem}
.limit-row-amounts{font-size:.78rem;color:var(--card-on-hero-muted);padding-left:44px}

/* Pantalla dedicada de Límites (Tarea #86, Figura 22/23/image21.png):
   filas de alternar de alerta + resumen combinado, dentro de las mismas
   tarjetas .card-hero ya usadas para el bloque de límites en Inicio, para
   mantener consistencia visual entre ambas pantallas. */
.alert-toggle-row{
  display:flex;align-items:center;gap:12px;
  padding:12px 0;border-bottom:1px solid var(--border);
}
.alert-toggle-row .row-text{flex:1;min-width:0}
.alert-toggle-row .row-text strong{display:block;font-size:.86rem;color:var(--card-on-hero-ink)}
.alert-toggle-row .row-text span{display:block;font-size:.74rem;color:var(--card-on-hero-muted);margin-top:1px}
.alert-toggle-row input[type="checkbox"]{width:20px;height:20px;accent-color:var(--accent);flex:none}
.limits-summary-row{display:flex;gap:12px}
.limits-summary-row > div{flex:1;background:#f3f4f8;border-radius:12px;padding:10px 12px}
.limits-summary-row span{display:block;font-size:.72rem;color:var(--card-on-hero-muted);margin-bottom:2px}
.limits-summary-row strong{font-size:1rem;color:var(--card-on-hero-ink)}

.donut-row{display:flex;gap:16px;align-items:center;margin-top:6px}
.donut-canvas-wrap{position:relative;flex:none;width:118px;height:118px}
.donut-canvas-wrap canvas{width:100%;height:100%}
.donut-total{
  position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;
  text-align:center;pointer-events:none;
}
.donut-total span:first-child{font-size:.66rem;color:var(--card-on-hero-muted);font-weight:700;text-transform:uppercase;letter-spacing:.04em}
/* Tarea #87: se detectó que un total largo (p. ej. "31.500,00 DOP") se
   desbordaba visualmente SOBRE el anillo de color de la dona — M()
   (Intl.NumberFormat) separa el número del código de moneda con un
   ESPACIO DE NO RUPTURA (U+00A0), así que el navegador nunca partía esa
   cadena por su cuenta. overflow-wrap:anywhere fuerza el corte; pero el
   max-width debe ajustarse al AGUJERO TRANSPARENTE de la dona, no al
   cuadrado completo del canvas: drawDonutChart (charts.js) dibuja el
   anillo con rInner = rOuter*0.6, es decir el hueco central mide ~55-58%
   del ancho de .donut-canvas-wrap, no el 88% usado en el primer intento
   de este fix (que dejaba el texto ancho de sobra pero solapado sobre el
   propio anillo de color). Afecta por igual a Inicio (donde ya existía
   este componente) y a Reportes (Tarea #87, que lo reutiliza) —
   corregido una sola vez aquí. */
.donut-total span:last-child{display:block;font-size:.72rem;font-weight:800;color:var(--card-on-hero-ink);max-width:56%;overflow-wrap:anywhere;line-height:1.15}
.donut-legend{flex:1;display:flex;flex-direction:column;gap:7px;min-width:0}
.donut-legend-row{display:flex;align-items:center;gap:7px;font-size:.78rem}
.donut-legend-dot{width:9px;height:9px;border-radius:50%;flex:none}
.donut-legend-row .cat-name{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-weight:650}
.donut-legend-row .cat-pct{font-weight:800;flex:none}
.donut-legend-row .cat-amt{display:block;font-size:.72rem;color:var(--muted);text-align:right}
/* Tanda 1 - Punto 9: dona y texto de leyenda más grandes SOLO en Inicio
   -- selector con prefijo "#homeCats" para no afectar el mismo
   componente compartido (.donut-*) usado por Reportes (reports.js,
   donutBlockInto), que no forma parte del alcance de esta tanda. */
#homeCats .donut-canvas-wrap{width:140px;height:140px}
#homeCats .donut-legend-row{font-size:.85rem}

.alert-banner{
  display:flex;align-items:center;gap:12px;
  background:#ef444417;border:1px solid #ef444440;border-radius:14px;
  padding:13px 14px;width:100%;text-align:left;
}
.alert-banner .stat-icon{background:var(--red)}
.alert-banner strong{display:block;font-size:.88rem;color:var(--red)}
.alert-banner span{display:block;font-size:.78rem;color:var(--muted);margin-top:1px}
.alert-banner .row-chevron{margin-left:auto;flex:none}

.section-label{
  font-size:.72rem;font-weight:800;letter-spacing:.06em;
  color:var(--muted-2);text-transform:uppercase;
  padding:4px 4px 0;
}
/* Subtítulo opcional bajo .section-label (Idioma, Figura 8/image18.png:
   "El cambio se aplicará en toda la aplicación"). */
.section-sublabel{font-size:.8rem;color:var(--muted);padding:4px 4px 0;margin:0}

/* Caja informativa reutilizable (Idioma, Figura 8/image18.png: "Puedes
   cambiar el idioma cuando quieras desde Ajustes"). Reutiliza --accent-soft
   ya definido para acentos de marca. */
.info-box{
  display:flex;align-items:flex-start;gap:10px;
  background:var(--accent-soft);border-radius:14px;
  padding:12px 14px;font-size:.8rem;color:var(--ink-soft);
}
.info-box-icon{flex:none;width:20px;height:20px;color:var(--accent)}
.info-box-icon svg{width:100%;height:100%}

/* Etiqueta "Idioma actual" (Figura 8/image18.png) sobre el idioma
   seleccionado en #languageList, sustituye visualmente al radio-dot simple
   por un indicador con texto, más fiel a la referencia. */
.lang-current-tag{
  font-size:.68rem;font-weight:800;color:var(--accent);
  white-space:nowrap;
}

/* Cabecera de grupo por día en Movimientos (Figura 19/image7.png):
   etiqueta del día + total neto del día, dentro del propio list-card. */
.mov-day-header{
  display:flex;justify-content:space-between;align-items:center;
  padding:12px 14px 6px;font-weight:800;font-size:.85rem;color:var(--ink);
}
.mov-day-header span:last-child{font-weight:800}

.muted{color:var(--muted)}
.ink-soft{color:var(--ink-soft)}

/* ---- Formularios ---- */
.field{display:grid;gap:6px;margin-bottom:12px}
/* AUDITORÍA HORIZONTAL (complemento Tanda 6): envoltorio opcional para
   agrupar 2 campos en una fila SOLO en horizontal (ver la regla real
   dentro de "@media (orientation:landscape)..." más abajo). En
   cualquier otra circunstancia es "display:contents" -- desaparece por
   completo de la caja de layout, así que los ".field" de adentro se
   comportan exactamente como si este envoltorio no existiera: cero
   cambio visual en el diseño vertical ya aprobado. */
.field-pair{display:contents}
/* Misma mecánica que ".field-pair" pero genérica para 2 controles
   cualesquiera que no sean ".field" (p. ej. 2 botones/label-botón
   consecutivos que hoy ocupan una fila completa cada uno) -- reutilizada
   en vez de crear una tercera variante ad-hoc, mismo criterio de
   "reglas consistentes y reutilizables" pedido en esta auditoría. */
.btn-pair{display:contents}
.field label{font-size:.82rem;font-weight:650;color:var(--muted)}
.input-wrap{
  display:flex;align-items:center;gap:10px;
  background:var(--surface-2);border:1px solid var(--border);
  border-radius:12px;padding:0 14px;min-height:50px;
}
.input-wrap input,.input-wrap select{
  flex:1;background:none;border:0;min-height:48px;color:var(--ink);
  min-width:0;
}
.input-wrap input::placeholder{color:var(--muted-2)}
.input-wrap:focus-within{border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-soft)}
.input-wrap .icon{color:var(--muted);flex:none;display:grid;place-items:center}
.input-wrap button.toggle-eye{color:var(--muted);flex:none}
/* CORRECCIÓN PUNTUAL — FASE 9 (Punto 1, "Nombre del banco" pasa a ser de
   solo lectura tras eliminar la duplicidad con "Buscar bancos"): sin
   cambiar bordes/colores/espaciados generales del campo (todo eso viene de
   .input-wrap de arriba, sin tocar), solo se evita el cursor de texto para
   no sugerir que se puede escribir ahí. */
#bankName[readonly]{cursor:default}
/* CORRECCIÓN PUNTUAL — FASE 9 (Punto 2, insignia de marca del banco
   seleccionado dentro de "Nombre del banco"): contenedor pequeño, MISMO
   espacio que ocupaba el ícono genérico de siempre (ver .input-wrap .icon
   arriba, sin tocarla) -- por defecto (sin banco reconocido) sigue
   mostrando ese mismo ícono sin ningún cambio visual. Solo cuando hay un
   banco reconocido (--brand) se convierte en un círculo de color con el
   monograma de esa marca. */
.bank-name-icon-slot{display:grid;place-items:center;flex:none}
/* Nota: las clases .bg-* (ver más abajo, sección de acentos) SOLO fijan la
   variable --rc; el color de fondo real de .row-icon lo pintan las reglas
   de [data-iconstyle] (Fase 10). Esta insignia vive FUERA de .row-icon (es
   un ícono de campo, no un ícono de fila), así que pinta su propio fondo
   directamente con var(--rc) para no depender de qué "Estilo de íconos"
   esté activo -- mismo bg-* de siempre, un uso más directo de --rc. */
.bank-name-icon-slot--brand{width:22px;height:22px;border-radius:50%;color:#fff;background:var(--rc,var(--accent))}
.bank-name-icon-slot--brand .bank-mono{font-size:.6rem}

input[type="date"],input[type="time"],select{color-scheme:dark}
[data-mode="light"] input[type="date"],[data-mode="light"] input[type="time"],[data-mode="light"] select{color-scheme:light}

/* ---- Botones ---- */
.btn{
  min-height:50px;display:flex;align-items:center;justify-content:center;gap:8px;
  border-radius:12px;font-weight:800;padding:10px 16px;width:100%;
}
.btn-primary{background:linear-gradient(120deg,var(--accent),var(--accent-2));color:#fff}
.btn-secondary{background:var(--surface-2);color:var(--ink);border:1px solid var(--border)}
.btn-outline{background:transparent;border:1.5px solid var(--accent);color:var(--accent)}
.btn-danger{background:var(--red);color:#fff}
.btn-danger-outline{background:transparent;border:1.5px solid var(--red);color:var(--red)}
.btn-success{background:linear-gradient(120deg,#22c55e,#16a34a);color:#fff}
.btn-sm{min-height:38px;padding:6px 12px;width:auto;font-size:.85rem}
.btn:disabled{opacity:.5;pointer-events:none}
.btn:focus-visible,.icon-btn:focus-visible,.back-btn:focus-visible,button:focus-visible{outline:3px solid var(--accent-soft);outline-offset:2px}

.btn-row{display:flex;gap:10px}
.btn-row .btn{flex:1}

/* ---- Filas de lista (settings-style) ---- */
/* CORRECCIÓN CRÍTICA (auditoría horizontal v2): el tamaño mínimo automático
   de un elemento con overflow≠visible dentro de un contenedor grid se
   resuelve a 0 según la especificación CSS, en vez de basarse en su
   contenido. Como <main> es SIEMPRE un grid (display:grid en la regla base
   de main, ver más abajo) y tiene una altura definida (flex:1;min-height:0
   dentro de .screen.active>main), cualquier .list-card —que tiene
   overflow:hidden— podía colapsar a una fracción de su alto real (se
   detectaron colapsos de 12px, 68px, 129px, 211px, 569px según el caso),
   ocultando filas sin posibilidad de scroll. Esto afectaba TANTO vertical
   como horizontal (ej. Historial con más de ~10 movimientos ya perdía
   filas en modo vertical, un bug preexistente a esta sesión). La corrección
   universal es forzar min-height:max-content para que el navegador calcule
   la altura real según el contenido en vez de aplicar el mínimo automático
   de 0. Se aplica en la regla base (no solo en la media query horizontal)
   porque el problema es independiente de la orientación. */
.list-card{background:var(--surface);border:1px solid var(--border);border-radius:16px;overflow:hidden;min-height:max-content}
.list-row{
  display:flex;align-items:center;gap:12px;
  padding:14px 16px;
  border-bottom:1px solid var(--border);
  width:100%;text-align:left;
}
.list-row:last-child{border-bottom:0}
.list-row:active,.list-row:hover{background:var(--surface-hover)}
.row-icon{
  width:38px;height:38px;border-radius:50%;flex:none;
  display:grid;place-items:center;color:#fff;font-size:1.05rem;
}
/* CORRECCIÓN PUNTUAL — FASE 9 (Punto 2, insignia/monograma de marca de
   banco): mismo patrón de .row-icon svg use{color:inherit} de abajo, pero
   para texto -- el monograma hereda el color correcto automáticamente en
   cualquiera de los 5 "Estilo de íconos" (Fase 10) sin código extra, ya
   que solo usa la propiedad `color` normal de CSS, igual que el ícono SVG
   que reemplaza. Único selector nuevo: .bank-mono, usado SOLO dentro de
   .row-icon (resultados de "Buscar bancos") y dentro de
   .bank-name-icon-slot--brand (ver input-wrap más abajo) -- no toca
   ningún otro texto de la app. */
.bank-mono{font-weight:800;letter-spacing:.2px;line-height:1}
.row-icon .bank-mono{font-size:.72rem}
.row-text{flex:1;min-width:0}
.row-text strong{display:block;font-size:.96rem}
.row-text span{display:block;font-size:.8rem;color:var(--muted);margin-top:1px}
.row-chevron{color:var(--muted);flex:none}
.row-danger .row-text strong{color:var(--red)}
.row-right{flex:none;color:var(--muted);font-size:.85rem}

/* FASE 8 — Reorganización del Perfil (Punto 7: "más limpio, más moderno,
   mejor distribuido"). Sección "Accesos rápidos" de Perfil: grilla de
   tarjetas cuadradas (ícono arriba + título + subtítulo), fiel al patrón
   de la imagen de referencia adjunta a la orden. Nombres de clase con
   prefijo "profile-" a propósito -- son de uso exclusivo de #screen-profile,
   no se reutilizan en ningún otro lugar de la app, para no arriesgar
   ninguna otra pantalla ya aprobada. Reusa las mismas variables de diseño
   que .list-card/.card (--surface/--border) para mantener la identidad
   visual intacta. */
.profile-quick-grid{display:grid;grid-template-columns:1fr 1fr;gap:12px}
.profile-quick-tile{
  background:var(--surface);border:1px solid var(--border);border-radius:16px;
  padding:16px 14px;text-align:left;display:flex;flex-direction:column;gap:8px;
}
.profile-quick-tile:active,.profile-quick-tile:hover{background:var(--surface-hover)}
.profile-quick-tile .row-icon{width:38px;height:38px}
.profile-quick-tile strong{font-size:.92rem;display:block}

/* FASE 8 (corrección puntual, Punto 1.1 "íconos del Perfil"): contenedor
   EXCLUSIVO de las 5 filas de Perfil que reciben el nuevo set de íconos a
   todo color (i-prof-*, ver icons.js). No se toca .row-icon (regla
   global, compartida por el resto de la app) -- esta clase se agrega
   ADEMÁS de .row-icon (mismo <span class="row-icon profile-icon">) y
   solo sobreescribe lo necesario para que "el fondo tenga menor
   protagonismo" que la figura: pasa de círculo con color sólido a
   cuadrado redondeado con un fondo muy claro y neutro (var(--surface-2)),
   más grande (44px, antes 38px) para que el ícono detallado se lea bien.
   quick-tile ya fija .row-icon a 38px con mayor especificidad (arriba) --
   se repite el tamaño aquí con el mismo peso de selector para que
   .profile-icon gane también dentro de "Accesos rápidos". */
.row-icon.profile-icon,.profile-quick-tile .row-icon.profile-icon{
  width:44px;height:44px;border-radius:14px;
  background:var(--surface-2);color:var(--ink);
  border:0;box-shadow:none;
}
/* ORDEN DE CORRECCIÓN (Fase 8, ajuste puntual, Punto 1 "resaltar más el
   icono, no el fondo"): el contenedor (.row-icon, 44px) NO cambia de
   tamaño a propósito -- solo crece la figura interna. Se detectó que la
   regla anterior (".profile-icon .icon", 2 clases) tenía la MISMA
   especificidad que la regla global ".row-icon .icon{width:22px}" de más
   abajo y, al venir antes en el archivo, perdía el empate -- el ícono
   real se estaba pintando a 22px en vez de los 28px que el código ya
   intentaba. Se sube el selector a 3 clases (".row-icon.profile-icon
   .icon") para ganarle siempre a la regla global sin importar el orden,
   y se aumenta el tamaño real (28px -> 32px, ~73% del contenedor) para
   que la figura se note claramente más grande y reconocible. */
.row-icon.profile-icon .icon,.row-icon.profile-icon svg{width:32px;height:32px}

/* FASE 8 (corrección puntual, Punto 1.2 "botón del lápiz"): botón
   EXCLUSIVO de la cabecera de Perfil -- se agrega a .topbar-action (no la
   reemplaza), así que conserva su tamaño/posición base y solo gana lo
   necesario para "verse más grande, llamativo y profesional": blanco
   puro (en vez del gris neutro de .topbar-action), borde sutil, sombra
   elevada tipo botón flotante, e ícono un poco más grande y en el color
   de acento (en vez de var(--ink) plano) para que se identifique de
   inmediato al entrar a la pantalla. */
.profile-edit-btn{
  width:48px;height:48px;border-radius:13px;
  background:#fff;border:1px solid var(--border);
  color:var(--accent);
  box-shadow:0 4px 14px rgba(20,24,40,.14);
}
[data-mode="dark"] .profile-edit-btn{background:var(--surface-2)}
/* ORDEN DE CORRECCIÓN (Fase 8, ajuste puntual, Punto 1 "también en el
   botón del lápiz"): mismo criterio que .profile-icon arriba -- el botón
   (48px) no cambia de tamaño, solo el trazo del lápiz dentro (22px ->
   28px, ~58% del botón) para que se lea más grande y llamativo sin
   agrandar la caja. */
.profile-edit-btn .icon{width:28px;height:28px}
/* Nota a propósito: el selector del subtítulo NO es un ".profile-quick-tile
   span" genérico -- eso también capturaría el <span class="row-icon"> (que
   ya trae su propio color:#fff con menor especificidad) y se lo pisaría,
   dejando el ícono gris en vez de blanco. Se excluye explícitamente con
   :not(.row-icon) para que solo afecte al subtítulo real. */
.profile-quick-tile > strong + span:not(.row-icon),.profile-quick-tile .row-text span{font-size:.76rem;color:var(--muted);line-height:1.3}
.profile-quick-tile-wide{grid-column:1/-1;flex-direction:row;align-items:center}

/* FASE 8 (corrección puntual, Punto 2 "Calendario financiero") --
   implementación real, reemplaza el grid estático de solo-interfaz de la
   Fase 8 original. Grilla de 7 columnas DOMINGO-primero (ver
   weekdayLabels() en render.js), generada en JS por
   renderFinanceCalendar()/buildFinCalMonthGrid() -- ver
   #screen-financeCalendar. Cada día real es ahora un <button> (antes un
   <div> decorativo) para poder seleccionarlo (Punto 2.1 "selección de un
   día específico"). */
.fin-cal-grid{display:grid;grid-template-columns:repeat(7,1fr);gap:4px;margin-top:4px}
.fin-cal-dow{font-size:.7rem;font-weight:700;color:var(--muted-2);text-align:center;padding:2px 0 6px}
.fin-cal-day{
  aspect-ratio:1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:2px;
  border-radius:10px;font-size:.82rem;color:var(--ink);position:relative;
}
/* Días de relleno del mes anterior/siguiente (Punto 2.1, fidelidad
   visual de la imagen aprobada, que sí los muestra en gris): NO llevan
   data-fincal-day, así que no son seleccionables -- solo referencia
   visual de dónde empieza/termina la semana. */
.fin-cal-day-outside{color:var(--muted-2);opacity:.55}
/* Columna domingo (primera columna del grid): mismo tratamiento en rojo
   suave que la imagen aprobada, independiente de si ese día tiene o no
   movimientos. */
.fin-cal-day-sunday{color:var(--red)}
.fin-cal-day-today{box-shadow:inset 0 0 0 2px var(--accent);font-weight:800}
.fin-cal-day-selected{background:var(--accent);color:#fff;font-weight:800}
.fin-cal-dots{display:flex;gap:2px;height:5px}
.fin-cal-dot{width:5px;height:5px;border-radius:50%;background:var(--gray);flex:none}
.fin-cal-dot-green{background:var(--green)}
.fin-cal-dot-red{background:var(--red)}
.fin-cal-dot-blue{background:var(--blue)}
.fin-cal-dot-gray{background:var(--gray)}
/* El día seleccionado usa fondo de acento sólido -- sus puntos de color
   perderían contraste, así que se muestran en blanco (Punto 2.4 "buena
   legibilidad"), igual que el pequeño punto blanco de la imagen
   aprobada dentro del círculo del día 14. */
.fin-cal-day-selected .fin-cal-dot{background:#fff!important}

/* Punto 2.4 "Colores e indicadores" -- leyenda de los 4 puntos, debajo
   del grid de la vista Mes. */
.fin-cal-legend{display:flex;flex-wrap:wrap;gap:10px 14px;margin-top:14px;padding-top:12px;border-top:1px solid var(--border)}
.fin-cal-legend span{display:inline-flex;align-items:center;gap:6px;font-size:.74rem;color:var(--muted)}
.fin-cal-legend .fin-cal-dot{width:8px;height:8px}

/* Punto 2.1 "navegación entre meses y años" + "búsqueda o acceso rápido
   a una fecha": fila con el selector de periodo (pill "Mayo 2025 ⌄", que
   abre #finCalJumpSheet) y las flechas ‹ › para avanzar/retroceder un
   paso (mes en vista Mes, año en vista Año). */
.fin-cal-nav{display:flex;align-items:center;gap:8px;margin:10px 0 14px}
.fin-cal-navpill{
  flex:1;display:flex;align-items:center;gap:8px;justify-content:center;
  padding:11px 12px;border-radius:12px;background:var(--surface);border:1px solid var(--border);
  font-weight:700;font-size:.9rem;color:var(--ink);min-width:0;
}
.fin-cal-navpill span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.fin-cal-navpill svg{flex:none;width:18px;height:18px;color:var(--muted)}
.fin-cal-arrows{display:flex;gap:6px;flex:none}
.fin-cal-arrows button{width:44px;height:44px;border-radius:12px;background:var(--surface-2);color:var(--ink);display:grid;place-items:center;flex:none}

/* Vista Año (Punto 2.1 "vista por año"): grilla de 12 meses, mismo
   patrón visual que .mode-grid/.freq-grid ya usados en otras pantallas
   (tarjeta con borde, ícono/indicador arriba, texto abajo). */
.fin-cal-yeargrid{display:grid;grid-template-columns:repeat(3,1fr);gap:10px}
.fin-cal-monthcell{
  background:var(--surface);border:1px solid var(--border);border-radius:14px;
  padding:14px 8px;display:flex;flex-direction:column;align-items:center;gap:6px;
  font-size:.85rem;color:var(--ink);
}
.fin-cal-monthcell-today{border-color:var(--accent);box-shadow:inset 0 0 0 1px var(--accent)}
.fin-cal-monthcell .fin-cal-dots{height:6px}
.fin-cal-monthcell .fin-cal-dots-empty{color:var(--muted-2);font-size:.7rem;height:auto}

/* ORDEN CORRECTIVA — Moneda/Idioma (Manual §3.9/§3.10, Figura 7/image16.png):
   cada fila necesita bandera real (no solo código de 2-3 letras) + datos
   centrales + indicador de selección tipo radio, en vez del texto "✓"
   plano que había antes. */
.flag-icon{
  width:38px;height:38px;border-radius:50%;flex:none;
  display:grid;place-items:center;font-size:1.3rem;
  background:var(--surface-2);border:1px solid var(--border);overflow:hidden;
}
.radio-dot{
  width:22px;height:22px;border-radius:50%;flex:none;
  border:2px solid var(--border);display:grid;place-items:center;
}
.radio-dot.is-checked{border-color:var(--accent);background:var(--accent)}
.radio-dot.is-checked::after{content:'';width:8px;height:8px;border-radius:50%;background:#fff}
.current-choice-card{
  background:var(--accent-soft);border:1.5px solid var(--accent);border-radius:16px;
  display:flex;align-items:center;gap:12px;padding:14px 16px;
}

/* Colores funcionales para row-icon: definen la variable --rc ("row
   color"), reutilizados en toda la app. El tratamiento visual real
   (relleno sólido / contorno / lineal / degradado / 3D) lo decide
   [data-iconstyle] más abajo (Fase 11 — Diseño de la aplicación),
   para que el estilo elegido en Imagen_33 se aplique consistentemente
   en cada pantalla, no solo en el selector. */
.bg-blue{--rc:var(--blue)}
.bg-green{--rc:var(--green)}
.bg-red{--rc:var(--red)}
.bg-orange{--rc:var(--orange)}
.bg-amber{--rc:var(--amber)}
.bg-purple{--rc:var(--purple)}
.bg-pink{--rc:var(--pink)}
.bg-teal{--rc:var(--teal)}
.bg-gray{--rc:var(--gray)}
.bg-accent{--rc:var(--accent)}

/* ---- Avatar ---- */
.avatar{
  width:44px;height:44px;border-radius:50%;
  display:grid;place-items:center;
  background:var(--surface-2);color:var(--ink);font-weight:800;flex:none;
  overflow:hidden;border:1px solid var(--border);
}
.avatar img{width:100%;height:100%;object-fit:cover}
.avatar-lg{width:104px;height:104px;font-size:2rem}

/* FASE 9 (Punto 2, mensaje motivacional de Metas): versión ampliada de
   .row-icon para el ícono hero de #goalsIntroView -- mismo componente
   (círculo de color + ícono blanco centrado), solo más grande, igual que
   .avatar-lg hace con .avatar. */
.goals-intro-icon{width:96px;height:96px}
/* Especificidad reforzada (#goalsIntroView + .icon) a propósito: el
   selector genérico ".row-icon .icon" (styles.css, sección de Bancos)
   fija width/height:20px con la MISMA especificidad de 2 clases y
   aparece más abajo en este archivo, así que un simple
   ".goals-intro-icon .icon" perdería la cascada y el ícono se quedaría
   en 20px pese a este bloque. */
#goalsIntroView .goals-intro-icon.icon,#goalsIntroView .goals-intro-icon .icon{width:46px;height:46px}

/* Botón de campana en Inicio (Manual Oficial §3.3: "Mostrar logo y saludo
   ... campana a la derecha" / "Abrir Notificaciones al tocar la campana").
   Vive sobre el .hero (fondo siempre oscuro vía --hero-grad), por eso usa
   colores fijos blancos translúcidos en vez de las variables de --surface
   que dependen del modo claro/oscuro de la página. */
.icon-btn{
  width:40px;height:40px;border-radius:50%;flex:none;
  display:grid;place-items:center;
  background:#ffffff26;color:#fff;border:1px solid #ffffff33;
}
.icon-btn .icon{width:20px;height:20px}

/* ---- Chips / badges ---- */
.badge{padding:4px 9px;border-radius:99px;font-size:.72rem;font-weight:800}
.badge-green{background:#22c55e26;color:#4ade80}
.badge-red{background:#ef444426;color:#f87171}
.badge-accent{background:var(--accent-soft);color:var(--accent)}
.badge-new{background:var(--accent);color:#fff}
/* Tanda 3 (Bancos, 5.6/5.12): estado "Cuenta inactiva" en la lista de
   #screen-bancos -- neutro (ni verde de éxito ni rojo de peligro), y
   siempre acompañado del texto de la etiqueta (nunca solo el color,
   ver bankRowHtml en render.js), así que basta un tono gris apagado. */
.badge-gray{background:#6b728033;color:#9ca3af}
[data-mode="light"] .badge-green{color:#15803d}
[data-mode="light"] .badge-red{color:#b91c1c}
[data-mode="light"] .badge-gray{color:#4b5563}

/* ---- Segmented control (tabs internas, p.ej. Reportes) ---- */
.segtabs{display:flex;gap:6px;background:var(--surface-2);border:1px solid var(--border);border-radius:12px;padding:4px;overflow-x:auto}
.segtabs button{flex:1;white-space:nowrap;padding:9px 10px;border-radius:9px;font-weight:700;font-size:.86rem;color:var(--muted)}
.segtabs button.active{background:var(--accent);color:#fff}
/* Variante para segtabs de 4 (Reportes, Tarea #87): con 4 botones el
   presupuesto de ancho por botón es menor que en los de 2-3 (mismo bug
   de desborde ya corregido en Respaldo/Tarea #85) — fuente y padding
   reducidos para que las 4 etiquetas quepan sin recortarse. */
.segtabs-4 button{font-size:.74rem;padding:9px 4px}

/* Tarjetas de estadística de Reportes (Tarea #87, Figura 24/25). */
.report-stat-row{display:flex;gap:10px}
.report-stat-card{flex:1;background:var(--surface);border:1px solid var(--border);border-radius:14px;padding:12px 14px}
.report-stat-card>span:first-child{display:block;font-size:.76rem;color:var(--muted)}
.report-stat-card strong{display:block;font-size:1.05rem;margin-top:2px}
.report-stat-delta{display:block;font-size:.72rem;margin-top:3px;font-weight:700;color:var(--muted)}
.report-stat-delta.up{color:var(--green)}
.report-stat-delta.down{color:var(--red)}
.report-quick-row{display:flex;justify-content:space-between;align-items:center;gap:10px;padding:10px 0;border-bottom:1px solid var(--border);font-size:.84rem;color:var(--muted)}
.report-quick-row strong{font-weight:800;color:var(--ink);text-align:right}
.report-ring-card{flex:1;display:flex;flex-direction:column;align-items:center;gap:8px;background:var(--surface);border:1px solid var(--border);border-radius:14px;padding:14px}
.report-ring-card>div{text-align:center}
.report-ring-card>div>span{display:block;font-size:.76rem;color:var(--muted)}
.report-ring-card strong{font-size:.92rem}
.report-ring-pct{font-size:1.05rem;font-weight:800;color:var(--ink)}

/* ---- Barra de navegación inferior ---- */
.tabs{
  position:fixed;left:50%;bottom:0;transform:translateX(-50%);
  width:min(100%,520px);z-index:20;
  /* Tanda 2 (fusionada con la Tanda 3): antes "1fr 1fr auto 1fr 1fr"
     reservaba la columna central "auto" para el FAB circular de 56px.
     Con el (+) retirado y sustituido por una pestaña normal ("Bancos"),
     las 5 pestañas vuelven a repartirse el ancho por igual, igual que ya
     ocurría antes de que existiera el FAB. */
  display:grid;grid-template-columns:repeat(5,1fr);
  align-items:center;gap:2px;
  padding:8px 10px calc(10px + env(safe-area-inset-bottom));
  background:var(--bg-elevated);
  border-top:1px solid var(--border);
}
.tab{
  height:54px;display:grid;place-items:center;gap:2px;
  border-radius:10px;color:var(--muted);font-size:.68rem;font-weight:650;
  transition:background-color .15s ease;
}
.tab svg{width:27px;height:27px} /* ORDEN DE CORRECCIÓN (Punto 4, "mayor fidelidad y presencia"): +3px adicional sobre el tamaño ya aumentado en la Tanda 5 (24px) */
/* Tanda 5 (íconos "Gradiente Suave" de referencia): antes el color
   activo/inactivo lo daba currentColor sobre un trazo (stroke) simple
   -- accent cuando .tab.active, --muted en otro caso -- y el ícono en sí
   cambiaba de color según el estado. Los íconos nuevos son ilustraciones
   con relleno en degradado PROPIO de cada pestaña (azul/verde/morado/
   rosa-naranja/naranja, ver <linearGradient> de cada <svg> más abajo en
   el HTML) que se mantienen IDÉNTICOS en activo/inactivo y en modo claro/
   oscuro -- así lo muestra la imagen de referencia en sus 4 combinaciones
   (claro/oscuro × activo/inactivo). La diferenciación de estado se movió
   entonces del propio ícono a: (1) el color/peso de la etiqueta de texto
   (ya lo hacía .tab.active{color:var(--accent)}, sin cambios) y (2) un
   fondo "píldora" suave detrás de toda la pestaña activa, reutilizando
   la variable --accent-soft ya existente (así la píldora respeta
   cualquier color de acento que el usuario elija en Apariencia, igual
   que ya hacía el color de la etiqueta). */
.tab.active{color:var(--accent);background:var(--accent-soft)}
/* .tab-fab queda sin uso tras la Tanda 2 (el botón central (+) se quitó
   de la barra inferior) -- se conserva la regla por trazabilidad y por si
   una futura orden explícita pide reintroducir un FAB en otra pantalla;
   no se elimina el CSS para no perder el historial de la decisión. */
.tab-fab{
  width:56px;height:56px;border-radius:50%;
  display:grid;place-items:center;color:#fff;
  background:linear-gradient(135deg,var(--accent),var(--accent-2));
  box-shadow:0 10px 24px var(--accent-soft);
  margin:0 4px;
}

/* ============================================================
   Fase 10 (segunda pasada, fidelidad estricta) — Login / Crear cuenta.
   Imagen_01.png y Imagen_02.png: el degradado del hero cubre TODA la
   pantalla (no solo una franja superior), con la tarjeta blanca (Login)
   u oscura sin tarjeta (Crear cuenta) flotando encima, y los botones
   secundarios (Crear una cuenta / Olvidé mi contraseña / continuar con
   Google-Apple / Tus datos están protegidos) viven directamente sobre el
   fondo del hero, no sobre el fondo neutro de la app.
   ============================================================ */
.screen-auth{background:var(--hero-grad);min-height:100vh;min-height:100dvh;padding-bottom:36px} /* ORDEN DE CORRECCIÓN (Punto 5): 100dvh además de 100vh, mismo patrón ya usado en el resto de pantallas, para que la barra de herramientas dinámica del navegador móvil no deje un hueco de fondo al girar */
/* ORDEN DE CORRECCIÓN (Punto 3, "logo tapado por la cámara/notch/isla
   dinámica en Iniciar sesión"): el padding superior era un valor fijo
   (30px) sin ningún término env(safe-area-inset-top) -- a diferencia de
   .topbar/.hero-home, que sí lo tenían desde tandas anteriores. En un
   iPhone con notch o isla dinámica, esos 30px fijos no alcanzan a
   despejar el área que el sistema reserva arriba, así que el logo quedaba
   parcialmente debajo de esa zona. Se agrega el mismo patrón ya probado
   en .topbar/.hero-home (ver Tanda 1, Punto 5). En dispositivos sin
   recorte (la mayoría de Android, iPhones sin notch) env() devuelve 0 y
   el padding queda igual que antes -- sin cambio visual ahí. */
.auth-logo{display:flex;flex-direction:column;align-items:center;gap:8px;text-align:center;padding:calc(30px + env(safe-area-inset-top)) 20px 22px;color:#fff}
.auth-logo img{width:98px;height:98px} /* Tanda 5: logo nuevo, +11% (antes 88px). border-radius/box-shadow de "tarjeta" retirados -- ver .logo-guard */
.auth-logo h1{margin:2px 0 0;font-size:1.55rem;font-weight:800}
.auth-logo p{margin:0;color:#dbe4ff;font-size:.9rem;text-align:center;max-width:280px}

.auth-card{background:#fff;color:#16192b;border-radius:20px;padding:22px 18px;margin:0 16px;box-shadow:0 20px 44px #00123f4d}
.auth-card .section-label{color:#6b7280;padding:0}
.auth-card h2{margin:0 0 2px;font-size:1.25rem}
.auth-card .field label{color:#4b5568}
.auth-card .input-wrap{background:#f4f5f9;border-color:#e2e5f1}
.auth-card .input-wrap input{color:#16192b}
.auth-card .input-wrap .icon{color:#8a90a6}
.auth-card .btn-primary{background:var(--accent);text-transform:uppercase;letter-spacing:.02em}
.screen-auth .btn-primary{text-transform:uppercase;letter-spacing:.02em}

.auth-divider{display:flex;align-items:center;gap:10px;margin:16px 0;color:#9aa0b4;font-size:.78rem}
.auth-divider::before,.auth-divider::after{content:'';flex:1;height:1px;background:#e2e5f1}

.auth-social{display:flex;gap:10px}
.auth-social button{
  flex:1;display:flex;align-items:center;justify-content:center;gap:8px;
  min-height:48px;border-radius:12px;border:1px solid #e2e5f1;background:#fff;
  color:#16192b;font-weight:650;font-size:.92rem;
}
.auth-social .icon{width:19px;height:19px}

.auth-actions{padding:20px 16px 0;display:grid;gap:14px;text-align:center}
.auth-btn-outline-green{
  display:flex;align-items:center;justify-content:center;gap:8px;
  min-height:52px;border-radius:14px;border:1.5px solid #22c55e;color:#22c55e;
  font-weight:800;letter-spacing:.02em;text-transform:uppercase;font-size:.92rem;
}
.auth-link-amber{
  display:flex;align-items:center;justify-content:center;gap:7px;
  color:#f59e0b;font-weight:800;letter-spacing:.02em;text-transform:uppercase;font-size:.86rem;
}
.auth-protected{display:flex;align-items:center;justify-content:center;gap:6px;color:#c7cee8;font-size:.78rem}
.auth-demo-hint{color:#8891ab;font-size:.74rem;text-align:center;margin:-2px 0 0}

/* ---- Toast ---- */
.toast{
  position:fixed;left:50%;bottom:88px;transform:translateX(-50%) translateY(16px);
  width:min(calc(100% - 28px),480px);
  padding:13px 16px;border-radius:12px;
  background:#111528;color:#fff;
  opacity:0;pointer-events:none;transition:.22s;z-index:60;
  font-size:.9rem;font-weight:600;
}
.toast.show{opacity:1;transform:translateX(-50%) translateY(0)}
@media(prefers-reduced-motion:reduce){.toast{transition:none}}

/* ---- Modal / hoja de confirmación ---- */
.modal-overlay{
  position:fixed;inset:0;background:#00000090;
  display:none;align-items:flex-end;justify-content:center;z-index:70;
}
.modal-overlay.show{display:flex}
.modal-sheet{
  width:min(100%,520px);background:var(--bg-elevated);
  border-radius:20px 20px 0 0;padding:22px 18px calc(22px + env(safe-area-inset-bottom));
  display:grid;gap:14px;text-align:center;
}
/* Tarea #88 (Soporte): se detectó que .modal-icon.bg-* nunca tenía
   background real -- igual que el bug de .swatch ya corregido en la
   Tarea #83 -- las clases .bg-* solo definen la variable --rc, y nada
   la consumía aquí. Afecta también a la pantalla "Correo enviado"
   (auth/emailSent), preexistente, corregida de paso por consistencia. */
.modal-icon{width:64px;height:64px;border-radius:50%;display:grid;place-items:center;margin:0 auto;font-size:1.6rem;color:#fff;background:var(--rc,var(--accent))}
.modal-icon svg{width:30px;height:30px}
/* FASE 13 (corrección puntual, Puntos 1 y 2): fondo suave dedicado
   SOLO para las dos ilustraciones a color de "Comparte tu idea"
   (bombillo) y "Cuéntanos qué pasó" (boya), inspirado en los tonos de
   la imagen aprobada (tarjeta lavanda / tarjeta rosa). Reglas nuevas y
   exclusivas: no tocan .modal-icon (compartida con el resto de la
   app) ni las clases genéricas .bg-amber/.bg-red. */
.modal-icon--idea-illustration{background:linear-gradient(180deg,#F1E7FF,#E6D6FF)}
.modal-icon--report-illustration{background:linear-gradient(180deg,#FFE3E3,#FFD1D1)}

/* ---- Progreso ---- */
.progress-track{height:10px;border-radius:99px;background:var(--surface-2);overflow:hidden}
.progress-fill{height:100%;border-radius:inherit;background:var(--accent)}
.progress-fill.warn{background:var(--amber)}
.progress-fill.bad{background:var(--red)}
.progress-fill.good{background:var(--green)}

/* ---- Swatches de color (Apariencia) ---- */
.swatch-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:12px}
.swatch{
  aspect-ratio:1;border-radius:14px;position:relative;
  border:2px solid transparent;
  display:grid;place-items:center;color:var(--ink);
  /* CORRECCIÓN — bug preexistente encontrado en la auditoría (Tarea
     #83): los swatches de COLOR (.swatch.bg-*, sin ícono) nunca tenían
     `background`, solo definían la variable --rc vía .bg-* — el
     selector de color de "Nueva categoría" era invisible salvo el
     borde del seleccionado. Los swatches de ÍCONO ya traen su propio
     `background` inline (var(--surface-2)), que sigue ganando por
     especificidad de estilo en línea. */
  background:var(--rc,var(--surface-2));
}
.swatch[aria-pressed="true"]{border-color:var(--ink)}
.swatch[aria-pressed="true"]::after{content:'✓';position:absolute;inset:0;display:grid;place-items:center;color:#fff;font-weight:900;font-size:1.2rem;text-shadow:0 1px 3px #00000070}
.swatch-label{text-align:center;font-size:.78rem;margin-top:6px;color:var(--muted)}
/* CORRECCIÓN PUNTUAL (Fase 12 -- solo tamaño INTERNO de los íconos):
   los íconos de #catIconSwatches (rejilla de "alimentación, transporte,
   vivienda, servicios, café, salud, educación, entretenimiento, ropa,
   mascotas, ahorro, otros" + botón "más íconos") heredaban el tamaño
   genérico de la clase compartida .icon (20px, ver regla global más
   arriba) dentro de una casilla de ~62px -- se veían diminutos. Esta
   regla SOLO agranda la figura interna (la propia etiqueta <svg>) a
   ~40px, el doble aproximado pedido, dejando margen de sobra dentro de
   la casilla para que no se recorte ni toque el borde. El tamaño de la
   casilla (.swatch), su borde/estado seleccionado, el espaciado
   (.swatch-grid gap) y la cuadrícula de columnas NO se tocan -- esta
   regla solo afecta al <svg> de adentro. Alcance limitado a
   #catIconSwatches (por id) para no afectar cualquier otro lugar que
   reutilice la clase .swatch (p. ej. los swatches de color de Bancos,
   que de todos modos no tienen ícono interno). */
#catIconSwatches .icon{width:40px;height:40px}

/* ---- FASE 12: editor de categorías (Punto 2/4/5) ---- */
/* Botón de texto en el topbar (imagen aprobada, "Guardar" arriba a la
   derecha de #screen-catEditor) -- distinto de .topbar-action (que es
   siempre un cuadro de 44x44 con un ícono), porque aquí el contenido es
   una palabra, no un ícono; mismo color de acento que cualquier acción
   primaria de la app. */
.topbar-action-text{flex:none;font-weight:800;font-size:.95rem;color:var(--accent);background:none;padding:8px 2px}
/* Insignia cuadrada-redondeada con el ícono de "etiqueta" en el
   encabezado del editor -- el color (verde/naranja) refuerza de un
   vistazo el tipo de movimiento ya fijado (Ingresos/Gastos), igual idea
   que .cat-type-dot de la lista pero en tamaño protagonista. */
.cat-editor-icon-badge{width:56px;height:56px;border-radius:18px;display:grid;place-items:center;color:#fff}
/* CORRECCIÓN PUNTUAL (Fase 12): ícono principal de la categoría (el
   grande dentro del cuadro de color verde/naranja) -- misma idea que
   #catIconSwatches arriba, se agranda SOLO la figura interna (28px ->
   46px). No es exactamente el doble (56px) a propósito: la propia
   casilla de color mide 56x56 y no se agranda (orden explícita, "no
   agrandar el cuadro naranja"), así que llevar el ícono a 56px lo haría
   tocar los 4 bordes -- se deja el margen mínimo indispensable para que
   la figura crezca lo más posible sin tocar el borde del cuadro. */
.cat-editor-icon-badge svg{width:46px;height:46px}
.cat-editor-icon-badge--income{background:var(--green)}
.cat-editor-icon-badge--expense{background:var(--orange)}
/* Punto reforzado visual de la lista de Categorías (renderCategoriesScreen,
   render.js): un punto fijo verde/naranja que indica el TIPO de
   movimiento de la fila, independiente del color propio de la
   categoría (Punto 5) -- ninguno de los dos reemplaza al otro. */
.cat-type-dot{width:10px;height:10px;border-radius:50%;flex:none;margin:0 2px}
/* Overlay "¿A qué tipo de movimiento pertenece esta categoría?"
   (#catTypeOverlay, imagen aprobada Panel 2 superior) -- mismo patrón de
   dos tarjetas que .mode-grid/.mode-card (Modo Claro/Oscuro) pero
   teñidas verde/naranja en vez de neutras, para reforzar Ingresos/Gastos. */
.cattype-grid{display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-top:4px}
.cattype-btn{
  border:2px solid transparent;border-radius:14px;padding:16px 10px;
  display:grid;justify-items:center;gap:8px;font-weight:700;
}
.cattype-btn svg{width:26px;height:26px}
.cattype-btn--income{background:#E9FBF0;color:var(--green)}
.cattype-btn--expense{background:#FFF1E6;color:var(--orange)}
[data-mode="dark"] .cattype-btn--income{background:#123423}
[data-mode="dark"] .cattype-btn--expense{background:#3a2412}
/* Campo de solo lectura "#FF8A00" de "Personalizar color" cuando el
   contexto es una categoría (#colorCustomizeHexSection) -- Punto 5,
   la imagen aprobada de esa variante muestra el código en vez de la
   vista previa/colores rápidos (que solo existen para el contexto
   'appearance', ver renderColorCustomize en render.js). */
.hex-readout{
  background:var(--surface-2);border:1px solid var(--border);border-radius:12px;
  padding:12px 14px;font-weight:800;font-size:1rem;letter-spacing:.03em;
  text-align:center;margin:6px 0 4px;
}

.mode-grid{display:grid;grid-template-columns:1fr 1fr;gap:12px}
.mode-card{
  border:2px solid var(--border);border-radius:14px;padding:18px 10px;
  display:grid;justify-items:center;gap:8px;background:var(--surface-2);
  position:relative;
}
.mode-card[aria-pressed="true"]{border-color:var(--accent)}
.mode-card .dot{width:18px;height:18px;border-radius:50%;border:2px solid var(--muted)}
.mode-card[aria-pressed="true"] .dot{border-color:var(--accent);background:var(--accent)}
.mode-card-icon{width:30px;height:30px;color:var(--muted)}
.mode-card[aria-pressed="true"] .mode-card-icon{color:var(--accent)}

/* FASE 10 (Punto 2, "el cuadro de Modo Oscuro debe verse REALMENTE
   oscuro para que la diferencia sea evidente"): hallazgo -- antes las
   dos tarjetas usaban "background:var(--surface-2)" (arriba), una
   variable que cambia según el MODO ACTIVO global. Con el modo activo
   en claro, ambas tarjetas se veían claras (incluida "Oscuro"); con el
   modo activo en oscuro, ambas se veían oscuras (incluida "Claro") --
   nunca se podía distinguir una de otra por color, contradiciendo el
   propósito mismo de un selector de vista previa. Se fijan colores
   PROPIOS por tarjeta (independientes del modo activo, igual que en la
   imagen de referencia: la tarjeta "Claro" siempre blanca, la "Oscuro"
   siempre casi negra) sin tocar la distribución/estructura ya aprobada
   (mismo grid, mismo ícono, mismo punto indicador). */
.mode-card[data-mode-choice="light"]{background:#ffffff;border-color:#e2e5f1;color:#16192b}
.mode-card[data-mode-choice="light"] .mode-card-icon{color:#94a3b8}
.mode-card[data-mode-choice="light"][aria-pressed="true"]{border-color:var(--accent)}
.mode-card[data-mode-choice="light"][aria-pressed="true"] .mode-card-icon{color:var(--accent)}
.mode-card[data-mode-choice="dark"]{background:#0b0d17;border-color:#0b0d17;color:#f4f6fb}
.mode-card[data-mode-choice="dark"] .mode-card-icon{color:#7d85ab}
.mode-card[data-mode-choice="dark"][aria-pressed="true"]{border-color:var(--accent)}
.mode-card[data-mode-choice="dark"][aria-pressed="true"] .mode-card-icon{color:var(--accent)}

/* ---- Vacíos ---- */
.empty-state{text-align:center;padding:30px 14px;color:var(--muted)}
.empty-state .icon{font-size:2.2rem;margin-bottom:8px}
.empty-state svg.icon{width:40px;height:40px;display:block;margin:0 auto 8px}
/* Estado vacío "de pantalla completa" (p. ej. Metas sin metas): a diferencia
   de los estados vacíos anidados dentro de un .card/.list-card (que ya
   quedan bien encuadrados por su tarjeta contenedora), este vive suelto
   directamente en <main>. Desde que "main{align-content:start}" dejó de
   estirar las filas de la grilla para rellenar el alto sobrante (fix de la
   Tarea #84, ver comentario junto a esa regla), este bloque quedaba pegado
   arriba con un vacío enorme debajo. Se centra explícitamente en el alto
   restante para que la ausencia de datos se vea intencional, no rota. */
.empty-state-standalone{
  min-height:min(46vh,360px);
  display:flex;flex-direction:column;align-items:center;justify-content:center;
}

.hidden{display:none !important}

/* ---- Utilidades de texto ---- */
.text-green{color:var(--green)}
.text-red{color:var(--red)}
.text-accent{color:var(--accent)}
.amount-lg{font-size:2.1rem;font-weight:900;line-height:1.05}

@media(max-width:340px){
  .tabs{grid-template-columns:repeat(5,1fr)}
  .tab{font-size:.62rem;height:50px}
}

/* Accesibilidad heredada de Fase 5 */
.tab:focus-visible{outline:3px solid var(--accent-soft);outline-offset:2px}

/* ============================================================
   Fase 11 (segunda pasada, fidelidad estricta) — "Diseño de la
   aplicación" → Estilo de íconos. Referencia ÚNICA y definitiva:
   Imagen_33.png ("CONFIGURA EL DISEÑO DE TU APLICACIÓN"), confirmada
   explícitamente por el usuario. Los 5 estilos, en el orden y con los
   nombres exactos de la imagen:
     1. Lineal moderno    — solo trazo, color de acento uniforme, sin
                             círculo de fondo.
     2. Relleno colorido  — círculo sólido de color por función,
                             glifo blanco.
     3. Gradiente suave    — círculo con degradado azul uniforme (mismo
                             tono para todos los íconos), glifo blanco.
     4. Contorno colorido  — círculo con anillo de color por función,
                             glifo del mismo color, fondo transparente.
                             *** PREDETERMINADO *** (marcado ✓ en la
                             imagen).
     5. 3D suave           — tarjeta clara redondeada con sombra/relieve
                             (efecto glossy), glifo de color por función.

   Los íconos ahora son SVG reales (sprite en js/icons.js, ver
   injectIconSprite()/svgIcon()), NO emoji — cumple la regla de
   fidelidad #3. Un solo trazo vectorial por ícono se "re-pinta" con
   estas 5 reglas CSS, así los 5 estilos son tratamientos reales y no
   una simulación con glifos distintos.

   Estas reglas se aplican tanto a) globalmente vía [data-iconstyle] en
   <html> (para que el estilo elegido se refleje en TODA la app, tal
   como indica la propia Imagen_33: "El cambio se aplicará en toda la
   aplicación"), como b) localmente vía [data-iconstyle-preview] en cada
   fila del selector, para poder mostrar los 5 ejemplos simultáneamente
   con su propio estilo (igual que en la imagen), sin depender del
   estilo activo global.
   ============================================================ */
/* FASE 10 (Punto 3): 20px → 22px dentro del mismo círculo de 38px (ver
   comentario extenso en icons.js sobre "menos protagonismo del círculo,
   más protagonismo del ícono") -- no se toca el tamaño del propio
   círculo (.row-icon, más arriba) para no alterar ninguna distribución
   ya aprobada, solo la proporción que ocupa el glifo dentro de él. */
.row-icon .icon{width:22px;height:22px}
.row-icon svg use{color:inherit}

/* Las reglas "globales" (activadas por [data-iconstyle] en <html>) se
   escriben dentro de :where(...) para que tengan especificidad CERO en
   esa parte del selector — así, cuando una fila de previsualización
   local ([data-iconstyle-preview], especificidad normal) pide un estilo
   distinto al global activo, la local SIEMPRE gana sin importar el
   orden de declaración. Sin esto, las 5 tarjetas del selector terminaban
   todas mostrando el estilo global activo en vez de su propio estilo
   (bug detectado en la verificación visual de esta fase). */
:where([data-iconstyle="lineal"]) .row-icon,[data-iconstyle-preview="lineal"] .row-icon{
  background:transparent;border:0;color:var(--accent);box-shadow:none;
}
:where([data-iconstyle="relleno"]) .row-icon,[data-iconstyle-preview="relleno"] .row-icon{
  background:var(--rc,var(--accent));border:0;color:#fff;box-shadow:none;
}
:where([data-iconstyle="gradiente"]) .row-icon,[data-iconstyle-preview="gradiente"] .row-icon{
  background-image:linear-gradient(135deg,#60A5FA,#2563EB);border:0;color:#fff;box-shadow:none;
}
:where([data-iconstyle="contorno"]) .row-icon,[data-iconstyle-preview="contorno"] .row-icon{
  background:transparent;border:2px solid var(--rc,var(--accent));color:var(--rc,var(--accent));box-shadow:none;
}
:where([data-iconstyle="3d"]) .row-icon,[data-iconstyle-preview="3d"] .row-icon{
  background:linear-gradient(160deg,#ffffff,#eef1f8);border:0;color:var(--rc,var(--accent));border-radius:11px;
  box-shadow:0 3px 0 #00000014, 0 6px 14px #00000030, inset 0 -3px 5px #00000014, inset 0 2px 2px #ffffff;
}

/* Fila del selector "Diseño de la aplicación": cada una de las 5 debe
   mostrarse en SU PROPIO estilo (no en el estilo global activo) para que
   las 5 opciones se puedan comparar a la vez, tal como en Imagen_33. */
.iconstyle-grid{display:grid;grid-template-columns:1fr 1fr;gap:12px}
.iconstyle-card{
  background:var(--surface);border:2px solid var(--border);border-radius:16px;
  padding:12px;text-align:left;
}
.iconstyle-card[aria-pressed="true"]{border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-soft)}
.iconstyle-card-head{display:flex;align-items:center;gap:8px;font-size:.86rem;font-weight:800}
.iconstyle-num{
  width:20px;height:20px;border-radius:50%;background:var(--accent);color:#fff;
  display:grid;place-items:center;font-size:.7rem;flex:none;
}
.iconstyle-check{margin-left:auto;color:var(--accent);flex:none}
.iconstyle-check .icon{width:18px;height:18px}
.iconstyle-mini-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:8px;margin-top:10px}
.iconstyle-mini-grid .row-icon{margin:0 auto}
/* CORRECCIÓN PUNTUAL — FASE 10 (forma y tamaño interno de los íconos de
   "Apariencia → Estilo de íconos"): se agranda ÚNICAMENTE la figura
   interior mostrada dentro de cada una de las 5 tarjetas de estilo,
   igual que en #catIconSwatches (Fase 12). Ámbito estrictamente
   local vía ".iconstyle-mini-grid .row-icon .icon" -- NO se toca la
   regla global ".row-icon .icon{width:22px;height:22px}" de más arriba,
   que sigue rigiendo el resto de la app (filas de listas, accesos
   rápidos de Perfil, etc.), para no alterar ninguna otra pantalla.
   El círculo/tarjeta contenedora (.row-icon, 38x38) NO cambia de tamaño.
   32px es el máximo verificado que no toca el aro en "Contorno colorido"
   (el más ajustado: el borde de 2px reduce el área útil interior a 34px)
   ni recorta la figura del ícono "Ajustes" (el diseño más ajustado al
   viewBox de los 6 íconos de muestra) -- un verdadero 2x (44px) excedería
   ese aro, así que se usa el tamaño seguro más grande posible en vez de
   un doble literal. */
.iconstyle-mini-grid .row-icon .icon{width:32px;height:32px}

/* ============================================================
   FASE 10 (Punto 5) — #screen-colorCustomize: selector circular de
   degradación + barra deslizante + vista previa en tiempo real. El
   degradado real de fondo de .color-wheel/.card-hero de esta pantalla se
   fija por JS (renderColorCustomize, render.js) según el color y el
   "tono" elegidos -- aquí solo se define la geometría/el "marco" fijo.
   ============================================================ */
.color-wheel-wrap{display:flex;justify-content:center;padding:10px 0 18px}
.color-wheel{
  width:230px;height:230px;border-radius:50%;position:relative;flex:none;
  box-shadow:0 14px 34px #00000030;
}
/* Botón real (no solo decorativo) para que el thumb sea alcanzable por
   teclado/lector de pantalla -- se mueve arrastrando (pointerdown/move,
   ver events.js) o, sin puntero, no tiene un equivalente por flechas
   todavía (mismo alcance que el resto de esta fase: interacción táctil/
   mouse, consistente con cómo ya funcionan swatches y sliders nativos
   del resto de la app). */
.color-wheel-thumb{
  position:absolute;top:50%;left:50%;width:30px;height:30px;
  border-radius:50%;border:3px solid #fff;background:transparent;
  box-shadow:0 2px 8px #00000055;transform:translate(-50%,-50%);
  cursor:grab;touch-action:none;
}
.color-wheel-thumb:active{cursor:grabbing}

/* Slider nativo re-estilizado (mismo patrón cross-browser de siempre:
   resetear -webkit/-moz-appearance y redefinir track+thumb) -- el
   degradado del track también lo fija JS por color/tono elegidos. */
.tone-slider{
  -webkit-appearance:none;appearance:none;width:100%;height:14px;border-radius:999px;
  margin:4px 0 18px;background:linear-gradient(90deg,#000,#fff);outline:none;
}
.tone-slider::-webkit-slider-thumb{
  -webkit-appearance:none;appearance:none;width:26px;height:26px;border-radius:50%;
  background:#fff;border:3px solid var(--accent);box-shadow:0 2px 6px #00000050;cursor:pointer;
}
.tone-slider::-moz-range-thumb{
  width:26px;height:26px;border-radius:50%;background:#fff;border:3px solid var(--accent);
  box-shadow:0 2px 6px #00000050;cursor:pointer;
}

/* ============================================================
   ORDEN CORRECTIVA — Apariencia unificada (Manual §3.8, Corrección 2):
   Fondos A-E y Paleta de 9 colores, dentro de la misma pantalla que
   Modo e Íconos. Tarjetas de Fondo (una por fila, con degradado real de
   muestra) y swatches de acento (grid 3x3, igual patrón visual que
   Imagen_06/07 y que .swatch-grid ya usado en Categorías).
   ============================================================ */
/* FASE 10 (Punto 4, "Unificar completamente: Fondo + Paleta bajo un
   único apartado ESTILO DE FONDO"): reemplaza los bloques .fondo-grid/
   .fondo-card (5 presets A-E) y .palette-grid/.palette-swatch (9
   acentos) de arriba por una sola cuadrícula de cuadros de color
   redondeados, fiel a la imagen de referencia de esta fase (2 filas de
   6). Pulsar un color YA NO lo selecciona in-place (por eso ya no hay
   variante ":pressed" con check aquí -- salvo el color ACTIVO
   persistido, que sí lleva check para reflejar la elección vigente):
   toda personalización real vive en #screen-colorCustomize. */
.fondo-color-grid{display:grid;grid-template-columns:repeat(6,1fr);gap:10px}
.fondo-color-swatch{
  position:relative;aspect-ratio:1;border-radius:14px;border:2px solid transparent;
  display:grid;place-items:center;box-shadow:inset 0 0 0 1px #ffffff26;
}
.fondo-color-swatch[aria-pressed="true"]{border-color:var(--ink)}
.fondo-color-swatch-check{color:#fff;filter:drop-shadow(0 1px 2px #00000080)}
.fondo-color-swatch-check .icon{width:20px;height:20px}
.fondo-color-swatch--arcoiris{background:conic-gradient(from 200deg,#F13D3C,#FC7F06,#FBB723,#04B543,#2A4DEE,#803FDB,#F13D3C)}
/* Variante compacta reutilizada dentro de "Colores rápidos" en
   #screen-colorCustomize -- mismos cuadros, más pequeños, sin el hueco
   visual de gap tan grande que sí tiene sentido en la pantalla
   principal. */
.fondo-color-grid-compact{grid-template-columns:repeat(6,1fr);gap:8px;margin-bottom:8px}
.fondo-color-grid-compact .fondo-color-swatch{border-radius:10px}
/* ORDEN CORRECTIVA — Fidelidad visual y Safe Area: generalizado a TODAS
   las pantallas internas (antes era un fix quirúrgico solo de
   Apariencia). Motivo: position:sticky solo "pega" respecto a un
   ancestro con scroll REAL. .app tiene overflow-x:hidden, y por la
   regla de interoperabilidad de CSS Overflow (cuando un eje no es
   'visible', el otro eje 'visible' se computa como 'auto') termina
   siendo un contenedor de scroll aunque no sea el que en la práctica se
   desplaza (la página/ventana crece y es quien hace scroll, porque .app
   no tiene alto fijo) — con eso, ninguna .topbar sticky "veía"
   desplazamiento real y la flecha de regreso se iba con el resto del
   contenido al hacer scroll en pantallas largas (Moneda, Categorías,
   etc.), quedando inaccesible sin desplazarse de vuelta hacia arriba —
   justo lo contrario de "accesible sin girar el teléfono" que pide esta
   orden. Cada pantalla interna pasa a ser su propio contenedor de
   scroll de alto fijo (100dvh), con su <main> desplazándose dentro de
   sí misma: la barra superior con la flecha queda SIEMPRE visible, sin
   depender de sticky. No se aplica a .screen-auth (Login/Crear cuenta),
   que usa un layout de una sola tarjeta sin overflow y no lo necesita —
   se deja su comportamiento de scroll de documento tal como está,
   verificado que cabe completo en pantalla sin recorte. */
.screen.active:not(.screen-auth){display:flex;flex-direction:column;height:100vh;height:100dvh}
/* La franja libre para la barra inferior fija (96px) ahora la reserva
   cada <main> internamente (arriba). El padding-bottom:96px que antes
   vivía en .app (ver regla .app más arriba) quedó eliminado: sumado al
   nuevo alto fijo 100dvh de cada pantalla, generaba un sobrante de
   scroll a nivel de documento que arrastraba la pantalla entera
   (incluida la barra superior) hacia arriba al desplazarse — la flecha
   de regreso se salía de la pantalla por completo. Detectado con
   Playwright (tools/verify-safearea.mjs) comparando la posición de
   .back-btn antes/después de un scroll grande. */
.screen.active:not(.screen-auth) > main{flex:1;min-height:0;overflow-y:auto;-webkit-overflow-scrolling:touch;padding-bottom:96px}

/* Textarea del formulario de Soporte (Fase 16) */
textarea{font-family:var(--font)}
textarea:focus{outline:none}

/* Checkbox de preferencias (Notificaciones, Respaldo automático) */
.list-row input[type="checkbox"]{width:20px;height:20px;accent-color:var(--accent);flex:none;margin-left:auto}

details > summary{list-style:none}
details > summary::-webkit-details-marker{display:none}
details > summary::before{content:'▸ ';color:var(--accent)}
details[open] > summary::before{content:'▾ '}

/* ============================================================
   TANDA 4 (Punto 4) — Adaptación real a orientación horizontal.
   ============================================================
   Diagnóstico (documentado como limitación en la Tanda 3, ahora resuelto
   aquí): en un viewport horizontal típico de teléfono (alto ~360-430px),
   el hero fijo de Inicio (~297px con su encabezado + resumen + accesos
   rápidos) más la barra inferior fija (~70px) dejaban a <main> con solo
   ~30-40px reales de alto visible -- técnicamente desplazable
   (verificado por entonces con getBoundingClientRect/scrollTop), pero
   inútil en la práctica para ver "Límites de gasto", "Gastos por
   categoría" o "Mis bancos".

   La solución NO es reducir uniformemente todo el contenido de la app
   (la orden de esta Tanda 4 lo prohíbe expresamente) sino comprimir
   ÚNICAMENTE los encabezados/franjas fijas que restan alto a <main>
   (que ya es flex:1 + overflow-y:auto en TODAS las pantallas, ver regla
   ".screen.active:not(.screen-auth) > main" más arriba) -- así <main>
   recupera espacio real y su scroll vertical (que ya funcionaba) por fin
   tiene algo útil que desplazar. El contenido en sí (textos, botones,
   tarjetas) no se oculta ni se elimina, solo se compacta su margen/
   relleno y se reducen ligeramente tamaños puramente decorativos (logo,
   dona de categorías). El umbral max-height:500px cubre teléfonos en
   horizontal (iPhone/Android típicos: 360-430px de alto) sin afectar
   tablets/escritorio en horizontal, que ya tienen alto de sobra y no lo
   necesitan.

   Se aplica a TODAS las pantallas (topbar/tabs son compartidas por
   Historial, Bancos, Metas, Ajustes, formularios y subpantallas), y
   además específicamente a Inicio (hero-home) por ser el caso más
   crítico ya documentado. */
@media (orientation:landscape) and (max-height:500px){
  /* Barra superior compartida por TODAS las pantallas internas
     (Historial, Bancos, Metas, Ajustes, formularios, subpantallas):
     menos padding vertical libera alto real a <main> sin ocultar el
     título ni mover la flecha de regreso fuera del área segura (el
     env(safe-area-inset-top) se conserva intacto). */
  .topbar{padding:calc(10px + env(safe-area-inset-top)) calc(16px + env(safe-area-inset-right)) 8px calc(16px + env(safe-area-inset-left))}
  .topbar h1,.topbar h2{font-size:1.05rem}

  /* Barra inferior: se reduce de 54px a 42px de alto por pestaña (sigue
     por encima del mínimo táctil de 44px de ANCHO -- en un grid de 5
     columnas repartiendo min(100%,520px), cada pestaña mide ~100px de
     ancho, muy por encima del mínimo; solo se reduce el ALTO, que no
     tiene un mínimo de accesibilidad equivalente al ser una barra
     continua, no un botón aislado). Los íconos y el texto se achican
     ligeramente en proporción, sin perder la etiqueta (no se oculta
     información). */
  .tabs{padding:4px calc(10px + env(safe-area-inset-right)) calc(6px + env(safe-area-inset-bottom)) calc(10px + env(safe-area-inset-left))}
  .tab{height:42px;font-size:.6rem;gap:1px}
  .tab svg{width:22px;height:22px} /* ORDEN DE CORRECCIÓN: proporcional al nuevo tamaño 27px en vertical (antes 20px) */
  /* <main> reserva exactamente el nuevo alto de .tabs (antes 96px,
     pensado para .tabs a 88px de alto aprox.) para que el último
     elemento de cada pantalla no quede tapado por la barra inferior. */
  .screen.active:not(.screen-auth) > main{padding-bottom:64px}

  /* ---- Inicio: hero compacto (Punto 4, caso crítico documentado) ---- */
  .hero-home{padding-top:calc(12px + env(safe-area-inset-top));padding-bottom:12px;padding-left:calc(16px + env(safe-area-inset-left));padding-right:calc(16px + env(safe-area-inset-right))}
  .home-header-center img{width:36px;height:36px;margin-bottom:2px} /* ORDEN DE CORRECCIÓN: proporcional al +38% del logo en vertical (antes 29px) */
  .home-header-center h1{font-size:.95rem}
  /* El subtítulo ("Ten el control de tus finanzas") es puramente
     decorativo -- se oculta SOLO aquí para ganar una línea de alto; el
     saludo principal (h1) y el resto de la información permanecen. No
     es el mismo caso que "ocultar información importante" (Punto 4):
     ningún dato financiero, botón o control desaparece. */
  .home-header-center p{display:none}
  .home-hero-stack{gap:8px;margin-top:10px}
  .card-on-hero-dark{padding:10px}
  .card-on-hero-dark > div[style*="margin-top:14px"]{margin-top:8px}
  .stat-icon{width:26px;height:26px}
  .stat-icon .icon{width:13px;height:13px}
  .quick-action-card{padding:7px}
  .quick-action-card .stat-icon{width:24px;height:24px}
  .home-limits-card{padding:10px 14px 4px}
  .home-section-card{padding:14px}
  /* Dona de "Gastos por categoría": 140px de diámetro (Tanda 1, Punto 9)
     es más de un tercio del alto disponible en horizontal -- se reduce
     a 92px (sigue siendo mayor que el tamaño base de 118px usado en
     Reportes/otras pantallas) para que la tarjeta completa quepa sin
     recortar la leyenda de categorías que la acompaña. */
  #homeCats .donut-canvas-wrap{width:92px;height:92px}

  /* Modales (confirmaciones, oferta biométrica, etc.): sin alto máximo
     podían salirse del área visible por arriba (el overlay los ancla al
     borde inferior con align-items:flex-end) en un viewport de ~360-
     430px de alto. Con max-height + overflow-y:auto, el contenido del
     modal se desplaza internamente en vez de recortarse; los botones
     "Cancelar"/"Confirmar"/"En otro momento" permanecen dentro del
     área visible siempre porque son el último elemento del propio
     sheet desplazable. */
  .modal-sheet{max-height:calc(100dvh - 16px);overflow-y:auto}

  /* ORDEN DE CORRECCIÓN (Punto 5, "al girar no abarca bien el tamaño del
     teléfono como otras aplicaciones"): la causa real no era la
     compactación de esta Tanda 4 (ya verificada 52/52 en el barrido de
     horizontal) sino un límite de ancho que ni siquiera es específico de
     horizontal -- ".app"/".tabs" usan "width:min(100%,520px)" en TODA la
     app, pensado originalmente como ancho de lectura cómodo para cuando
     el sitio se abre en un navegador de escritorio ancho. En un teléfono
     normal en vertical (390-430px de ancho típico) ese límite nunca se
     activa porque 100% ya es menor que 520px -- por eso nunca se notó
     hasta ahora. Pero un teléfono en HORIZONTAL puede medir 700-930px de
     ancho real (iPhone/Android típicos), y ahí el límite de 520px SÍ se
     activa: la app entera queda encogida en una columna centrada con
     franjas vacías a los lados, en vez de usar el ancho real del
     teléfono como hacen otras apps. Se libera el límite únicamente
     dentro de este mismo umbral ya establecido en la Tanda 4
     (orientation:landscape + max-height:500px, que en la práctica
     identifica "teléfono girado", no tablet/escritorio en horizontal,
     que sí tienen alto de sobra y no entran aquí) -- así un teléfono
     girado usa su ancho real, y una tablet o el navegador de escritorio
     en horizontal siguen viendo la columna de 520px, que ahí sí tiene
     sentido como ancho de lectura. */
  .app{width:100%}
  .tabs{width:100%}

  /* ================================================================
     CORRECCIÓN FINAL — ADAPTACIÓN HORIZONTAL (COMPLEMENTO DE LA TANDA 6)
     Hasta aquí este mismo media query ya liberaba el ANCHO real del
     teléfono girado (".app"/".tabs" arriba) y compactaba encabezados/
     barra inferior -- pero el CONTENIDO seguía en una sola columna,
     igual que en vertical, solo que estirada al ancho nuevo: por eso
     "seguía pareciendo una versión vertical estirada" tras esa
     corrección. Esta corrección redistribuye el contenido en columnas
     reales para aprovechar el ancho, sin tocar logo/íconos/barra
     inferior/nombres de pestañas ya aprobados (Punto 6 de la orden). */

  /* ---- Punto 2: encabezado de Inicio más compacto ----
     Se reduce aún más el aire vertical alrededor de logo/usuario/
     campana (ya compactados en la corrección anterior), SIN mover el
     logo de su posición aprobada: sigue centrado en la misma fila
     junto al avatar y la campana, mismo tamaño. */
  .hero-home{padding-bottom:8px}

  /* ---- Puntos 1 y 3: "Resumen de este mes" + accesos rápidos, lado a
     lado en vez de apilados ----
     Antes: tarjeta de Resumen arriba, botones "Agregar ingreso/gasto"
     debajo -- el doble de alto del necesario cuando sobra ancho. En
     fila se recupera casi la mitad de ese alto Y se usa el ancho real
     de un teléfono girado (redistribución, no una simple reducción de
     tamaños: mismo texto, mismos íconos, mismo tamaño de letra). Los
     accesos rápidos pasan de una fila de 2 botones anchos a una
     columna angosta de 2 botones apilados junto al Resumen. */
  .home-hero-stack{flex-direction:row;align-items:stretch;gap:10px;margin-top:8px}
  .card-on-hero-dark{flex:1.3}
  .quick-action-row{flex:1;flex-direction:column;justify-content:center}

  /* ---- Puntos 3 y 4: "Límites de gasto" / "Gastos por categoría" /
     "Mis bancos", en columnas dentro de <main> ----
     <main> ya es un grid de una sola columna (ver regla base "main{...}"
     más arriba, compartida por toda la app); aquí se amplía a 2
     columnas SOLO para Inicio, solo en este mismo umbral de "teléfono
     real girado" ya establecido. "Límites de gasto" y "Gastos por
     categoría" quedan lado a lado (misma fila). La alerta de límite
     (si aparece) y "Mis bancos" (fila de tarjetas con su propio scroll
     horizontal) ocupan el ancho completo debajo -- partirlas en 2
     columnas no aportaría nada, ya son horizontales por sí mismas.
     Nada se oculta ni se elimina: solo cambia dónde cae cada tarjeta. */
  #screen-home.active>main{grid-template-columns:repeat(2,minmax(0,1fr))}
  #screen-home.active>main>.home-limits-card{grid-column:1}
  #screen-home.active>main>.home-section-card:not(#homeBanksCard){grid-column:2}
  #screen-home.active>main>#homeLimitAlert{grid-column:1/-1}
  #screen-home.active>main>#homeBanksCard{grid-column:1/-1}
  .home-limits-card{padding:10px 14px 4px}
  .home-section-card{padding:12px}
  .limit-row+.limit-row{margin-top:10px}

  /* ---- Punto 5: la dona de "Gastos por categoría" CRECE, no se
     achica ----
     La corrección anterior la reducía a 92px porque tenía que competir
     por ALTO en una única columna angosta. Ahora que "Gastos por
     categoría" tiene su propia columna de ~400px de ancho en un
     teléfono girado típico, se le da más diámetro -- mismo canvas de
     180px de resolución real (ver drawDonutChart()/render.js), así que
     no se ve borrosa al escalarla -- en vez de quedarse con apariencia
     de pantalla vertical achicada. */
  #homeCats .donut-canvas-wrap{width:128px;height:128px}

  /* ---- Punto 4: Historial en 2 columnas ----
     El buscador y los 3 filtros (Todos/Ingresos/Gastos) comparten fila
     -- ya no hace falta apilarlos con el ancho real disponible. La
     lista de movimientos (agrupada por día, ver groupedMovRows() en
     render.js) se reparte en 2 columnas: cada cabecera de día ("Hoy
     +$120.00"...) sigue ocupando el ancho COMPLETO -- para no
     separarla visualmente de sus propios movimientos -- y sus filas se
     reparten debajo, de izquierda a derecha, dentro de ese mismo
     grupo. Se ve más información sin desplazarse, sin romper el
     agrupamiento por fecha. */
  #screen-movements.active>main{grid-template-columns:1fr 1fr;column-gap:12px}
  #screen-movements.active>main>.input-wrap{grid-column:1}
  #screen-movements.active>main>#movTabs{grid-column:2;align-self:center}
  #screen-movements.active>main>#movList{grid-column:1/-1;display:grid;grid-template-columns:repeat(2,1fr);column-gap:14px}
  #screen-movements .mov-day-header{grid-column:1/-1}

  /* ---- Punto 4: Bancos y Metas en 2 columnas ----
     "#bancosList"/"#goalsList" ya eran "display:grid;gap:12px" (una
     sola columna implícita, sin "grid-template-columns" propio -- ver
     HTML) -- se agrega la segunda columna únicamente aquí. Las
     tarjetas de cada cuenta/tarjeta bancaria y de cada meta ya son
     compactas y legibles a la mitad del ancho: se diseñaron pensando
     en el ancho de un teléfono en vertical, muy similar al de media
     columna de uno girado. */
  #bancosList{grid-template-columns:repeat(2,1fr)}
  #goalsList{grid-template-columns:repeat(2,1fr)}

  /* ================================================================
     CORRECCIÓN FINAL — AUDITORÍA COMPLETA DEL MODO HORIZONTAL
     (COMPLEMENTO DE LA TANDA 6)
     Las dos correcciones anteriores ya arreglaron el ANCHO real del
     teléfono girado y la redistribución de Inicio/Historial/Bancos/
     Metas. Esta auditoría cubre TODA la app: pantallas de
     autenticación, formularios, Notificaciones, Bancos (mensaje +
     botón), encabezado de Ajustes, y un huso sistémico para las ~20
     pantallas tipo "lista de opciones" (Moneda, Idioma, Categorías,
     Manual, Acerca de, Soporte, Respaldo, Documentos, Perfil, Ajustes,
     Legal...) que comparten el mismo componente `.list-card`. No se
     toca logo/íconos/barra inferior/nombres de pestañas/colores
     aprobados (Punto 8 de la orden). */

  /* ---- Punto 7 (hallazgo de arquitectura): notch/isla dinámica en
     horizontal ----
     env(safe-area-inset-left)/env(safe-area-inset-right) NO se usaban
     en ningún lugar de este CSS (confirmado por búsqueda antes de esta
     corrección) -- únicamente top/bottom. Mientras la app estaba
     limitada a una columna de 520px centrada, esto no importaba: nunca
     tocaba el borde físico del teléfono. Pero la corrección anterior ya
     liberó ese límite (".app{width:100%}"), así que ahora el contenido
     SÍ llega al borde real -- y en un iPhone con notch/isla dinámica
     girado, la isla se recorta hacia uno de los bordes laterales, no
     arriba. Por eso la flecha de "Atrás" de Crear cuenta (y cualquier
     otro contenido pegado al borde) podía quedar parcialmente debajo
     del área del sistema en un iPhone real -- algo que ningún
     navegador de escritorio ni el modo responsive genérico reproduce
     (env() siempre da 0 sin hardware real), por eso no se había
     detectado antes. env(safe-area-inset-left/right) es 0 en
     dispositivos sin recorte lateral (Android, la mayoría de iPhones
     sin isla, escritorio), así que sumarlo aquí nunca reduce espacio
     ya existente, solo lo protege donde hace falta -- mismo patrón ya
     usado con safe-area-inset-top/bottom en toda la app. Se añade a
     ".topbar"/"main"/".tabs"/".hero-home" (arriba) y aquí también a
     ".auth-logo" y los contenedores de Login/Crear cuenta (abajo),
     que son las únicas piezas que faltaban por cubrir. Nota de
     verificación honesta: un navegador (incluida esta suite de
     pruebas) SIEMPRE reporta env(safe-area-inset-*)=0 sin hardware
     real, así que este arreglo no se puede fotografiar "funcionando"
     en horizontal -- se verifica por revisión de código (grep
     confirmando que ya no hay ninguna pieza de borde sin el inset) y
     queda documentado como tal, no como una captura visual. */
  main{padding-left:calc(16px + env(safe-area-inset-left));padding-right:calc(16px + env(safe-area-inset-right))}

  /* ---- Puntos 1/2/9: Login, Crear cuenta, Recuperar contraseña,
     Correo enviado -- ya no se ven como una pantalla vertical
     apilada y cortada por el alto de 393px ----
     Login y Crear cuenta usan ".screen-auth" (fondo degradado a toda
     página, sin la barra "topbar+main" del resto de pantallas) con
     logo/título arriba, tarjeta de formulario en medio y accesos
     (crear cuenta/olvidé contraseña) abajo -- las 3 secciones
     apiladas verticalmente se salían muy por debajo de 393px de alto.
     Se redistribuyen en 2 columnas (logo a la izquierda, formulario +
     accesos a la derecha) reutilizando la misma técnica de asignar
     "grid-column" a los hijos directos ya usada en Inicio/Historial --
     sin envolver nada en HTML nuevo, sin cambiar textos ni campos. Si
     aun así el contenido de la derecha no cabe entero en 393px de
     alto, la página sigue permitiendo scroll normal (igual que ya
     ocurría en vertical, donde estas pantallas también son más altas
     que un único viewport) -- no se oculta ni se recorta nada. */
  #screen-login.active{
    display:grid;grid-template-columns:minmax(0,34%) minmax(0,1fr);
    align-items:start;gap:2px 18px;
    padding:8px calc(18px + env(safe-area-inset-right)) calc(10px + env(safe-area-inset-bottom)) calc(18px + env(safe-area-inset-left));
  }
  #screen-login.active>.auth-logo{grid-column:1;grid-row:1/3;padding:4px 0;gap:4px;align-self:center}
  #screen-login.active>.auth-logo img{width:52px;height:52px}
  #screen-login.active>.auth-logo h1{font-size:1rem;margin-top:0}
  #screen-login.active>.auth-logo p{font-size:.72rem;max-width:190px}
  #screen-login.active>.auth-card{grid-column:2;grid-row:1;margin:6px 0 0;padding:12px 16px}
  #screen-login.active>.auth-card h2{font-size:1.05rem}
  #screen-login.active>.auth-card .field{margin-bottom:8px}
  #screen-login.active>.auth-actions{grid-column:2;grid-row:2;padding:4px 0 0;gap:6px}

  #screen-createAccount.active{
    display:grid;grid-template-columns:minmax(0,34%) minmax(0,1fr);
    align-items:start;padding-bottom:calc(10px + env(safe-area-inset-bottom));
  }
  #screen-createAccount.active>.topbar{grid-column:1/-1}
  #screen-createAccount.active>.auth-logo{
    grid-column:1;gap:4px;
    padding:4px 12px 4px calc(12px + env(safe-area-inset-left));
  }
  #screen-createAccount.active>.auth-logo img{width:48px;height:48px}
  #screen-createAccount.active>.auth-logo h1{font-size:.95rem;margin-top:0}
  #screen-createAccount.active>.auth-logo p{font-size:.7rem;max-width:200px}
  #screen-createAccount.active>main{
    grid-column:2;padding:4px calc(16px + env(safe-area-inset-right)) 10px 0;
  }
  #screen-createAccount.active>main .field{margin-bottom:8px}
  #screen-createAccount.active>main .auth-divider{margin:10px 0}

  /* Recuperar contraseña / Correo enviado: ya usan el mismo patrón de
     "topbar + main con scroll propio" que el resto de la app (no son
     ".screen-auth"), así que su alto ya se maneja bien -- lo único
     que se veía raro en horizontal era la tarjeta central estirándose
     al ancho completo del teléfono real (700-930px) con un solo campo
     angosto adentro. Se limita el ancho de la tarjeta a una columna de
     lectura cómoda y se centra, en vez de dejarla estirarse.
     FASE 7 (Punto 1): "Correo enviado" no está en el alcance de esta
     fase (la orden solo lista Iniciar sesión/Crear cuenta/Olvidé mi
     contraseña) y queda exactamente igual que antes (420px) -- se separa
     de "Olvidé mi contraseña" en dos selectores para poder ajustar solo
     esta última sin tocar la otra. "Olvidé mi contraseña" pasaba
     prácticamente inadvertida en un teléfono horizontal real (700-930px
     de ancho): con el límite de 420px, más de la mitad del ancho
     disponible quedaba vacío a ambos lados de una tarjeta angosta,
     exactamente el "no aprovecha el ancho disponible" que reporta esta
     orden. Se amplía a un máximo más generoso (620px) -- suficiente para
     usar el espacio de forma notoria sin estirar el campo de correo ni el
     botón a un ancho poco natural (que sí se vería como "una pantalla
     vertical simplemente estirada", justo lo que la orden pide evitar). */
  #screen-emailSent.active>main>.card{max-width:420px;margin:0 auto;width:100%}
  #screen-forgotPassword.active>main>.card{max-width:620px;margin:0 auto;width:100%}

  /* ---- Punto 3: pares de campos en formularios ----
     ".btn-row" ya existe pero es INCONDICIONAL (se usa en TODAS las
     orientaciones para Fecha/Hora y Moneda/Saldo) -- reutilizarla tal
     cual para estos pares nuevos alteraría también el diseño vertical
     ya aprobado, fuera del alcance de esta corrección. ".field-pair"
     es una clase nueva que en vertical es "display:contents" (invisible
     para el layout -- los dos ".field" de adentro se comportan
     exactamente igual que si el envoltorio no existiera, cero cambio
     visual en vertical) y solo se activa como fila de 2 columnas aquí,
     en horizontal. Los pares elegidos son campos cortos que hoy ocupan
     una fila completa cada uno sin necesitarla: Monto/Categoría (Nuevo
     movimiento), Monto objetivo/Monto ahorrado (Nueva meta), Alias/
     Últimos 4 dígitos (Agregar cuenta), Nombre/Correo (Editar perfil),
     Contraseña actual/Nueva contraseña (Seguridad), ¿En qué pantalla?/
     ¿Con qué frecuencia? (Reportar problema), ¿En qué área?/Prioridad
     (Enviar sugerencia). */
  .field-pair{display:flex;gap:12px}
  .field-pair>.field{flex:1;margin-bottom:0;min-width:0}

  /* ---- Auditoría completa (post-iPhone real): pares de botones ----
     Mismo mecanismo que ".field-pair" arriba, para 2 botones/controles
     consecutivos que hoy ocupan una fila completa cada uno: "Crear
     copia ahora"/"Restaurar copia" (Copia de seguridad). */
  .btn-pair{display:flex;gap:12px}
  .btn-pair>.btn,.btn-pair>label{flex:1;min-width:0}

  /* ---- Auditoría completa (post-iPhone real): Editar perfil ----
     Formulario muy corto (2 campos + 1 botón) -- con el par Nombre/
     Correo ya agrupado en una fila, el resto de la pantalla quedaba
     como un bloque angosto arriba y un área vacía injustificada abajo,
     exactamente el defecto que reportó el usuario. En vez de forzar
     más columnas donde no hay más contenido que repartir, se centra
     verticalmente el contenido dentro del alto disponible -- mismo
     "main" grid de siempre, solo se cambia "align-content" de "start"
     a "center" únicamente en esta pantalla corta. */
  #screen-editProfile.active>main{align-content:center}

  /* ---- Auditoría completa (post-iPhone real): Soporte (hub) ----
     "Reportar problemas" y "Enviar sugerencias" son 2 tarjetas de
     opción del mismo tamaño, una debajo de la otra -- se reparten lado
     a lado como las 2 opciones grandes que son. La tarjeta de
     introducción y los 2 avisos informativos siguen a ancho completo. */
  #screen-support.active>main{grid-template-columns:repeat(2,minmax(0,1fr))}
  #screen-support.active>main>*{grid-column:1/-1}
  #screen-support.active>main>.list-card:nth-child(2){grid-column:1}
  #screen-support.active>main>.list-card:nth-child(3){grid-column:2}

  /* ---- Auditoría completa (post-iPhone real): Mis documentos ----
     "Cierres mensuales (PDF)" y "Respaldos (JSON)" son 2 categorías
     independientes, cada una con su propia etiqueta + lista, apiladas
     una debajo de la otra -- se reparten en 2 columnas (etiqueta +
     lista de cada categoría alineadas en su propia columna). El
     buscador sigue a ancho completo arriba. Se apoya en la colocación
     automática de la grilla (misma fila para ambas etiquetas, misma
     fila para ambas listas) usando solo "grid-column", sin fijar
     números de fila a mano. */
  #screen-documents.active>main{grid-template-columns:repeat(2,minmax(0,1fr))}
  #screen-documents.active>main>.input-wrap{grid-column:1/-1}
  #screen-documents.active>main>.section-label:nth-of-type(1){grid-column:1}
  #screen-documents.active>main>.section-label:nth-of-type(2){grid-column:2}
  #screen-documents.active>main>#docPdfList{grid-column:1}
  #screen-documents.active>main>#docBackupList{grid-column:2}

  /* ---- Auditoría completa (post-iPhone real): Copia de seguridad ----
     "Crear copia ahora"/"Restaurar copia" pasan de estar apiladas a
     compartir fila (".btn-pair", ver arriba) -- requiere envolverlas en
     el HTML (ver gastos_personales_app.html), documentado en la
     bitácora igual que los envoltorios ".field-pair" ya existentes. */

  /* ---- Auditoría completa (post-iPhone real): Reportes -- "Resumen
     rápido" y "Comparación con el periodo anterior" ----
     Estas 2 tarjetas tienen varias filas "etiqueta ... valor" apiladas
     (".report-quick-row") que hoy ocupan una fila completa cada una sin
     necesitarlo -- se reparten en una grilla de 2 columnas. Ambos
     grupos usados hoy en la app tienen un número PAR de filas (4 y 2),
     así que ":nth-last-child(-n+2)" (las últimas 2 filas del HTML, es
     decir, la última fila VISUAL de 2 columnas) es exactamente la fila
     final sin borde inferior -- si en el futuro se agrega una fila y el
     total pasa a ser impar, esto se debe revisar (documentado aquí para
     quien continúe este trabajo). Ver ".report-quick-grid" añadida al
     HTML sobre los 2 contenedores existentes (mismo criterio de
     etiquetar el contenedor exacto en vez de adivinarlo por CSS). */
  .report-quick-grid{display:grid;grid-template-columns:repeat(2,1fr);column-gap:16px}
  .report-quick-grid>.section-label{grid-column:1/-1}
  .report-quick-grid>.report-quick-row{border-bottom:1px solid var(--border) !important}
  .report-quick-grid>.report-quick-row:nth-last-child(-n+2){border-bottom:0 !important}

  /* ---- Punto 5: Bancos -- mensaje informativo + botón "Agregar
     cuenta o tarjeta", lado a lado en vez de apilados ----
     La lista de cuentas (#bancosList) ya se reparte en 2 columnas
     desde la corrección anterior; lo que seguía apilado verticalmente
     era el aviso informativo y el botón de arriba, cada uno ocupando
     una fila completa por sí solo. */
  #screen-bancos.active>main{grid-template-columns:1.7fr 1fr}
  #screen-bancos.active>main>.card{grid-column:1}
  #screen-bancos.active>main>#bancosAddBtn{grid-column:2;align-self:center}
  #screen-bancos.active>main>#bancosList{grid-column:1/-1}

  /* ---- Punto 6: encabezado de Ajustes ("Más") más compacto ----
     ".hero" de esta pantalla trae su padding por ATRIBUTO "style" en
     el HTML (más específico que cualquier regla externa sin
     "!important"), así que es la única excepción de esta auditoría
     donde hace falta "!important" para poder compactarlo sin tocar el
     HTML -- mismo criterio ya usado para no reescribir marcado
     aprobado. El subtítulo decorativo se oculta igual que ya se hizo
     en el encabezado de Inicio (mismo criterio: información
     decorativa, no un dato o control). El ícono de tuerca decorativo
     se achica en proporción. */
  #screen-more .hero{
    padding:10px calc(16px + env(safe-area-inset-right)) 10px calc(16px + env(safe-area-inset-left)) !important;
  }
  #screen-more .hero h1{font-size:1.25rem !important;margin:0 !important}
  #screen-more .hero p{display:none !important}
  #screen-more .hero svg{width:40px !important;height:40px !important;top:8px !important;right:10px !important}

  /* ---- Punto 1/2/4: huso sistémico para pantallas tipo "lista de
     opciones" (".list-card") ----
     Este componente se reutiliza en ~20 pantallas: Moneda, Idioma,
     Categorías, Notificaciones (lista + preferencias), Respaldo,
     Documentos, Manual (índice), Acerca de (hub + Información de la
     app), Soporte, Legal, Perfil, Ajustes... -- todas comparten el
     mismo problema: una lista de filas angostas apiladas que no
     aprovecha el ancho real del teléfono girado. En vez de repetir una
     regla por pantalla, un único selector ligado al componente arregla
     todas a la vez (mismo criterio de "punto único de alto impacto" ya
     usado con la regla base de "main{...}").
     REVISIÓN (auditoría completa post-iPhone real): la versión anterior
     de esta regla usaba ":has(.list-row:nth-child(2))" para activar las
     2 columnas solo con 2+ filas. Tras el reporte de que varias
     pantallas que dependían de este mecanismo (Idioma, Categorías,
     Copia de seguridad, Actualizaciones, Perfil) seguían viéndose como
     en vertical en un iPhone real, y sin poder confirmar con certeza si
     la causa era soporte de ":has()" en esa versión de Safari u otra
     razón, se optó por el criterio más defensivo posible: dejar de
     depender de ":has()" por completo (soportado en Safari desde 15.4,
     pero no universal) y usar en su lugar únicamente pseudo-clases de
     soporte universal (":last-child"/":nth-child()", disponibles desde
     hace más de una década en cualquier navegador). El caso de "una
     sola fila" se resuelve con ".list-row:last-child:nth-child(odd)"
     (ver abajo): en vez de "no aplicar 2 columnas", la única fila (o la
     última de un total impar) pasa a ocupar el ancho completo -- mismo
     resultado visual de "no dejar media tarjeta vacía", logrado con una
     técnica más simple y sin ninguna dependencia de soporte moderno.
     El espacio entre columnas usa el color de borde de fondo de la
     tarjeta para dibujar una línea divisoria fina entre celdas (mismo
     truco ya usado en otras tarjetas de esta app). Se excluye
     explícitamente "#movList" (la lista de Historial): ya tiene su
     propia regla de 2 columnas más específica desde la corrección
     anterior, con cabeceras de día que NO son ".list-row" -- incluirla
     aquí también arriesgaría un color de fondo/gap inconsistente en una
     pantalla que el usuario confirmó que ya funciona bien y pidió no
     tocar salvo necesidad real. */
  .list-card:not(#movList){
    display:grid;grid-template-columns:repeat(2,1fr);
    background:var(--border);column-gap:1px;row-gap:1px;
  }
  .list-card:not(#movList) > .list-row{background:var(--surface)}
  /* Una lista con total IMPAR de filas (incluida una lista de 1 sola
     fila) deja su última fila sola en la última línea de la grilla --
     en vez de dejarla a media tarjeta con la celda derecha vacía, se
     estira a las 2 columnas. ":last-child:nth-child(odd)" es verdadero
     únicamente cuando la última fila del HTML está en una posición
     impar (1ª, 3ª, 5ª...), que es exactamente cuándo queda sola en su
     fila de la grilla de 2 columnas. */
  .list-card:not(#movList) > .list-row:last-child:nth-child(odd){grid-column:1/-1}

  /* ---- Punto 1: Límites de gasto (pantalla dedicada, no la mini-
     tarjeta de Inicio ya arreglada en la corrección anterior) ----
     "Límite semanal" y "Límite mensual" son 2 tarjetas idénticas en
     estructura, cada una a ancho completo, apiladas -- se reparten
     lado a lado. El resumen combinado y el botón de guardar siguen a
     ancho completo debajo (no ganan nada partiéndose en 2). */
  #screen-limits.active>main{grid-template-columns:repeat(2,minmax(0,1fr))}
  #screen-limits.active>main>.card-hero:nth-of-type(1){grid-column:1}
  #screen-limits.active>main>.card-hero:nth-of-type(2){grid-column:2}
  #screen-limits.active>main>.card-hero:nth-of-type(3){grid-column:1/-1}
  #screen-limits.active>main>#limitsSaveBtn{grid-column:1/-1}
}

/* ============================================================
   FASE 11 — ventana emergente compartida de Moneda/Idioma
   (#localeInfoOverlay): se muestra únicamente al pulsar una moneda o un
   idioma de la lista (nunca antes), con contenido que cambia según la
   selección (ver openLocaleInfo/renderLocaleInfoModal en render.js/
   events.js). Es UN solo componente reutilizado para ambos casos --
   difieren solo en el color fijo (verde moneda / morado idioma, ver
   variantes --currency/--language) y en qué campos llenan la tarjeta de
   detalle, nunca en la estructura. No reutiliza .modal-overlay/
   .modal-sheet (bottom sheet) porque la imagen aprobada de esta fase
   muestra una tarjeta centrada con esquinas redondeadas en las 4
   esquinas, no una hoja inferior.
   ============================================================ */
.locale-info-overlay{
  position:fixed;inset:0;background:#00000090;z-index:75;
  display:none;align-items:center;justify-content:center;padding:18px;
}
.locale-info-overlay.show{display:flex}
.locale-info-card{
  width:min(100%,440px);max-height:calc(100% - 8px);overflow-y:auto;
  background:var(--bg-elevated);border-radius:22px;padding:20px 18px calc(18px + env(safe-area-inset-bottom));
  position:relative;box-shadow:0 20px 60px #00000040;
}
.locale-info-close{
  position:absolute;top:14px;right:14px;width:32px;height:32px;border-radius:50%;
  border:0;background:var(--surface-2);color:var(--ink);font-size:1rem;line-height:1;cursor:pointer;
  display:grid;place-items:center;
}
.locale-info-icon{
  width:56px;height:56px;border-radius:50%;margin:0 auto;display:grid;place-items:center;color:#fff;
}
.locale-info-icon svg{width:28px;height:28px}
.locale-info-icon--currency{background:var(--green)}
.locale-info-icon--language{background:var(--purple)}
.locale-info-detail-card{
  border:1px solid var(--border);border-radius:14px;padding:12px 14px;
  display:flex;flex-direction:column;gap:8px;margin:4px 0 16px;
}
.locale-info-detail-row{display:flex;align-items:center;justify-content:space-between;gap:10px}
.locale-info-detail-main{display:flex;align-items:center;gap:10px;min-width:0}
.locale-info-detail-main strong{font-size:.95rem}
/* OJO: .flag-icon TAMBIÉN es un <span> dentro de este mismo contenedor
   -- si se necesita estilar el texto del nombre por separado, usar un
   selector de clase dedicado (ej. ">strong"), nunca ">span" a secas, o
   se le pisa su propio font-size/display a la bandera (recorte visual,
   bug real encontrado y corregido en esta misma fase). */
.locale-info-detail-code{font-weight:700;font-size:.85rem}
.locale-info-detail-code--currency{color:var(--green)}
.locale-info-detail-code--language{color:var(--purple)}
.locale-info-detail-value{font-weight:800;font-size:1.05rem;text-align:right}
.locale-info-detail-value--currency{color:var(--green)}
.locale-info-badge{
  flex:none;font-size:.68rem;font-weight:700;padding:4px 10px;border-radius:99px;white-space:nowrap;
}
.locale-info-badge--currency{background:var(--green);color:#fff;opacity:.9}
.locale-info-badge--language{background:var(--purple);color:#fff;opacity:.9}

.locale-globe-wrap{
  position:relative;width:100%;aspect-ratio:1/1;max-width:230px;margin:0 auto 20px;
}
/* ORDEN DE CORRECCIÓN (Fase 11, ajuste puntual, "sensación general de
   realismo"): sombra de contacto propia debajo del globo (elipse
   difuminada, igual que las imágenes aprobadas muestran el planeta
   "flotando" sobre una sombra suave) -- puramente decorativa, con
   pointer-events:none para no interferir con el cierre del modal ni
   ningún otro control. */
.locale-globe-wrap::after{
  content:'';position:absolute;left:50%;bottom:-6px;width:74%;height:14%;
  transform:translateX(-50%);
  background:radial-gradient(ellipse at center, #00142a55, #00142a00 72%);
  pointer-events:none;
}
/* ORDEN CORRECTIVA (Fase 11, 5ta corrección puntual -- "sistema de
   globos regionales aprobados", compartido Moneda/Idioma): imagen real
   (foto de la región aprobada correspondiente, ya recortada al círculo
   exacto del planeta) en vez del <svg> dibujado a mano que usaba esta
   misma clase con otro nombre en rondas anteriores -- object-fit:cover +
   border-radius:50% aseguran que llene el contenedor circular
   .locale-globe-wrap sin deformarse. */
.locale-globe-photo{
  width:100%;height:100%;display:block;object-fit:cover;border-radius:50%;
  filter:drop-shadow(0 10px 22px #00000035);position:relative;z-index:1;
}
.locale-globe-marker{
  position:absolute;width:32px;height:32px;transform:translate(-50%,-100%);
  filter:drop-shadow(0 3px 5px #00000060);z-index:2;
}
.locale-globe-marker svg{width:100%;height:100%}
.locale-globe-marker--currency{color:var(--green)}
.locale-globe-marker--language{color:var(--purple)}
.locale-globe-arrow{
  /* ORDEN CORRECTIVA (Fase 11, 5ta corrección puntual): tamaño reducido
     (antes 46x23) para que, junto al nuevo origen relativo al marcador
     (ver GLOBE_ARROW_MARKER_OFFSET en render.js), la flecha quede corta
     y pegada al marcador en vez de estirarse por buena parte del globo. */
  position:absolute;width:34px;height:17px;transform-origin:0% 100%;
  filter:drop-shadow(0 3px 5px #00000040);z-index:2;
}
.locale-globe-arrow svg{width:100%;height:100%}

.locale-info-note{
  display:flex;align-items:flex-start;gap:8px;font-size:.85rem;color:var(--ink-soft);
  margin-bottom:12px;
}
.locale-info-note-icon{flex:none;width:19px;height:19px;margin-top:1px}
.locale-info-note-icon svg{width:100%;height:100%}
.locale-info-note--currency .locale-info-note-icon{color:var(--green)}
.locale-info-note--language .locale-info-note-icon{color:var(--purple)}
.locale-info-note b{font-weight:700}
.locale-info-note--currency b{color:var(--green)}
.locale-info-note--language b{color:var(--purple)}

.locale-info-disclaimer{
  display:flex;align-items:flex-start;gap:10px;border-radius:14px;padding:12px 14px;
  font-size:.8rem;margin-bottom:16px;
}
.locale-info-disclaimer--currency{background:#22c55e1f;color:var(--ink-soft)}
.locale-info-disclaimer--language{background:#8b5cf61f;color:var(--ink-soft)}
.locale-info-disclaimer-icon{flex:none;width:20px;height:20px}
.locale-info-disclaimer-icon svg{width:100%;height:100%}
.locale-info-disclaimer--currency .locale-info-disclaimer-icon{color:var(--green)}
.locale-info-disclaimer--language .locale-info-disclaimer-icon{color:var(--purple)}
